C 프로그래밍:유니코드를 프로그래밍하는 방법?
엄격한 유니코드 프로그래밍을 하려면 어떤 전제조건이 필요한가?
내 코드가 다음을 사용하지 않아야 함을 의미하는가?char
어느 곳에서나 사용할 수 있는 기능을 사용할 수 있는 유형wint_t
, 그리고wchar_t
?
그리고 이 시나리오에서 멀티바이트 캐릭터 시퀀스가 수행하는 역할은 무엇인가?
C99 또는 이전
C표준(C99)은 와이드 문자와 멀티바이트 문자를 제공하지만, 그 와이드 문자들이 무엇을 담을 수 있는지에 대한 보장이 없기 때문에 그 가치는 다소 제한적이다.주어진 구현에 대해, 그것들은 유용한 지원을 제공하지만, 만약 당신의 코드가 구현들 사이를 이동할 수 있어야 한다면, 그것들이 유용할 것이라는 보장이 불충분하다.
따라서, 한스 반 에크가 제안한 접근방식(ICU - 유니코드를 위한 국제 구성요소 - 라이브러리 주위에 포장지를 작성하는 것)은 건전한 IMO이다.
UTF-8 인코딩은 많은 장점을 가지고 있는데, 그 중 하나는 (예를 들어 데이터를 잘라냄으로써) 망치지 않으면 UTF-8 인코딩의 복잡성을 완전히 인식하지 못하는 함수에 의해 복사될 수 있다는 것이다.이것은 분명히 의 경우는 아니다.wchar_t
.
전체 유니코드는 21비트 형식이다.즉, 유니코드는 U+0000에서 U+10FFFFF까지의 코드 포인트를 예약한다.
UTF-8, UTF-16 및 UTF-32 형식(여기서 UTF는 유니코드 변환 포맷을 나타낸다 - 유니코드 참조)에 관한 유용한 사항 중 하나는 정보의 손실 없이 세 가지 표현 사이에서 변환할 수 있다는 것이다.각각은 다른 사람들이 대표할 수 있는 모든 것을 대표할 수 있다.UTF-8과 UTF-16은 모두 멀티바이트 형식이다.
UTF-8은 멀티바이트 형식으로 잘 알려져 있는데, 문자열의 어느 지점에서 시작해도 안정적으로 문자열의 문자 시작을 찾을 수 있는 세심한 구조를 갖추고 있다.단일 바이트 문자는 하이비트를 0으로 설정한다.멀티바이트 문자는 비트 패턴 110, 1110 또는 11110(2바이트, 3바이트 또는 4바이트 문자) 중 하나로 시작하는 첫 번째 문자를 가지며, 후속 바이트는 항상 10으로 시작한다.연속 문자는 항상 0x80 범위에 있다.0xBF. UTF-8 문자는 가능한 최소 형식으로 표시되어야 한다는 규칙이 있다.이러한 규칙의 한 가지 결과는 바이트 0xC0과 0xC1 (또한 0xF5..0xFF)이 유효한 UTF-8 데이터에 나타날 수 없다는 것이다.
U+0000 .. U+007F 1 byte 0xxx xxxx
U+0080 .. U+07FF 2 bytes 110x xxxx 10xx xxxx
U+0800 .. U+FFFF 3 bytes 1110 xxxx 10xx xxxx 10xx xxxx
U+10000 .. U+10FFFF 4 bytes 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
원래 유니코드는 16비트 코드 세트가 되어 모든 것이 16비트 코드 공간에 맞기를 바랐다.불행히도 현실 세계는 더 복잡하고, 현재의 21비트 인코딩으로 확장되어야 했다.
따라서 UTF-16은 유니코드 코드가 U+0000인 문자를 의미하는 '기본 다국어 평면'을 위한 단일 단위(16비트 워드) 코드 세트다.U+FFFFF. 그러나 이 범위를 벗어나는 문자에 대해 두 단위(32비트)를 사용한다.따라서 UTF-16 인코딩과 함께 작동하는 코드는 UTF-8이 반드시 해야 하는 것처럼 가변 폭 인코딩을 처리할 수 있어야 한다.이중 단위 문자의 코드는 대리모라고 불린다.
대리인은 UTF-16에서 쌍체 코드 단위의 선행 및 후행 값으로 예약된 유니코드 값의 두 가지 특수 범위에서 코드 포인트. 선행(high)이라고도 하며 대리인은 U+D800에서 U+DBFF로, 후행(drailing) 또는 하행(low) 대리인은 U+DC00에서 U+DFFF로 한다.그들은 직접 등장인물을 나타내지 않고 단지 한 쌍으로만 표현하기 때문에 대리모라고 불린다.
물론 UTF-32는 단일 스토리지 단위로 모든 유니코드 코드 포인트를 인코딩할 수 있다.계산에는 효율적이지만 저장에는 효율적이지 않다.
당신은 ICU와 유니코드 웹사이트에서 더 많은 정보를 찾을 수 있다.
C11과<uchar.h>
C11 표준은 규칙을 변경했지만, 지금도(2017년 중반) 모든 구현이 그 변화를 따라잡지는 못했다.C11 표준은 유니코드 지원에 대한 변경사항을 다음과 같이 요약한다.
- 유니코드 문자 및 문자열(
<uchar.h>
) (원래 ISO/IEC TR 19769:2004에 명시됨)
다음은 기능에 대한 최소한의 개요다.규격에는 다음이 포함된다.
6.4.3 범용 문자 이름
구문
범용 문자 이름:
\u
육각형의
\U
육각형 육각형
16진수:
16진수 16진수 16진수 16진수 16진수7.28 유니코드 유틸리티
<uchar.h>
머리글
<uchar.h>
유니코드 문자를 조작하는 유형과 함수를 선언한다.선언된 유형은 다음과 같다.
mbstate_t
(7.29.1에 수록됨) 및size_t
(7.19절 참조);char16_t
16비트 문자에 사용되는 부호 없는 정수 유형이며, 동일한 유형이다.
uint_least16_t
(7.20.1.2에 수록됨) 및char32_t
이는 32비트 문자에 사용되는 부호 없는 정수 유형이며 동일한 유형이다.
uint_least32_t
(7.20.1.2에도 설명되어 있다.)
(교차 참조의 변환:<stddef.h>
규정하다size_t
,<wchar.h>
규정하다mbstate_t
, 그리고<stdint.h>
규정하다uint_least16_t
, 그리고uint_least32_t
.) The<uchar.h>
헤더는 또한 최소의 (변환 가능) 변환 함수 세트를 정의한다.
mbrtoc16()
c16rtomb()
mbrtoc32()
c32rtomb()
를 사용하여 식별자에 유니코드 문자를 사용할 수 있는 규칙이 있다.\unnnn
또는\U00nnnnnn
명언식별자에서 그러한 문자에 대한 지원을 적극적으로 활성화해야 할 수도 있다.예를 들어, GCC는-fextended-identifiers
이를 식별자로 허용한다.
하나의 플랫폼을 제외하고 macOS Sierra(10.12.5)는 지원하지 않는다는 점에 유의하십시오.<uchar.h>
.
이것은 "엄격한 유니코드 프로그래밍"에 관한 것이 아니라 실제 경험에 관한 것이라는 점에 유의하십시오.
우리 회사에서 한 일은 IBM의 ICU 라이브러리 주변에 포장지 라이브러리를 만드는 것이었습니다.래퍼 라이브러리는 UTF-8 인터페이스가 있어 ICU에 전화할 필요가 있을 때 UTF-16으로 전환된다.우리 같은 경우 성능 적중 걱정을 크게 하지 않았다.성능이 문제가 되자 UTF-16 인터페이스(자체 데이터 유형을 사용)도 공급했다.
어떤 경우에는 특정 문제에 대해 인지해야 하지만 애플리케이션은 대체로 그대로 유지될 수 있다(차어 사용).예를 들어, strncpy() 대신 우리는 UTF-8 시퀀스를 차단하지 않는 포장지를 사용한다.우리의 경우 이 정도면 충분하지만 캐릭터 조합에 대한 점검도 고려할 수 있다.우리는 또한 코드의 수, 제자 수 등을 세는 포장지도 가지고 있다.
다른 시스템과 인터페이스할 때, 우리는 때때로 사용자 지정 문자 작성을 해야 하기 때문에, 당신은 그 곳에서 약간의 융통성이 필요할 수 있다.
우리는 wchar_t를 사용하지 않는다.ICU를 사용하면 휴대성에서 예상치 못한 문제가 발생하지 않는다(물론 다른 예상하지 못한 문제:-).
내가 아는 바로는 wchar_t는 (이 wiki 기사에서 알 수 있듯이) 구현에 의존한다.그리고 유니코드가 아니다.
이 FAQ는 풍부한 정보다.그 페이지와 조엘 스폴스키의 이 기사 사이에는 시작이 좋을 것이다.
내가 내린 결론은 다음과 같다.
wchar_t
Windows에서는 16비트지만 다른 플랫폼에서는 16비트라고 할 수 없다.나는 그것이 윈도우에 필요한 악이라고 생각하지만, 아마도 다른 곳에서는 피할 수 있을 것이다.Windows(윈도우)에서 중요한 이유는 ASC가 아닌 파일이 필요하기 때문이다.이름의 II 문자(함수의 W 버전과 함께)Windows API가 필요한 경우
wchar_t
문자열은 UTF-16 인코딩을 예상한다.또한 이는 UCS-2와 다르다는 점에 유의하십시오. 대리모 쌍에 유의하십시오.이 시험 페이지에는 계몽적인 시험들이 있다.Windows에서 프로그래밍하는 경우
fopen()
,fread()
,fwrite()
, 등등 그들은 단지 취하기만 하기 때문에char *
그리고 UTF-8 인코딩을 이해하지 못한다.휴대성을 고통스럽게 한다.
나는 어떤 표준적인 도서관 구현도 믿지 않을 것이다.나만의 유니코드 타입을 굴려봐.
#include <windows.h>
typedef unsigned char utf8_t;
typedef unsigned short utf16_t;
typedef unsigned long utf32_t;
int main ( int argc, char *argv[] )
{
int msgBoxId;
utf16_t lpText[] = { 0x03B1, 0x0009, 0x03B2, 0x0009, 0x03B3, 0x0009, 0x03B4, 0x0000 };
utf16_t lpCaption[] = L"Greek Characters";
unsigned int uType = MB_OK;
msgBoxId = MessageBoxW( NULL, lpText, lpCaption, uType );
return 0;
}
가장 중요한 것은 항상 텍스트와 이진 데이터를 명확히 구분하는 것이다.Python 3.x vs. 또는 SQL의 모델을 따르십시오.TEXT
대BLOB
.
불행하게도 C는 이 문제를char
ASCII 문자 및int_least8_t
. 당신은 다음과 같은 것을 하고 싶을 것이다.
typedef char UTF8; // for code units of UTF-8 strings
typedef unsigned char BYTE; // for binary data
UTF-16과 UTF-32 코드 단위에 대한 타이프도 원할 수 있지만, 이는 다음 부호화 때문에 더 복잡하다.wchar_t
정의되지 않음.그냥 전처리기만 하면 돼#if
s. C와 C++0x의 일부 유용한 매크로:
__STDC_UTF_16__
— 정의된 경우 유형_Char16_t
존재하며 UTF-16이다.__STDC_UTF_32__
— 정의된 경우 유형_Char32_t
존재하며 UTF-32이다.__STDC_ISO_10646__
— 정의된 경우wchar_t
UTF-32이다._WIN32
— Windows에서는wchar_t
UTF-16이 기준치를 어긴다고 해도WCHAR_MAX
— 의 크기를 결정하는 데 사용할 수 있음wchar_t
그러나 OS가 유니코드를 나타내기 위해 그것을 사용하는지는 아니다.
이것은 내 코드가 char type을 어디에서도 사용하지 않아야 하며 wint_t와 wchar_t를 처리할 수 있는 기능을 사용해야 함을 의미하는가?
참고 항목:
No. UTF-8은 완벽하게 유효한 유니코드 인코딩으로char*
줄들프로그램이 비 ASC에 투명할 경우 이점이 있음II 바이트(예: 작용하는 라인 엔딩 컨버터)\r
, 그리고\n
다른 문자는 변경하지 않고 통과), 변경하지 마십시오!
UTF-8로 간다면 그 모든 가정을 바꿀 필요가 있을 것이다.char
= 문자(예: 호출하지 않음)toupper
반복적으로) 또는char
= 화면 열(예: 텍스트 래핑)
UTF-32로 가면 고정 너비 문자(단, 고정 너비 그래프가 아니라 모든 문자열의 유형을 변경해야 함)의 단순성을 갖게 된다.
UTF-16을 사용할 경우 고정 너비 문자 가정과 8비트 코드 단위를 모두 폐기해야 하므로 단일 바이트 인코딩에서 업그레이드 경로가 가장 어렵다.
적극적으로 피하기를 권하고 싶다. wchar_t
크로스 플랫폼이 아니기 때문에: 때로는 UTF-32, 때로는 UTF-16, 때로는 유니코드 이전 동아시아 인코딩.사용하는 것을 추천한다.typedefs
더 중요한 것은, 피하라.
엄격한 유니코드 프로그래밍을 수행하려면:
- 유니코드를 인식하는 문자열 API만 사용(NOT)
strlen
,strcpy
... 하지만 그들의 가장 넓은 상대는wstrlen
,wsstrcpy
, ...) - 텍스트 블록을 처리할 때 유니코드 문자(utf-7, utf-8, utf-16, usc-2, ...)를 손실 없이 저장할 수 있는 인코딩을 사용하십시오.
- OS 기본 문자 집합이 유니코드 호환되는지 확인(예: utf-8)
- 유니코드 호환 글꼴 사용(예: arial_unicode)
멀티바이트 문자 시퀀스(Multi-byte 문자 시퀀스)는 UTF-16 인코딩(일반적으로 사용되는 인코딩)을 미리 예약하는 인코딩이다.wchar_t
) 그리고 내가 보기엔 그것은 오히려 윈도우 전용인 것 같다.
들어본 적이 없다.wint_t
.
당신은 기본적으로 기억 속의 끈을wchar_t
철자 대신 배열어떤 종류의 I/O(예: 파일 읽기/쓰기)를 할 때, 당신은 UTF-8을 사용하여 인코딩/디코딩할 수 있는데, 이 인코딩이 아마도 가장 일반적인 인코딩일 것이다.RFC만 검색하면 돼따라서 인메모리에서는 어떤 것도 멀티바이트가 되어서는 안 된다.하나wchar_t
한 글자를 나타내다그러나 직렬화를 하려면 UTF-8과 같은 어떤 문자로 인코딩해야 하는데, 여기서 어떤 문자는 다중 바이트로 표현된다.
당신은 또한 새로운 버전의strcmp
넓은 캐릭터 끈을 위한 등, 그러나 이것은 큰 문제가 아니다.가장 큰 문제는 char 배열만 허용하는 라이브러리/기존 코드와의 상호접속이 될 것이다.
그리고 에 관한 한sizeof(wchar_t)
(정확하게 하려면 4바이트가 필요할 것이다) 항상 더 큰 크기로 재정의할 수 있다.typedef
/macro
필요하면 해킹을 해
참조URL: https://stackoverflow.com/questions/526430/c-programming-how-to-program-for-unicode
'IT이야기' 카테고리의 다른 글
현재 구성 요소와 동일한 수준이 아닌 다른 구성 요소에서 $ref 액세스 (0) | 2022.05.12 |
---|---|
Global Guard 내부 모의 상점 게이터가 작동하지 않음 (0) | 2022.05.12 |
Java에서 메서드를 분리하거나 종료하는 방법 (0) | 2022.05.11 |
스프링 부트에서 필터 클래스를 추가하려면 어떻게 해야 하는가? (0) | 2022.05.11 |
값을 기준으로 해시맵 정렬 (0) | 2022.05.11 |