유니 코드 "Argv"를 사용할 수 있습니까?
-
12-09-2019 - |
문제
파일을 인수로 사용하는 응용 프로그램에 대한 작은 래퍼를 작성하고 있습니다.
래퍼는 유니 코드에 있어야하므로 캐릭터와 문자열에 WCHAR_T를 사용하고 있습니다. 이제 나는 문제가 있는데, 나는 wchar_t의 배열과 WCHAR_T 문자열에 프로그램의 인수를 가져야한다.
가능합니까? 나는 정의하고있다 main
기능
int main(int argc, char *argv[])
WCHAR_T를 사용해야합니까? argv
?
대단히 감사합니다. C에서 유니 코드를 올바르게 사용하는 방법에 대한 유용한 정보를 찾지 못하는 것 같습니다.
해결책
일반적으로 아니요. O/S에 따라 다르지만 C 표준은 'main ()'에 대한 인수는 'main (int argc, char ** argv)이어야하거나 동등한 것이기 때문에 char and wchar_t가 동일한 기본 유형이 아니라면 , 당신은 그것을 할 수 없습니다.
말하면, UTF-8 인수 문자열을 프로그램에 넣고 UTF-16 또는 UTF-32로 변환 한 다음 인생을 계속할 수 있습니다.
Mac (10.5.8, Leopard)에서는 다음과 같습니다.
Osiris JL: echo "ï€" | odx
0x0000: C3 AF E2 82 AC 0A ......
0x0006:
Osiris JL:
그것은 모두 UTF-8 인코딩되었습니다. (ODX는 HEX 덤프 프로그램입니다).
다른 팁
휴대용 코드는 지원하지 않습니다. Windows (예를 들어)는 사용을 지원합니다 wmain
대신에 main
,이 경우 ArgV는 넓은 문자로 전달됩니다.
Windows에서 사용할 수 있습니다 GetCommandLineW()
그리고 CommandLineToArgvW()
Argv 스타일을 생산합니다 wchar_t[]
앱이 유니 코드 용으로 컴파일되지 않더라도 배열.
어쨌든 창문에서는 a를 가질 수 있습니다 wmain()
유니 코드 빌드 용. 그래도 휴대용이 아닙니다. GCC 또는 UNIX/LINUX 플랫폼이 비슷한 것을 제공하는 경우에도 모릅니다.
Linux 환경이 UTF-8 인코딩을 사용한다고 가정하면 다음 코드는 C ++에서 쉽게 유니 코드 처리를 위해 프로그램을 준비합니다.
int main(int argc, char * argv[]) {
std::setlocale(LC_CTYPE, "");
// ...
}
다음으로, WCHAR_T 유형은 Linux에서 32 비트이므로 개별 유니 코드 코드 포인트를 보유 할 수 있으며 C ++ (문자 별 문자)의 클래식 스트링 처리에 WSTRING 유형을 안전하게 사용할 수 있습니다. 위의 SetLocale 호출을 사용하면 WCOUT에 삽입하면 출력이 자동으로 UTF-8으로 변환되고 WCIN에서 추출하면 UTF-8 입력이 UTF-32 (1 문자 = 1 코드 포인트)로 자동으로 변환됩니다. 남아있는 유일한 문제는 argv [i] 줄이 여전히 UTF-8 인코딩된다는 것입니다.
다음 함수를 사용하여 UTF-8을 UTF-32로 디코딩 할 수 있습니다. 입력 문자열이 손상되면 UTF-8 규칙이 파손 된 장소까지 올바르게 변환 된 문자를 반환합니다. 더 많은 오류보고가 필요한 경우 개선 할 수 있습니다. 그러나 ARGV 데이터의 경우 UTF-8이 올바른 것으로 가정 할 수 있습니다.
#define ARR_LEN(x) (sizeof(x)/sizeof(x[0]))
wstring Convert(const char * s) {
typedef unsigned char byte;
struct Level {
byte Head, Data, Null;
Level(byte h, byte d) {
Head = h; // the head shifted to the right
Data = d; // number of data bits
Null = h << d; // encoded byte with zero data bits
}
bool encoded(byte b) { return b>>Data == Head; }
}; // struct Level
Level lev[] = {
Level(2, 6),
Level(6, 5),
Level(14, 4),
Level(30, 3),
Level(62, 2),
Level(126, 1)
};
wchar_t wc = 0;
const char * p = s;
wstring result;
while (*p != 0) {
byte b = *p++;
if (b>>7 == 0) { // deal with ASCII
wc = b;
result.push_back(wc);
continue;
} // ASCII
bool found = false;
for (int i = 1; i < ARR_LEN(lev); ++i) {
if (lev[i].encoded(b)) {
wc = b ^ lev[i].Null; // remove the head
wc <<= lev[0].Data * i;
for (int j = i; j > 0; --j) { // trailing bytes
if (*p == 0) return result; // unexpected
b = *p++;
if (!lev[0].encoded(b)) // encoding corrupted
return result;
wchar_t tmp = b ^ lev[0].Null;
wc |= tmp << lev[0].Data*(j-1);
} // trailing bytes
result.push_back(wc);
found = true;
break;
} // lev[i]
} // for lev
if (!found) return result; // encoding incorrect
} // while
return result;
} // wstring Convert
Windows에서는 tchar.h 및 _tmain을 사용할 수 있습니다. _unicode 기호가 컴파일 시간에 정의되거나 그렇지 않으면 주된 경우 wmain으로 바뀝니다. TCHA * argv []는 유니 코드가 정의 된 경우 WCHAR * argv []로 유사하게 확장되고, 그렇지 않은 경우 char * argv [].
주요 방법 작업 크로스 플랫폼을 원한다면 자신의 매크로를 동일한 효과로 정의 할 수 있습니다.
TCHAR.H에는 WCHAR과 Char 간의 전환을위한 여러 편의 매크로가 포함되어 있습니다.