Fscanf et sscanf sont dans un bato

Up, bon j’ai un petit probleme avec fscanf et sscanf.

Voilà, en fait, ce que je veux réaliser, c’est de pouvoir traiter un fichier texte mot par mot pour ensuite effectuer un filtrage.
Le problème que je viens de rencontrer est le suivant, je veux pouvoir lire le mot tout en ayant connaissance de sa position dans le fichier texte (ligne).

Donc, j’ai utilisé fgets pour ligne une ligne du fichier texte (où j’ai précisé qu’une ligne ne contenait au max 100 caractères), pour pouvoir traiter la position des mots.
Ensuite, une boucle de fscanf pour la lecture mot par mot, cependant, au lieu de lire la ligne, elle lit la totalité du fichier et donc impossible de savoir leur disposition dans le fichier (ligne).

Par contre j’ai ouvert le fichier 2 fois. Sinon, l’adresse du pointeur fichier serait identique dès qu’il y a du changement sur l’une des variables.

Pour ceux qui ne voient pas trop d’où je veux en venir, voici le bout de code :

[code]void ouvrir_doc()
{
FILE *nf;
FILE *nf_aux;
char nomfic[20];
char temp[31];
char string_buffer[100];
int line = 1;
int arg;

// test si document ouvert actuellement
printf("Sasir le fichier à traiter : ");
fflush(stdin);
gets(nomfic);
fflush(stdin);
if( (nf = fopen(nomfic, "r"))== NULL )  //ouverture d'un fichier
{

 fputs(“ERREUR : Fichier Inexistant\n”, stderr);
} else
{
 //traitement mot à mot

 //nf_aux = nf;
 nf_aux = fopen(nomfic, “r”);
 
 while(fgets(string_buffer, 100, nf))
 {
 //fscanf(nf, “%s”, &temp) != -1
 //arg = sscanf(string_buffer, “%s”, &temp);
 //while(arg)
 while( (fscanf(nf_aux, “%s”, &temp) != -1))
 {
   line = atoi(string_buffer) + 1;
   printf(“Mot lu : %s - position : %d\n”, temp, line);
   //arg–;
 
 //comptage de n° ligne d’apparition
 //mot suivant
 }
 line++;
 }

 printf(“TRAITEMENT EFFECTUER\n”);
}
}[/code]

Si j’ai bien compris c’est ça que tu veux ? Faut aussi ajouter #include <string.h> en haut.

[code]  while(fgets(string_buffer, 100, nf))
 {
   char * word = strtok(string_buffer, " \n");

   while(word) {

     printf(“Mot lu : %s - position : %d\n”, word, line);
     word = strtok(NULL, " \n");
   }

   line++;
 }[/code]

[quote name=‘Drealmer’ date=’ 4 Jan 2005, 22:22’]Si j’ai bien compris c’est ça que tu veux ? Faut aussi ajouter #include <string.h> en haut.

[code]  while(fgets(string_buffer, 100, nf))
 {
   char * word = strtok(string_buffer, " \n");

   while(word) {

     printf(“Mot lu : %s - position : %d\n”, word, line);
     word = strtok(NULL, " \n");
   }

   line++;
 }[/code]
[right][post=“318953”]<{POST_SNAPBACK}>[/post][/right][/quote]

Que fais exactement strtok ??

Au punaise faut que je t’embrasse :stuck_out_tongue: :P"
Merci , c’est bien ca que je voulais me reste plus qu’à traiter les ponctuations.
Sur ce, j’aimerais savoir le role du strtok ?

msdn ? ou peut etre man si tu prefere, dans tous les cas, google !

EDIT: et meme en francais !

[quote name=‹ Kzi › date=’ 4 Jan 2005, 22:40’]msdn ? ou peut etre man si tu prefere, dans tous les cas, google !

EDIT: et meme en francais !
[right][post=« 318962 »]<{POST_SNAPBACK}>[/post][/right][/quote]

Merci bien. Avec le nombre d’heure passé dessus pour un truc simplet, je n’ai pas eu le courage de chercher. :stuck_out_tongue:

Mouais. Je sais pas pour vous, mais mon prof de C qui nous a explique comment fonctionnait les Xscanf nous a dit au final: Vous savez ce que ca fait, maintenant, je vous interdit de l’utiliser.
Pourquoi? parce qu’on a aucun controle de ce qui est lu et les risques de buffer overflow sont omnipresent.
Alors, c’est pas mal vu le coup de fgets, mais:
_Si ta ligne fait 100 caracteres ou plus, ca segfault parce que fgets rajoute le leading 0 a la fin du buffer (qui va utiliser 101 cases du coup)

Moi perso, j’utiliserais un fread(&c,sizeof(char),1,file_handle) pour lire le fichier caractere par caractere, avec un switch© sur les caracteres important: ’ ', ‹ \n ›, etc etc.
De plus, c’est nettement plus modulaire vu que c’est toi qui gere tout. (donc tu peux rajouter un cas ‹ . › pour compter le nombre de phrases.

Note pour strtok:
BUGS
Never use this function. This function modifies its first
argument. The identity of the delimiting character is
lost. This function cannot be used on constant strings.

LoneWolf
Le C, ca rulez, et c’est tout :stuck_out_tongue:

LoneWolf: ah mais t’ as pas honte gros crado :stuck_out_tongue: si fread (je suppose que c est l equivalent de read avec des handle facon windows et pas des fd facon unix) est une bonne idee, l appeler char par char c est pas beau.

par contre lire N char, rechercher les token, si pas present concatener dans un autre buffer tout ca en boucle, ca serait legerement plus propre :stuck_out_tongue:

NOTE: mdr pour strtok, je l avais jamais utilisé, et c est peut etre mieux comme ca ^^

[quote name=‹ Kzi › date=’ 4 Jan 2005, 23:13’]LoneWolf: ah mais t’ as pas honte gros crado :stuck_out_tongue: si fread (je suppose que c est l equivalent de read avec des handle facon windows et pas des fd facon unix) est une bonne idee, l appeler char par char c est pas beau.

par contre lire N char, rechercher les token, si pas present concatener dans un autre buffer tout ca en boucle, ca serait legerement plus propre :stuck_out_tongue:

NOTE: mdr pour strtok, je l avais jamais utilisé, et c est peut etre mieux comme ca ^^
[right][post=« 318981 »]<{POST_SNAPBACK}>[/post][/right][/quote]
ben non c’est pas crade, fread, c’est bufferise justement :stuck_out_tongue:

Et lire N char pose plein d’autres problemes hyper chiant a gerer, vaut mieux carrement faire un malloc du fichier entier dans ce cas la B)

edit: Tiens, un exemple qui marche: http://perso.wanadoo.fr/gestival/cafzone/story/cafzone.c
Rapide et efficace. Optimise, peut etre pas B)"

LoneWolf
Test ma solution, tu verras :stuck_out_tongue:

si il bufferise (a la mmap) ok :stuck_out_tongue:

chiant a gerer ? pas forcement, les fonctions c est fait pour etre reutilisé. se faire une fonction (qui prend un fd et une chaine ou un char qui sert de delimiteur) qui lit en boucle et qui renvoie une chaine (basiquement une ligne) c est super utile. et reutilisable.

et malloc tout le fichier … c est encore pire !!

[quote name=‹ LoneWolf › date=’ 4 Jan 2005, 23:00’]Mouais. Je sais pas pour vous, mais mon prof de C qui nous a explique comment fonctionnait les Xscanf nous a dit au final: Vous savez ce que ca fait, maintenant, je vous interdit de l’utiliser.
Pourquoi? parce qu’on a aucun controle de ce qui est lu et les risques de buffer overflow sont omnipresent.
Alors, c’est pas mal vu le coup de fgets, mais:
_Si ta ligne fait 100 caracteres ou plus, ca segfault parce que fgets rajoute le leading 0 a la fin du buffer (qui va utiliser 101 cases du coup)

