2013-08-18 2 views
0

Я работаю над кодом, и я попытался ввести символ вместо целого числа, и результат был «2», независимо от введенного символа, является ли это неопределенным поведением или чем-то еще?Ввод символа с помощью scanf и сохранение его в int может привести к неопределенному поведению?

Код:

#include <stdio.h> 
int f1(int n); 
int f2(void); 

int main(void) 
{ 
    int t; 

    printf("Enter a number: "); 
    scanf("%d", &t); 
    /* print proper message */ 
    t ? f1(t) + f2() : printf("zero entered.\n"); 
    return 0; 
} 

int f1(int n) 
{ 
    printf("%d ", n); 
    return 0; 
} 

int f2(void) 
{ 
    printf("entered.\n"); 
    return 0; 
} 

, когда я вошел a, результат был «2 вошел», и когда я вошел в g результат был «2 вошел», и когда я вошел в i,h,k,..... результат был тот же. Что это?

+2

В чем смысл добавления: 'f1 (t) + f2()'? – Michael

+0

@ Майкл объединяет вывод на экране ... – A4L

+1

@ A4L Uh ... это не так, как это работает. – thejh

ответ

0

Это происходит потому, что scanf не удалось разобрать вам вход. Он ожидает, что вы введете decimal digits, так как вы использовали %d.

Вы должны проверить возвращаемое значение scanf, чтобы избежать такого поведения:

В случае успеха функция возвращает количество элементов списка аргументов успешно наполненный. Этот счетчик может соответствовать ожидаемому количеству элементов или меньше (даже нулю) из-за соответствия сбоя, ошибки чтения или досягаемости конца файла.

Итак:

int items_matched; 

// ... 
items_matched = scanf("%d", &t); // Get the return value 

if (items_matched != 1)   // Check it 
{ 
    printf("Matching failure with scanf.\n"); 
    return 0; 
} 
else 
{ 
    if (t == 0) 
     printf("zero entered\n"); 
    else 
     printf("%d entered\n", t); 
} 

Вам не нужна ваша f1(t) + f2() кто довольно запутанным ...

+0

Возможно, вы имели в виду это: #include int main (void) { int t, m; int items_matched; // ... printf ("Введите два числа:"); items_matched = зсапЕ ("% d,% d", &t,&m); // Получить возвращаемое значение если (items_matched = 2) // Проверяем его { Е ("Matching провал с зсапЕ \ п.");! возвращать 0;} еще { , если (т == 0) Е ("нулевой вошел \ п"); остальное Е ("% d вошел \ N", т); }} –

+0

@ ArmiaWagdy Hum да, это сработает: http://ideone.com/A5qmkX –

+0

Фактически An Int и Char могут быть взаимоисключаемыми .. 'A' == 65 –

3

Если scanf() сталкивается с чем-то, что он не может проанализировать на основе указанной строки формата, он просто останавливается и возвращается раньше. Поэтому он никогда ничего не пишет t (вы видите только то, что неопределенное значение t было до вызова).

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

0

Проблема в том, что scanf, использующий формат% d, ожидает ввода одной или нескольких цифр ascii. Он останавливает сканирование ввода с символом, отличным от цифр, поэтому он никогда не читает, что вы набираете, и t имеет любое значение, которое оно имело до того, как был вызван scant.

+0

на самом деле An Int и Char могут быть взаимоисключаемым. 'A' == 65 –

+0

Правда, но не имеет отношения к синтаксическому поведению скудного. –

0

Вам необходимо проверить код возврата scanf. Взгляните на the manpage:

Возвращаемое значение

Эти функции возвращают число входных элементов успешно подобранных и присвоенных, который может быть меньше, чем предусмотрено, или даже ноль в случае раннего отказа согласования ,

Значение EOF возвращается, если конец ввода достигнут до того, как произойдет первое успешное преобразование или соответствующий сбой. EOF также возвращается, если возникает ошибка чтения, и в этом случае устанавливается индикатор ошибки для потока (см. Ferror (3)), а значение errno - ошибка.

Другими словами, scanf ничего не писать в t, это неинициализированным все время.

Таким образом, вместо этого:

scanf("%d", &t); 

попробовать это:

int items_matched = scanf("%d", &t); 
if (items_matched != 1) { 
    printf("bad number entered\n"); 
    exit(1); 
} 
0

От Linux man page

Строка формата состоит из последовательности директивы, описывающие , как обрабатывать последовательность входных символов. Если обработка директивы завершается с ошибкой, дальнейший ввод не читается, а scanf() возвращается. A «сбой» может быть либо следующим: входной сбой, что означает, что входные символы были недоступны или соответствовали сбоям, что означало, что вход был неуместным.

В стандартном описании C11 из зсапЕ (7.21.6.4 Функция зсапЕ) раздел 3:

Функция зсапЕ возвращает значение макро EOF, если сбой ввода происходит до того, первая конверсия (если таковая имеется) завершена. В противном случае функция scanf возвращает количество введенных позиций , которое может быть меньше, чем предусмотрено, или даже ноль в событии раннего совпадения.

Акцент - мой. Так как @oli charlesworth сказал, что вы должны проверить возвращаемое значение scanf, когда сомневаетесь :)