Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How do check the stdin without stopping? 2

Status
Not open for further replies.

darceo

Programmer
Sep 30, 2002
3
US
ok, this is my problem. I'm running an infinite loop where i am gathering data and writing it to a file. I want to be able to check the stdin so the user can input 'q' or something like that and then break the loop. The problem is that scanf(), getchar(), getc(), etc stop the loop and wait for the user to press "Enter". is there anyway of checking the stdin without stopping the program? Please Help.
 
It depends on what OS you are using.

1) DOS/Windows - use kbhit or _kbhit. It lives in conio.h and will tell you whether the user has hit the keyboard or not. If the user has hit the keyboard then you can do a getch otherwise continue looping.

2) Unix - use pthreads: create 2 threads: one to poll the keyboard and one to do your continuous loop

3) Any other OS - I haven't got a clue.
 
Example of using pthreads with a polling loop. This is written with a C++ compiler so there may be bits that do not compile with C.

#include <pthread.h>
#include <stdio.h>

struct Common
{
bool mRunning; /* Tells us when to quit */
float mCount;
};
/* The number crunching bit */
void* Cruncher (void* info)
{
struct Common* cptr = (struct Common*) info;
cptr->mCount = 0.0;
while (cptr->mRunning)
{
cptr->mCount++;
}

return (void*) 0;
}

void* PollKbd (void* info)
{
struct Common* cptr = (struct Common*) info;
int ch;

printf (&quot;Press q followed by return to quit\n&quot;);
do {
ch = getchar ();

} while (ch != 'q');
cptr->mRunning = false;

return (void*) 0;
}

main ()
{
pthread_t crunchThread, pollThread;
struct Common common = { true, 0.0 };

pthread_create (&pollThread, 0, PollKbd, &common);
pthread_create (&crunchThread, 0, Cruncher, &common);

pthread_join (pollThread, 0);
pthread_join (crunchThread, 0);

printf (&quot;Count got up to %f\n&quot;, common.mCount);

return 0;
}
 
fork the job
child writes to files
father reads stdin, stop child if got 'q'
or what ever you want vox clamantis in deserto.
 
The posix thread solution seems okay.
A quicker, easier solution might be to check the input
queue to see if anything's available.
This short example just increments a counter until
the user presses a 'q' and <enter>.
Normally, the input will be in &quot;cooked&quot; mode, so
whatever is typed will not be available for reading
until the <enter> is pressed. Then suddenly everything
is made available. If the input is in &quot;raw&quot; (or &quot;cbreak&quot;)
mode, then each character is made available as it's typed.
Use the stty command to try that before running it.

This is a posix thing, for Linux and the like. This particular
example was tested on a Solaris 8 machine.

Hope that helps!
-BUD

Code:
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/filio.h>

main( int c, char *v[])
{
    int numAvailable;
    char buf[100];
    int counter;

    for( counter = 0; ; ++counter) {

        sleep( 1);
        fprintf( stdout, &quot;%d\n&quot;, counter);

        /*
         * see if anything is available on the input queue
         */
        if( ioctl( 0, FIONREAD, &numAvailable) < 0) {
            fprintf( stderr, &quot;ioctl failed: %s\n&quot;, strerror( errno));
            break;
        }

        /*
         * input awaits - a read won't block now
         */
        if( numAvailable <= 0)
            continue;

        /*
         * one wouldn't typically use read.
         */
        if( read( 0, buf, sizeof buf) <= 0) {
            fprintf( stderr, &quot;read failed: %s\n&quot;, strerror( errno));
            break;
        }
        /*
         * as long as the standard input is in normal &quot;cooked&quot;
         * mode, the read call will never return 1; there will
         * always be at least 1 more byte available, the '\n'.
         * Nothing is available for reading until the user
         * presses return.
         */
        if( buf[0] == 'q') {
            fprintf( stderr, &quot;Quit.\n&quot;);
            break;
        }
    }
}
 
I always wondered what the Unix equivalent of kbhit was. Thanks BigUglyDude.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top