2016-09-04 6 views
2

Я самообучаюсь C, и сейчас я изучаю функции Scanf и Printf.Scanf/Printf in C ... что здесь происходит?

Я приспособил эту программу, чтобы проверить себя:

char topping[24]; 
int slices; 
int day, year; 
float cost; 
char month[10]; 

printf(" How much does a pizza cost in your area?\n"); 
printf("$"); 
scanf(" %f", &cost); 

printf("What is your favorite one-word pizza topping?\n"); 
scanf(" %s",topping); 
printf("How many slices of %s pizza, topping can you eat in one sitting\n",topping); 
scanf(" %d", &slices); 

printf(" What is today's date (enter in the following format 1-Jan-2016)\n"); 
scanf(" %d-%s-%d", &day, month, &year); 
printf("\nWhy not treat yourself to dinner on %d-%s-%d and have %d slices of %s pizza ? It will only cost you %.2f", day, month, year,slices, topping,cost); 

Цель упражнения для меня, чтобы понять понимание функций Scanf и как «тонкий» они могут быть.

Моя тестовая программа здесь хорошо работает ... за исключением выхода в переменной года.

Почему выходные данные в переменной года выплевывают тарабарщину и как я могу ее исправить?

спасибо.

+1

Попробуйте использовать «% d-% 9 [^ -] -% d» –

+2

Также узнайте, как использовать отладчик для перехода по вашему коду, чтобы увидеть, как он работает –

ответ

5

В этом проблема. Спецификатор %s означает считывание любых символов до следующего пробела. Итак, после %d- соответствует 1-, затем %s соответствует Jan-2016. Затем следующий %d терпит неудачу, так как нет ничего, что можно было бы сопоставить.

Прежде всего, вы всегда должны проверять возвращаемое значение scanf, чтобы вы знали, был ли соответствующий сбой. Например, в этом случае:

if (3 != scanf(" %d-%s-%d", &day, month, &year)) 
{ 
    printf("Matching failure occurred.\n"); 
    // do something else... 
} 
else 
{ 
    printf("Why not treat yourself... 

Во-вторых, чтобы избежать этой проблемы. Функция scanf довольно ограничена, как вы можете видеть. Для того, чтобы использовать другие разделители вместо пробелов, вы можете использовать набор сканируемых символов спецификатор %[.....] вместо:

scanf(" %d-%9[^-]-%d", &day, month, &year) 

(с проверкой та же ошибка). Спецификатор scanset означает чтение любых символов (возможно, включая пробелы), которые соответствуют символам внутри [], за исключением того, что ^ указывает, что НЕ соответствует следующему символу. Таким образом, это будет читать все до следующего -. Также я добавил 9, чтобы избежать переполнения вашего буфера размером 9+1.

Конечно, это означает, что если человек никогда не набирает другого -, то программа идет немного странно. Вы можете исправить это, сделав строку формата более сложной; или вместо этого вы можете читать целую строку с fgets, а затем использовать функцию sscanf с указанной выше строкой. Это приведет к тому, что человек, нажав Enter, набрал еще один номер -.

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

На каком-то этапе вы устанете от ужаса scanf и сделаете свой собственный парсер.

+0

Я не думаю, что '% [' является новым в C99. – unwind

+0

@unwind Правильно, вы ... исправлены –

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