Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Débutant - passer de gets à fgets

11 réponses
Avatar
bpascal123
Bonnes f=EAtes,

Je rencontre une difficult=E9 sur l'exercice 8.23 de ce tutoriel :
http://www.ltam.lu/Tutoriel_Ansi_C/
(il faut naviguer manuellement, il n'est pas possible de copier-coller
l'adresse qui m=E8ne directement =E0 l'exercice, d'ailleurs sans rapport
avec ce groupe, quelqu'un saurait me dire comment s'est possible de
naviguer dans diff=E9rentes pages d'un site sans que la barre d'adresse
indique l'adresse de la page???).

Bref, pour en revenir =E0 8.23, l'auteur n'a pas mis =E0 jour le site
(tant mieux, =E7a ajoute un peu de piment et des fois un peu d'injure =E0
la blessure de ne pas y arriver...). Le code de l'auteur fonctionne
tr=E8s bien et le r=E9sultat est coh=E9rent. Mais il fait appel =E0 "gets".

Gets ne semble plus tr=E8s populaire pour cause de s=E9curit=E9, je pense
que c'est C99 ou Posix qui veut, =E7=E0, je ne connais pas tr=E8s bien la
diff=E9rence entre les 2.

Voici mon code, qui inclut fgets et qui sur le m=EAme principe
fonctionne tr=E8s bien avec les 2 exercices pr=E9c=E9dents qui sont
l=E9g=E8rement diff=E9rent de l'exercice 8.23 (remplacement de chaine de
caract=E8re...) :

/* EXERCICE 8.23
Ecrire un programme qui remplace toutes les occurrences d'une cha=EEne
de caract=E8res CH1 par la cha=EEne CH2 dans une cha=EEne de caract=E8res S=
UJ.
Utiliser une cha=EEne de sauvegarde FIN pendant le remplacement.
*/

#include <stdio.h>

int main(void)
{

char Suj[50] ; /* Chaine sujet */
char Ch1[50] ; /* Chaine =E0 rechercher */
char Ch2[50] ; /* Chaine =E0 remplacer */
char Fin[50] ; /* Chaine de sauvegarde pour la fin de sujet*/

int i, j, in ; /* variable d'aide */

/* SAISIE SUJET, CHAINE 1, 2 ...*/

printf("\n\nEntrez une chaine sujet : ") ;
fgets(Suj, 50, stdin) ;

/* Suppression du '\n' dans le buffer lu par fgets*/

for ( i =3D 0 ; Suj[i] ; i++ )
;
i-- ;
Suj[i] =3D '\0' ;

printf("\nEntrez une chaine objet Ch1 a rechercher dans sujet :") ;
fgets(Ch1, 50, stdin) ;

/* Suppression du '\n' dans le buffer lu par fgets*/

for ( i =3D 0 ; Ch1[i] ; i++ )
;
i-- ;
Ch1[i] =3D '\0' ;

printf("\nEntrez une chaine objet Ch2 a rechercher dans sujet :") ;
fgets(Ch2, 50, stdin) ;

/* Suppression du '\n' dans le buffer lu par fgets*/

for ( i =3D 0 ; Ch2[i] ; i++ )
;
i-- ;
Ch2[i] =3D '\0' ;

/* */
/* Boucle de recherche et remplacement */
/* */

for ( i =3D 0 ; Suj[i] ; i++)
{
if ( Suj[i] =3D=3D Ch1[0] )
{
for ( j =3D 1 ; Ch1[i] && (Ch1[i] =3D=3D Suj[i+j]) ; j++)
;
if ( Ch1[j] =3D=3D '\0' )
{
printf("\nTrouve!!!") ;
/* sauvegarde de la fin de Suj dans Fin */
for ( in =3D 0 ; Suj[i+j+in] ; in++ )
Fin[in] =3D Suj[i+j+in] ;
Fin[in] =3D '\0' ;

/* copie de Ch2 ds Suj */
for ( in =3D 0 ; Ch2[in] ; in++, i++ )
Suj[i] =3D Ch2[in] ;

/*recopier Fin dans Suj */
for ( in =3D 0 ; Fin[in] ; in++)
Suj[i+in] =3D Fin[in] ;
Suj[i+in] =3D '\0' ;
i-- ;
}
}
}

printf("\nResultat : %s", Suj) ;

printf("\n\n") ;

return 0 ;
}

