在NCURSES中无法正确打印扩展ASCII字符

4

我有这个程序:

#include <ncurses.h>
int main () {
    initscr();
    mvaddstr(0, 0, "              A         B         C         D         E       ");
    mvaddstr(1, 24, "ñandñ");
    mvaddstr(1, 34, "esdrñjulñ");
    refresh();
    getch();
    endwin();
    return 0;
}

当ncurses打印第一个单词(ñandñ)时,移动到其他位置(在此例中为1,34)之后,实际上它会移动到另一个位置,因此第二个单词会被打印在另一列。

所以正确的显示应该是:

          A         B         C         D         E       
                              ñandñ     esdrñjulñ

看起来像这样:

          A         B         C         D         E       
                              ñandñ   esdrñjulñ

由于第一个单词中有两个扩展ASCII字符'ñ',导致出现问题。有任何想法吗?谢谢!

你使用的是哪个平台?你是否使用了 -Wall 编译选项并且修复了所有警告 - rici
1
你的源文件是否具有ncurses在你的环境中所期望的编码? - Ulrich Eckhardt
我使用了 -Wall 进行编译,但没有任何输出。没有警告,什么都没有。 - Andres Martinelli
文件采用“UTF-8 Unicode C程序文本”编码。我如何知道ncurses期望的编码是什么? - Andres Martinelli
有一个适用于宽字符处理的ncurses版本。你需要它。 - Luis Colorado
1个回答

6

如果您想使用多字节UTF-8字符,则必须使用编译了多字节支持的ncurses库版本,并且需要在程序开头正确设置locale。

通常称为libncursesw 的多字节ncurses库,因此只需在链接器选项中将-lncurses更改为-lncursesw即可使用。 您不需要不同的头文件。 但是,如果您实际上想要使用宽字符函数,则必须在任何#include指令之前#define符号_XOPEN_SOURCE_EXTENDED。 使用gcc(或clang)最简单的方法是将-D_XOPEN_SOURCE_EXTENDED添加到编译器选项中。

如果您的shell locale已设置为UTF-8 locale(这通常是现代Linux发行版的情况),则插入以下内容就足够了

setlocale(LC_ALL, "");

在调用ncurses例程之前,需要将可执行文件的区域设置为由环境变量配置的区域设置。您需要添加:

#include <locale.h>

将以下内容添加到您的头文件中,无需链接任何特殊库即可支持本地化。


原问题指出正在使用mvaddwstr。对于多字节字符,这通常是更好的解决方案,但如上所述,如果您愿意,也可以使用窄字符串接口。然而,您不能输出不完整的UTF-8序列,因此单字符窄接口(如addch)只能用于字符代码小于128的情况。

这个注释适用于尝试使用char*而不是wchar_t*参数调用mvaddwstr的情况。请不要这样做:

像所有接受字符串的w ncurses函数一样,mvaddwstrwchar_t*作为其字符串参数。您的编译器应该已经警告了您(除非它警告您没有mvaddwstr的原型)。所以这些字符串应该加上L长度属性:L"ñandñ"


正如我之前所说,我的程序使用的是mvaddstr而不是mvaddwstr调用。 我写错了。只需编辑帖子并进行更正即可。 我正在使用ncurses lib而不是ncursesw,当我运行gcc file.c -lncurses -Wall时,没有警告出现。 - Andres Martinelli
@andres:你仍然需要调用setlocale,并且需要链接-lncursesw而不是-lncurses。然后它应该可以工作了。 - rici
它使用-lncursesw和设置区域设置工作了! 现在,如果我使用mvaddstr,是否必须使用-lncursesw而不是-lncurses? - Andres Martinelli
@Andres:如果你想正确处理UTF-8序列,无论你是使用宽字符还是窄字符ncurses函数输出它们,这都是必须的。既然你已经编辑了问题,我会编辑答案。 - rici
由于我只想在我的程序中处理扩展ASCII,所以我可以使用ISO 8859-1编码,然后链接到-lncurses吗? - Andres Martinelli
@Andres:当然可以。但是你的整个环境可能都是为UTF-8设置的。因此,您需要更改区域设置、终端程序使用的编码以及许多其他内容。我保证这比仅向链接器命令添加一个字符要更费力。 - rici

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接