开发者

scanf is skipping scans

开发者 https://www.devze.com 2023-02-13 20:29 出处:网络
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 i开发者_如何转开发t and puts in a different value that be

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 i开发者_如何转开发t and puts in a different value that begins executing an endless loop. I have even tried separating each of the scanfs into multiple functions and the same thing happens. 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.


The main problem people strike with scanf is that the data isn't what they expected. 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:

The scanf function returns the value of the macro EOF if an input failure occurs before any conversion. 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.

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.

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.

The first scanf will take in what you're looking for, but the rest of the buffer will remain.

For code:

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

and input:

1 2 3 4 5

num will be 5, as expected. 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.

Your scanf may be reading residual data from a previous buffer.

0

精彩评论

暂无评论...
验证码 换一张
取 消