Moi perso, j’utiliserais un fread(&c,sizeof(char),1,file_handle) pour lire le fichier caractere par caractere, avec un switch© sur les caracteres important: ’ ', ‹ \n ›, etc etc.
De plus, c’est nettement plus modulaire vu que c’est toi qui gere tout. (donc tu peux rajouter un cas ‹ . › pour compter le nombre de phrases.

Note pour strtok:
BUGS
      Never use this function.  This function modifies its first
      argument.  The  identity  of  the delimiting character is
      lost.  This function cannot be used on constant strings.

LoneWolf
Le C, ca rulez, et c’est tout  :stuck_out_tongue:
[right][post=« 318976 »]<{POST_SNAPBACK}>[/post][/right][/quote]

Ouais j’ai vu ca que strtok modifiait les paramètres mais vu que j’en ai pas besoin. Ce que je veux c’est pouvoir lire chaque ligne mot par mot. Pour ensuite analyser ce mot afin de le classer celon une certaine catégorie.
Quant aux ponctuations ou autre, j’ai fait un chtit traitement dans une boucle for. Il va aller vérifier si le contenu du mot lu ne contient pas un de ces caractères spéciaux tel ‹ . ›, ‹ ; ›, …

Mais si vraiment je trouve une autre alternative assez simple. Je m’y pencherai. Sinon au cours de mes 3 années à faire de la prog, je n’ai entendu aucun prof nous dire que les Xscanf étaient un mal. Sinon, c’est quoi ce lien que tu nous filer, celui du cafzone.c ?

C"est juste un exemple de parseur txt fait en C, et qui lit caractere par caractere.
La solution du N bytes reste (a mon avis) une solution beaucoup plus complexe a gerer, notamment parce qu’on a pas de moyen d’etre sur que dans les N bytes, on aura une phrase minimum. Il y a donc tout un systeme de gestion de buffer a faire qui peut etre tres contraignant a utiliser.

edit: Demande a ton prof comment il fait pour gerer un probable buffer overflow avec scanf.
(c’est simple, tu peux pas gerer :P)

LoneWolf
Vive le bufferise :stuck_out_tongue:

rahlala LoneWolf :stuck_out_tongue:

Je suis tout à fait d’accord avec toi sur les risques présentés par les xprintf et xscanf, mais d’un autre côté, je pense que c’est pas plus mal de commencer avec un truc trèc simple, quitte à ne pas être secure ou flexible. Ensuite de réaliser les différents problèmes qui se présentent, et d’alors s’orienter vers des solutions plus évoluées.

J’ai vu tellement d’étudiants (et même de « professionnels ») se perdre dans leur propre code en essayant dès le départ de concevoir « le meilleur » système pour finalement n’arriver à rien… Que je dis et répète à qui veut l’entendre : « commencez par avoir un truc basique qui fonctionne et vous donne une vue globale de ce que vous réalisez, et ensuite améliorez-le ».

Bien entendu, tout dépend du contexte. J’ai bossé avec des gens qui fesaient de la maintenance d’un projet vieux de quinze ans, composé de plusieurs dizaines de millions de lignes de code. Le temps d’analyse minimum avant de faire le moindre changement au programme était de plusieurs mois, car il était hors de question de risquer le moindre problème. Là c’est justifié.

Mais tout à l’autre extrêmité, on a l’apprentissage. Et je pense ne pas me tromper en disant que MetalDestroyer apprend le C. Et là, c’est bien plus important de comprendre de façon progressive que de se perdre dans des méandres en essayant de faire « parfait » du premier coup. J’estime que les 3/4 de ce que j’ai appris, je l’ai appris de mes propres erreurs.

Et pour finir, ce passage-ci de ton post me surprend :

[quote name=‹ LoneWolf › date=’ 4 Jan 2005, 23:00’]Note pour strtok:
BUGS
      Never use this function.  This function modifies its first
      argument.  The  identity  of  the delimiting character is
      lost.  This function cannot be used on constant strings.
[right][post=« 318976 »]<{POST_SNAPBACK}>[/post][/right][/quote]

C’est pas des bugs, c’est la façon dont strtok fonctionne. C’est bien défini que ça fait ça. Cette fonction a un potentiel très limité, mais elle fait ce qu’elle est sensée faire.

Bien entendu, tout ceci n’est que mon point de vue :stuck_out_tongue:

[quote name=‹ Drealmer › date=’ 5 Jan 2005, 11:55’]rahlala LoneWolf :stuck_out_tongue:

Je suis tout à fait d’accord avec toi sur les risques présentés par les xprintf et xscanf, mais d’un autre côté, je pense que c’est pas plus mal de commencer avec un truc trèc simple, quitte à ne pas être secure ou flexible. Ensuite de réaliser les différents problèmes qui se présentent, et d’alors s’orienter vers des solutions plus évoluées.

Mais tout à l’autre extrêmité, on a l’apprentissage. Et je pense ne pas me tromper en disant que MetalDestroyer apprend le C. Et là, c’est bien plus important de comprendre de façon progressive que de se perdre dans des méandres en essayant de faire « parfait » du premier coup. J’estime que les 3/4 de ce que j’ai appris, je l’ai appris de mes propres erreurs.

Et pour finir, ce passage-ci de ton post me surprend :
C’est pas des bugs, c’est la façon dont strtok fonctionne. C’est bien défini que ça fait ça. Cette fonction a un potentiel très limité, mais elle fait ce qu’elle est sensée faire.

Bien entendu, tout ceci n’est que mon point de vue :stuck_out_tongue:
[right][post=« 319095 »]<{POST_SNAPBACK}>[/post][/right][/quote]

Exacte, je continue encore à apprendre le C, vu que je ne connais pas la totalité des possibilité offerte en C. Et puis, j’ai encore du mal à comprendre en quoi ces xprintf et xscanf sont un mal. Si c’est vraiment un mal, je me pose la question suivant alors comment faire un affichage du programme ?
Pour le xscanf je peux trouver une alterntive mais en xprintf, je ne vois pas.

Quant à strtok(), elle semble limité vu comme ca, mais elle a une utilité enfin juste quand je sais comment elle fonctionne.

Oh lui heh! B)

