Linux 터미널에서 상자 문자가 올바르게 표시되지 않습니다.

Linux 터미널에서 상자 문자가 올바르게 표시되지 않습니다.

방금 상자 문자를 사용하여 정보를 표시하는 C++] 프로그램을 작성했습니다. 터미널 앱을 사용하여 macOS에서 프로그램을 실행했는데 제대로 작동했습니다.

내가 전환 할 때데비안 리눅스동일한 코드를 사용하고 다시 컴파일했더니 이 문제가 발생했습니다! 온라인에서 답변을 검색했지만 이 질문과 관련된 답변을 찾지 못했습니다. 나는 이것을 두 가지 모두로 테스트했습니다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

문제는 별도의 기호를 사용하는 대신 리터럴 문자 , , , , 를 사용하고 있다는 것입니다 . ( pper/ ower 및 eft/ ight) 및 기호 이름을 사용해야 하며 터미널에서 이러한 이름을 나타내는 방법을 알아봅시다.ncursesACS_??CORNERULLRACS_HLINEncurses

여기에서 코드를 수정하세요.

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에서 -lncurses와이드 문자 구성을 위한 ncurses에 대한 링크는 일반적으로 로 제공됩니다 -lncursesw. setlocale호출은 다른 결과(일반 문자 대 와이드 문자)를 제공했으며 상자 문자 리터럴 문자열(UTF-8)에 대한 결과도 달랐습니다.

추가 자료:

  • 128보다 큰 값은 다음과 같은 메타 문자입니다(화면이 초기화되지 않았거나 메타(3x)가 TRUE 인수로 호출된 경우).MX기호 또는 그 자체로 나타납니다. 후자의 경우 값이 인쇄되지 않을 수 있습니다. 이는 X/Open 사양을 따릅니다.

근본적인 문제는 상자 문자의 UTF-8 인코딩이 128보다 높은 바이트코드를 사용하고 와이드 문자 라이브러리에서 사용되는 로케일 지원이 없으면 바이트를 와이드 문자로 재조립할 수 없다는 결과를 얻게 된다는 것입니다. 특징.

다음을 포함하는 Arch Linux(참고 참고)와 같은 일부 다른 플랫폼도 -lncurses의 별칭으로 표시됩니다 .-lncursesw/usr/lib/ncurses.so

INPUT(-lncursesw)

또 다른 댓글에서는 "두꺼운 선"에 대해 질문했습니다. 다음은 몇 가지 사항입니다.

저는 일반적인 이유로 두꺼운/이중선 WACS_xxx 표기법만 구현했습니다. 이는 실험적이며 유니코드에만 유용합니다.

  • 이 기호는 다음과 같이 기록됩니다.wadd_wch맨 페이지.
  • 이 기능은 MacOS용 번들 ncurses에서는 작동하지 않습니다. 해당 버전(ncurses 5.7)이 ncurses 변경 사항보다 약 1년 앞서기 때문입니다.
  • Linux 콘솔 터미널에서는 작동하지 않습니다(512개의 글리프만 있는 글꼴에 의존하기 때문입니다).
  • 실제로모습굵은 선/이중 선의 수는 지정되지 않습니다(글꼴에 따라 다름).

답변3

문제는 Linux 터미널에서 상자 문자가 올바르게 표시되지 않는다는 것입니다. 해결책은 코드를 다르게 컴파일해야 한다는 것입니다.

ncurses를 라이브러리로 사용하여 ncurses나 다른 텍스트 표시 방법을 사용하는 경우 printw이것이 적용됩니다. 이는 OS에 따라 다르므로 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

관련 정보