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

problème avec getchar();

14 réponses
Avatar
gabriel
bonjour,

je suis développeur java alors désolé si mes questions sont naives mais
j'ai décidé de me mettre au C sur mon temps libre :)

je viens demander votre aide dans le pb suivant

char
askQuestion (char *questionLabel)
{
printf(questionLabel);

char answer = getchar();
getchar();
return answer;
}

int
main ()
{

struct people *userList = malloc (sizeof (struct people));
char *answer;

bool continueLoop = true;
int userListLength = 0;
while (continueLoop == true)
{
showNewMemberForm (userList);
userList++;
userListLength++;
askQuestion("Enter a new member (y/n) ?");

if (strcmp(answer, "n") == 0)
{
continueLoop = false;
}
}


return 0;
}
Malgré la lecture de la FAq, je ne comprends pas ....
Prq ce code ne fonctionne pas ?

si je rentre "n" à la question, il ne sort pas de la boucle
et en plus il ne me repose pas la première question, il lui envoie
directement "\n".

Pourtant j'ai bien un double getchar() pour supprimer le \n dans "n\n" .


Si vous avez des remarques sur le style ou des choses "qu'on ne fait pas
en C", je suis preneur puisque grand débutant :)

Merci pour votre patience,

cordialement,

10 réponses

1 2
Avatar
Vincent Lefevre
Dans l'article <44789f7d$0$6162$,
gabriel écrit:

je suis développeur java alors désolé si mes questions sont naives mais
j'ai décidé de me mettre au C sur mon temps libre :)


Apparemment, le Java fait prendre de mauvaises habitudes.

je viens demander votre aide dans le pb suivant

