OVH Cloud OVH Cloud

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,

4 réponses

1 2
Avatar
Christian
gabriel wrote:
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)


Bonjour Gabriel.

Les saisies clavier posent souvent problème en C car les scanf, ou
autres, ne sont pas fiables en cas de saisie erronées.
Donc on gère son clavier soit même.
Donc pour saisir en toutes fiabilité un caractère unique ou une
chaîne, le mieux, de mon point de vue, est de créer soi même sa
librairie d'utilitaire.

Explication avec un exemple :

On lit le clavier, comme un fichier, caractère par caractère, avec
l'instruction ou macro getchar.
Le gros embêtement pour ne pas prendre un autre nom, est qu'on ne peut
commencer à lire le tampon, ou buffer, du clavier que quand
l'utilisateur a frappé sur la touche entrée ! getchar nous met en
attente de saisie mais on ne peut saisir la saisie que quand celle ci
est finie... Donc quand tu commences à lire le buffer qui contient la
saisie tu ne sais pas ce qu'il a dedans et tu peux y avoir de 0 à
plusieurs centaines de caractères !

Pour saisir simplement un caractère en toute sécurité j'ai créé la
fonction suivante :

//*************
char saisie_car(void)
//*************
{
char c1, c;
c1 = getchar();
if (c1 != 'n') {
// il faut vider le buffer du clavier
while ((c = getchar() ) != 'n' && c != EOF) g_NC++;
}//end if
else {
c1=0;
}//end else
return c1;
}//end saisie_car

Pourquoi lire TOUS les caractères du buffer et non pas s'arrêter au
premier caractère ?
Par ce que si il restait des caractères non lu dans le buffer du
clavier il feraient alors partie de la prochaine saisie et seraient
alors interprété comme tel.

A titre d'exemple plus poussé voici quatre fonctions :

//pour les saisies
typedef char chaine_type [128];

// renvoi le nbre de caracteres saisie en frappe clavier
int g_NC;

void message(char mes[]);
char saisie_car_select(char mes[], char select[]);
char saisie_car(void);
char saisie_car(void);

//**********
void message(char mes[])
//**********
{// affiche mes et attend la touche entree
printf("%s. FRAPPEZ [ENTREE] ",mes);
saisie_car();
}//end message

//********************
char saisie_car_select(char mes[], char select[])
//********************
{ // renvoi la majuscule du caratere saisie.
// Recommence la saisie si plusieurs caractere rentres
// ou caractere saisi different de ceux de select.
char rep;
int i;
while (VRAI){
printf("%s", mes);
rep=toupper(saisie_car());
if (g_NC > 1) continue;//si plusieurs carateres frappes, erreur
for (i=0; select[i] != 0; i++) {
if (rep==toupper(select[i])) {
return rep;
}//end if
}//end for
}//end while
}//end saisie_car_select

//*************
char saisie_car(void)
//*************
{// renvoi le 1er caractere frappe
char c1, c;
c1 = getchar();
if (c1 != 'n') {
g_NC=1;
// il faut vider le buffer du clavier
while ((c = getchar() ) != 'n' && c != EOF) g_NC++;
}//end if
else {
g_NC=0;
c1=0;
}//end else
return c1;
}//end saisie_car

//****************
void saisie_chaine(chaine_type chaine)
//****************
{ // attention, n'envoyer que des chaine_type a cette fonction
// Le compilateur ne fera pas de message d'avertissement.
int i;
char c;
i=0;
// il faut vider le buffer du clavier
while ((c = getchar() ) != 'n' && c != EOF) {
if (i < (sizeof(chaine_type)-1))
chaine[i++]=c;
}//end while
chaine[i]=0;// ne pas oublier le zero terminal
}//end saisie_chaine

Pour plus de détail tu peux voir ces fonctions incluses dans deux
sources du site http://www.i2i.fr

Cordialement.

Christian.

Avatar
gabriel
Bnosoir Christian,

Merci bcp pour toutes ces précisions et librairies qui m'amènent à mieux
comprendre l'esprit "C" .

Je vais continuer mon apprentissage tranquillement,

bien à toi,

Gabriel
Avatar
Emmanuel Delahaye
char answer = getchar();
getchar();

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".


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

--
A+

Emmanuel Delahaye

Avatar
Pierre Maurette
[...]
int userListLength = 0;
while (continueLoop == true)


C'est idiot. Pourquoi pas:

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

ou même:

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


ou:

while (((continueLoop == (true != false)) == !false) == !(true &&
false))
while (continueLoop == (continueLoop || !continueLoop))
while (continueLoop == !(continueLoop && !continueLoop))
etc.

?


Certainement. Surtout avec un nom comme 'continueLoop' et le choix de
'true' qui rendent la sémantique booléenne indiscutable.

Dans ces conditions (continueLoop à sens booléen), n'est-t-il pas tout
aussi "idiot" d'écrire:

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

"ou même:"

continueLoop = (answer == 'n') ? 0 : 1;

à la place de:

continueLoop = (answer != 'n');

?

--
Pierre Maurette


1 2