• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 323
  • Last Modified:

console input

Gday,

Say I have a console app that has a menu like this say:

1. go here
2. go there
q. quit

At the moment I am using read() calls to read in the data.. the problem is the read call waits for the enter button to be pressed before stopping reading. This sux.. I want a way so that if 1 is pressed *instantly* my program reacts to the input and goes to 1.. I don't want to wait for say 1 and then "enter".

Anyone got any ideas?
0
ramsay
Asked:
ramsay
  • 5
  • 5
  • 4
  • +1
1 Solution
 
jlevieCommented:
It waits because you are doing buffered reads. You at least need to use unbuffered asynchronus I/O and quite possibly need to associate a signal to tell when a character has been typed. The man page on open and fcntl would be good to look at.
0
 
ramsayAuthor Commented:
i want an example
0
 
ramsayAuthor Commented:
Adjusted points to 200
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
alien_life_formCommented:
You need to do raw input and your best bet for doing it portably would be using ncurses, with something like:

#include <curses.h>

initscr();
cbreak();
noecho();
/*
 * your stuff here
 */

endwin();

If you want to do it the hard way, do a  man termios and prepare to meet madness on your path.

Alternatively, and for a quicky, this might work:
system("stty cbreak </dev/tty >/dev/tty 2>&1");
c=getc(stdin);
system("stty -cbreak </dev/tty >/dev/tty 2>&1");

but it's pretty ugly.

Also, you'll have to unbuffer stdin before it'll work.

Cheers,
     alf

0
 
ramsayAuthor Commented:
thanks alf.. i'll look into it now
0
 
nils pipenbrinckCommented:
what about that?

#include <stdio.h>

int menu (int argc, char **args)
{
  char c;
  printf ("a. foo\n");
  printf ("b. bar\n");
  printf ("c. quit\n");

  c = getch();
  switch (c)
  {
    case 'a':
      // code for a goes here
    break;
    case 'b':
      // code for b goes here
    break;
    case 'q':
      return;
    break;
  }
}

getch just returns the first character
from stdin. if there is no such charater it waits for one..

  Nils

0
 
nils pipenbrinckCommented:
ehm. ****

getch needs conio.h..

forgot to include it.

Nils
0
 
alien_life_formCommented:
Grretings.

Nils, may work *under windows* (which also has conio.h). But, this is a Linux forum - wrong OS.

Cheers,
 alf
0
 
nils pipenbrinckCommented:
Hm...

Ok, I'm from the win32 corner, that's true..

But isn't conio.h part of the ANSI clib standard?

at least fgetc is ANSI (according to my clib reference)..

so char c = fgetc (stdin) should work on any os supporting a ANSI clib.

Nils

0
 
alien_life_formCommented:
Greetings.

i) No, conio.h is a windows-only header.

ii) Yes, fgetc and company are ANSI, however, the problem with console input is the line discipline: the character is made available only after the user has pressed enter (line buffering, and then some). This behavior is what the original poster wants to avoid.

Cheers,
   alf
   
0
 
nils pipenbrinckCommented:
hm..

as you know I'm no linux expert, but stdio.h is ansi standard, isn't?

maybe a setbuf (stdin, 0) will do the job.. that would disable all buffering.

Nils
0
 
alien_life_formCommented:
Greetings.

That would indeed  be correct for a file. However, here we're talking a file descriptor that's really connected to a terminal. When this is the case,
you're really talking to a device driver responsible for shuttling keystrokes back and forth from the keyboard to the stdio data structures.

This driver interfaces to stdio through (?) a system layer that can be controlled by means provided by termios.h and/or ioctl.h.

Problem is, this interface is not, will I put it mildly, the most user friendly piece of the Unix programming environment (the un-mild version is that it's mummbo-jumbo). The historical reason is that it allows you to handle many different terminal-like devices, including teletypes and long-forgotten terminal brands.

However. What this subsystem does, roughly, is slapping a layer of preprocessing between the device itself and stdio. This is often referred to as 'cooked' mode, and part of it is the line discipline bit: stdio will not get hold of the keystrokes until they have been processed *and* <enter> has been pressed. So just unbuffering stdin won't be sufficient (unlike what happens when you read from, say, a pipe, where unbuffering is enough).

If you want to get rid of this, you have to put the terminal in 'raw' or 'cbreak' mode, and be prepared to handle keystrokes.

Hence this thread.

Cheers,

   alf

0
 
nils pipenbrinckCommented:
strange system you are working on.for gods sake I have my win32 :)

I'll uncheck the notify.. it looks like I can't help here at all..

bye,
  Nils


0
 
alien_life_formCommented:

Ramsay, is the problem closed? If so,
pls. take appropriate action.

Cheers,
   alf

0
 
ramsayAuthor Commented:
Thanks alf.. that worked for me.. sorry i was slow getting back to ya..
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 5
  • 5
  • 4
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now