1

I want to know how to check if my input buffer (perhaps its called stdin) is empty or not. I dont want the program to stop if the buffer is empty, and I dont want the input to necessarily end with \n, therefore just using scanf is not enough.

I tried searching on google and on this website but no answer was enough. I tried using feof(stdin) like this:

int main()
{
    char c,x;
    int num;
    scanf("%c",&c);
    scanf("%c",&x);
    num=feof(stdin);
    printf("%d",num);
}

but all it did was printing 0 no matter the input. adding fflush(stdin) after the second scanf gave the same result. other answers suggested using select and poll but I couldnt find any explanations for those functions.

Some other forum told me to use getchar() but I think they misunderstood my question.

if you suggest I use select/poll, could you please add an explanation about how to use those?

9
  • See how to ask a question on SO. There is no code here... Commented Apr 5, 2016 at 13:42
  • 1
    Read from the input in a dedicated thread. Commented Apr 5, 2016 at 13:42
  • 'i tried searching on google and on this website but no answer was enough' - please tell us what seach string you used, and why the links returned were not enough. Commented Apr 5, 2016 at 13:43
  • This is no tutorial site. Commented Apr 5, 2016 at 13:43
  • 'could you please add an explanation about how to use those' and 'this is a general question, its not for a specific code' are mutually exclusive. Commented Apr 5, 2016 at 13:46

4 Answers 4

2

Here is the code for solving this:

fseek (stdin, 0, SEEK_END);
num = ftell (stdin);

fseek will put the pointer at the end of the stdin input buffer. ftell will return the size of file.

Sign up to request clarification or add additional context in comments.

4 Comments

fseek() and ftell() won't work on FIFOS a.out < file. Error: invalid seek. returning -1.
Yeah, this does not work, and seems to always return -1.
Where did you test it? On Windows it works as expected for a.out < file. I use rewind() afterwards and check if num != 0.
I just discovered that it does not work as I expect on Windows when piping stuff. All piped commands are started simultaneously, so in "c1 | c2", c2's stdin is empty until c1 writes something into it. The above check in c2 would yield false and c2 would stop immediately. But c2 has to block and wait for stdin. In my case, either I expect stdin or i do not because the parameters tell me.
1

If you don't want to block on an empty stdin you should be able to fcntl it to O_NONBLOCK and treat it like any other non-blocking I/O. At that point a call to something like fgetc should return immediately, either with a value or EAGAIN if the stream is empty.

1 Comment

well i sort of gave up on this thing. instead im now trying to learn the whole standart c input/output in details, i mean i want to learn more than just "just scanf to get things". like i want to know exacly what stdin is and how the input thing works. mind recommending me any learning source?
1
int ch = getc(stdin);
if (ch == EOF)
    puts("stdin is empty");
else
    ungetc(ch, stdin);

Try this, ungetc(ch, stdin); is added to eliminate the side effect.

1 Comment

This doesn't address the issue, because getc() blocks.
0

You can use select() to handle the blocking issue and the man page select(2) has a decent example that polls stdin. That still doesn't address the problem of needing a line-delimiter ('\n'). This is actually due to the way the terminal handles input.

On Linux you can use termios,

#include <stdio.h>
#include <unistd.h>
#include <termios.h>

// immediate mode getchar().
static int getch_lower_(int block)
{
    struct termios tc = {};
    int status;
    char rdbuf;
    // retrieve initial settings.
    if (tcgetattr(STDIN_FILENO, &tc) < 0)
        perror("tcgetattr()");
    // non-canonical mode; no echo.
    tc.c_lflag &= ~(ICANON | ECHO);
    tc.c_cc[VMIN] = block ? 1 : 0; // bytes until read unblocks.
    tc.c_cc[VTIME] = 0; // timeout.
    if (tcsetattr(STDIN_FILENO, TCSANOW, &tc) < 0)
        perror("tcsetattr()");
    // read char.
    if ((status = read(STDIN_FILENO, &rdbuf, 1)) < 0)
        perror("read()");
    // restore initial settings.
    tc.c_lflag |= (ICANON | ECHO);
    if (tcsetattr(STDIN_FILENO, TCSADRAIN, &tc) < 0)
        perror("tcsetattr()");
    return (status > 0) ? rdbuf : EOF;
}

int getch(void)
{
    return getch_lower_(1);
}

// return EOF if no input available.
int getch_noblock(void)
{
    return getch_lower_(0);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.