简体   繁体   English

scanf正在跳过扫描

[英]scanf is skipping scans

I am writing a program in C with multiple scanfs, but when running it, whenever I get to a scan that is reading for an integer value, it skips it and puts in a different value that begins executing an endless loop. 我正在用C编写带有多个scanfs的程序,但是运行它时,每当我进入读取整数值的扫描时,它都会跳过它并放入一个不同的值,从而开始执行无穷循环。 I have even tried separating each of the scanfs into multiple functions and the same thing happens. 我什至尝试将每个scanfs分成多个函数,并且发生相同的事情。 I have absolutly no idea what is wrong, or what to do for that matter. 我绝对不知道什么是错的,或者该怎么做。

Check the return value. 检查返回值。 C library functions return status codes for a reason. C库函数出于某种原因返回状态代码。

The main problem people strike with scanf is that the data isn't what they expected. 人们用scanf遇到的主要问题是数据不是他们期望的。 That can lead to a partial scan, leaving you at an unexpected point in the file for future scans. 这可能会导致部分扫描,使您处于文件中意外的位置以备将来扫描。 This may be what's causing your infinite loop and you would normally detect it by ensuring that the return value is what you expect (the number of items you tried to scan). 可能是导致无限循环的原因,通常可以通过确保返回值是您期望的值(尝试扫描的项目数)来检测到它。 It's a little hard to tell without seeing the code. 如果不看代码,很难说出来。

C99 states, in section 7.19.6.4 The scanf function : C99在7.19.6.4 The scanf function节中7.19.6.4 The scanf function

The scanf function returns the value of the macro EOF if an input failure occurs before any conversion. 如果在任何转换之前发生输入失败,则scanf函数将返回宏EOF的值。 Otherwise, the scanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure. 否则,scanf函数将返回分配的输入项数,如果早期匹配失败,该数目可能少于所提供的输入项数,甚至为零。

But, almost invariably, input should be retrieved as lines and then processed from there with sscanf , since this allows an easy way to try multiple scans on the input data for different format strings, as many times as it takes to figure out what format the line is in. 但是,几乎总是应该将输入检索为 ,然后使用sscanf从那里进行处理,因为这是一种简单的方法,可以尝试对输入数据进行多次扫描以查找不同格式的字符串,以进行多次扫描以找出哪种格式的字符串。线在。

For example, the following code is a safe way of retrieving user input with buffer overflow protection and detection, and buffer clearing so excess input doesn't affect the next input operation: 例如,以下代码是通过缓冲区溢出保护检测以及缓冲区清除来检索用户输入的安全方法,因此多余的输入不会影响下一个输入操作:

#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;
}

You can call this code with something like: 您可以通过以下方式调用此代码:

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.

If you are reading from stdin, scanf will read from a buffer that ends when you press return. 如果您正在从stdin中读取,则scanf将从按回车键结束的缓冲区中读取。

The first scanf will take in what you're looking for, but the rest of the buffer will remain. 第一个scanf将接受您要查找的内容,但其余缓冲区将保留。

For code: 对于代码:

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

and input: 并输入:

1 2 3 4 5

num will be 5, as expected. num将为5,正如预期的那样。 But

2 3 4 5

will still be in the buffer, so the next scanf you run will not prompt for another input, but instead take that as the input. 仍然会在缓冲区中,因此您运行的下一个scanf不会提示您输入其他内容,而是将其作为输入。

Your scanf may be reading residual data from a previous buffer. 您的scanf可能正在从先前的缓冲区读取残留数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM