Question

I'm trying to get multiple consecutive user inputs, which will later be printed. It works fine as long as you don't input a string longer than the boundary, but when you do input something longer it overflows into the next input. For example, this code:

printf("Enter student's first name:\t");
char nameF[20];
scanf("%20s", nameF);

printf("Enter student's last name:\t");
char nameL[20];
scanf("%20s", nameL);

printf("Enter student's ID Number:\t");
char id[9];
scanf("%9s", id);

printf("Enter student's e-mail:\t");
char mail[26];
scanf("%26s", mail);

Results in this:

Enter student's first name:     01234567890123456789012345
Enter student's last name:      Enter student's ID Number:      0123456789012345
Enter student's e-mail:

First:          01234567890123456789
Last:
ID Number:      012345678
E-mail:         9012345

I skipped over the print function for the sake of not having a wall of code. If you want to see that as well, let me know and I'll add it.

It should be noted that I tried fgets(), with very similar results. If I replace each scanf() line with fgets(var, sizeof(var), stdin);, I get this:

Enter student's first name:     01234567890123456789012345
Enter student's last name:      Enter student's ID Number:      0123456789012345
Enter student's e-mail:

First:          0123456789012345678
Last:           9012345

ID Number:      01234567
E-mail:         89012345

When I inserted getchar() after the scanf() statements, it ignored the overflow input, but still skipped over the next scan. I have tried throwaway input variables, and I've looked into other input methods, but couldn't seem to find anything to help. I'm sure this is a pretty simple fix for someone with experience, but I'm only a couple of weeks into learning C, so I don't know much beyond pointers and structs.

I can almost guarantee somebody will find a duplicate of this - they always do - but I did search around, for about a solid hour, and I didn't find anything that worked.

Thanks in advance for any help you can give me.

EDIT: I understand why the input is overflowing into the next one. It saves the first x characters, and the rest remains in the buffer and is entered into the next input scan.

I guess the more narrowed down question would be: How can I clear or divert the input buffer so that if the user inputs extra characters they won't remain in the buffer?

Was it helpful?

Solution

I believe scanf is using buffered input. It allows you to enter characters until you press enter. At that point, it takes the 20 that you specify, and the remaining buffer is then used as the input for the next scanf call. fgets's results are more predictable, with the next string being populated with the remnants of the previous buffer.

I cannot, however, explain why last name is blank, yet email is not in the first example.

Take a look here for an example of how to flush the type-ahead input. You can write a function like so:

void flushInput(void)
{
    int c;
    while((c = getchar()) != '\n' && c != EOF)
    /* discard */ ;
}

...and then call flushInput(); after each scanf().

As an additional note, I believe you should be specifying one character less in your scanf calls. It appears that....

char nameF[20];
scanf("%20s", nameF);

...is putting 20 characters into nameF and the '\0' terminator is going beyond the bounds of the array. fgets appears to properly place the terminator within the specified size.

OTHER TIPS

There's an off-by-one problem:

char nameF[20];
scanf("%20s", nameF);

This is incorrect; the size in the format string doesn't count the trailing null, so you have to use 19 in the format with 20 in the variable definition, or 20 in the format and 21 in the variable definition:

char nameF[21];
scanf("%20s", nameF);

The original code means that you can easily have one variable clobbering another with its trailing null.

This is different from most other parts of C where you specify the whole length and the function reserves the last byte for the terminating null byte (for example: fgets()). In an ideal world, the inconsistency would be fixed, but it was there since the Standard I/O library was created in the late 70s and there was too much code that would be broken if C standard had changed the behaviour. So, you have to be aware of this quirk and work around it accordingly.

Also note that when it reaches the end of the format specified, scanf() leaves any left-over data on the line for the next input. If you want line-by-line input, read a line of data (fgets() or POSIX getline()), then scan with sscanf(). This is very often a better way of doing business.

char line[4096];

if (fgets(line, sizeof(line), stdin) == 0)
    ...handle EOF...
if (sscanf(line, "%19s", nameF) != 1)
    ...handle format error...

Note that you should error check every raw input functions (fgets()) for EOF, and sscanf() or scanf() for the correct number of conversions.

It's not programs fault but I will tell you what is happening when range is crossed. . . Actually the characters which comes in range are stored in ID and others are covered to characters and stored to it's next variable which is E-mail. . Program is not telling to enter email because the value is overflowed from id and our is stored in email so email already contains value overflowed by ID . I hope it will help you

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top