【问题标题】:Cannot read from stdin extended ASCII character in NCURSES无法从 NCURSES 中的标准输入扩展 ASCII 字符读取
【发布时间】:2016-04-06 20:16:51
【问题描述】:

我在尝试读取 NCURSES 中的扩展 ASCII 字符时遇到问题。

我有这个程序:

#include <ncurses.h>
int main () {
    initscr();
    int d = getch();
    mvprintw(0, 0, "letter: %c.", d);
    refresh();
    getch();
    endwin();
    return 0;
}

我用:gcc -lncursesw a.c 构建它

如果我在 7 位 ascii 中键入一个字符,例如 'e' 字符,我会得到:

letter: e.

然后我必须键入另一个才能结束程序。

如果我在扩展的 ascii 中键入一个字符,例如 'á' 字符,我会得到:

letter:  .

程序结束。

就像第二个字节被读取为另一个字符。

我怎样才能得到正确的 char 'á' ???

谢谢!

【问题讨论】:

  • 没有标准的“扩展 ASCII”。只是一堆不同的编码。目前尚不清楚您的终端使用的是哪一个,可能是 UTF-8,它是一种可变长度代码。因此,您必须阅读多个chars 来组成一个字符。您应该验证并检查 ncurses 是否提供处理此问题的函数,例如使用宽 chars.
  • 我不了解 ncurses,但 Windows conio.h 函数 getch() 在按下某些键(如功能键)时在连续调用中返回 2 个值。编写一个简单的程序来显示连续按键的(数字)结果。

标签: c ncurses


【解决方案1】:

您要输入的字符需要程序设置语言环境。如manual中所述:

Initialization

   The  library uses the locale which the calling program has
   initialized.  That is normally done with setlocale:

         setlocale(LC_ALL, "");

   If the locale is not initialized, the library assumes that
   characters  are  printable  as in ISO-8859-1, to work with
   certain legacy programs.  You should initialize the locale
   and  not  rely on specific details of the library when the
   locale has not been setup.

除此之外,您的语言环境很可能使用 UTF-8。要使用 UTF-8,您应该编译并链接到 ncursesw 库。

此外,getch 函数仅返回单字节编码的值,例如 ISO-8859-1,有些人将其与 Windows cp1252 混淆,因此返回“扩展 ASCII”(这说明了两个谬误不取消)。 UTF-8 是一种多字节编码。如果你使用getch 读取那个,你会得到字符的第一个字节。

相反,要读取 UTF-8,您应该使用 get_wch(除非您想自己解码 UTF-8)。这是一个修改后的程序:

#include <ncurses.h>
#include <locale.h>
#include <wchar.h>
int
main(void)
{   
    wint_t value;
    setlocale(LC_ALL, "");
    initscr();
    get_wch(&value);
    mvprintw(0, 0, "letter: %#x.", value);
    refresh();
    getch();
    endwin();
    return 0;
}

我将结果打印为数字,因为printw 不知道 Unicode 值。 printw 使用与 printf 相同的 C 运行时支持,因此您可以直接打印该值。例如,我看到POSIX printf 有一个格式化选项来处理wint_t

c
int 参数应转换为unsigned char,并写入结果字节。
如果存在 l (ell) 限定符,则 wint_t 参数应按照 ls 转换规范进行转换没有精度且参数指向wchar_t 类型的双元素数组,其中第一个元素包含 ls 转换规范的wint_t 参数,第二个元素包含一个空宽字符。

由于 ncurses 可在许多平台上运行,并非所有平台都支持该功能。但您可以假设它适用于 GNU C 库:大多数发行版通常都提供可行的语言环境配置。

这样做,例子更有趣:

#include <ncurses.h>
#include <locale.h>
#include <wchar.h>
int
main(void)
{   
    wint_t value;
    setlocale(LC_ALL, "");
    initscr();
    get_wch(&value);
    mvprintw(0, 0, "letter: %#x (%lc).", value, value);
    refresh();
    getch();
    endwin();
    return 0;
}

【讨论】:

  • 我正在链接 ncursesw ..我确实添加了 setlocale(LC_ALL, "");在 initscr() 之前,但现在我得到了..“ etter: M-!”,没有引号..
  • 我让它在另一台电脑上工作,就像你展示的一样!!是否存在类似“mvwprintw”的功能,但对于宽字符???
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多