方框字符在 Linux 终端中无法正确显示

方框字符在 Linux 终端中无法正确显示

我刚刚编写了一个 C++] 程序,它使用方框字符来显示信息。我在 macOS 上运行了该程序并使用了终端应用程序,它运行得很好。

当我切换到Debian Linux使用相同的代码并重新编译它,我才遇到这个问题!我在网上搜索了答案,但没有找到与这个问题相关的答案。我已经用两者测试过这个LX终端和 URXVT

这是这个问题的最小可重现示例:

#include <ncurses.h>
#include <iostream>

int ch;

int main() {
    setlocale(LC_CTYPE, "");
    initscr();
    noecho();
    keypad(stdscr, true);
    nodelay(stdscr, true);
    curs_set(0);
    start_color();
    use_default_colors();

    init_pair(1, COLOR_BLUE, -1);

    clear();
    refresh();

    while ((ch = getch()) != 'q' && ch != 'Q') {

        attrset(COLOR_PAIR(1));

        mvprintw(0,0,"┏━┓");
        mvprintw(1,0,"┗━┛");

    }

    refresh();
    endwin();

    return 0;
}

使用以下命令编译此演示:

g++ -g -c -o main.o test.cpp && g++ -g -o test main.o -std=c++11 -Wall -pedantic -lncurses

或者

LDLIBS=-lncurses make test

而不是显示

┏━┓
┗━┛

它显示这个:

M-b~T~OM-b~T~AM-b~T~S
M-b~T~WM-b~T~AM-b~T~[

实际屏幕图像

macOS 上的正常(所需)显示:

macOS 上的正常(所需)显示

Linux下显示异常:

Linux下显示异常

答案1

问题是您使用的是文字字符, , , , 而不是使用ncurses独立的符号。您应该使用ACS_??CORNERUpper/ Lower 和Left/ Right)和ACS_HLINE符号名称,并让ncurses我们弄清楚如何在终端上表示这些名称。

从此修改您的代码,

mvprintw(0,0,"┏━┓");
mvprintw(1,0,"┗━┛");

对此,

move(0,0); addch(ACS_ULCORNER); addch(ACS_HLINE); addch(ACS_URCORNER);
move(1,0); addch(ACS_LLCORNER); addch(ACS_HLINE); addch(ACS_LRCORNER);

应确保代码可移植地工作。我还将程序的结尾main()从简单的更改return 0为以下内容,以便在程序结束时正确重置终端:

endwin();
exit(0);

编译test.cpp并执行,

LDLIBS=-lncurses make test && ./test

有用的参考资料,排名不分先后:

答案2

在 MacOS 上,-lncursesncurses 的宽字符配置的链接通常由-lncursesw.该setlocale调用给出了不同的结果(正常字符与宽字符),并且框字符的文字字符串(UTF-8)的结果也不同。

进一步阅读:

  • 大于 128 的值要么是元字符(如果屏幕尚未初始化,或者使用 TRUE 参数调用了 meta(3x)),如MX符号,或显示为它们自己。在后一种情况下,这些值可能无法打印;这遵循 X/Open 规范。

根本问题是盒字符的 UTF-8 编码使用高于 128 的字节码,并且如果没有宽字符库中使用的区域设置支持,您将得到这样的结果 — 无法将字节重新组装成宽字符。特点。

其他一些平台也-lncurses作为 的别名出现-lncursesw,例如(注意注释)Arch Linux,其中有/usr/lib/ncurses.so

INPUT(-lncursesw)

另一条评论询问了“粗线”。这里有几点:

出于通常的原因,我只实现了粗线/双线的 WACS_xxx 符号:它是实验性的,并且仅对 Unicode 有用。

  • 这些符号记录在wadd_wch手册页。
  • 该功能不适用于 MacOS 的捆绑 ncurses,因为该版本(ncurses 5.7)比 ncurses 的更改早了大约一年。
  • 它不适用于 Linux 控制台终端(因为它依赖于只有 512 个字形的字体)。
  • 实际上外貌粗/双线的数量未指定(这取决于字体)。

答案3

问题是方框字符在 Linux 终端中无法正确显示。解决方案是您需要以不同的方式编译代码。

如果您正在使用printwncurses 或其他一些使用 ncurses 作为库的文本显示方法,那么这将适用于您。这取决于操作系统,因此如果您在 macOS 上,您将 -lncurses在编译时使用该标志(也根据@terdon,这也适用于架构Linux,但我还没有测试过),如果你使用的是 Linux(我只测试过 Debian),你需要使用该-lncursesw标志。

如果您想自动使您的代码交叉兼容此问题,请将其放入您的 makefile 中。

ifneq ($(OS),Windows_NT)
    UNAME_S := $(shell uname -s)
    ifeq ($(UNAME_S),Linux)
        NCURSES += -lncursesw
    endif
    ifeq ($(UNAME_S),Darwin)
        NCURSES += -lncurses
    endif
endif

相关内容