2013-06-05 3 views
7

iostream을 사용하여 Linux 터미널에서 일부 유니 코드 문자를 인쇄해야합니다. 이상한 일들이 일어난다. 내가 쓸 때 :C++ 유니 코드 문자 인쇄

cout << "\u2780"; 

를 내가 얻을 : 을 거의 정확하게 내가 원하는이다. 그러나 내가 쓰는 경우 :

cout << '\u2780'; 

나는 14851712를 얻는다.

문제는 컴파일 타임에 인쇄 할 정확한 문자를 모른다는 것입니다. 그러므로 나는 다음과 같이하고 싶다 :

int x; 
// some calculations... 
cout << (char)('\u2780' + x); 

어느 것이 인쇄되는 : . 대신 wcout 또는 wchar_t을 사용하면 작동하지 않습니다. 올바른 인쇄 방법은 무엇입니까?

인터넷에서 발견 한 바로는 데비안 Wheezy 저장소에서 바로 g ++ 4.7.2 컴파일러를 사용하는 것이 중요해 보입니다.

+0

는'L' 연산자 wchar_t를 사용하고 있습니까? 가능한 경우 전체 코드 게시 또는 [sscce.org] (SSCCE) – pinkpanther

+0

유니 코드 인코딩을 사용하지 않으려면 테이블을 사용하여 문자열을 추가하는 대신 가능한 'x'값으로 매핑 할 수 있습니다. – dyp

+0