-o-

S'il vous pla=EEt, sauf si c'est utile pour d'autres membres du groupe,
ne changez pas compl=E8tement le code dans la mesure ou le tout me
semble "carr=E9" et coh=E9rent, je connais d=E9j=E0 les pointeurs mais je v=
eux
m'en sortir sans dans la mesure ou la solution de l'exercice qui
correspond au chapitre en cours n'inclut pas des choses compliqu=E9es
qui rendent le code plus performant ou moins long...je sais que =E7a
doit d=E9manger certains mais dans l'imm=E9diat, je ne vais pas me
concentrer sur une r=E9ponse trop "experte".

Juste pour dire, il me semble que le non-fonctionnement provient de la
premi=E8re partie fgets avec recherche du '\n', or fgets fonctionne tr=E8s
bien de la m=EAme mani=E8re dans les 2 exercices pr=E9c=E9dents. ( printf
("\Trouv=E9!!!") ) s'affiche. Peut-=EAtre cette manipulation ne convient
pas dans cette situation. Pour quelle raison?

Merci,

Pascal

10 réponses

1 2
Avatar
Benoit Izac
Bonjour,

le 21/12/2009 à 17:47, bpascal a écrit dans le message
:

Bonnes fêtes,

Je rencontre une difficulté sur l'exercice 8.23 de ce tutoriel :
http://www.ltam.lu/Tutoriel_Ansi_C/
(il faut naviguer manuellement, il n'est pas possible de copier-coller
l'adresse qui mène directement à l'exercice, d'ailleurs sans rapport
avec ce groupe, quelqu'un saurait me dire comment s'est possible de
naviguer dans différentes pages d'un site sans que la barre d'adresse
indique l'adresse de la page???).



Il suffit de n'afficher que la frame (traduction ?) de droite.
<http://www.ltam.lu/Tutoriel_Ansi_C/prg-c76.htm>

Bref, pour en revenir à 8.23, l'auteur n'a pas mis à jour le site
(tant mieux, ça ajoute un peu de piment et des fois un peu d'injure à
la blessure de ne pas y arriver...). Le code de l'auteur fonctionne
très bien et le résultat est cohérent. Mais il fait appel à "gets".

Gets ne semble plus très populaire pour cause de sécurité, je pense
que c'est C99 ou Posix qui veut, çà, je ne connais pas très bien la
différence entre les 2.



Est-ce que tu lis les réponses aux questions que tu poses ?

Voici mon code, qui inclut fgets et qui sur le même principe
fonctionne très bien avec les 2 exercices précédents qui sont
légèrement différent de l'exercice 8.23 (remplacement de chaine de
caractère...) :

/* EXERCICE 8.23
Ecrire un programme qui remplace toutes les occurrences d'une chaîne
de caractères CH1 par la chaîne CH2 dans une chaîne de caractères SUJ.
Utiliser une chaîne de sauvegarde FIN pendant le remplacement.
*/

#include <stdio.h>