char
askQuestion (char *questionLabel)
{
printf(questionLabel);


printf("%s", questionLabel);

est plus fiable, au cas où questionLabel contiendrait un %.

char answer = getchar();


getchar() renvoie un int (c'est dans la FAQ, non?).

getchar();


Pourquoi un 2e getchar()? Pour le n? En tout cas, ce n'est pas
robuste (i.e. ça manque de tests).

return answer;
}

int
main ()


int
main(void)

est préférable.

{

struct people *userList = malloc (sizeof (struct people));


C'est normal que tu ne réserves que pour un seul élément?
Il faudrait tester la valeur de retour de malloc (c'est dans la FAQ,
non?).

char *answer;

bool continueLoop = true;


Je suppose que tu as fait un #include <stdbool.h>. Attention, c'est
une nouveauté de C99. Ça risque donc de ne pas fonctionner partout.
À toi de voir...

int userListLength = 0;
while (continueLoop == true)


C'est idiot. Pourquoi pas:

while ((continueLoop == true) == true)

ou même:

while (((continueLoop == true) == true) == true)

?

{
showNewMemberForm (userList);
userList++;
userListLength++;
askQuestion("Enter a new member (y/n) ?");

if (strcmp(answer, "n") == 0)


answer n'a pas été affecté. Le compilateur devrait te le dire.
Ensuite, une comparaison sur un int te suffirait.

{
continueLoop = false;


Ce genre de chose n'est pas maintenable. Mais je suppose que c'est
typique de Java (enfin, je ne connais pas trop, mais c'était comme
ça avec Eiffel). C'est plutôt une boucle do ... while qui te faudrait
ici.

}
}

return 0;
}


Tu as pensé au return 0. C'est bien.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/>
Work: CR INRIA - computer arithmetic / SPACES project at LORIA

Avatar
Vincent Lefevre
Dans l'article <44789f7d$0$6162$,
gabriel écrit:

je suis développeur java alors désolé si mes questions sont naives mais
j'ai décidé de me mettre au C sur mon temps libre :)


Apparemment, le Java fait prendre de mauvaises habitudes.

je viens demander votre aide dans le pb suivant

char
askQuestion (char *questionLabel)
{
printf(questionLabel);


printf("%s", questionLabel);

est plus fiable, au cas où questionLabel contiendrait un %.

Et ajoute un

fflush(stdout);

Ça doit être encore dans la FAQ...

char answer = getchar();


getchar() renvoie un int (c'est dans la FAQ, non?).

getchar();


Pourquoi un 2e getchar()? Pour le n? En tout cas, ce n'est pas
robuste (i.e. ça manque de tests).

return answer;
}

int
main ()


int
main(void)

est préférable.

{

struct people *userList = malloc (sizeof (struct people));


C'est normal que tu ne réserves que pour un seul élément?
Il faudrait tester la valeur de retour de malloc (c'est dans la FAQ,
non?).

char *answer;

bool continueLoop = true;


Je suppose que tu as fait un #include <stdbool.h>. Attention, c'est
une nouveauté de C99. Ça risque donc de ne pas fonctionner partout.
À toi de voir...

int userListLength = 0;
while (continueLoop == true)


C'est idiot. Pourquoi pas:

while ((continueLoop == true) == true)

ou même:

while (((continueLoop == true) == true) == true)

?

{
showNewMemberForm (userList);
userList++;
userListLength++;
askQuestion("Enter a new member (y/n) ?");

if (strcmp(answer, "n") == 0)


answer n'a pas été affecté. Le compilateur devrait te le dire.
Ensuite, une comparaison sur un int te suffirait.

{
continueLoop = false;


Ce genre de chose n'est pas maintenable. Mais je suppose que c'est
typique de Java (enfin, je ne connais pas trop, mais c'était comme
ça avec Eiffel). C'est plutôt une boucle do ... while qui te faudrait
ici.

}
}

return 0;
}


Tu as pensé au return 0. C'est bien.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/>
Work: CR INRIA - computer arithmetic / SPACES project at LORIA

Avatar
Targeur fou

bonjour,


Salut,


je suis développeur java alors désolé si mes questions sont naives mais
j'ai décidé de me mettre au C sur mon temps libre :)

je viens demander votre aide dans le pb suivant

char
askQuestion (char *questionLabel)
{
printf(questionLabel);


Attention, vérifier ici que questionLabel n'est pas nul, sinon boum.
Sinon, la fonction devrait AMA retourner un int, char pouvant être
signé ou non signé. Si c'est non signé, tu peux avoir comme ennui de
ne pas pouvoir récupérer EOF (valeur signée négative) du getchar()
et ainsi ne pas povoir détecter d'erreur.
D'autre part, l'usage de puts() serait plus approprie ici => sortie sur
stdout avec saut de ligne automatique => pas besoin de vider le tampon
de sortie (en mettant un fflush() ou en insérant un n laid dans
questionLabel) pour éventuellement garantir l'affichage de
questionLabel.

char answer = getchar();


Ici, ce n'est pas possible, tu as déjà une instruction (le printf() )
avant d'avoir déclaré ta variable answer (à mettre en int à cause
du pb ci dessous) . Cela ne compile pas.

getchar();
return answer;
}


int askQuestion(char const * questionLabel)
{
int c, rc = 0;

if (questionLabel == NULL) {
rc = EOF;
}

if (rc >= 0) {
/* affichage question */
puts(questionLabel);
/* lecture du caractere entré */
rc = getchar();
/* J'ai regardé le code en dessous pour ça */
if (rc != 'y' || rc != 'n') { rc = EOF; }
}

/* avale le 'n' */
getchar();

return rc;
}

Toujours est-il que fegts() est la meilleure solution pour lire une
entree utilisateur sur console, même pour un caractère, car
getchar(), qui n'est que getc() sur sur stdin, peut

int
main ()
{


int main(void)

struct people *userList = malloc (sizeof (struct people));
char *answer;


Pareil, instructions avant déclarations de variables, ce n'est pas du
C. Et il faut vérifier que l'allocation de mémoire pour userList
s'est bien passée.

bool continueLoop = true;


bool n'est présent qu'en C99, mais vu le code fourni au dessus, je
soupçonne une compilation en C++. Utiliser int si nécessaire.
Une nouvelle variable pour la suite, qui remplace
answer.
int gg = 0;

int userListLength = 0;
while (continueLoop == true)


while (continueLoop == true && gg >= 0)

{
showNewMemberForm (userList);
userList++;
userListLength++;
askQuestion("Enter a new member (y/n) ?");


gg = askQuestion("Enter a new
member (y/n) ?");

Hé bé, on oublie que
askQuestion retourne quelquechose ?


if (strcmp(answer, "n") == 0)


D'où sort ce answer ???, y'a rien dedans. C'est un pointeur non
initialisé avec une valeur bidon que le compilo à choisi. Le strcmp
va comparer la valeur pointée par answer avec la chaine littérale "n"
(n), sûr que cela ne va pas marcher. Pas besoin de strcmp() pour un
caractère de toute façon.

if (gg == 'n') { continueLoop = 0; }

[coupé]

}


return 0;
}
Malgré la lecture de la FAq, je ne comprends pas ....
Prq ce code ne fonctionne pas ?

si je rentre "n" à la question, il ne sort pas de la boucle
et en plus il ne me repose pas la première question, il lui envoie
directement "n".

Pourtant j'ai bien un double getchar() pour supprimer le n dans "nn" .


Oui, mais le strcmp() était complètement faux de toute façon.


Si vous avez des remarques sur le style ou des choses "qu'on ne fait pas
en C", je suis preneur puisque grand débutant :)

Merci pour votre patience,

cordialement,


A+
Regis

Avatar
gabriel
Tout d'abord, merci pour vos conseils !

char answer = getchar();
Ben si ca compile :


version gcc 4.0.2 20050808 (prerelease) (Ubuntu 4.0.1-4ubuntu9)

je développe sous linux avec anjuta.


Ici, ce n'est pas possible, tu as déjà une instruction (le printf() )
avant d'avoir déclaré ta variable answer (à mettre en int à cause
du pb ci dessous) . Cela ne compile pas.
Je n'ai pas le droit en C de mettre des instructions avant des

déclarations ??

getchar();
return answer;
}


