I am trying to read a number character with character, but I don't know if the stdin buffer is empty or not.
My first solution whas to look for \n
character in stdin buffer, but this is no good if I what to enter multiple numbers separated by " "
.
How can I know if in stdin buffer I have characters or not?
I need to do it in C and to be portable.
If you want to check if the buffer holds no characters, you can use the strlen() function from string. h (make sure the buffer is \0-terminated after fread(). If you want to check if malloc failed, compare the pointer with NULL.
Default Buffer sizes: if stdin/stdout are connected to a terminal then default size = 1024; else size = 4096.
However, calling fclose(stdin) will work on any POSIX compliant operating system as well as Windows operating systems, so you should hit pretty much anything in general use at the moment. As stated by the previous answer as well as my comment, there is no need to call close on the file handle.
There are several soutions:
poll or select with timeout of 0 - these would return immediately and result is either -1 with errno EAGAIN
if no data available or number of descriptors with data (one, since you're checking only stdin).
ioctl is a swiss army knife of using descriptors. The request you need is I_NREAD
:
if (ioctl(0, I_NREAD, &n) == 0 && n > 0)
// we have exactly n bytes to read
However the correct solution is to read everything you got (using scanf
) as a line, then process the result - and this works good enough with sscanf
:
char buf[80]; // large enough
scanf("%79s", buf); // read everything we have in stdin
if (sscanf(buf, "%d", &number) == 1)
// we have a number
... as long as you properly handle re-reading, strings that are longer than your buffer, and other real-life complications.
For anyone who comes here from google – easy select
solution to check stdin
emptyness:
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(STDIN_FILENO, &readfds);
fd_set savefds = readfds;
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
int chr;
int sel_rv = select(1, &readfds, NULL, NULL, &timeout);
if (sel_rv > 0) {
puts("Input:");
while ((chr = getchar()) != EOF) putchar(chr);
} else if (sel_rv == -1) {
perror("select failed");
}
readfds = savefds;
Needs unistd.h
, stdlib.h
and stdio.h
.
Explanation can be found here.
UPD: Thanks DrBeco for noticing that select returns -1 on error -- error handling was added.
Actually, select returns:
I inspired from this as referenced by @stek29's post on this page and prepared a simple example as follows:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
fd_set readfds;
FD_ZERO(&readfds);
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
char message[50];
while(1)
{
FD_SET(STDIN_FILENO, &readfds);
if (select(1, &readfds, NULL, NULL, &timeout))
{
scanf("%s", message);
printf("Message: %s\n", message);
}
printf("...\n");
sleep(1);
}
return(0);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With