2013-06-29 2 views
4

Я имею немного проблемы при работе с вложенными условными операторами в С.Вложенные условные операторы в C

int is_correct() { 

    char YN ; 

    printf("Y or N : ") ; 
    scanf("%c", &YN) ; 
    YN = toupper(YN) ; 

    return (YN == 'Y')? 1 : (YN == 'N')? 0 : is_correct() ; 
}  

Я был под впечатлением, что последняя строка кода будет возвращать 1 или 0, если в «Y» или «N» было введено или называть себя снова, если был введен неожиданный символ. Вместо этого он постоянно называет себя независимо от ввода.

+2

Возможно, это не проблема, но я бы использовал круглые скобки в условном выражении: 'return (YN == 'Y')? 1: ((YN == 'N')? 0: is_correct()); ' – lurker

+1

Почему вы пишете глупый код и ожидаете не-глупый ответ? –

+3

@Mat: Нет, это не так. Пока условия завернуты в '()', как и в случае OP, нет никаких двусмысленностей при анализе этих условных операторов. Дополнительные '()' абсолютно не нужны. Для некоторых они могут улучшить читаемость, для некоторых они могут на самом деле ухудшить ситуацию. На самом деле условия '()' around тоже не нужны, но они помогают прочитать код. Что касается дополнительных '()' ... no, версия OP отлично. – AnT

ответ

2

Возможно, сканирование неисправно, и вы не проверяете его.

Вы не указываете, что «непрерывно» означает «без остановки, чтобы читать больше ввода», что он, конечно, должен делать.

Заметим, например, что toupper() использует int -typed аргумент и результаты, и ожидающие значения типа unsigned char вы можете ударить неопределенное поведение там.

Это действительно запутанный аспект функций ctype.h. Я склоняюсь к тому, чтобы передать в unsigned char вызов, если данные поступают из текстового (char) буфера.

Добавить printf() позвонить, чтобы распечатать значение YN перед окончательной строкой.

+2

UB вступает в игру, если 'c' не является' unsigned char', что, вероятно, имеет место здесь. –

+0

Нет ничего плохого в 'scanf()'; проблема заключается в том, что преобразование '% c' указано для того, чтобы вести себя иначе, чем вы могли бы разумно ожидать. –

1

Преобразование %c не считывает символ новой строки, который вы должны вводить после односимвольного ответа.

В общем, scanf() вызывает гораздо больше проблем, чем того стоит. Попробуйте использовать getline(), чтобы прочитать строку из stdin в строку, а затем использовать sscanf() для извлечения символа из строки.

Помимо прочего, getline() позволяет указать максимальную длину ввода, поэтому вы можете легко избежать переполнения буфера строк.

+1

'fgets()' было устарело некоторое время назад и удалено в C11. Вместо этого вы должны использовать 'fgets_s()'. – idoby

+0

Спасибо, @busy_wait. Заменен 'fgets()' на 'getline()', как описано в http://stackoverflow.com/questions/16323185/why-is-the-fgets-function-deprecated –

+2

Не верно. Может быть, вы думаете о получении(). – fizzer

0

В scanf("%c",&YN) месте пробел перед спецификатором преобразования %c как scanf(" %c",&YN) съедать символ новой строки (\n)

#include <stdio.h> 
#include <ctype.h> 

int is_correct(void) 
{ 
    char YN ; 
    printf("Y or N : ") ; 
    scanf(" %c",&YN); 
    YN = toupper(YN); 

    return YN == 'Y' ? 1 : YN == 'N' ? 0 : is_correct() ; 
}  

int main() 
{ 
    printf("%d",is_correct()); 
    return 0; 
} 

Я проверял. Работает отлично, если вы набираете только один символ (исключая \n)!
Более эффективным способом вы можете это сделать; сохраните первый символ в char ch, а затем используйте петлю while((YN = getchar()) != '\n'), чтобы съесть все остальные символы, включая \n. Пример: Если вы наберете ynabcd, первый символ y будет сохранен в ch как Y, а отдых будет поедать while(.

int is_correct(void) 
{ 
    char YN ; 
    printf("Y or N : ") ; 
    scanf("%c",&YN); 
    char ch = toupper(YN); 
    while((YN = getchar()) != '\n') 
    ; 
    return ch == 'Y' ? 1 : ch == 'N' ? 0 : is_correct() ; 
} 
+2

Не имеет значения, используете ли вы 'getchar' или' scanf («% c»). Проблема одна: вы только читаете 1 символ из входного буфера, но есть два: действительный символ вы набрали и \ n, потому что вы закончили ввод с помощью ENTER. Таким образом, функция будет читать символ с помощью 'getchar' и видит, что есть один левый и снова проверяет его значение. Если вы введете более одного символа типа «ab», вы получите «Y или N» 3 раза, потому что в буфере есть 3 символа. Вот почему вы видите «Y или N» дважды. – qwertz

+0

Но когда вы будете использовать 'scanf', он не даст результат при вводе символа, отличного от' Y' или 'N'. Но ваша точка верна, главной проблемой является' \ n'. – haccks

+0

Чтобы удалить эту проблему, вам просто нужно прочитать все символы из буфера перед возможным повторным вызовом: put 'while (getchar()! = '\ N');' перед оператором return будет одним из решений. – qwertz

Смежные вопросы