int askQuestion(char const * questionLabel)
{
int c, rc = 0;

if (questionLabel == NULL) {
rc = EOF;
}

if (rc >= 0) {
/* affichage question */
puts(questionLabel);
/* lecture du caractere entré */
rc = getchar();
/* J'ai regardé le code en dessous pour ça */
if (rc != 'y' || rc != 'n') { rc = EOF; }
}

/* avale le 'n' */
getchar();

return rc;
}

Toujours est-il que fegts() est la meilleure solution pour lire une
entree utilisateur sur console, même pour un caractère, car
getchar(), qui n'est que getc() sur sur stdin, peut



oui mais non, je suis tjs bloqué :
/* lecture du caractere entré */
//rc = getchar();
char* answer;
getLine(answer,2);
/* J'ai regardé le code en dessous pour ça */
if (rc != 'y' || rc != 'n') { rc = EOF; }
}

Aucune solution ne fonctionne : ni getline (fonction de la FAQ) ni
getchar...
Je continue à chercher....
int main(void)
Ok, Corrigé


struct people *userList = malloc (sizeof (struct people));
char *answer;


Pareil, instructions avant déclarations de variables, ce n'est pas du
C. Et il faut vérifier que l'allocation de mémoire pour userList
s'est bien passée.
OK

bool continueLoop = true;


bool n'est présent qu'en C99, mais vu le code fourni au dessus, je
soupçonne une compilation en C++. Utiliser int si nécessaire.
Ok, j'ai enlevé le bool, je vais essayer de m'habituer à 0 et 1 :)

Une nouvelle variable pour la suite, qui remplace
answer.
int gg = 0;

int userListLength = 0;
while (continueLoop == true)


while (continueLoop == true && gg >= 0)

{
showNewMemberForm (userList);
userList++;
userListLength++;
askQuestion("Enter a new member (y/n) ?");


gg = askQuestion("Enter a new
member (y/n) ?");

Hé bé, on oublie que
askQuestion retourne quelquechose ?

if (strcmp(answer, "n") == 0)


D'où sort ce answer ???
Exact, j'avais pas fait attention :(

if (gg == 'n') { continueLoop = 0; }

[coupé]

}


return 0;
}



En java c'est tout facile de demander à l'utilisateur de rentrer une
chaine ! Là, je suis confronté à pleins de pbs super intéressants en
attendant :)

Merci pour votre aide


Avatar
Vincent Lefevre
Dans l'article <4478c370$0$19538$,
gabriel écrit:

Je n'ai pas le droit en C de mettre des instructions avant des
déclarations ??


Tu as tout à fait le droit, mais c'est une nouveauté de C99:

-- mixed declarations and code

Personnellement, je n'utilise pas...

oui mais non, je suis tjs bloqué :
/* lecture du caractere entré */
//rc = getchar();
char* answer;
getLine(answer,2);
/* J'ai regardé le code en dessous pour ça */
if (rc != 'y' || rc != 'n') { rc = EOF; }
}


C'est quoi ce getLine? Et puis rc n'est toujours pas affecté.

Aucune solution ne fonctionne : ni getline (fonction de la FAQ)


Il y a une extension GNU getline(), mais il vaut mieux éviter de
l'utiliser, sauf si c'est uniquement pour Linux.

En java c'est tout facile de demander à l'utilisateur de rentrer une
chaine ! Là, je suis confronté à pleins de pbs super intéressants en
attendant :)


Disons que stdin en raw n'est pas vraiment fait pour ça, et par
conséquent, il n'y a pas moyen de faire en standard en C: en pratique,
on se repose sur des bibliothèques style curses ou readline.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/>
Work: CR INRIA - computer arithmetic / SPACES project at LORIA

Avatar
Emmanuel Delahaye
Malgré la lecture de la FAq, je ne comprends pas ....
Prq ce code ne fonctionne pas ?


Beaucoup d'erreurs et de méconnaissance du langage...

Code corrigé et compilé.

/* main.c */
/* -ed- headers manquants */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct people
{
int dummy;
};

/* -ed-
char askQuestion (char *questionLabel)

fonction non exportee, donc static.
La fonction ne modifiant pas la chaine pointee par questionLabel,
elle devrait accepter les chaines non modifiables. Ajoute 'const'
Le type retourne doit etre int
*/
static int askQuestion (char const *questionLabel)
{
/* -ed-
char answer;

le type retourne par getchar() est int. */
int answer;

/* -ed-
printf(questionLabel);

il est risque de ne pas mettre un format connu
en premier parametre de printf. Les seqieunces "%x" pourraient
etre mal interpretees.*/
printf("%sn", questionLabel);

/* -ed-
char answer = getchar();

en C90, on doit definir une variable au debut d'un bloc.
*/
answer = getchar();
getchar();
return answer;
}