Moi, ce qui me gene, c’est que metal n’ait jamais entendu parle des problemes inherents a scanf et printf.
Apres, pour faire un truc en speed, c’est pratique.

Mouais. J’ai pas dit non plus que ma solution etait parfaite, j’ai juste dit que je la preferais aux autres :stuck_out_tongue:
Et commencer par du basique pour l’ameliorer, j’ai fait ca au taf et… c’est pas toujours une bonne idee. B)

J’ai pas dit non plus qu’il fallait etre parfait, j’ai juste dit que sa methode pouvait poser probleme, que pour faire ce qu’il veut, y a plein de solutions, et qu’il peut tres bien revoir le probleme pour faire autrement.

[quote name=‹ Drealmer › date=’ 5 Jan 2005, 11:55’]Et pour finir, ce passage-ci de ton post me surprend :
C’est pas des bugs, c’est la façon dont strtok fonctionne. C’est bien défini que ça fait ça. Cette fonction a un potentiel très limité, mais elle fait ce qu’elle est sensée faire.[/quote]
C’est dans le manpage. Et perso, quand je vois « never use this function » dans un manpage, je cherche une autre solution :stuck_out_tongue:

LoneWolf
Let’s programm! :stuck_out_tongue:

[quote name=‹ LoneWolf › date=’ 5 Jan 2005, 14:57’]Et commencer par du basique pour l’ameliorer, j’ai fait ca au taf et… c’est pas toujours une bonne idee. :stuck_out_tongue:
[right][post=« 319164 »]<{POST_SNAPBACK}>[/post][/right][/quote]

meme experience, tu te retrouve souvent avec un code bordelique a force de vouloir tout empiler des que le projet devient un peu important.

en plus commencer par du basique si c est pour prendre des mauvaises habitudes ca sert a rien.

L’idée de commencer par un truc basique mais qui fonctionne c’est que si l’idée de départ est mauvaise, on s’en rend compte très vite et on peut repartir sur des bases saines.

Sans entrer dans les détails, j’ai déjà vu deux semaines de design s’écrouler à cause d’une limitation d’un sdk. Si après un petit design, un premier prototype avait été réalisé, le problème serait apparu immédiatement.

Je n’ai jamais dit qu’il ne fallait pas planifier, mais je veux juste dire que la phase « je fais un prototype rapide pour tester mes idées » passe souvent à la trappe et que c’est la pire chose à faire.

J’ai aussi pas mal souffert sur un prog dont le développement a duré trois ans mais débuté trop rapidement. La fin du dev était un enfer sans nom, par contre tout ce que j’ai pu apprendre comme « pitfalls » c’est fou. Et c’est des leçons que je n’oublierai jamais.

Pour finir, j’était « assistant » pour des travaux dirigés à une époque, et j’ai vu des tonnes d’étudiants implémenter tout leur code (disons une dizaine de fonctions), le lancer et puis… « ah ça marche pas, help » et puis quand tu discute avec, tu te rends compte qu’il n’ont jamais essayé de tester le programme morceau par morceau avant de tout mettre ensemble.

:stuck_out_tongue: (j’aime bien ce smiley)

Finalement, je pense qu’on est du même avis :stuck_out_tongue:

Ben pareil.
On va dire que c’est en parti ce qui m’a fait partir de mon ancien taf.

Maintenant, je trouve que personne n’a vraiment repondu a la question de metal: Pourquoi pas de scanf/printf et quels alternatives?

