I'm creating a command line application with a prompt. It works fine as long as the input fits inside the buffer, but when the input is larger I get some weird behavior. Below is a simplified minimal example which has the same bug.
int main()
{
for (;;) {
const int size = 8;
char str[size];
printf("> ");
fgets(str, size, stdin);
toupper_str(str);
printf("Result: %s\n", str);
}
}
It works fine if the input is in smaller than size
.
> asdf
Result: ASDF
>
When the input is larger, the portion of the input in range is processed, and in the next loop iteration, the rest of the given input is immediately returned from fgets
. This leads to that portion of the input also being processed and some weird output.
> asdfghjk
Result: ASDFGHJ
> Result: K
>
I can see if the input is larger than or equal to size by comparing the last character to a newline. fgets
retains the newline as long as it fits.
fgets(str, size, stdin);
if (str[strlen(str) - 1] != '\n') {
fprintf(stderr, "Input too long\n");
}
When this is detected, how do I stop it from reading the rest of the too long input on the next iteration?
I've seen similar questions on here, but none that ask the same question.
how do I stop it from reading the rest of the too long input on the next iteration?
Code needs to 1) detect if input is "too long" 2) consume the additional input.
fgets()
will not overfill it buffer. If it does fill the buffer, the last char
in the buffer is '\0'
. So set that to non-'\0'
before reading. Then code knows if the entire buffer was filled. Then check if the preceding char
was a '\n'
. If it is not an end-of-line, additional char
may exist in stdin
char str[100]; // Insure buffer is at least size 2
for (;;) {
str[sizeof str - 1] = `x`;
if (fgets(str, size, stdin) == NULL) {
// No more to read or IO error
break;
}
int extra_data_found = 0;
if (str[sizeof str - 1] == '\0' && str[sizeof str - 2] != '\n') {
// Cope with potential extra data in `stdin`: read and toss
int ch;
while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
extra_data_found = 1;
}
}
// Use `str` as needed, noting if additional unsaved data found
foo(str, extra_data_found);
}
Note: on a file error, fgets()
returns NULL
and the contents of str
are undefined.
Note: Instead of str[sizeof str - 1] == '\0'
, code could use strlen(str) == sizeof str - 1
. This gets fooled should fgets()
read a null character '\0'
.
Corner cases:
1. Typical str
will be up to 98 char
and then '\n'
and '\0'
. Is it OK is the last str
is 99 char
and then '\0'
?
2. If #1 is OK, then may a typical str
have 99 char
and then '\0'
?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With