int main(void)
{

char Suj[50] ; /* Chaine sujet */
char Ch1[50] ; /* Chaine à rechercher */
char Ch2[50] ; /* Chaine à remplacer */
char Fin[50] ; /* Chaine de sauvegarde pour la fin de sujet*/

int i, j, in ; /* variable d'aide */

/* SAISIE SUJET, CHAINE 1, 2 ...*/

printf("nnEntrez une chaine sujet : ") ;



Je crois que ça a été dis déjà pas mal de fois :
__ __ _ _ __ _ _ _ __
/ _|/ _| |_ _ ___| |__ / /__| |_ __| | ___ _ _| | _
| |_| |_| | | | / __| '_ | / __| __/ _` |/ _ | | | | __| (_)
| _| _| | |_| __ | | | __ || (_| | (_) | |_| | |_| |_
|_| |_| |_|__,_|___/_| |_| |___/____,_|___/ __,_|__| ( )
_ /_/|/

fgets(Suj, 50, stdin) ;



Comment sais-tu que fgets a fonctionné correctement et que Suj ne
contient pas n'importe quoi ?

/* Suppression du 'n' dans le buffer lu par fgets*/

for ( i = 0 ; Suj[i] ; i++ )
;
i-- ;
Suj[i] = '' ;

printf("nEntrez une chaine objet Ch1 a rechercher dans sujet :") ;
fgets(Ch1, 50, stdin) ;

/* Suppression du 'n' dans le buffer lu par fgets*/

for ( i = 0 ; Ch1[i] ; i++ )
;
i-- ;
Ch1[i] = '' ;

printf("nEntrez une chaine objet Ch2 a rechercher dans sujet :") ;
fgets(Ch2, 50, stdin) ;

/* Suppression du 'n' dans le buffer lu par fgets*/

for ( i = 0 ; Ch2[i] ; i++ )
;
i-- ;
Ch2[i] = '' ;

/* */
/* Boucle de recherche et remplacement */
/* */


[snip, trop compliqué]

printf("nResultat : %s", Suj) ;

printf("nn") ;



printf("nResultat : %snn", Suj);
fait la même chose en moins fatigant pour les doigts.

return 0 ;
}



Franchement, avec toutes les remarque qui t'ont été faites et dont tu ne
tiens pas compte, comment veux-tu progresser ? Relis les réponses de tes
questions précédentes, tu y trouveras les réponses à tes problèmes.

--
Benoit Izac
Avatar
bpascal123
> Franchement, avec toutes les remarque qui t'ont été faites et dont tu ne
tiens pas compte, comment veux-tu progresser ? Relis les réponses de te s
questions précédentes, tu y trouveras les réponses à tes problè mes.

--
Benoit Izac



Bjr-sr,

Je n'ai pas vu de réponse. Je suppose que tu me renvoies à la
discussion : "Copie de chaine de caracteres sans succes" d'il y a
quelques jours dans ce groupe. Je suis allé voir ton post. Je vais
faire un copié-collé pour l'étudier attentivement car il semble que t a
solution est exactement celle qui me convient, à tes yeux.

L'auteur de ce tutoriel n'a pas inclut stdlib.h et encore moins du
code comme (fgets(str, STR_S, stdin) == NULL).
Sache que ça reste à un niveau simple et qu'avec tout le respect que
j'ai pour ton niveau, aujourd'hui, je suis incapable d'utiliser les
instructions que tu proposes.

La solution de l'auteur ne prend en compte que stdio.h, et le code est
très basique. Ici, je cherche juste à comprendre comment de manière
simple ajuster fgets pour que ça fonctionne. Et ca fonctionne de la
même manière pour les 2 exercices précédents. Alors pourquoi faudra it-
il tout changer pour cet exercice similaire en tout point.

Oui, j'essaie de lire les réponses, des fois en diagonale quand c'est
un niveau qui est pour le moment largement au-dessus de ce que je peux
comprendre et faire.

Merci,
Pascal
Avatar
espie
In article ,
wrote:
Gets ne semble plus très populaire pour cause de sécurité, je pense
que c'est C99 ou Posix qui veut, çà, je ne connais pas très bien la
différence entre les 2.



Tentative d'humour ? la securite reelle et les normes diverses et variees n'ont guere
de rapport. Non, c'est juste du buffer overflow, et fgets existe en C depuis avant la
norme C89.


fgets(Suj, 50, stdin) ;

/* Suppression du 'n' dans le buffer lu par fgets*/

for ( i = 0 ; Suj[i] ; i++ )
;
i-- ;
Suj[i] = '' ;




Tu es desesperant !!! on t'a repete quinze fois, environ, que ce code etait *faux* et tu
persistes.


1/ fgets peut tres bien echouer. Ce sera le cas si tu fais ^Z sur ton windows pour terminer
le flux d'entree. Auquel cas, ton tampon ne sera pas affecte.

2/ Tu supposes qu'il y a un "n" dans ton tampon. La-aussi, si on tape plus de 50 caracteres
ca ne sera pas le cas.

Au minimum, ca se blinde comme ca.

if (fgets(Suj, 50, stdin)) == NULL) {
if (ferr(stdin)) {
perror("Probleme de lecturen");
exit(EXIT_FAILURE);
} else {
fprintf(stderr, "Fin prematureen");
exit(EXIT_FAILURE);
}
}

