Problème avec fgets()

Fermé
Nox - 5 août 2014 à 18:44
 Nox - 6 août 2014 à 15:04
Bonjour,
Je programme depuis peu en C et j'ai créé un programme "menu" qui est simple: il me permet, grâce à switch(), soit de sortir soit de lancer un autre programme qu'il va chercher à l'endroit indiqué. J'ai rajouté une sorte de mot de passe pour l'exercice (inutile car si le code source est ouvert, on voit le mot de passe).
Je ne vous demande pas de me corriger pour la vérification du code mais de me dire pourquoi, quand je l'exécute, le programme passe la fonction fgets() et n'attend pas que je lui donne les 5 caractères. Le plus étonnant, c'est que quand j'isole cette partie du programme en recréant un programme, plus simple, la fonction fgets() marche.
D'avance, merci:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int choix;
int main ()
{
while (1)
{
start: ;
puts("\nBienvenue dans le menu: pour utiliser l'algorythme des nombres premiers,");
puts("tapez 1; pour sortir, tapez 2");
scanf("%d", &choix);

switch (choix)
{ case 1: {puts("\nVous avez choisis les nombres premiers");
goto localisation1 ;}
break;
case 2 : {
goto localisation2 ;}
break;

}
}

localisation1: ;
{
char line[5];
char bon [5] = {'m', 'o', 't', 's', '\0' };

printf ("Entrez le mot de passe:\n");
fflush(stdin);
fgets(line, sizeof(line), stdin);

if (line[1] == bon[1]& line[2]==bon[2]& line[3]==bon[3]& line[4]==bon[4]& line[5]==bon[5] )
{puts("\nInitialisation des nombres premiers");
system ("./Programmes/nbr1.exe");}
else
puts("Désolé, mauvais mot de passe");
return (1);
goto end;
}
localisation2:;
{
puts("\nVous avez choisis de sortir");
end: ;
}
}

5 réponses

fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
Modifié par fiddy le 5/08/2014 à 21:53
Bonjour,

#include <unistd.h>
Non standard.

int choix;
On évite les variables globales en C.

while (1)
Dans la mesure du possible, on évite les boucles infinies. Il vaut mieux mettre une condition d'arrêt.

start: ;
Ce n'est pas une instruction mais une étiquette. Le ';' est donc inutile.
De plus, les goto sont à éviter (sauf cas particulier). Il vaut mieux utiliser une fonction. Ca sera beaucoup plus propre.

char bon [5] = {'m', 'o', 't', 's', '\0' };
C'est correct. Pour info, tu peux écrire plus simplement : char bon[5] = "mots"; ou encore plus simplement : char bon[] = "mots"; C'est pareil mais plus rapide :-).

fflush(stdin);
Fonctionnement non standard. Pour vider le buffer clavier, il vaut mieux se faire une fonction :
static void viderBuffer(void) {
     int c;
     while ( ( c=getchar() ) != '\n' && c != EOF );
}

A la place de ton fflush(stdin); il te suffit d'appeler la fonction créée : viderBuffer();

fgets(line, sizeof(line), stdin);
Attention, fgets() stocke le '\n' s'il a de la place. Ici tu as de la chance, il n'y aura pas de place si tu tapes le bon mot de passe. Mais je doute que ça soit prévu... Il vaut mieux donc remplacer le '\n' par '\0'. Pour cela, tu peux utiliser la fonction strchr(), largement documentée sur le net.

if (line[1] == bon[1]& line[2]==bon[2]& line[3]==bon[3]& line[4]==bon[4]& line[5]==bon[5] )
Attention, en C, les tableaux commencent à l'indice 0. Donc plutôt : line[0] == bon[0] etc, jusque line[4] == bon[4]. D'ailleurs, habituellement, on ne vérifie pas le '\0' qui est un caractère de terminaison.
Est-ce voulu le '&' au lieu du plus conventionnel '&&' ? (genre, raison sécuritaire, ce dont je doute :-))
Sinon pour info, tu peux utiliser tout simplement :
if(strcmp(line, bon)==0);


Tu as oublié un return 0; en fin de programme. Pour info, pas besoin de mettre de parenthèse autour du chiffre, ce n'est pas une fonction. Et il faut mettre 0 pour signaler à l'appelant que le programme s'est bien déroulé.

