我正在为使用文件作为参数的应用程序编写一个小包装。是否可以使用Unicode“argv”?
包装需要在Unicode中,所以我使用wchar_t作为我有的字符和字符串。现在我发现自己遇到了问题,我需要将程序的参数放在wchar_t和wchar_t字符串中。
可能吗?我定义main
功能
int main(int argc, char *argv[])
我应该使用wchar_t的对argv
?
非常感谢你,我似乎无法找到如何反正使用Unicode正确的C.
我正在为使用文件作为参数的应用程序编写一个小包装。是否可以使用Unicode“argv”?
包装需要在Unicode中,所以我使用wchar_t作为我有的字符和字符串。现在我发现自己遇到了问题,我需要将程序的参数放在wchar_t和wchar_t字符串中。
可能吗?我定义main
功能
int main(int argc, char *argv[])
我应该使用wchar_t的对argv
?
非常感谢你,我似乎无法找到如何反正使用Unicode正确的C.
一般来说,没有。它将取决于O/S,但是C标准认为'main()'的参数必须是'main(int argc,char ** argv)'或等价的,所以除非char和wchar_t是相同的基本类型,你不能这样做。话虽如此,你可以在程序中获得UTF-8参数字符串,将它们转换为UTF-16或UTF-32,然后继续生活。
在Mac(10.5.8,豹),我得到:
Osiris JL: echo "ï€" | odx
0x0000: C3 AF E2 82 AC 0A ......
0x0006:
Osiris JL:
这就是UTF-8编码。 (odx是一个十六进制转储程序)。
参见:Why is it that UTF-8 encoding is used when interacting with a UNIX/Linux environment
在Windows上有用的信息,你可以有一个UNICODE构建wmain()
。虽然不便携。我不知道如果GCC或Unix/Linux平台提供类似的东西。
便携式代码不支持它。 Windows(例如)支持使用wmain
而不是main
,在这种情况下,argv作为宽字符传递。
在Windows上,你可以使用TCHAR.H和_tmain,这将变成wmain如果_UNICODE符号在编译时定义,或以其他方式为主。如果定义了unicode,则TCHAR * argv []将类似地扩展为WCHAR * argv [];如果不是,则将char * argv []扩展为。
如果你想让你的主要方法跨平台工作,你可以定义自己的宏来达到同样的效果。
TCHAR.h包含许多用于在wchar和char之间进行转换的便利宏。
假设你的Linux环境使用UTF-8编码然后将以下代码将准备程序,方便的Unicode治疗在C++:
int main(int argc, char * argv[]) {
std::setlocale(LC_CTYPE, "");
// ...
}
接着,wchar_t的类型是在Linux 32位,这意味着它可以保存单独的Unicode代码点,并且可以安全地使用wstring类型在C++中进行经典字符串处理(逐字符)。通过上面的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上,你可以使用GetCommandLineW()
和CommandLineToArgvW()
产生的argv的风格wchar_t[]
阵列,即使应用程序未编译的Unicode 。