Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I clear stdin in a C progam?

Tags:

c

stdin

This is a seemingly simple question that I have not been able to answer for far too long:

I am trying to read input from a user in a C program using fgets(). However, I am running into the problem that if the user enters more characters than fgets() is set to read, the next call to read a string from the user automatically reads the remaining characters in the stdin buffer, and this is NOT behavior I want.

I have tried many ways to clear the stdin stream, and while I know something like

while(getchar()!='\n'); will work, this requires the user to hit enter an additional time which is not something I want.

The structure of the code looks something like this:

    void read_string(char *s, int width){
        fgets(s,width,stdin);
        clear_stdin();
        .
        .   
    }

    while (1){
        read_string()
        .
        .
    }

But I cannot get a clear_stdin() function that works desirably. How on earth can I clear the stdin, without having the user needlessly need to hit enter twice?

like image 823
xjka Avatar asked Dec 10 '25 17:12

xjka


1 Answers

To achieve what you want — reading and ignoring extra characters up to a newline if the buffer you supplied is over-filled — you need to conditionally read up to the newline, only doing so if there isn't a newline already in the input buffer that was read.

void read_string(char *s, int width)
{
    if (fgets(s, width, stdin) != 0)
    {
        size_t length = strlen(s);
        if (length > 0 && s[length-1] != '\n')
        {
            int c;
            while ((c = getchar()) != '\n' && c != EOF)
                ;
        }
        /* Use the input data */
    }
    else
        /* Handle EOF or error */
}

The other part of the technique is to make sure that you use a big enough buffer that it is unlikely that anyone will overflow it. Think in terms of char buffer[4096]; as an opening bid; you can increase it if you prefer. That makes it unlikely that anyone will (be able to) type enough data on a single line to overflow the buffer you provide, thus avoiding the problem.

Another option is to use POSIX getline(). It reads a line into allocated space, allocating more space until the data fits (or you run out of memory). It has at least one other major advantage over fgets() — it reports the number of characters in the line it read, which means it is not confused by null bytes ('\0', usually typed as Control-@) in the input. By contrast, you can't tell whether there was any data entered after the first null byte with fgets(); you have to assume that the input stopped at the first null byte.

Note that the simple loop shown in the question (while (getchar() != '\n');) becomes infinite if it encounters EOF before reading a newline.

like image 92
Jonathan Leffler Avatar answered Dec 12 '25 12:12

Jonathan Leffler



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!