/* Suppression d'un eventuel n, maintenant qu'on est sur qu'il y a eu lecture. */

for ( i = 0 ; Suj[i] ; i++ )
;
if (i > 0 && Suj[i-1] == 'n') {
i-- ;
Suj[i] = 0;
}


Et sinon, soit coherent: soit tu testes Suj[i] != '' et tu affectes Suj[i] = '',
soit tu testes directement Suj[i] et tu affecte Suj[i] = 0...
Mais pas un melange des deux.
Avatar
Benoit Izac
Bonjour,

le 21/12/2009 à 20:11, bpascal a écrit dans le message
:

Franchement, avec toutes les remarque qui t'ont été faites et dont tu ne
tiens pas compte, comment veux-tu progresser ? Relis les réponses de tes
questions précédentes, tu y trouveras les réponses à tes problèmes.





Je n'ai pas vu de réponse. Je suppose que tu me renvoies à la
discussion : "Copie de chaine de caracteres sans succes" d'il y a
quelques jours dans ce groupe. Je suis allé voir ton post.



C'est ce que j'appelle une « réponse ».

Je vais faire un copié-collé pour l'étudier attentivement car il
semble que ta solution est exactement celle qui me convient, à tes
yeux.



Où ai-je écrit que je pensais que cette solution était celle qui te
convenais ? J'ai simplement repris ton code, sans savoir vraiment ce
qu'il était sensé faire et essayé de te donner des explications sur ce
à quoi il faut faire attention.

L'auteur de ce tutoriel n'a pas inclut stdlib.h et encore moins du
code comme (fgets(str, STR_S, stdin) == NULL).



C'est précisément pourquoi j'ai pris le soin de préciser « pour
exit() ». Si ton code à un problème, tu ne peux pas simplement l'ignorer
et espérer que ça marche. Par analogie, c'est un peu comme si tu jouais
au loto et, sans regarder le résultat du tirage, tu vas voir un agent
immobilier et tu lui fais un chèque pour un château.

Sache que ça reste à un niveau simple et qu'avec tout le respect que
j'ai pour ton niveau, aujourd'hui, je suis incapable d'utiliser les
instructions que tu proposes.



Donne moi un exemple d'instruction que j'ai écrit et que tu n'es pas
capable d'utiliser. Quand à mon niveau, disons simplement qu'il est très
loin de la plupart des intervenants de ce groupe. Vu que je n'ai pas été
repris, je pense que pour une fois, je n'ai pas dit trop de bêtises.

La solution de l'auteur ne prend en compte que stdio.h, et le code est
très basique. Ici, je cherche juste à comprendre comment de manière
simple ajuster fgets pour que ça fonctionne. Et ca fonctionne de la
même manière pour les 2 exercices précédents. Alors pourquoi faudrait-
il tout changer pour cet exercice similaire en tout point.



Je n'ai pas lu les énoncés des exercices, je ne vois donc pas de quoi tu
parles. Dans tous les cas IL FAUT TOUJOURS TESTER LE RETOUR DES
FONCTIONS.

