getch and putchar not working without return

2019-01-15 17:28发布

I have been trying to get getch to work in another program with no success. So I have made the most basic program I can using getch the way I want it to work in the main program.

I have researched the need for noecho, cbreak, initscr and nodelay, I have also tried using newscr() but to no success.

The problem I am having is that the chars aren't being printed to the screen till I hit "enter", when they should be put to the screen every loop. Why is this happening? Also the cursor doesn't return to the left of the screen at the new line. eg.

abc  
   def
      ghi

I have looked for the answer but am stumped again...

#include <stdio.h>
#include <ncurses.h>

int main()
  {
     initscr();cbreak(); noecho();nodelay(stdscr,0);
    char c ;
    while((c=getch())!=EOF){
    putchar(c);}

    return 0;
  }

2条回答
贪生不怕死
2楼-- · 2019-01-15 17:47

Yes, ncurses is a good way to get character-by-character control.

And yes, you must call "initscr()" and "cbreak()".

SUGGESTIONS:

1) Compare your code with this ncurses "hello world":

#include <ncurses.h>

int main()
{   
    initscr();          /* Start curses mode          */
    printw("Hello World !!!");  /* Print Hello World          */
    refresh();          /* Print it on to the real screen */
    getch();            /* Wait for user input */
    endwin();           /* End curses mode        */

    return 0;
}

2) See what happens if you do a "refresh()" and/or remove the "noecho()".

3) This tutorial has lots of good info that might also help:

http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/

查看更多
霸刀☆藐视天下
3楼-- · 2019-01-15 18:03

You're not seeing the output because your stdout stream is line buffered.

Your program is getting the individual characters all right; but the output stream is buffering them.

Try fflush(stdout); or switching stdout to unbuffered mode with setbuf(stdout, NULL);.

The problem with disabling buffering is that it's inefficient for bulk data processing when the output isn't a terminal.

You can make it conditional on the standard output being a tty:

if (isatty(fileno(stdout)))  /* #include <unistd.h> */
  setbuf(stdout, NULL);

To return the cursor to the start of the line, you need to put out a carriage return \r. This is because curses' cbreak mode has disabled the ONLCR tty mode (on Output, when sending NL add CR).

If you unconditionally add \r, then it will appear in files when your output is redirected. So again you need some isatty hack.

A much better might be to learn how to use the tcgetattr and tcsetattr functions to precisely control specific tty parameters, if all you want is to do character-at-a-time input without echo, and not actually develop an interactive curses-based program.

Do you really want character-at-a-time input, or just to diable echo? It's easy to disable echo. Call tcgetattr to fill a struct termios with the current settings of file descriptor 0 (if it is a tty). Flip some flags to turn off echoing, then call tcsetattr to install the updated structure. When your program exits, be nice and put back the original one. Done.

查看更多
登录 后发表回答