scanf est le Mal car tu as aucune maitrise de ce qui se passe a l’entree des caracteres. Exemple:

[code]char entry[10], final[15];

printf(« please enter a number between 1 and 100\n »);
scanf(« %s »,entry);

sprintf(final, « you entered %s\n », entry);[/code]
Bon, le code est debile, c’est juste pour l’exemple.
on demande un chiffre entre 1 et 100, donc a priori, la taille maximal de entry est de 4: 3 car et le leading 0.
Sauf que l’utilisateur est con, et qu’il peut tres bien mettre n’importe quoi,genre:
krjhfukhfizhrfiheirg
et la, ben t’as pas de solution a part faire un segfault (non, mettre entry a 100 n’est pas une solution :P)
et la, meme si tu passes le scanf, tu vas planter le sprintf pour la meme raison.

Au niveau alternatif, il n’y a pas grand chose pour printf, a moins d’utiliser une GUI texte (ncurse) ou graphique (kde ou gnome). En fait, c’est a toi de faire gaffe a ce que tu fais avec printf. J’ai lu un super article sur les buffer overflow dans MISC, mais je sais plus lequel.

pour scanf, la solution simple reste fgets (ne pas oublier que c’est N + 1 pour le leading 0.)

Pour faire les choses proprement, il faut utiliser une GUI, en regle general. Si tu es sous linux en mode texte, je te recommande chaudement ncurses, c’est vraiment sympa a utiliser.

LoneWolf
Roh putain 23h15, au dodo! :stuck_out_tongue:

[quote name=‹ LoneWolf › date=’ 5 Jan 2005, 23:13’]Ben pareil.
On va dire que c’est en parti ce qui m’a fait partir de mon ancien taf.

Maintenant, je trouve que personne n’a vraiment repondu a la question de metal: Pourquoi pas de scanf/printf et quels alternatives?

scanf est le Mal car tu as aucune maitrise de ce qui se passe a l’entree des caracteres. Exemple:

[code]char entry[10], final[15];

printf(« please enter a number between 1 and 100\n »);
scanf("%s",entry);

sprintf(final, « you entered %s\n », entry);[/code]
Bon, le code est debile, c’est juste pour l’exemple.
on demande un chiffre entre 1 et 100, donc a priori, la taille maximal de entry est de 4: 3 car et le leading 0.
Sauf que l’utilisateur est con, et qu’il peut tres bien mettre n’importe quoi,genre:
krjhfukhfizhrfiheirg
et la, ben t’as pas de solution a part faire un segfault (non, mettre entry a 100 n’est pas une solution :P)
et la, meme si tu passes le scanf, tu vas planter le sprintf pour la meme raison.

Au niveau alternatif, il n’y a pas grand chose pour printf, a moins d’utiliser une GUI texte (ncurse) ou graphique (kde ou gnome). En fait, c’est a toi de faire gaffe a ce que tu fais avec printf. J’ai lu un super article sur les buffer overflow dans MISC, mais je sais plus lequel.

pour scanf, la solution simple reste fgets (ne pas oublier que c’est N + 1 pour le leading 0.)

Pour faire les choses proprement, il faut utiliser une GUI, en regle general. Si tu es sous linux en mode texte, je te recommande chaudement ncurses, c’est vraiment sympa a utiliser.

LoneWolf
Roh putain 23h15, au dodo!  :stuck_out_tongue:
[right][post=« 319353 »]<{POST_SNAPBACK}>[/post][/right][/quote]

Ah merci, je vois de quoi il s’agit, je me suis aussi posé la question en faisant mes tas de projets. Et j’ai du passer par une fonction de gestion d’erreur mais j’ai eu vraiment du mal, je crois même que je n’ai finalement pas pu résoudre ce cas là.
Et effectivement, c’est super genant pour un programme pour le grand public ou encore un prog pour une entreprise quelconque.

[quote name=‘MetalDestroyer’ date=’ 6 Jan 2005, 00:16’]Et effectivement, c’est super genant pour un programme pour le grand public ou encore un prog pour une entreprise quelconque.
[right][post=“319383”]<{POST_SNAPBACK}>[/post][/right][/quote]
C’est aussi de là que viennent les fameuses attaques par buffer overflow : on fait intentionnellement déborder le buffer pour remplacer des morceaux de code auxquels on n’a normalement pas accès.