Oui, j'essaie de lire les réponses, des fois en diagonale quand c'est
un niveau qui est pour le moment largement au-dessus de ce que je peux
comprendre et faire.



Rassure toi, moi aussi j'ai lu en diagonale le reste du fil de
discussion, par contre les réponses qui t'on été apporté (juste derrière
ton message), ne sont pas d'un niveau « largement au-dessus ». Si tu
veux vraiment atteindre tes objectifs, il faudrait faire un minimum
d'effort pour essayer de comprendre.

Je ne sais pas sur quelle plateforme tu développes, mais il te faut au
minimum l'équivalent des pages de manuel sous UNIX qui vont te dire ce
qu'est sensé faire une fonction. Par exemple pour fgets() :
<http://www.opengroup.org/onlinepubs/9699919799/functions/fgets.html>

| RETURN VALUE
| Upon successful completion, fgets() shall return s. If the stream is
| at end-of-file, the end-of-file indicator for the stream shall be
| set and fgets() shall return a null pointer. If a read error occurs,
| the error indicator for the stream shall be set, fgets() shall
| return a null pointer, and shall set errno to indicate the error.

Ce qui veut dire que pour bien utiliser fgets, il faut :
- lire sa valeur de retour
- si elle vaut NULL, il faut vérifier si on est à la fin du fichier
(avec feof()) ou s'il y a eu une erreur (avec ferror() et errno)

Ensuite tu vas lire la description de feof(), ferror() et errno.

C'est beaucoup de lecture, beaucoup de prise de tête pour comprendre
comment ça marche mais malheureusement, il n'y a pas moyen d'y échapper
si tu veux vraiment programmer. Es-tu toujours motivé ?

--
Benoit Izac
Avatar
Benoit Izac
Bonjour,

le 21/12/2009 à 20:37, Marc Espie a écrit dans le message
<hgoipu$jr$ :

Tentative d'humour ? la securite reelle et les normes diverses et variees n'ont guere
de rapport. Non, c'est juste du buffer overflow, et fgets existe en C depuis avant la
norme C89.



Tes lignes sont un poil trop longues aujourd'hui.

--
Benoit Izac
Avatar
bpascal123
for ( j = 1 ; Ch1[j] && (Ch1[j] == Suj[i+j]) ; j++)

comme quoi, il ne faut pas chercher midi à quatorze heure
(une journée de perdue, heureusement que c'est une révision que je
m'impose de temps à autre).

Le but de cette révision est de comprendre la différence entre
l'algorithme méthodologie tableau et l'algorithme méthodologie
pointeurs pour le même code (voir sur le tutoriel, le même exercice
dans le chapitre pointeur : Exercice 9.14 et 9.13). Fatiguant mais
nécessaire. Si le langage c est décourageant, il ne faut s'en vouloir
qu'à soi-même avant d'accuser son chien de rage mais comme l'histoire
est un perpétuel recommencement le temps perdu ne se retrouve jamais
(sauf avec le temps passé à chercher des erreurs comme celles-là!).

Merci,
Pascal
Avatar
batyann811
a écrit :
nécessaire. Si le langage c est décourageant, il ne faut s'en vouloir
qu'à soi-même avant d'accuser son chien de rage mais comme l'histoire



Sincèrement si tu es vraiment débutant en programmation tu ferais mieux
de commencer par autre chose que le C ce sera beaucoup moins frustrant...

Merci,
Pascal



Le pascal, voilà un bonne idée :

http://www.taoyue.com/tutorials/pascal/index.html

http://uva.ulb.ac.be/cit_courseware/FPASCAL/DEFAULT.HTM

Une fois que tu te sens à l'aise tu passeras plus facilement au C (si tu
en as toujours envie) ou à autre chose (c++, java).

Mais bon c'est juste mon avis (et un peu mon histoire).
Avatar
bpascal123
On Dec 22, 9:26 am, batyann811 wrote:
a écrit :

> nécessaire. Si le langage c est décourageant, il ne faut s'en voulo ir
> qu'à soi-même avant d'accuser son chien de rage mais comme l'histoi re

