【问题标题】:How can getch (ncurses) return values be different between programs?程序之间的 getch (ncurses) 返回值如何不同?
【发布时间】:2014-03-06 01:33:28
【问题描述】:

我通过创建一个测试程序开始使用 ncurses,这样我就可以映射我可以从函数中得到的输入,并使用函数指针实现一个控件。但是,在获得我需要的数据后,具有上述控制结构的程序没有按预期响应。我注意到的第一个问题是,当使用箭头键时,程序在每次按下后都会显示文本。我注意到的第二个问题是,我自己的调试打印输出中显示的值表明第二个程序中的 getch 值与第一个程序中的不同。

两个程序具有相同的 init 函数,具有相同的 args 以相同的顺序,并且在同一台机器上,所以应该没有理由为什么输出和行为应该不同。

有人知道为什么会这样吗?

编辑: 该系统运行在 Linux Mint 16 x86_64 架构上。我使用 eclipse 用 gcc 编译。 libncurses 是项目中唯一包含的库。

这是测试代码:

int main()
{
 int i = 0;
 initscr();
 raw();
 keypad( stdscr, TRUE );
 noecho();
 while( 1 ) // need to catch all available keys
 {
  i = getch();

  mvprintw( 0, 0, "%d    ", i );

 }

 getch();
 endwin();
 return 0;

}

当按下向上键时,输出为:“259”

在不同文件中拆分相同代码的另一个程序会给出以下输出:“got 27 OA”,并在每次再次按下向上键时添加“^[OA”,就好像它在配置为不时回显一样。

我创建了另一个测试程序,但我的简化尚未重现该行为。

我删除了部分代码,其中包含计划在按 Enter 时调用的此函数导致/发现更改。目前,该函数与输入无关,但似乎仍在影响程序对输入的解释。

void select( int n, Point *p )
{
 if( 16 == p->Y )
  phase = SETUP;

 else if( 18 == p->Y )
  ;

 else
  phase = QUIT;

}

【问题讨论】:

  • 这将很难追踪。您可能应该确定您正在使用的平台。您应该验证两个程序的编译选项是否相同。如果这没有任何意义,您可能需要发布一些代码。理想情况下,您应该将代码缩减为两个独立的小程序,以重现您看到的效果——SSCCE (Short, Self-Contained, Correct Example) 或 MCTRE (Minimal, Complete, Tested and Readable Example)。
  • 当您的代码中没有出现字符串“got”时,它如何输出“got”?
  • @JonathanLeffler:没那么难。 8-)} (不过一般来说是个好建议。)
  • 第二个程序的调试输出与我显示的略有不同,但是把其他代码放上去会有点问题,所以我只能这样引用它。 "got" 来自第二个程序的行,相当于 "mvprintw( 0, 0, "%d ", i );"

标签: c gcc ncurses getch


【解决方案1】:

快速实验:

#include <stdio.h>
#include <curses.h>
int main(void) {
   printf("KEY_UP = %d\n", (int)KEY_UP);
}

表示259KEY_UP 的值,getch() 在读取向上箭头时通常会返回该值(因为该键没有单个 ASCII 甚至 Unicode 代码)。

至少在 xterm 中,方向键有两组不同的代码序列。向上箭头键通常发送序列^[[A,其中^[ 是Escape 键。但是当我在 xterm 的中键菜单中启用“应用程序光标键”时,向上箭头键改为发送^[OA,这与您看到的27 OA 一致。

所以如果getch() 看到^[[A 序列,它会将其识别为向上箭头键并返回KEY_UP。但它不能识别^[OA,所以它只是将它作为3 个不同字符的序列返回。 (getch() 识别的序列由终端类型的 terminfo 条目控制,具体取决于 $TERM 的值。)

了解如何在终端模拟器中禁用“应用程序光标键”;这应该可以解决问题。

【讨论】:

  • 感谢您深入了解密钥的不同输出。我对此有两个问题。第一:当 noecho() 成功时,为什么程序会继续回显按下的键(我确认它是通过使用普通文本键来完成的,并且它们被添加到输出字符的字符串中)?第二:为什么在同一个控制台中运行时第一个输出会正确?
【解决方案2】:

在我进行了跟踪这一点的测试之后,问题归结为导致该行为的函数的名称。这可能是因为有另一个名为 select 的函数在 ncurses 中被覆盖。这有助于解释奇怪的行为问题,即输入不是原始的,并且在以其他方式显式配置后仍然启用回显。

所以这个问题有一个简单的解决方案:不要在包含 ncurses 的范围内使用名称“select”。

【讨论】:

  • 这也引发了另一个问题:为什么gcc会允许程序在前面提到的场景下编译?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-28
  • 1970-01-01
  • 2011-05-13
  • 1970-01-01
  • 2023-03-23
  • 2012-04-02
相关资源
最近更新 更多