[C++에서 유니 코드 문자를 인쇄하는 방법] 가능한 복제본 (http://stackoverflow.com/questions/12015571/how-to-print-unicode-character-in-c) –

답변

6

유니 코드 문자 \u2780char 데이터 형식의 범위를 벗어납니다. 당신은 그것에 대해 당신에게이 컴파일러 경고를 받았어야 :

test.cpp:6:13: warning: multi-character character constant [-Wmultichar] 

것은 당신이 U + 2780 같은 문자로 작업 할 경우 (적어도 내 g ++ 4.7.3를 제공합니다) 당신이해야 하나의 단위로 widechar 데이터 유형 wchar_t을 사용하거나 C++ 11, char32_t 또는 char16_t으로 작업 할 수 있다면 충분히 운이 좋다면 사용할 수 있습니다. 하나의 16 비트 단위로 모든 유니 코드 문자를 나타 내기에는 충분하지 않습니다.

이것이 작동하지 않는다면 기본 "C"로켈이 비 ASCII 출력을 지원하지 않기 때문일 수 있습니다. 이 문제를 해결하려면 프로그램 시작시 setlocale으로 전화하십시오. 그런 식으로 출력 할 수 있습니다 사용자의 로켈이 지원하는 문자의 전체 범위 (또는 사용하는 모든 문자를 지원하지 않을 수도있는)

#include <clocale> 
#include <iostream> 

using namespace std; 

int main() { 
    setlocale(LC_ALL, ""); 
    wcout << L'\u2780'; 
    return 0; 
} 
+0

물론 같은 문제가있을 수 있습니다 'sizeof (wchar_t) <4 '이면 다른 문자 (SMP). 'char16_t' 또는'char32_t'btw를 사용하는 것이 좋습니다. – dyp

+2

추가적으로 인코딩 접두사'L'에'U8 ','char16_t'에'u','char32_t'에'U'가 있습니다. – Appleshell

+0

''''을 로케일 이름으로 전달할 때'setlocale'은 사용자가 선호하는 로케일을 설정하는데, 반드시 유니 코드 로켈 일 필요는 없습니다. – dyp

4

당신은 쓸 때

cout << "\u2780"; 

컴파일러는 \ u2780을 실행 문자 집합에서 해당 문자의 적절한 인코딩으로 변환합니다. 아마 UTF-8이기 때문에 문자열은 4 바이트 (문자의 경우 3 개, 널 종결 자의 경우 1 개)를 갖게됩니다.

런타임시 문자를 생성하려면 런타임시 컴파일러가 컴파일시에 수행하는 UTF-8로 동일한 변환을 수행 할 방법이 필요합니다.


C++ (11)는 그러나 된 libstdC++, GCC와 함께 제공되는 표준 라이브러리 구현, 아직 (GCC 4.8로)를 구현 주위를 확보하지 있으며,이 작업을 수행 할 수있는 편리한 wstring_convert 템플릿과 codecvt 측면을 제공합니다 . 다음은 이러한 기능을 사용하는 방법을 보여줍니다. 그러나 다른 표준 라이브러리 구현을 사용하거나 libstdC++가이를 구현할 때까지 기다려야합니다.

#include <codecvt> 

int main() { 
    char32_t base = U'\u2780'; 

    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert; 
    std::cout << convert.to_bytes(base + 5) << '\n'; 
} 

사용할 수있는 다른 UTF-8을 만드는 방법을 사용할 수도 있습니다.예를 들어, iconv, ICU 및 pre-C++ 11 codecvt_byname 패싯의 수동 사용은 모두 작동합니다. (즉, 코드가 wstring_convert 허용하는 간단한 코드보다 더 복잡 것 때문에 이들의 예를 표시하지 않습니다.)


문자의 소수를 위해 일하는 것이 대안의 배열을 생성하는 것입니다 문자열은 리터럴을 사용합니다.

char const *special_character[] = { "\u2780", "\u2781", "\u2782", 
    "\u2783", "\u2784", "\u2785", "\u2786", "\u2787", "\u2788", "\u2789" }; 

std::cout << special_character[i] << '\n'; 
0

프로그램 인해 정수를 출력 C++ 11 §2.14.3/1

위해 다중 문자 또는 단일 문자-C가 함유으로 표현할 수없는 통상의 캐릭터 문자 조건부 지원, 유형 int, 구현 정의 값을가집니다.

실행 문자 집합은 char이 표현할 수있는 즉 ASCII입니다.

14851712 또는 U + 2780의 UTF-8 표현 인 16 진수 e29e80입니다. int에 멀티 바이트 인코딩 인 UTF-8을 넣는 것은 당황 스럽지만 어쨌든 "조건부로 지원되는 구현 정의"기능에서 얻은 것입니다.

UTF-32 값을 얻으려면 U'\u2780'을 사용하십시오. 첫 번째 Uchar32_t 유형 및 UTF-32 인코딩 (즉, 최대 31 비트이지만 서로 게이트 쌍 없음)을 지정합니다. 두 번째 \u은 코드 포인트가 들어있는 범용 문자 이름을 지정합니다. wcout과 호환 될 수있는 값을 얻으려면 L'\u2780'을 사용하십시오.하지만 반드시 유니 코드 런타임 값을 사용하거나 2 바이트 이상의 저장 공간을 사용할 필요는 없습니다.

유니 코드 코드 포인트를 안정적으로 조작하고 인쇄하는 방법에 대해서는 다른 답변에서 언급했듯이 C++ 표준은 아직 그다지 익숙하지 않았습니다. Joni의 답변이 가장 좋은 방법이지만, 컴파일러와 사용자 환경이 동일한 로케일을 사용하고 있다고 가정합니다. 이는 종종 사실이 아닙니다.

u8"\u2780"을 사용하여 소스에서 UTF-8 문자열을 지정하고 std::locale::global(std::locale("en_US.UTF-8"));과 같은 것을 사용하여 런타임 환경을 UTF-8로 강제 설정할 수도 있습니다. 하지만 여전히 거친 부분이 있습니다. Joni는 C++ 인터페이스 std::locale::global에서 <locale>까지 의 C 인터페이스 std::setlocale을 사용하는 것이 좋습니다. 이는 OS X 및 다른 플랫폼의 GCC에서 깨진 C++ 인터페이스에 대한 해결 방법입니다. 이 문제는 플랫폼에 민감하므로 Linux 배포판이 자신의 GCC 패키지에 패치를 설치했을 수도 있습니다.

리눅스에서
+0

컴파일러가 "U가 범위에서 선언되지 않았습니다"라고 촉구하기 때문에 당신이나 내가 아마 놓친 것 같습니다. – Sventimir

+0

@Sventimir 분명히 GCC 4.7.2에서는 지원되지 않지만 C++ 11 표준의 일부입니다. 그냥'Lxxxx'로 가라. 리눅스에서는 본질적으로 같은 것을해야합니다. – Potatoswatter

+0

'gcc --std = C++ 11' 호출로 C++ 11 지원을 추가해도 작동하지 않습니다. 이제 컴파일되지만 char 자체가 아닌 char (10112)의 십진 값을 인쇄합니다. – Sventimir

0

, 내가 가장 순진 방법으로 직접 유니 코드를 인쇄 성공적이었다 :

std::cout << "ΐ , Α, Β, Γ, Δ, ,Θ , Λ, Ξ, ... ±, ... etc"