Sincèrement si tu es vraiment débutant en programmation tu ferais mie ux
de commencer par autre chose que le C ce sera beaucoup moins frustrant...

> Merci,
> Pascal

Le pascal, voilà un bonne idée :

http://www.taoyue.com/tutorials/pascal/index.html

http://uva.ulb.ac.be/cit_courseware/FPASCAL/DEFAULT.HTM

Une fois que tu te sens à l'aise tu passeras plus facilement au C (si t u
en as toujours envie) ou à autre chose (c++, java).

Mais bon c'est juste mon avis (et un peu mon histoire).



Bjr,sr,

Je me suis intéressé au langage C le jour ou j'ai cherché des
ressources pour savoir pourquoi je galérais avec les drivers sur mon
netbook. Le site web how-to a été directe et a conseillé d'apprendre
le langage C.

J'ai commencé à chercher des ressources, à faire quelques programmes,
à acheter un livre d'occas et puis 2 livres et puis 3 livres... et le
K&R et la solution.

Même si je galère 2 ou 3 ans avec un langage que je reconnais ne me
permettra pas d'aller jusqu'à la programmation d'un driver, j'ai déjà
investit beaucoup de temps, d'effort et un peu d'argent.

A ce stade, avec toutes les personnes qui me disent de faire tout sauf
le C dans le monde francophone, ça me pousse à m'y intéresser de plus
près, dsl, je suis têtu et j'ai déjà eu beaucoup de déconvenues s ur ma
vie personnelle à écouter des conseils à ce jour et c'est largement
aujourd'hui une raison pour laquelle je ne suis pas dans une situation
simple aujourd'hui mais c'est autre chose. Les bons conseilleurs...

Merci quand même,

Pascal
Avatar
Hamiral
wrote:
A ce stade, avec toutes les personnes qui me disent de faire tout sauf
le C dans le monde francophone, ça me pousse à m'y intéresser de plus
près, dsl, je suis têtu et j'ai déjà eu beaucoup de déconvenu es sur ma
vie personnelle à écouter des conseils à ce jour et c'est largeme nt
aujourd'hui une raison pour laquelle je ne suis pas dans une situation
simple aujourd'hui mais c'est autre chose. Les bons conseilleurs...



En fait, ton problème, c'est que tu veux apprendre, mais tu ne tiens pa s
compte des réponses que les gens qui connaissent le C te donnent. Alors ,
désespérés, certains te suggèrent une autre approche.
Donc (mais je sais que tu ne suivras pas ce conseil), si tu veux
vraiment apprendre le C, commence par suivre les conseils que les pros
te donnent. Et c'est aussi une question de respect ! Tu demandes de
l'aide mais tu n'as que faire de l'aide que tu reçois...
Je ne fais pas partie de ceux qui perdent un temps précieux à essayer de
t'aider, mais si j'étais à leur place, je ressentirais un mélange d e
frustration et d'énervement face à ton attitude. Bref, à leur place
j'aurais abandonné depuis longtemps.

Ham
Avatar
batyann811
a écrit :
A ce stade, avec toutes les personnes qui me disent de faire tout sauf
le C dans le monde francophone,



Et à ton avis pourquoi ces gens te proposent de suivre un autre chemin ?
Peut être parce qu'il est plus simple, plus rapide,moins décourageant et
plus sûr.

Tu peux très bien faire un peu de pascal pendant quelques temps histoire
d'apprendre les bases (variables, boucles, fonctions, récursivité,
quelques algos de tri) puis passer au C le moment venu si tu en éprouves
toujours le besoin.

Tes livres de C ne seront pas perdu et te sembleront beaucoup plus
simple quand tu les reprendras avec ces nouvelles bases.

De plus si tu persistes avec ta méthodes actuelles tu risques de prendre
de mauvaises habitudes.

Mais bon comme le disait Tonton David : "chacun sa route, chacun son
chemin"...
1 2