Сравнение введенных пользователем символов в C - PullRequest
15 голосов
/ 12 октября 2010

Следующие фрагменты кода взяты из программы на Си.

Пользователь вводит Y или N.

char *answer = '\0';

scanf (" %c", answer);

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

Я не могу понять, почему этот оператор if не делаетоцените как true.

Я проверил ввод y или n с помощью printf, и он там, так что я знаю, что получаю пользовательский ввод.Также, когда я заменяю условие оператора if на 1 (делая его истинным), оно оценивается правильно.

Ответы [ 4 ]

22 голосов
/ 12 октября 2010

Я вижу две проблемы:

Указатель answer является указателем null, и вы пытаетесь разыменовать его в scanf, это приводит к неопределенному поведению .

Вам не нужен char указатель здесь. Вы можете просто использовать переменную char как:

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

Далее, чтобы увидеть, является ли прочитанный символ 'y' или 'Y', вам нужно сделать:

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

Если вам действительно нужно использовать указатель на символ, вы можете сделать что-то вроде:

char var;
char *answer = &var; // make answer point to char variable var.
scanf (" %c", answer);
if( *answer == 'y' || *answer == 'Y') {
9 голосов
/ 12 октября 2010

answer не должен быть указателем, очевидно, что целью является удержание символа. scanf принимает адрес этого символа, поэтому он должен называться

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

Далее ваше утверждение "или" сформировано неправильно.

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

То, что вы изначально написали, просит сравнить answer с результатом 'Y' || 'y', что, я полагаю, не совсем то, что вы хотели сделать.

5 голосов
/ 12 октября 2010

Для начала ваша переменная answer должна иметь тип char, а не char*.

Что касается оператора if:

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

Этосначала оценивается 'Y' || 'y', что в булевой логике (и для ASCII) является истинным, поскольку оба они являются "истинными" (ненулевыми).Другими словами, вы можете запустить оператор if только в том случае, если вы каким-либо образом введете CTRL A (опять же, для ASCII, где истинные значения равны 1) * a .

Вы могли бы использовать более правильное:

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

, но вам действительно следует использовать:

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

, поскольку это более переносимый способ достижения той же цели.


* a Вы можете удивиться, почему я добавляю всевозможные условия для своих утверждений,Хотя подавляющее большинство реализаций C использует ASCII и некоторые известные значения, это не обязательно предписывается стандартами ISO.Я точно знаю, что по крайней мере один компилятор все еще использует EBCDIC, поэтому я не люблю делать необоснованные предположения.

5 голосов
/ 12 октября 2010

Потому что сравнение не работает таким образом. 'Y' || 'y' - логический или оператор; он возвращает 1 (true), если любой из его аргументов равен true. Поскольку 'Y' и 'y' оба имеют значение true, вы сравниваете *answer с 1.

То, что вы хотите, это if(*answer == 'Y' || *answer == 'y') или, возможно:

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