3

在尝试使用 ncurses 进行一些工作时,我已经到了需要使用宽字符来绘制方框图以及其他东西的地步,而且我处于每个图块控制很有用的情况。

但是,当尝试使用以下代码时,我遇到了麻烦:

#define _XOPEN_SOURCE_EXTENDED

#include <locale.h>
#include <curses.h>
#include <stdlib.h>
#include <time.h>

#define ESC 27

int main() {
  setlocale(LC_CTYPE, "");

  initscr();
  keypad(initscr(),1);
  curs_set(9);
  nonl();

  cchar_t special;
  setcchar(&special, L"æ", 0, COLOR_PAIR(0), NULL);

  cchar_t speshul;
  setcchar(&speshul, L"朝", 0, COLOR_PAIR(0), NULL);

  int c=0;
  do {
    clear();

    mvadd_wch(3,6, &special);
    mvadd_wch(4,6,&speshul);

    refresh();

  } while ((ESC!=(c=getch())));

  endwin();
}

编辑:

更新了要使用的代码setcchar;输出令人沮丧:

?

一个问号special应该在哪里,什么也不speshul应该在哪里。

两个角色都没有按预期出现。

问题出在哪里,我该如何解决?

编辑:回应Petesh的一些额外信息:

预期的结果是打印字符“æ”,在其下方,朝。我在 Mac OS X 上使用 Terminal.app;我正在编译它 Xcode。

4

3 回答 3

5

您的代码中还有许多其他“问题”,其中一些可能与您的宽字符问题有关:


initscr();
keypad(initscr(),1);

避免initscr()无缘无故打两次电话。将第一次调用的结果存储在WINDOW指针中,或者简单地使用内置的stdscr. 还要避免bool值的数字常量,更喜欢命名常量TRUEFALSE. 语义完全不同。

所以使用:

WINDOW *screen = initscr();
keypad(screen, TRUE);

或者

initscr();
keypad(stdscr, TRUE);

curs_set(9);

9不是 的有效参数curs_set()。来自手册:“curs_set 例程将光标状态设置为不可见、正常或非常可见,可见性分别等于012


setcchar(&special, L"æ", 0, COLOR_PAIR(0), NULL);

的第四个参数setcchar()short color_pair。它需要一个颜色对number,而不是它的属性掩码(应该应用于 a chtype)。我同意,这没有很好的记录。usingCOLOR_PAIR()仅适用于对 0。对于任意对,例如 pair 4,使用:

setcchar(&special, L"æ", WA_NORMAL, 4, NULL);

也使用WA_NORMAL代替0. 不要依赖常量值,使用命名的值!


while ((ESC!=(c=getch())))

您还应该测试ERR退货。不要假设c将始终包含有效的字符代码:

while ((c=getch()) != ERR && c != ESC)

另外,如果你真的想ESC用作打破循环的角色,你应该阅读关于ESCDELAY. 默认情况下,在用户按下 ESC 和该键对您的程序可用之间需要一整秒钟的时间。简单来说,原因是 ESC 也用于启动转义序列,因此 curses 必须等待查看 ESC 后面是否有其他控制字符,然后才能确定它是一个孤立的按键。所以你无法避免延迟,但你可以将它减少到一个不太可感知的时间,比如 100 毫秒。这必须在初始化诅咒之前设置!

setenv("ESCDELAY", 100, FALSE);

getch()在宽字符世界中使用时要小心。get_wch()对于一个简单的“循环直到 ESC”,这很好,但是当您想要实际解析用户输入时替换它。


最后,您不需要将语言环境设置为"en_US.UTF-8",因为这将覆盖用户的语言环境。如果您的终端设置为非字符编码UTF-8,或者您的语言不是,该en_US怎么办?只需将您的程序设置为使用用户环境中设置的任何语言环境

setlocale(LC_ALL, "");

这与根本不设置语言环境有很大不同,因为默认情况下,语言 C 假定语言环境是C,即仅 7 位 ASCII 字符。诅咒尊重这一点。

于 2015-03-12T08:10:47.550 回答
3

事实证明,魔鬼在细节中。

原来我的问题是对语言环境的调用:

  setlocale(LC_CTYPE, "");

它应该是:

  setlocale(LC_ALL, "en_US.UTF-8") // or similar

解决问题的设置,字符现在可以正确显示。

于 2012-06-10T00:34:31.053 回答
0

你需要问以下问题:

  1. 预期的结果是什么(因为它适用于我的系统)
  2. 您使用的终端是什么 - 即操作系统(windows/etc)、应用程序
  3. 您是否在正在编译的窗口中编辑文件
  4. 如果您的环境没有正确解释它,并且假设文件处于 UTF-8 模式,您可能想在编译行尝试 --encoding=UTF-8。如果您使用的是 Windows,则可以只使用 UCS-16 作为编码。
于 2012-06-10T00:14:53.533 回答