/* -ed- fonction 'dummy' ajoutee pour pouvoir compiler... */
static void showNewMemberForm (struct people* userList)
{
}

int main ()
{
/* -ed-
la definition de la structure est incomplete.
On ne peut donc pas l'instancier.

Definition struct people au dessus.
*/
struct people *userList = malloc (sizeof (struct people));

/* -ed-
char *answer;


jamais initialise : valeur indeterminee.
recyclage en int pour recuperer la valeur retournee par askQuestion()
*/
int answer;
/* -ed-
bool continueLoop = true;

pas de 'bool' ni de 'true' en C90

*/
int continueLoop = 1;
int userListLength = 0;
while (continueLoop)
{
/* -ed- fonction inconnue */
showNewMemberForm (userList);
userList++;
userListLength++;
/* -ed- ajoute recuperation de la retournee par askQuestion() */
answer = askQuestion("Enter a new member (y/n) ?");

/* -ed-
if (strcmp(answer, "n") == 0)


passer une valeur indetermine a une fonciton invoque un
comportement indetermine.
Tout peut arriver (chez mois rapport d'erreur...)

Il faut probablement recuperer la valeur retournee par askQuestion()
qui est un caractere (type int) et la comparer à 'n'.
*/
if (answer == 'n')
{
continueLoop = 0;
}
}

return 0;
}

Mais getchar() n'est pas la bonne fonction pour faire une saisie. Le
mieux est fgets(), mais il est encore préférable de construire ses
propres fonctions.

http://mapage.noos.fr/emdel/notes.htm#saisie
http://mapage.noos.fr/emdel/notes.htm#fichiers

--
A+

Emmanuel Delahaye

Avatar
Emmanuel Delahaye
Ben si ca compile :
version gcc 4.0.2 20050808 (prerelease) (Ubuntu 4.0.1-4ubuntu9)


Alors ajoute au minimum les options de compilation :

-Wall -Wextra -O2

Je n'ai pas le droit en C de mettre des instructions avant des
déclarations ??
(définitions) http://mapage.noos.fr/emdel/notes.htm#definitions


Non, pas en C90. En C99, oui.

Ok, j'ai enlevé le bool, je vais essayer de m'habituer à 0 et 1 :)


C'est pas trop dur, c'est logique, rapide a écrire et ce sont
précisément les valeurs retournées par les expressions C.

En java c'est tout facile de demander à l'utilisateur de rentrer une
chaine ! Là, je suis confronté à pleins de pbs super intéressants en
attendant :)


Si le C ne te plaît pas, reste en Java... En attendant, il faut
apprendre le langage. Des références de livres et de tutoriels sur mon site.

http://mapage.noos.fr/emdel/

--
A+

Emmanuel Delahaye

Avatar
gabriel
Malgré la lecture de la FAq, je ne comprends pas ....
Prq ce code ne fonctionne pas ?


Beaucoup d'erreurs et de méconnaissance du langage...

Code corrigé et compilé.
Merci bcp, je vais analyser tout cela.


Si le C ne te plaît pas, reste en Java... En attendant, il faut
apprendre le langage. Des références de livres et de tutoriels sur mon

site.
Je n'ai pas dit que le C ne me plaisait pas, j'ai dit que c'était plus
dur en C :) C'est pour ca d'ailleurs que je me suis lancé dans le C !! ;)
Très bien ton site, je sens que je vais y passer du temps :)
Merci pour le lien et bonne journée !

cordialement,


Avatar
Michaël Grünewald
gabriel writes:

Malgré la lecture de la FAq, je ne comprends pas ....
Prq ce code ne fonctionne pas ?

si je rentre "n" à la question, il ne sort pas de la boucle


Je n'ai pas vu d'affectation à la variable 'answer', du coup 'answer'
vaut n'importe quoi et strcmp(answer,"n") a un comportement indéfini.

Pour le reste je ne m'y connais certainement pas assez.
--
Michaël Grünewald

Avatar
gabriel
gabriel writes:

Malgré la lecture de la FAq, je ne comprends pas ....
Prq ce code ne fonctionne pas ?

si je rentre "n" à la question, il ne sort pas de la boucle


Je n'ai pas vu d'affectation à la variable 'answer', du coup 'answer'
vaut n'importe quoi et strcmp(answer,"n") a un comportement indéfini.

Pour le reste je ne m'y connais certainement pas assez.
C'était effectivement une des (nombreuses) erreurs que j'avais commise !!


merci bcp cpdt,

cdlt,


1 2