views:

337

answers:

10
+1  A: 

It depends on your platform. The C language doesn't define stuff like this.

Windows? linux? (gnome app? kde app? terminal?) something else?

smcameron
A: 

The function you are calling to read a character is blocking. If there is no character there you want it to return instead.

Magic search terms here are non-blocking and non/unbufferred input.

Kieran Tully
A: 

Why would counting in loop until somebody press the key make the sense?

You if you realy want something like than check the timings for like 10k iterrations. Then make waiting in non blocking itteration whit sleep(). When you get the time you can use it to approximate what the "final value" is

ralu
+5  A: 

If you are trying to read a single character at a time (without pressing enter) from a terminal in linux then you will need to set the terminal for un-buffered input.

See this example:

Non buffered getc(3) under GNU/Linux

Karl Voigtland
+2  A: 

If you're working on windows, and are using MSVC, you might want getch() and kbhit(), something like so

#include <conio.h>

while( looping ) {

    // do regular loop stuff

    // check if a key is hit, w/o blocking, using kbhit()
    if( kbhit() ) {
        // only runs when user has hit a key
        // so display stuff here,
        // and wait for permission to resume with getch()
        getch();
    }
}
JustJeff
+2  A: 

If you are permitted to specify what is pressed and you are on a POSIX.1-compliant system, you could set up a signal handler to catch SIGINT (sent by Ctrl+C). Have your handler change the value of a variable such that you fall out of the while loop.

If you choose this approach, be careful. If an incorrect implementation results in an infinite loop and a caught SIGINT, you will not be able to terminate your program via Ctrl+C. You would need to use kill(1) to terminate your program in this case.

Sean
+2  A: 

I think there is no trivial solution, take a look at this related question

detect keyboard event in C

901
A: 

This is one place where the C standard leaves programmers hanging out to dry. The most portable solution to this problem is to do your I/O using the curses library, which handles so-called "raw" keyboard input (which is what you want) plus a whole lot more. The learning curve is a little steep, but there are good tutorials, especially in the BSD programmers' documentation.

Norman Ramsey
A: 

Depending upon the system and how it works, you could try to use the select function with the STDIN as a file handle. You can set the time on the select statement to zero to poll to see if there is data or set it to a time to wait.

You can look at the link http://www.gnu.org/s/libc/manual/html_node/Waiting-for-I_002fO.html for an example of using the select statement with sockets.

I have modified that example to use STDIN as the file descriptor. The function will return a 0 if there is no pending input, 1 if there is pending input (i.e. someone hit a key on the keyboard of input), or -1 if there was an error of some nature

 #include <errno.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/time.h>

 int waitForKBInput(unsigned int seconds)
 {
   /* File descriptor set on which to wait */
   fd_set set;
   /* time structure which indicate the amount of time to
      wait.  0 will perform a poll */
   struct timeval timeout;

   /* Initialize the file descriptor set. */
   FD_ZERO (&set);
   /* Use the Standard Input as the descriptor on which 
      to wait */
   FD_SET (STDIN, &set);

   /* Initialize the timeout data structure. */
   timeout.tv_sec = seconds;
   timeout.tv_usec = 0;

   /* select returns 0 if timeout, 1 if input available, -1 if error. */
   /* and is only waiting on the input selection */
   return select (FD_SETSIZE,
                  &set, NULL, NULL,
                  &timeout));
 }

I know this will not work on VMS system, as I tried this and they implemented the Select and STDIN differently so it would not work (had to use other means to detect keyboard input).

For Visual C/C++ could could use the function kbhit which would indicate if there is keyboard inputs to be read.

Glenn
A: 

I will try to look not at the verbatim question that you are asking, but at your intent - apparently you want to present the result of computation, triggered by some user reaction.

Checking 'is the key pressed?' at each and every iteration is fairly wasteful - your CPU could spend all that time doing more useful things.

So, the best approach here is using signals, in my opinion - namely, SIGINT that is triggered when you hit "Ctrl-C". Here's a code that will print the value of the variable when you hit the Ctrl-C, and will exit after you do it three times:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

long globalvar = 0;
int interrupts_before_exit = 3;

void ctrl_c_handler(int x) {
  printf("Value of the variable: %ld\n", globalvar);
  if(--interrupts_before_exit) {
    printf("Press Ctrl-C %d more times to stop\n", interrupts_before_exit);
  } else {
    printf("Computation interrupted!\n");
    exit(0);
  }
}


int main(int argc, char *argv[]) {
  struct sigaction act;

  act.sa_handler = ctrl_c_handler;
  sigemptyset(&act.sa_mask);
  act.sa_flags = 0;

  if(sigaction(SIGINT, &act, NULL) >= 0) {
    while (1) {
      /* The work happens here */
      globalvar++; 
    }
  }
  exit(1);
}

You can pass the signals between the programs, so in fact you could fork the program that does the "work", and then the second program would lazily monitor the keyboard - and as soon as the key is pressed there it would send the signal to the first one, which would print the result.

Andrew Y