0

I'm trying to write a program that uses the arrow keys to choose an option and than select it with the enter key. The problem is, and i've researched this, is that getchar() needs a (second) enter keystroke to choose the option. I haven't found a solution to my problem while researching this. Here's (part of) the code:

 ..... system("/bin/stty --file=/dev/tty -icanon"); ch = getchar(); switch (ch) { case 66: // up arrow value += 1; if (value > numOptions-1) { value = numOptions-1; } break; case 65: // down arrow value -= 1; if (value < 0) { value = 0; } break; } } while (ch != 13); // Our termination cond: then hit enter. .... const char *options2[]={"option1", "option2", "option3", "option4"}; const char *selected2[]={"OPTION1", "OPTION2", "OPTION3", "OPTION4"}; .... 

Ok. I finally solved this. Apparently, a text file was causing the program to somehow not parse the carriage return properly. Getchar does work, after all. Thanks everyone for your help.

3 Answers 3

2

Instead of using getchar(), getch() should be used. Since getchar() accept the char after hitting the enter key.

Sign up to request clarification or add additional context in comments.

Comments

1

I'd recommend the ncurses library.

From this neat ncurses guide:

No echoing. If you have called noecho(), the character ch will not be printed on the screen, otherwise it will. Disabling automatic echoing gives you more control over the user interface.

No buffering. If you have called cbreak(void) each key the user hits is returned immediately by getch(). Otherwise the keys hit by the user are queued until a newline is read. Then calls to getch() take characters from the queue in FIFO manner until the queue is empty and the next whole line is read.

Special keys. If you have called keypad(stdstr, TRUE), then if the user hits a special key such as the Delete key, the arrow keys, Ctrl combined keys and function keys, a single int value will be returned. [...] To use these keys, you need to check the return value of getch(). For example:

 int ch = getch(); switch (ch) { case KEY_BACKSPACE: /* user pressed backspace */ ... case KEY_UP: /* user pressed up arrow key */ ... case KEY_DOWN: /* user pressed up arrow key */ ... case 'A' .... /* user pressed key 'A' */ ... } 

Reading the neat guide mentioned above should give all the insight you'll need; but if you have any doubts, don't hesitate on asking.

5 Comments

Ok. I'm trying ncurses. Now i'm having the problem where it doesn't "initialize" the screen properly, nor are the "choices" displayed. cbreak(); noecho(); keypad(stdscr, TRUE);
ncurses is simple, but is kind of confusing at the beginning. Remember to update screen and not to mix printw with printf functions. If you are experiencing major difficulties with ncurses itself - start another topic.
@user2990606 Don't forget to initialize -- with initscr(); -- but you should probably change your printf to printfw, as mentioned above.
I assume you mean "printw"? I changed all of my "printf"s to "printw"'s and well, the program no longer parses them. Or, does, but doesn't display anything.
Yes, that is what I meant. Anyway, glad you've solved your problem.
0

You could do a manual read of one char on the input.

psedo code :

int main(){ char buf; int fd = open(0, READ); // can't remember if open input is necessary while (read(fd, buf, 1)) { doStuff(buf); } } 

Also, you might want to do a non blocking read. This way each keypress will be sent to your program :

int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); 

2 Comments

What header file has the fcntl function?
Yeah my bad. french or not #include <fcntl.h> looks the same. Make some effort here.