C: Stdin - Removing Excess Data

2019-08-11 12:14发布

问题:

Short version

I want to get rid of excess user input from stdin but I understand fflush(stdin) is not recommended. I found this replacement:

int ch;
while ((ch = getchar()) != '\n' && ch != EOF);

However, if there is no excess data to remove, this will remove the user's next input. How can I check if there is data to remove from stdin so I can choose whether or not to use this method of clearing the buffer?

Long version with explanation

I'm making a command-line tool in Obj-C/C.

I understand that declaring char str[SIZE] syntax allocates SIZE bytes of memory to str. I'd like to allocate as little memory as possible to each variable in order to avoid wasting memory.

However, if you use fgets(str,sizeof(str),stdin) and you enter more than SIZE bytes of input, fgets will take SIZE bytes of your input and store that in str, leaving all the other data in the buffer. If you call fgets again, the remaining data will be stored in the variable you pass as fgets's first variable and essentially skip the prompt completely. I don't want this to happen. A common solution is fflush(stdin).

Various internet resources (including SO) state that using fflush(stdin) is not a good idea because it is "undefined" when you pass an input stream as argument.

I found this replacement on CProgramming.com

int ch;
while ((ch = getchar()) != '\n' && ch != EOF);

However, the same source mentions that if there is no excess data in stdin to get rid of, it will do this with the user's next input, so the second time fgets is called it might not receive all the data.

How can I check if there is data in stdin so I can decide whether or not to clear it?

回答1:

If you use fgets to read lines, and you're worried that you might not have read the whole line, remember that if fgets read the whole line the newline character should be the last character in the input buffer.

Example:

char smallBuffer[10];
while (fgets(smallBuffer, sizeof(smallBuffer), stdin) != NULL)
{
    if (strlen(smallBuffer) > 0)
    {
        // Check if we got the whole line
        if (smallBuffer[strlen(smallBuffer) - 1] == '\n')
        {
            // Yes, we got the whole line
        }
        else
        {
            // Whole line not read, there is still "excess" input
        }
    }
}


标签: c stdin fflush