为什么广泛的性格困扰?

Wil*_*and 1 c ncurses

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

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

#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();
}
Run Code Online (Sandbox Code Playgroud)

编辑:

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

?
Run Code Online (Sandbox Code Playgroud)

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

两个角色都没有按预期显示.

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

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

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

Mes*_*ion 5

您的代码中还有许多其他"问题",有些可能与您的广泛字符问题有关:


initscr();
keypad(initscr(),1);
Run Code Online (Sandbox Code Playgroud)

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

所以使用:

WINDOW *screen = initscr();
keypad(screen, TRUE);
Run Code Online (Sandbox Code Playgroud)

要么

initscr();
keypad(stdscr, TRUE);
Run Code Online (Sandbox Code Playgroud)
curs_set(9);
Run Code Online (Sandbox Code Playgroud)

9不是一个有效的论据curs_set().从该手册:"该curs_set例程将光标设置状态到不可见的,正常的,或为非常明显的可见度等于0,1,或2分别为"


setcchar(&special, L"æ", 0, COLOR_PAIR(0), NULL);
Run Code Online (Sandbox Code Playgroud)

第四个论点setcchar()short color_pair.它需要一个颜色对编号,而不是它的属性掩码(应该应用于a chtype).我同意,这个记录很少.COLOR_PAIR()仅使用对0对.对于任意对,比如对4,使用:

setcchar(&special, L"æ", WA_NORMAL, 4, NULL);
Run Code Online (Sandbox Code Playgroud)

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


while ((ESC!=(c=getch())))
Run Code Online (Sandbox Code Playgroud)

你还应该测试一个ERR回报.不要假设c将始终包含有效的字符代码:

while ((c=getch()) != ERR && c != ESC)
Run Code Online (Sandbox Code Playgroud)

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

setenv("ESCDELAY", 100, FALSE);
Run Code Online (Sandbox Code Playgroud)

getch()在广泛的角色世界中使用时要小心.对于一个简单的"循环直到ESC"这很好,但是get_wch()当你想要实际解析用户输入时替换它.


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

setlocale(LC_ALL, "");
Run Code Online (Sandbox Code Playgroud)

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

  • 这是这个问题的真正答案,特别是关于语言环境问题. (2认同)