web-dev-qa-db-fra.com

Comparaison des caractères saisis par l'utilisateur en C

Les extraits de code suivants proviennent d'un programme C.

L'utilisateur entre Y ou N.

char *answer = '\0';

scanf (" %c", answer);

if (*answer == ('Y' || 'y'))
    // do work

Je n'arrive pas à comprendre pourquoi cette instruction if ne donne pas la valeur true.

J'ai vérifié l'entrée y ou n avec un printf et il est là, donc je sais que j'obtiens l'entrée utilisateur. De plus, lorsque je remplace la condition de l'instruction if par 1 (la rendant vraie), elle est correctement évaluée.

15
Joe Scho

Je vois deux problèmes:

Le pointeur answer est un pointeur null et vous essayez de le déréférencer dans scanf, cela conduit à comportement indéfini.

Vous n'avez pas besoin d'un pointeur char ici. Vous pouvez simplement utiliser une variable char comme:

char answer;
scanf(" %c",&answer);

Ensuite pour voir si le caractère lu est 'y' ou 'Y' tu devrais faire:

if( answer == 'y' || answer == 'Y') {
  // user entered y or Y.
}

Si vous vraiment devez utiliser un pointeur char, vous pouvez faire quelque chose comme:

char var;
char *answer = &var; // make answer point to char variable var.
scanf (" %c", answer);
if( *answer == 'y' || *answer == 'Y') {
22
codaddict

answer ne doit pas être un pointeur, l'intention est évidemment de contenir un caractère. scanf prend l'adresse de ce caractère, elle doit donc être appelée comme

char answer;
scanf(" %c", &answer);

Ensuite, votre instruction "ou" est mal formée.

if (answer == 'Y' || answer == 'y')

Ce que vous avez écrit à l'origine demande de comparer answer avec le résultat de 'Y' || 'y', ce qui, je suppose, n'est pas tout à fait ce que vous vouliez faire.

9
Mark Elliot

Pour commencer, votre variable answer doit être de type char, et non char*.

Quant à l'instruction if:

if (answer == ('Y' || 'y'))

Il s'agit d'abord d'évaluer 'Y' || 'y' ce qui, dans la logique booléenne (et pour ASCII) est vrai puisque les deux sont "vrais" (non nuls). En d'autres termes, vous obtiendrez uniquement l'instruction if à déclencher si vous aviez saisi CTRLA (encore une fois, pour ASCII, et où une vraie valeur équivaut à 1)*une.

Vous pourriez utiliser le plus correct:

if ((answer == 'Y') || (answer == 'y'))

mais vous devriez vraiment utiliser:

if (toupper(answer) == 'Y')

car c'est la façon la plus portable d'atteindre le même objectif.


*une Vous vous demandez peut-être pourquoi je mets toutes sortes de conditions pour mes déclarations. Bien que la grande majorité des implémentations C utilisent ASCII et certaines valeurs connues, ce n'est pas nécessairement obligatoire par les normes ISO. Je sais pertinemment qu'au moins un compilateur utilise toujours EBCDIC, donc je ne le fais pas comme faire des hypothèses injustifiées.

5
paxdiablo

Parce que la comparaison ne fonctionne pas de cette façon. 'Y' || 'y' Est un opérateur logique ou; il renvoie 1 (true) si l'un de ses arguments est vrai. Puisque 'Y' Et 'y' Sont tous deux vrais, vous comparez *answer Avec 1.

Ce que vous voulez, c'est if(*answer == 'Y' || *answer == 'y') ou peut-être:

switch (*answer) {
  case 'Y':
  case 'y':
    /* Code for Y */
    break;
  default:
    /* Code for anything else */
}
5
hobbs