4

I'm writing a C program that prints something on terminal using ncurses. It should stop printing when user press 's' and continue again when press 's'. How can I read a key from input without waiting user to press the key?

I tried getch() and getchar() but they wait until a key is pressed...

Edit

This is my code:

int main(void)
{
   initscr(); /* Start curses mode         */
   refresh(); /* Print it on to the real screen */
   int i = 0, j = 0;
   int state = 0;
   while (1)
   {
      cbreak();
      int c = getch(); /* Wait for user input */
      switch (c)
      {
         case 'q':
            endwin();
            return 0;
         case 'c':
            state = 1;
            break;
         case 's':
            state = 0;
            break;
         default:
            state = 1;
            break;
      }
      if(state)
      {
         move(i, j);
         i++;
         j++;
         printf("a");
         refresh();
      }
   }
   nocbreak();
   return 0;
}

EDIT 2 This works well. I got 100 points :)

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

int main(void)
{
   initscr();
   noecho();
   cbreak();         // don't interrupt for user input
   timeout(500);     // wait 500ms for key press
   int c = 0;        // command: [c|q|s]
   int s = 1;        // state: 1= print, 0= don't print ;-)
   int i = 0, j = 0;
   while (c != 'q')
   {
      int c = getch();
      switch (c)
      {
         case 'q':
            endwin();
            return 0;
         case 'c':
            s = 1;
            break;
         case 's':
            s = 0;
            break;
         default:
            break;
      }
      if (s)
      {
         move(i, j);
         printw("a");
         i++;
         j++;
      }
   }
   endwin();
   nocbreak();
   return 0;
}
sorush-r
  • 10,490
  • 17
  • 89
  • 173
  • 1
    @FailedDev : I saw programs doing something like this... for example the tennis game moves the pad only when arrow keys one of right or left arrow keys is presses... – sorush-r Oct 14 '11 at 19:07
  • 1
    You don't want to use `printf("a")` in a curses program. curses won't be aware that you've written anything. It probably won't erase the `a` character, because it doesn't know it needs to, but you really want to use the appropriate curses function to write `"a"` into the current window, not to stdout. – Keith Thompson Oct 14 '11 at 20:45
  • @Keith Thompson: Ok, I replaced `printf` with `printw`. Thank you. – sorush-r Oct 15 '11 at 06:10

3 Answers3

4

ncurses has the capability to do this through it's own getch() function. See this page

#include <curses.h>

int main(void) {
  initscr();
  timeout(-1);
  int c = getch();
  endwin();
  printf ("%d %c\n", c, c);
  return 0;
}
KevinDTimm
  • 14,226
  • 3
  • 42
  • 60
  • Any elucidation of what failed? Or shall we just guess? Your question is not clear. In one part you want to do something when a key is pressed; later, you want it to return whether a key is pressed or not. What is the real need? – KevinDTimm Oct 14 '11 at 19:23
  • I want this: print `a` when idle (always), stop printing `a` when `s` is pressed, continue printing `a` when c pressed. exit program when `q` pressed. – sorush-r Oct 14 '11 at 19:28
  • sorry, not going to do all that work (note that all the modifications to your code were done after I answered the original question). look at how to setup ncurses so that it returns immediately - timeout() - when no character is there and then test the return value to see if a valid character was input. – KevinDTimm Oct 14 '11 at 19:31
  • Thank you. It works with few changes. just timeout(500) and noecho(). – sorush-r Oct 15 '11 at 05:53
  • @downvoter - I think maybe if you don't like the answer you should say why - no comment, no down vote. – KevinDTimm Mar 10 '14 at 18:06
0

Since you're using ncurses, you start by calling cbreak to turn off line buffering. Then you'll call nodelay to tell it not to wait before returning -- getch will always return immediately. When it does, you'll check whether a key was pressed, and if so what key that was (and react appropriately).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • `timeout` sets the timeout for interpreting multibyte function key codes, and does not cause the `getch` call to return if no key has been pressed. You want `nodelay` – Chris Dodd Oct 14 '11 at 19:42
-1

There's an answer to this in the comp.lang.c FAQ. See question 19.1, "How can I read a single character from the keyboard without waiting for the RETURN key? How can I stop characters from being echoed on the screen as they're typed?".

It's a bit long to post here.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • seems strange since curses is not part of 'standard' C – KevinDTimm Oct 14 '11 at 19:10
  • @KevinDTimm: That's why it's in the "System dependencies" section. It is a frequently asked question, after all; the answer happens to be along the lines of "You can't do that in standard C, but here's how you can do it on systems X and Y". – Keith Thompson Oct 14 '11 at 19:15
  • only strange as I just remember the responses from the comp.lang.c newsgroup regulars when someone would ask about items outside the standard - "You're in the wrong place, there is no in the standard" – KevinDTimm Oct 14 '11 at 19:17