[C] astuces needed, gestion/browsing dans fichiers

astuces needed, gestion/browsing dans fichiers [C] - C - Programmation

Marsh Posté le 19-07-2005 à 15:46:26    

Hello,
 
je cherche du code (ou idée de code, ca suffira) assez simple pour gérer qq contraintes (liste non exhaustive, je risque de repasser par là):
 
pr commencer:
 
-ignorer toutes les lignes commençant par *
-rechercher une chaine de caractere?
-récup des chaines de caractère, elle même encadrée par un séparateur (ca peut être des "" ou n'importe quoi d'autre) qui peuvent contenir des espaces (ou même n'être qu'une série d'espace).
 
voila pr commencer...
 
merci bcp pr votre aide!!


Message édité par mart le 19-07-2005 à 15:46:54
Reply

Marsh Posté le 19-07-2005 à 15:46:26   

Reply

Marsh Posté le 19-07-2005 à 15:52:44    

Reply

Marsh Posté le 19-07-2005 à 15:57:37    

euh...Rapport?
 
sinon une question plus simple qui me permetterait de savoir s'il faut "bourriner" ou non:
 
- Peut-on indiquer lors de la lecture d'un fichier d'aller à la ligne suivante autrement qu'en scannant ts les caractère d'une ligne jusqu'à \n ?

Reply

Marsh Posté le 19-07-2005 à 16:43:21    

en fait le format de fichiers peut etre tel que:

Code :
  1. * blablabla commentaires
  2. * blablalba commentaires
  3. * blablalba commentaires
  4. <SECTION 1>
  5. MONTRUC  :'salut   '
  6. *
  7. MONTRUC2 :/                   /
  8. *
  9. *
  10. <SECTION2>


etc..
 
 
la dedans je dois repérer la section désirée, capter MONTRUC, et la chaine de caractère entre les ' ' ou les / /

Reply

Marsh Posté le 19-07-2005 à 16:47:53    

n'y aurait-il pas une bibliothèque pour faire des expressions régulières en C ? [:petrus75]
 
(edit : sinon, c'est pas compliqué non plus, à faire "à la main" )


Message édité par theshockwave le 19-07-2005 à 16:48:24
Reply

Marsh Posté le 19-07-2005 à 16:52:15    

on je ne crois pas. Et il faut surtt pas que je sorte du cadre ANSI.
 
A la main je veux bien mais j'ai jamais trop bidouillé avec les fichiers d'où ma demande d'idée / principe.

Reply

Marsh Posté le 19-07-2005 à 17:00:14    

mart a écrit :

on je ne crois pas


 
cf le lien ci-dessus, posté par Manatane
 
Essaye de te lancer dans un algo, sinon, on t'aidera si tu bloques, mais c'est assez "logique", comme traitement à effectuer.

Reply

Marsh Posté le 19-07-2005 à 17:06:48    

mmmh il y a ecrit perl dans le lien de manatane nan?
 
de toute facon je ne dois rien utiliser de non-standard. C'est un programme qui devra être portable et ne nécessiter aucun add-on.  
 
Dans l'algo je suis mais je ne connais pas toutes les finesses du C pr se balader dans un fichier. Etant donné que mes données à recup peuvent être quelconque et sutout séparé d'un quelconque caractère, est ce que cela implique que je dois traiter la chose caractère par caractère? tout en fgetc?

Reply

Marsh Posté le 19-07-2005 à 17:09:11    

mart a écrit :

on je ne crois pas. Et il faut surtt pas que je sorte du cadre ANSI.


 
Si, si.  
Cf. contenu de regex.h
 
Par contre c'est POSIX (P2001), c'est pas ANSI.  
 
Si tu veux de l'ANSI strict, va falloir écrire ta propre bibliothèque, basée je pense sur string.h : strchr(), strstr(), etc.

Reply

Marsh Posté le 19-07-2005 à 17:34:02    

je pense pas besoin de tant pour faire ce qu'il y a a faire, en tout cas je ne pense pas que ce soit le but du truc, on m'en aurait parlé.
 
Il faut  
1. skip les lignes commencant par un *:
je l'ai fait avec un truc bien pourri du genre (qui fait ne qu'afficher les lignes non commentés):

Code :
  1. Tant que !eof{
  2. lis le caractère
  3. si le caractère=*{
  4.    lis dans le vent jusqu'à que le caractère soit \n ou eof
  5. }
  6. sinon{
  7.    affiche le caractère
  8.    affiche les caractère jusqu'a que le caractère soit \n ou eof
  9. }
  10. }


 
et je trouve ca bien super moisi :)


Message édité par mart le 19-07-2005 à 17:34:15
Reply

Marsh Posté le 19-07-2005 à 17:34:02   

Reply

