【问题标题】:getch and putchar not working without returngetch 和 putchar 不返回就无法工作
【发布时间】:2023-08-25 01:53:01
【问题描述】:

我一直试图让getch 在另一个程序中工作,但没有成功。所以我制作了最基本的程序,我可以使用getch,按照我希望它在主程序中的工作方式。

我研究过noechocbreakinitscrnodelay的需求,我也尝试过使用newscr()但没有成功。

我遇到的问题是,在我点击“输入”之前,字符不会被打印到屏幕上,而每个循环它们应该是put 到屏幕上。为什么会这样?此外,光标不会在新行返回到屏幕左侧。例如。

abc  
   def
      ghi

我一直在寻找答案,但又被难住了......

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

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

    return 0;
  }

【问题讨论】:

  • 如果您想知道我为什么要这样做,我正在尝试从标准输入获取输入,并且只打印到非空的标准输出行。
  • 如果你只是想实现一个文本过滤器,那么通过curses引入终端控制是一个非常糟糕的主意。交互式字符一次输入与过滤掉空行的问题无关。
  • 要将非空行从标准输入复制到标准输出,请尝试grep '.'。我可以向你保证,它不使用 ncurses。
  • @Kaz;我已经使用重定向的标准输入文件成功地使用了一次字符过滤,但是当仅将它与标准输入一起使用时,终端会回显我不想要的标准输入。所以这就是为什么我要尝试终端控制
  • 顺便说一句,你应该把getch()读成int,而不是char*.com/questions/8464030/…

标签: c ncurses getch putchar


【解决方案1】:

您没有看到输出,因为您的 stdout 流是行缓冲的。

您的程序正在正确处理各个字符;但输出流正在缓冲它们。

尝试fflush(stdout); 或使用setbuf(stdout, NULL);stdout 切换到无缓冲模式。

禁用缓冲的问题在于,当输出不是终端时,批量数据处理效率低下。

您可以使其以标准输出为 tty 为条件:

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

要将光标返回到行首,您需要输出一个回车符\r。这是因为 curses 的 cbreak 模式禁用了 ONLCR tty 模式(在输出上,发送 NL 时添加 CR)。

如果您无条件添加\r,那么当您的输出被重定向时,它将出现在文件中。所以你又需要一些isatty hack。

学习如何使用tcgetattrtcsetattr 函数来精确控制特定的tty 参数可能会更好,如果您只想在没有回显的情况下进行一次字符输入,而不是实际上开发一个基于诅咒的交互式程序。

您真的想要一次输入一个字符,还是只是为了禁用回显?禁用回声很容易。调用 tcgetattr 以使用文件描述符 0 的当前设置填充 struct termios(如果它是 tty)。翻转一些标志以关闭回显,然后调用tcsetattr 安装更新的结构。当您的程序退出时,请善待并放回原来的程序。完成。

【讨论】:

  • 但这并不能解决缺少回车的问题。我更新了答案。
  • 谢谢,我会看看他们,它可能会比我做的方式少很多。 p.s. if((c == '\n'))putchar('\r');} 有效,但我知道的代码很垃圾。
  • ;感谢tcsetattr 在许多关于如何设置标志的谷歌搜索之后就像做梦一样干杯。
【解决方案2】:

是的,ncurses 是获得逐个字符控制的好方法。

是的,你必须调用“initscr()”和“cbreak()”。

建议:

1) 将您的代码与此 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) 看看如果你执行“refresh()”和/或删除“noecho()”会发生什么。

3) 本教程包含许多有用的信息,可能也会有所帮助:

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

【讨论】:

  • 感谢书签,显然我不明白什么是窗口。
  • 嗨 - Kaz 是对的。如果您想对文本模式应用程序进行终端控制,Ncurses 是一个不错的选择。如果您想要一个简单的过滤器来去除空行(正如您随后解释的那样),只需使用“sed”或“grep”。例如:“cat myfile|grep '.'
  • 我会用猫...但这是为了家庭作业,因此制作了一个过滤器。