Subodh Asthana
Subodh Asthana

Reputation: 393

I am not able to flush stdin. How can I flush stdin in C?

How to flush the stdin??

Why is it not working in the following code snippet?

#include <string.h>
#include <stdio.h>
#include <malloc.h>
#include <fcntl.h>

int main() {
    int i = 0, j = 0, sat;
    char arg[256];
    char *argq;
    argq = malloc(sizeof(char) * 10);
    
    printf("Input the line\n");
    i = read(0, arg, sizeof(char) * 9);
    arg[i - 1] = '\0';
    fflush(stdin);
    
    i = read(0, argq, sizeof(char) * 5);
    argq[i - 1] = '\0';

    puts(arg);
    puts(argq);
    
    return 0;
}

Now if I give the input as 11 characters, only 9 should be read but the remaining two characters in the stdin are not flushed and read again in the argq. Why?

Input: 123 456 789

Output:

123 456
89

Why am I getting this 89 as the output?

Upvotes: 23

Views: 72633

Answers (8)

Zopazz
Zopazz

Reputation: 56

If you use GLIBC you can just mess with the stdin ptr manually

void flush_stdin(){
    unsigned long* tmpstdin = (unsigned long*)stdin;
    unsigned long* oldbuf = (unsigned long*)*(tmpstdin+4);
    free((void*)oldbuf);
    *tmpstdin=(unsigned long)0xfbad2088;
    tmpstdin+=1;
    memset(tmpstdin,'\x00',64);
}

Upvotes: 2

Sunny127
Sunny127

Reputation: 293

You can't clean stdin in Linux without bumping into scenarios that the command will start waiting for input in some cases. The way to solve it is to replace all std::cin with readLineToStdString():

void readLine(char* input , int nMaxLenIncludingTerminatingNull )
{
    fgets(input, nMaxLenIncludingTerminatingNull , stdin);

    int nLen = strlen(input);

    if ( input[nLen-1] == '\n' )
        input[nLen-1] = '\0';
}

std::string readLineToStdString(int nMaxLenIncludingTerminatingNull)
{
    if ( nMaxLenIncludingTerminatingNull <= 0 )
        return "";

    char* input = new char[nMaxLenIncludingTerminatingNull];
    readLine(input , nMaxLenIncludingTerminatingNull );

    string sResult = input;

    delete[] input;
    input = NULL;

    return sResult;
}

This will also allow you to enter spaces in std::cin string.

Upvotes: 0

In Windows you can use rewind(stdin) fuction.

Upvotes: -2

user1831086
user1831086

Reputation:

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

Is how I'd clear the input buffer.

Upvotes: 11

jschmier
jschmier

Reputation: 15796

I believe fflush is only used with output streams.

You might try fpurge or __fpurge on Linux. Note that fpurge is nonstandard and not portable. It may not be available to you.

From a Linux fpurge man page: Usually it is a mistake to want to discard input buffers.

The most portable solution for flushing stdin would probably be something along the lines of the following:

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

Upvotes: 46

Nikolai Fetissov
Nikolai Fetissov

Reputation: 84239

You are overriding the last element of the input in arg with '\0'. That line should be arg[i]='\0'; instead (after error and boundary checking you are missing.)

Other's already commented of the flushing part.

Upvotes: 2

dirkgently
dirkgently

Reputation: 111280

How to flush the stdin??

Flushing input streams is invoking Undefined Behavior. Don't try it.

You can only flush output streams.

Upvotes: 3

Related Questions