Marsh Posté le 19-07-2005 à 17:51:38    

oui, au lieu d'afficher les caractères, tu peux les stocker sous forme de chaines (attention à la mémoire, cependant :/ ) et ensuite, l'extraction de ta donnée dans chacune des chaines sélectionnées est aussi assez simple, dans son principe.

Reply

Marsh Posté le 19-07-2005 à 18:14:43    

mart a écrit :


- Peut-on indiquer lors de la lecture d'un fichier d'aller à la ligne suivante autrement qu'en scannant ts les caractère d'une ligne jusqu'à \n ?


Il suffit d'utiliser la fonction qui sert à lire des lignes, à savoir fgets(), et ensuite de tester la ligne reçue (soit directement : ligne[i], soi via des fonctions de recherche comme strchr(), strstr(), strpbrk() etc.)
 
http://mapage.noos.fr/emdel/notes.htm#saisie
http://mapage.noos.fr/emdel/notes.htm#fichiers


Message édité par Emmanuel Delahaye le 19-07-2005 à 18:16:03

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 20-07-2005 à 09:18:53    

Emmanuel Delahaye a écrit :

Il suffit d'utiliser la fonction qui sert à lire des lignes, à savoir fgets(), et ensuite de tester la ligne reçue (soit directement : ligne[i], soi via des fonctions de recherche comme strchr(), strstr(), strpbrk() etc.)
 
http://mapage.noos.fr/emdel/notes.htm#saisie
http://mapage.noos.fr/emdel/notes.htm#fichiers


 
 
hehe merci bcp en effet le pire c'est que j'ai eu echo de fgets avant mais je faisais la confusion avec fscanf, et ta solution me parait tout ce qu'il y a de plus appropriée...
 

Citation :

 oui, au lieu d'afficher les caractères, tu peux les stocker sous forme de chaines (attention à la mémoire, cependant :/ ) et ensuite, l'extraction de ta donnée dans chacune des chaines sélectionnées est aussi assez simple, dans son principe.


 
Evidemment l'affichage était un test. Je suis aller plus loin dans cette solution qui me paraissait pas très élégante des le départ (et que je vais abandonné, merci emmanuel), voila un code qui permet de stocker/afficher les noms de section (pas tres utile la car il les fait tous sans traitement lorsqu'il en a scanné une).
 

Code :
  1. int read_control_section(FILE * cntl_prm_file){
  2.    char c;
  3.    char section_name[MAX_SECTION_NAME_LEN];
  4.    int i=0;
  5.    //skip commented lines
  6.    while(!feof(cntl_prm_file)){
  7.       if ((c=fgetc(cntl_prm_file))=='*'){
  8.          //go to the end of the line
  9.          while(c!='\n' && !feof(cntl_prm_file)){
  10.             c=fgetc(cntl_prm_file);
  11.          }
  12.       }
  13.       else{
  14.          //line begins with a <: start of a section
  15.          if(c=='<'){
  16.                test_function(cntl_prm_file);
  17.             //get section name
  18.             while(c!='>'){
  19.                section_name[i]=c;
  20.                c=fgetc(cntl_prm_file);
  21.                i++;
  22.             }
  23.          section_name[i]=c;
  24.          section_name[i+1]='\0';
  25.          //go to the end of the line
  26.          while(c!='\n' && !feof(cntl_prm_file)){
  27.             c=fgetc(cntl_prm_file);
  28.          }
  29.          i=0;
  30.          printf ("%s\n",section_name);
  31.          }
  32.          //common line (parameter), skip
  33.          else{
  34.             while(c!='\n' && !feof(cntl_prm_file)){
  35.                c=fgetc(cntl_prm_file);
  36.             }
  37.          }
  38.       }
  39.    }
  40. }


 
 
vous en conviendrez que c'est moche.
 
voilà finalement ce que j'ai fait:

Code :
  1. long get_section_pos(FILE * cntl_prm_file, char * section){
  2.    char line[MAX_LINE_SIZE];
  3.    char section_name[MAX_SECTION_NAME_LEN];
  4.    int pos;
  5.    int i=1;
  6.    while(!feof(cntl_prm_file)){
  7.       fgets(line,sizeof(line),cntl_prm_file);
  8.       //skip commented lines
  9.       if (line[0]!='*'){
  10.          //line begins with a <: start of a section
  11.          if(line[0]=='<'){
  12.             //get section name
  13.             while(line[i]!='>' && line[i]!=EOF && line[i]!='\n'){
  14.                section_name[i-1]=line[i];
  15.                i++;
  16.             }
  17.             if (line[i]!='>'){//means that line[i]==EOF or line[i]=='\n' : section field was never closed, syntax error
  18.                return -1;
  19.             }
  20.             else{ //valid section name, string has to be ended by '\0'
  21.                section_name[i-1]='\0';
  22.                printf ("%s\n",section_name);
  23.                i=1;
  24.                if(!strcmp(section,section_name)){
  25.                   return ftell(cntl_prm_file);
  26.                }
  27.             }
  28.          }
  29.       }
  30.    }
  31. //at this stage no section of the name given was found
  32.    return -1;
  33. }


