scanf пропускает сканы - PullRequest
0 голосов
/ 01 марта 2011

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

Ответы [ 3 ]

2 голосов
/ 01 марта 2011

Основная проблема, с которой люди сталкиваются с 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.
2 голосов
/ 01 марта 2011

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

0 голосов
/ 01 марта 2011

Если вы читаете из stdin, scanf будет читать из буфера, который заканчивается, когда вы нажимаете return.

Первый scanf примет то, что вы ищете, но остальная часть буфера останется.

Для кода:

int num;
scanf("%d", &num);

и ввода:

1 2 3 4 5

num будет 5, как и ожидалось.Но

2 3 4 5

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

...