Scanf %i с буквами дает отрицательное число?

#c #string #math #integer #scanf

#c #строка #математика #целое число #scanf

Вопрос:

Я, по сути, решил свою проблему, объединив работу, но я просто хочу понять, почему такое поведение происходит, поэтому сначала мой код:

 #include <stdio.h>
#pragma warning(disable : 4996) // Just so MVS stops having a meltdown over scanf.

/* Simple question and answer of math equasion. */

int main() 
{
    printf("What is 5   5?nnAnswer: ");

    int userInput;
    if (scanf("%i", amp;userInput) amp;amp; userInput != (5   5)) // Give 'userInput' a variable from scanf and compare to hard coded answer.
    {
        printf("nIncorrect!n");
        return 0;
    }

    printf("nCorrect!n"); // Else without the 'else'.
    return 1;
}
 

Это достаточно простой, жестко закодированный математический вопрос и запрос ответа от пользователя. Предполагаемый ответ будет правильным для соответствия решаемого ответа userInput , и все, что не совпадает, считается неправильным. Когда я передаю ему кучу букв или просто просто «asdf», он рассматривает его как правильное и выдает отрицательное число: -858993460.

Моя работа заключается в добавлении || userInput < 0 к моему оператору if следующим образом:

if (scanf("%i", amp;userInput) amp;amp; userInput != (5 5) || userInput < 0)

Итак, по сути, проблема была решена с помощью какой-то гибкой ленты, нанесенной на нее, но, похоже, я не могу ответить на вопрос: «Почему он выдает это отрицательное число, независимо от того, какие буквы или нечисловые символы я ему добавляю?»

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

Комментарии:

1. Что вы подразумеваете под «выдает отрицательное число»? В показанном коде нет ничего, что печатало бы число. В любом случае, основная проблема заключается в том, что код не совсем корректен. Если введен неверный ввод, scanf вернется EOF . В этом случае ваш исходный код по-прежнему рассматривает его как правильный регистр. Проверка должна быть scanf() == 1 .

2. Если я добавлю printf("i%", userInput); ниже правильное при вводе букв, вот где это дает мне указанное отрицательное число. Извините, я должен был добавить это в код.

3. Ну, это потому scanf , что сбой и не устанавливает никакого значения userInput . Поскольку userInput он не инициализирован, в этом случае он будет просто содержать данные мусора. Вы не должны использовать userInput , если scanf не завершится успешно.

4. Нет, в случае scanf сбоя он вообще не трогается userInput . Это просто любой случайный мусор, который оказывается в переменной. Обращение к переменным, которые не инициализированы, является неопределенным поведением, и поэтому значение непредсказуемо и не имеет значения.

5. Кроме того, вы почти наверняка никогда не захотите использовать scanf with %i и, возможно, должны использовать %d вместо этого. %i будет принимать восьмеричные числа, поэтому, если вы введете 012, это тоже правильно , поскольку 012 декабря равно 010 декабря.

Ответ №1:

scanf Функция возвращает количество совпадающих элементов, поэтому в логическом содержимом она принимает значение true, если вы ввели число, и false, если вы этого не сделали. Это также означает, что значение не записывается userInput , поэтому его значение (поскольку оно не было инициализировано) все еще не определено.

Это означает, что в вашем условии указано, что ответ «Неверный», если пользователь ввел число, а оно не равно 10, поэтому оно считается правильным, если вы не ввели число. Вместо этого вы хотите напечатать «Неверно», если либо число не введено, либо введенное число не равно 10:

 if (!scanf("%i", amp;userInput) || userInput != (5   5)) 
 

Комментарии:

1. Интересно. Спасибо за ответ. Я все еще привыкаю к логическим соглашениям. Мои первоначальные мысли с дополнительными инструкциями заставляют меня думать, что лучший маршрут сейчас с моим фрагментом кода — поменять местами условия. Вместо того, чтобы делать оператор if для чего-то неправильного, я, вероятно, должен выбрать оператор if для правильного ответа, и если он не совпадает (5 5) , он просто передаст его в другой раздел. Насколько я понимаю сейчас, userInput это просто приводит к случайным ненужным данным, поэтому при печати он выдает мне указанный результат, если встречается с буквами?

2. @BluZero Вы хотите сначала проверить, был ли scanf он успешным или нет (что делает этот код), а затем читать только userInput в том случае, если он был.

3. Если конец ввода достигнут до первого допустимого преобразования или ошибки сопоставления, EOF возвращается (обычно -1 ), который также будет проверять true с помощью scanf("%i", amp;userInput)