Reply

Marsh Posté le 20-07-2005 à 09:23:37    

mart a écrit :


voilà finalement ce que j'ai fait:

Code :
  1. while(!feof(cntl_prm_file)){
  2.       fgets(line,sizeof(line),cntl_prm_file);



Merci de lire complètement les articles dont je t'ai donné les liens. Il y est expliqué le rôle de feof() qui n'est pas ce que tu crois, et la façon correcte d'utiliser fgets()...


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 20-07-2005 à 13:20:46    

Emmanuel Delahaye a écrit :

Merci de lire complètement les articles dont je t'ai donné les liens. Il y est expliqué le rôle de feof() qui n'est pas ce que tu crois, et la façon correcte d'utiliser fgets()...


 
merci bien pour tes indications. Maintenant je suis un peu confus avec ce que tu me dis.  
 
Pour le feof:
 
http://www-prima.inrialpes.fr/reig [...] node3.html
 

Citation :

La fin de fichier lors d'une opération de lecture peut être détectée par la fonction feof().

Code :
  1. while (!feof(file))
  2. {
  3.   ...
  4. }




 
man page unix:
 

Citation :


The function feof() tests the end-of-file indicator for the stream pointed to by stream, returning non-zero if it is set.


Ce qui veut bien dire que feof renvoie une valueur non-nulle tant que le pointeur de flux ne pointe pas sur EOF, pr moi ca me parait logique.
 
et enfin, microsoft (oui bon ok..., mais msdn c'est serieux qd meme):
 
http://msdn.microsoft.com/library/ [...] T_feof.asp
 
illustré d'un exemple qui reprend la même idée que mon code.
 
EDIT: ok j'ai compris (je crois), ce n'est pas vraiment faux, mais tu considères qu'il est plus juste de constater la fin de lecture (avec le retour de fgets) PUIS d'analyser s'il s'agit de la fin du fichier ou d'une erreur.
Right? Y avait-il qqch d'autre avec le fgets car je ne vois pas vraiment de diff dans le simple appel de fonction?
 
 
Pr l'alloc dynamique tu peux en dire plus (pr le fgets)? comment avoir la taille d'une ligne avant de l'avoir lu?
 
Merci bcp en tout cas, et si tu peux m'éclairer sur mes confusions c'est cool :)


Message édité par mart le 20-07-2005 à 13:53:36
Reply

Marsh Posté le 20-07-2005 à 14:03:23    

mart a écrit :

merci bien pour tes indications. Maintenant je suis un peu confus avec ce que tu me dis.  
 
Pour le feof:
 
http://www-prima.inrialpes.fr/reig [...] node3.html
 

Citation :

La fin de fichier lors d'une opération de lecture peut être détectée par la fonction feof().

Code :
  1. while (!feof(file))
  2. {
  3.   ...
  4. }






Erreur courante. Tout est déjà expliqué sur mon site. Quels sont les mots que tu ne comprends pas ?

Citation :


man page unix:
 

Citation :


The function feof() tests the end-of-file indicator for the stream pointed to by stream, returning non-zero if it is set.


Ce qui veut bien dire que feof renvoie une valueur non-nulle tant que le pointeur de flux ne pointe pas sur EOF, pr moi ca me parait logique.


C'est ton interprétation. En réalité, la norme est claire. Pour détecter la fin de lecture, on doit utiliser le code retour des fonctions de lecture. Ensuite et seulement ensuite, on a le droit d'utiliser feof() et ferror() pour déterminer la cause de l'arrêt (j'ai l'impression de recopier mon site... passons...).
 
Toutes ces informations sont issues de la lecture des FAQs de clc et fclc...
 
http://docs.mandragor.org/files/Pr [...] q/top.html
http://docs.mandragor.org/files/Pr [...] lc_faq_fr/
 

Citation :


et enfin, microsoft (oui bon ok..., mais msdn c'est serieux qd meme):
 
http://msdn.microsoft.com/library/ [...] T_feof.asp
 
illustré d'un exemple qui reprend la même idée que mon code.


Toujours la même erreur. Cette méconnaissance du langage est hélas très répandue... Si il se produit une erreur de lecture (défaut disque, rupture de lien avec un serveur etc.), la fin de fichier ne sera pas détectée, et on bouclera indéfiniment.

Citation :


Et  pr le fgets je ne vois pas ce qui diffère:
 
Ton exemple:  

Code :
  1. if (fp != NULL)
  2.    {
  3.       /* definition d'un tableau de char destine a recevoir la ligne
  4.        * La taille est arbitraire. Elle doit etre cependant adaptee * aux besoins courants.
  5.        * Pour les grandes tailles (disons > 256 char),
  6.        * il est preferable d'utiliser une allocation dynamique.
  7.        */
  8.       char ligne[32];
  9.       /* lecture de la premiere ligne */
  10.       fgets (ligne, sizeof ligne, fp);

 
et ca:

Code :
  1. fgets(line,sizeof(line),cntl_prm_file);


 
la verif du fichier est faite avant. Je vois pas d'autre moif?


Il manque le test de la valeur retournée par fgets(). Le fameux test qui permet de savoir si la lecture s'est arrétée. (avec fgets() : NULL). Des exemples sont donnés plus loin dans l'article de mon site...

Citation :


Pr l'alloc dynamique tu peux en dire plus? comment avoir la taille d'une ligne avant de l'avoir lu?


On ne peut pas savoir, mais on peut allouer un bloc d'une taille 'raisonnable'. Il sera alors possible de déterminer si la ligne a été entièrement lue ou non en testant la présence du '\n' (strchr()).
 
Si il en manque, on peut agrandir (realloc()), et continuer à lire (sans écraser le début de la ligne, bien sûr) jusqu'à ce qu'on detecte enfin le '\n'...
 
C'est un petit algo rigolo, un peu piégeux... Quand on l'a fait une fois, on le colle en bibliothèque et on en parle plus...


Message édité par Emmanuel Delahaye le 14-09-2005 à 13:09:31

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 20-07-2005 à 15:49:25    

sorry, cf edit (trop tard), il faut que j'apprenne a lire plus lentement au lieu de foncer tete baissée :)

Reply

Marsh Posté le 20-07-2005 à 15:54:23    

Heu et flex c'est pour les chiens ?

Reply

Marsh Posté le 20-07-2005 à 16:58:45    

flex? http://www.gnu.org/software/flex/  
ok rapport?


Message édité par mart le 20-07-2005 à 16:59:55
Reply

Marsh Posté le 20-07-2005 à 17:03:55    

flex : fast lexical analyzer generator
 
Ca sert à générer des programmes qui font du pattern-matching sur du texte.
 
http://cs.wwc.edu/~aabyan/464/Book/LexFlex.html


---------------
Scheme is a programmable programming language ! I heard it through the grapevine !
Reply

Marsh Posté le 21-07-2005 à 12:16:26    

utiliser flex pour ca, c'est pas un peu démesuré ?

Reply

Marsh Posté le 21-07-2005 à 13:33:34    

ca pourrait etre interressant, le pattern est au final plus compliqué que ca. On dirait que le mec s'est amusé à réinventer le XML. Mais bon, merci, je crois pas que je puisse l'utiliser...

Reply

Marsh Posté le 30-07-2005 à 08:35:52    

C'est quoi les contraintes exactes qui font que tu ne peux pas utiliser des librairies ultra standard comme flex/bison ou même regex (voire pcre) ?
Si la syntaxe à parser est complexe, ou destinée à évoluer dans cette direction (ce qui est souvent le cas), des outils comme flex/bison valent le coût d'être appris et utilisés.


Message édité par el muchacho le 30-07-2005 à 08:40:21
Reply

Marsh Posté le 30-07-2005 à 10:55:23    

ANSI

Reply

Marsh Posté le 31-07-2005 à 11:52:23    

Ca, ce n'est pas une contrainte, sauf si c'est pour un devoir d'études (à la rigueur, et encore, uniquement si le prof est particulièreement obtus...). Ce que j'appelle contraintes, ce sont des contraintes imposées par la machine (mémoire, cpu, etc) et l'environnement d'exécution (OS, temps réel, etc).
ANSI ne concerne que le coeur du langage et la lib C de base, et celà n'implique que la portabilité (contrainte que l'on devrait chercher à respecter au maximum de toute façon). Ca ne limite pas l'utilisation de bibliothèques portables comme celles qui ont été citées, et qui sont programmées e conformité avec les règles de la norme.


Message édité par el muchacho le 31-07-2005 à 11:57:29
Reply

Marsh Posté le 31-07-2005 à 18:20:26    

en gros le soft doit tourner sur tout type d'archi et tout type d'os sans installation tierce. Ca c'est la contrainte.

Reply

Marsh Posté le 14-09-2005 à 12:25:32    

ah voui et je viens d'y penser. Le soft sera proprio.

Reply

Marsh Posté le 15-09-2005 à 06:47:13    

Cool, si on poste du code GPL ici donnant solution à ton problème, on peut te reprocher de l'avoir vu :ange:


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed