1

I am trying to write a code to read input from the console continuously and update a variable in the application. But if we use scanf function, whenever the function hits it expects an input from the user through console and continues with further instruction only if it receives an input from the console, otherwise it waits unconditionally.

My code is something like

    int x, y;
    while(1)
    {
        scanf("%d", &x);
        y = x;
        ----
        ----
       //Remaining code for execution
    }

My expectation is the application should not be waiting for input from the console. If the user enters some input in the console, it should read and use that input, otherwise even if no input is entered, the application should execute remaining instructions or it should use the old values. Is there any other way to write such code without using scanf? Thanks!

Mahonri Moriancumer
  • 5,993
  • 2
  • 18
  • 28
rilwan
  • 51
  • 3

3 Answers3

0

You can select()/epoll() function for taking input, if timeout occurs it will proceed further. Since stdin is also an FD, you can register than FD for select to work on that given FD.

Refer : https://stackoverflow.com/a/21198059/6686352

Mohit Jain
  • 270
  • 2
  • 6
0

You can use select() with a zero (not NULL) timeout to check if data is available, and only then call scanf.

Example (without correct error handling):

#include <stdio.h>
#include <unistd.h>
#include <sys/select.h>

int main()
{
    int x;
    fd_set fds;
    struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };

    while (1) {
        FD_ZERO(&fds);
        FD_SET(0, &fds);  // Watch stdin (fd 0)
        if (select(1, &fds, NULL, NULL, &tv)) {
            scanf("%d", &x);
            printf("Got %d from stdin", x);
        }

        printf("Working..\n");
        sleep(1);
    }
}
Mattias Wallin
  • 1,418
  • 1
  • 10
  • 8
  • Any idea how to get the select library? – rilwan Sep 26 '19 at 06:17
  • It is part of POSIX, so it is always available on a POSIX compliant system, for example Linux. I don't know what platform you are using. Windows seems to have select in `winsock2.h`. – Mattias Wallin Sep 26 '19 at 06:24
  • @Mattias: I think Windows `select` only works on sockets, not arbitrary file descriptors such as terminals. But my Windows knowledge could be really out of date. – rici Sep 26 '19 at 07:50
  • @MattiasWallin: In windows, this code executes but always enters the `if `condition and blocks at scanf. `select.h` was replaced with `winsock2.h`. – rilwan Sep 26 '19 at 09:29
  • @rilwan: Then there may be some difference to how Microsoft Windows is doing it. rici suggests that select only works for sockets on Windows. There are other solutions: Use platform specific API, do blocking reads in a seperate thread, use ncurses, use fcntl to set stdin to O_NONBLOCKING (again, maybe not on Windows?). – Mattias Wallin Sep 26 '19 at 09:46
  • The function: `select()` can return -1, so the `if()` on the select() statement is error prone. Suggest checking for the returned value >0 – user3629249 Sep 27 '19 at 15:42
  • 1
    @user3629249 Yes, and not only -1. And you should probably use FD_ISSET(0, &fds) to check for available data. And check the status from scanf. – Mattias Wallin Sep 27 '19 at 15:53
0

You can set stdin to non-blocking with fcntl. This makes scanf return early with EAGAIN if it would otherwise have blocked.

Example (without correct error handling):

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

int main()
{
    int x;
    fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);

    while (1) {
        int ret = scanf("%d", &x);
        if (ret > 0)
            printf("Got %d from stdin", x);

        printf("Working..\n");
        sleep(1);
    }
}
Mattias Wallin
  • 1,418
  • 1
  • 10
  • 8