Основная проблема, с которой люди сталкиваются с scanf
, заключается в том, что данные не соответствуют ожиданиям. Это может привести к частичному сканированию, оставляя вас в неожиданном месте в файле для будущих проверок. Это может быть тем, что вызывает ваш бесконечный цикл, и вы обычно определяете его, гарантируя, что возвращаемое значение соответствует ожидаемому (количеству элементов, которые вы пытались отсканировать). Немного трудно сказать, не видя код.
C99 состояний, в разделе 7.19.6.4 The scanf function
:
Функция scanf возвращает значение макроса EOF, если перед каким-либо преобразованием произошел сбой ввода. В противном случае функция scanf возвращает количество назначенных элементов ввода, которое может быть меньше предусмотренного или даже равно нулю в случае неудачного раннего сопоставления.
Но почти всегда вход должен быть извлечен как строки , а затем обработан оттуда с помощью sscanf
, поскольку это позволяет легко выполнить многократное сканирование входных данных для строк различного формата, например столько раз, сколько нужно, чтобы выяснить, в каком формате находится строка.
Например, следующий код является безопасным способом получения пользовательского ввода с защитой от переполнения буфера и обнаружением и очисткой буфера, поэтому избыточный ввод не влияет на следующую операцию ввода:
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
Вы можете назвать этот код примерно так:
char buff[50];
int rc = getLine ("What?> ", buff, sizeof(buff));
if (rc != OK) {
// Error condition, either EOF or to long.
}
// Now use sscanf on buff to your heart's content,
// remembering to check the return value.