Как мы проверяем возвращаемые значения из функции scanf ()?

Я хочу подтвердить, является ли значение, возвращаемое функцией scanf (), плавающим числом или нет. Как я могу это сделать? Мой код работает не так, как должно, если в функцию scanf () переданы неправильные типы данных. аналогично, как я могу подтвердить, является ли возвращаемое значение символьной строкой или нет?

 Keith Thompson10 апр. 2012 г., 09:07
Пожалуй, самое важное, что нужно знать о*scanf() Семейство функций состоит в том, что если вы сканируете число, значение которого выходит за границы соответствующего типа, поведение не определено. Например, еслиscanf("%d") пытается читать999999999999999999999, все может случиться; нет способа справиться с ошибкой. Нет хорошего обходного пути, кроме использования чего-то другого, кроме*scanf(), такой какstrto*() функции.
 Jonathan Leffler10 апр. 2012 г., 09:12
Даже сstrtol() и т.д. функции, тестирование на ошибки не совсем тривиально. Прочитайте спецификацию очень внимательно. Затем перечитайте его еще несколько раз.
 KawaiKx10 апр. 2012 г., 14:52
@PavanManjunath Да, я еще не узнал ни о каких других функциях, кроме printf и scanf. поэтому мне было трудно следовать предыдущим ответам. Все, что я мог собрать, - это то, что функция не является надежным решением от всех возможных ошибок ... с помощью этого вопроса я хочу узнать, как улучшить мой предыдущий код, содержащий scanf ..
 Pavan Manjunath10 апр. 2012 г., 08:51
@Saurabh Продолжая свой предыдущий вопрос, я думаю, ты хочешь знатьwhether scanf successfully scanned a float и неwhether its return value is a float как указано на ваш вопрос?
 leppie10 апр. 2012 г., 08:44
Все версииscanf Я видел, возвращаетint.

Ответы на вопрос(2)

Решение Вопроса

scanf() et al возвращает количество успешных конверсий.

Если у вас есть:

scanf("%f", &f);

Вы должны проверить:

if (scanf("%f", &f) == 1)
    ...all OK...
else
    ...EOF or conversion failure...

Если у вас есть несколько конверсий, убедитесь, что все они завершены. Если вы используете%n «конверсии», они не учитываются.

Хотяscanf() возвращает EOF для EOF, вы не должны проверять это & # x2014; Вы должны всегда проверять, прежде всего, что вы получили ожидаемое количество конверсий. Например, рассмотрим ошибочный код:

while (scanf("%f %d %s", &f, &i, s) != EOF)  // Here be BUGS!
    ...loop body...

Если вы печатаете3.14 x23 yes, тогда у вас будет бесконечный цикл, потому чтоscanf() вернет 1 на первой итерации (она успешно преобразовала 3.14) и 0 после этого (не EOF).

Вы можете быть в порядке с:

while ((rc = scanf("%f %d %s", &f, &i, s)) != EOF)
{
    if (rc != 3)
        ...oops data problems...
    else
        ...all OK...
}

Судя по предыдущим вопросам, вы должны смотреть на использованиеfgets() (или, возможно, POSIXgetline()) читать строки данных, а затем с помощьюsscanf() или даже такие функции, какstrtol() а такжеstrtod() читать конкретные значения из строки. Если вы используетеsscanf()комментарии, сделанные выше относительно проверки количества успешных конверсий, по-прежнему применимы.

Я не используюscanf() в производственном коде; это слишком чертовски сложно правильно контролировать. Я считаю, что это почти подходит для начинающих программ & # x2014; кроме того, что это вызывает много путаницы. В целом, лучший совет - держаться подальше отscanf() а такжеfscanf()& APOS ;. Обратите внимание, что это не означает, что вы должны держаться подальше отsscanf()хотя некоторая осторожность необходима даже приsscanf().

 23 мар. 2017 г., 13:03
Отличный ответ! Но у меня есть сомнения: Уиллchar a; scanf("%c", &a); когда-нибудь вернуть ноль?
 23 мар. 2017 г., 19:08
Взятые в изоляции, как показано на рисунке,"%c" никогда не должен возвращать 0, потому что либо есть символ для чтения, так что результатом будет 1, либо ничего не осталось для чтения, поэтому результатом будет EOF. Вам все еще нужно проверить, какой из этих двух вариантов применяется, и используяif (scanf("%c", &a) == 1) { …got a char… } все еще правильно, что и рекомендуется в основном ответе.

scanf указывает количество элементов, успешно прочитанных и присвоенных вашим переменным, или EOF:

These functions return the number of input items successfully matched and assigned, which can be fewer than provided for, or even zero in the event of an early matching failure.

The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs. EOF is also returned if a read error occurs, in which case the error indicator for the stream (see ferror(3)) is set, and errno is set indicate the error.

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

Однако, если вы хотите выполнить более тщательную проверку числа с плавающей запятой, вам следует рассмотреть возможность использованияstrtod(), то есть. для ввода"1.23abc", scanf будет хранить1.23 в вашу переменную и сказать вам, что все прошло хорошо, но сstrtod вы можете проверить, является ли последний преобразованный символ концом анализируемой строки.

Ваш ответ на вопрос