我确实在文件系统中搜索不可移植的名称中的字符。为此,请使用 mbtowc 函数检查每个字符。
在 OSX 上我尝试过:
//在 OSX 上
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
string s1 = "Ä";
size_t len = s1.length(); // will be 2, ok
const char* s1c = s1.c_str(); // 0xC3 0x84 0x00, ok
char a = s1[0]; // 0xc3, ok
char b = s1[1]; // 0x84, ok
mbtowc(NULL,NULL,0); // reset
wchar_t wc;
int mb_len = mbtowc(&wc,s1c,len); // mb_len = 1, wc=0xc3 00 00 00
// why only one byte?
// how can i get the right Wchar???
char mb2[10];
int mblen2 = wctomb(mb2,wc); // mblen2 = 1; mb2 = 0xC3
string s2 = string(mb2); // len = 1 only 0xC3
return 0;
}
为什么 mbtows 对于所有字符只返回 1?
赫里伯特
最佳答案
您的程序在 C 语言环境中启动,它将字符串视为 ASCII(或未指定的 ASCII 兼容 8 位编码)。因此,mbtowc()
只是将字符串中的第一个字节复制到 wchar_t
中。您需要使用使用 UTF-8 的语言环境调用 setlocale(LC_CTYPE, locale)
,因为您的源代码是用 UTF-8 编码的,因此字符串常量也是如此。
setlocale(LC_CTYPE, "")
使用用户当前的区域设置,因此如果您要读取用户提供的文件,这是合适的;但是,如果有人尝试在不使用 UTF-8 语言环境的计算机上运行您的程序,您的示例可能会失败。您可以改为使用 setlocale(LC_CTYPE, "UTF-8")
,这是一个始终使用 UTF-8 的区域设置(我不相信它是标准化的,但它至少存在于我的 Mac 操作系统上) X 和 Linux 盒子)。
这是一个示例(这次是纯 C 语言,而不是 C++,以使其更简单一些)。我添加了一些 printfs 来显示发生了什么。它在调用 setlocale()
之前和之后运行相同的 mbtowc()
。
#include <stdio.h>
#include <locale.h>
#include <string.h>
#include <stdlib.h>
void test_mbtowc(char *s) {
size_t len = strlen(s);
wchar_t wc;
mbtowc(NULL,NULL,0);
int mb_len = mbtowc(&wc,s,len);
printf("%d, %08x\n", mb_len, wc);
}
int main()
{
char *s = "Ä";
printf("%02hhx %02hhx %02hhx\n", s[0], s[1], s[2]);
test_mbtowc(s);
setlocale(LC_CTYPE, "UTF-8");
test_mbtowc(s);
return 0;
}
这是输出。如您所见,我们的字符串采用 UTF-8 编码。对 mbtowc 的第一次调用只是简单地复制第一个字节; mb_len
是 1
,我们得到 c3
作为结果。第二个给出了 mb_len
为 2,以及 c4
,即 WC
中 Ä
的 Unicode 代码点。
c3 84 00
1, 000000c3
2, 000000c4
关于c++ - mbtowc 在 osx 上始终返回一个字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13570891/