Note : dans ton cas, ton problème se situait au niveau du fflush(stdin); Dorénavant, ça devrait bien fonctionner.

Corrige tout ça, et si ça plante encore, reposte ton programme avec les corrections. N'oublie pas d'utiliser la balise "code c".
Exemple :
<"code c">/*ici tu mets ton code*/<"/code"> (sans les guillemets)

Bon courage

Google is your friend
0
J'ai modifié mon programme selon tes dire fiddy mais quelques problèmes persistent. L'ordinateur dit qu'il attend un caractère juste avant le premier appel des fonctions et qu'il attend des '(' juste avant l'utilisation des fonctions.
Voici ce qu'il me dit:

test2.c: In function `main':
test2.c:16:1: error: expected expression before `void'
test2.c:18:1: error: expected expression before `void'
test2.c: At top level:
test2.c:23:1: error: expected identifier or `(' before `{' token
test2.c:43:1: error: expected identifier or `(' before `{' token

Il me reste, de plus, quelques interrogations: pourquoi fflush(stdin) ne remplis pas sa tâche et bloque fgets?
Je n'ai pas vus l'utilité de strchr(), je me suis renseigné, c'est pour trouver un caractère dans une chaine?
Qu'est-ce que la balise c, j'ai essayé de l'inclure dans le programme, cela m'a posé pleins de problèmes de compilation.
Merci
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
6 août 2014 à 11:19
La balise "code c" n'est pas à mettre dans ton programme.
J'ai dit, si tu as encore des problèmes, reposte ton programme ici, sur CCM, comme tu as fait dans ton 1er post pour qu'on puisse l'analyser. Mais, mets-le entre deux balises "code" comme dans mon exemple. Sans ça, on ne peut pas voir ton programme, donc pas d'aide possible.

pourquoi fflush(stdin) ne remplis pas sa tâche ?
Car la norme dit que fflush() ne précise rien sur un flux d'entrée. Parfois, ça fonctionnera, parfois ça ne fonctionnera pas. Il faut donc ne pas l'utiliser et implémenter soi-même la fonction.

Je n'ai pas vus l'utilité de strchr(), je me suis renseigné, c'est pour trouver un caractère dans une chaine?
Oui, c'est bien ça. 1ère étape tu recherches '\n', 2ème étape tu le remplaces par '\0' (fin de chaîne).
Par exemple :
char *p = strchr(line,'\n');
if (p != NULL) {
     *p = '\0';
}


Cdlt,
0
ok, voici le nouveau code, qui pose encore problème:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main ()
{

while (1)
{
int choix;
puts("\nBienvenue dans le menu: pour utiliser l'algorythme des nombres premiers,");
puts("tapez 1; pour sortir, tapez 2");
scanf("%d", &choix);
if (choix == 1)
void vers_nbr1(void);
else
void vers_rien(void);
}
}
exit (EXIT_SUCCESS);
void vers_nbr1(void);
{
char line[5];
char bon [] = "mots";
short i;

printf ("Entrez le mot de passe:\n");
viderBuffer();
fgets(line, sizeof(line), stdin);
i=0
while( line[i]!= '\n') i++
line[i]='\0';
if (strcmp(line, bon)==0);)
{puts("\nInitialisation des nombres premiers");
system ("./Programmes/nbr1.exe");}
else
{ puts("Désolé, mauvais mot de passe");
return 1;}
return 0;
}
void vers_rien(void);
{
puts("\nVous avez choisis de sortir");
return 1;
}


static void viderBuffer(void)
{
int c;
while ( (c=getchar() )!= '\n' && c!= EOF);
}
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
6 août 2014 à 14:03
Ce n'est pas "<code>" qu'il fallait mettre mais "<code c>". C'est encore plus lisible.

if (choix == 1)
void vers_nbr1(void);

Pour appeler une fonction, c'est vers_nbr1(); tout simplement.
A corriger pour tous les appels.

void vers_rien(void);
{

Pas de ';' avant. Ensuite, il faut mettre ces blocs avant le main().

i++
Il manque un ';' en fin de phrase.

if(strcmp(line, bon)==0);)
Pas de ';'

Je te conseille vraiment de (re)lire un tuto comme celui-ci : https://openclassrooms.com/fr/courses/19980-apprenez-a-programmer-en-c
Et de relire totalement ton programme, il y a plein de fautes.
Cdlt,
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
merci
0