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?

Neuron
  • 5,141
  • 5
  • 38
  • 59
G Eldar
  • 31
  • 1
  • 1
  • 4
  • See how to ask a question on SO. There is no code here... – Boiethios Apr 05 '16 at 13:42
  • 1
    Read from the input in a dedicated thread. – Martin James Apr 05 '16 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. – Martin James Apr 05 '16 at 13:43
  • This is no tutorial site. – too honest for this site Apr 05 '16 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. – Martin James Apr 05 '16 at 13:46
  • "this is a general question" If so, it is a general question based on wrong assumptions. `stdin` isn't an input buffer, it's an input stream, from which you can read into buffers. `scanf` has nothing to do with input being terminated with ´\n`. Unless you clarify what you want to achieve, there's no way to know what "empty" means in the context of your question. – M Oehm Apr 05 '16 at 13:47
  • Welcome to Stack Overflow. Please put some effort in your question. You've mentioned different words such as "this website" but haven't provided a website. Please be detailed and clear in your question. Post what you've tried, and always post a [Minimal, Complete and Verifiable Example](http://stackoverflow.com/help/mcve). Also read the [How to Ask](http://stackoverflow.com/help/how-to-ask) page. – Box Box Box Box Apr 05 '16 at 13:54
  • sorry about that. editted the original post – G Eldar Apr 05 '16 at 14:29
  • This question is a duplicate. Maybe you can find an option that fits you in my answer here: https://stackoverflow.com/questions/26948723/checking-the-stdin-buffer-if-its-empty/51074378#51074378 – DrBeco Jun 28 '18 at 03:44

4 Answers4

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.

Box Box Box Box
  • 5,094
  • 10
  • 49
  • 67
Shubham Agrawal
  • 559
  • 6
  • 15
  • `fseek()` and `ftell()` won't work on _FIFOS_ `a.out < file`. Error: invalid seek. returning -1. – DrBeco Jun 27 '18 at 22:00
  • Yeah, this does not work, and seems to always return -1. – Andrew Lalis Mar 20 '19 at 08:37
  • 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. – Fabian Sep 26 '19 at 06:19
  • 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. – Fabian Sep 27 '19 at 05:41
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.

laughingcoyote
  • 259
  • 2
  • 9
  • 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? – G Eldar Apr 05 '16 at 16:04
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.

nalzok
  • 14,965
  • 21
  • 72
  • 139
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);
}
Johnny Cage
  • 528
  • 2
  • 6