为什么广泛的性格困扰?

时间:2012-06-09 23:05:52

标签: c ncurses

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

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

#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。

3 个答案:

答案 0 :(得分: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例程将光标状态设置为不可见,正常或非常可见可见性等于 0 1 ,或 2 分别为“


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

setcchar()的第四个参数是short color_pair。它需要一个颜色对 number ,而不是它的属性掩码(它应该应用于chtype)。我同意,这个记录很少。使用COLOR_PAIR()仅适用于对0.对于任意对,例如对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是否跟随其他控制字符,然后才能确定它是一个孤立的按键。所以你无法避免延迟,但你可以把它减少到一个不太明显的时间,比如说100ms。必须在初始化curses之前设置

setenv("ESCDELAY", 100, FALSE);

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


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

setlocale(LC_ALL, "");

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

答案 1 :(得分:2)

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

事实证明我的问题是对语言环境的调用:

  setlocale(LC_CTYPE, "");

应该是:

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

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

答案 2 :(得分:0)

您需要提出以下问题:

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