c语言 - mbstowcs() 在 Windows 中给出不正确的结果



我正在使用mbstowcs()将UTF-8编码的char*字符串转换为wchar_t*,后者将被馈送到_wfopen()中。但是,我总是从_wfopen()那里得到一个NULL指针,我发现问题来自mbstowcs()的结果。

我准备了以下示例并使用printf进行调试...

size_t out_size;
int requiredSize;
wchar_t *wc_filename;
char *utf8_filename = "C:/Users/xxxxxxxx/Desktop/xcexb1xcexb2xcexb3.stdf";
wchar_t *expected_output = L"C:/Users/xxxxxxxx/Desktop/αβγ.stdf";
printf("input: %s, length: %dn", utf8_filename, strlen(utf8_filename));
printf("correct out length is %dn", wcslen(expected_output));
// convertion start here
setlocale(LC_ALL, "C.UTF-8");
requiredSize = mbstowcs(NULL, utf8_filename, 0);
wc_filename = (wchar_t*)malloc( (requiredSize+1) * sizeof(wchar_t));
printf("requiredsize: %dn", requiredSize);
if (!wc_filename) {
// allocation fail
free(wc_filename);
return -1;
}
out_size = mbstowcs(wc_filename, utf8_filename, requiredSize + 1);
if (out_size == (size_t)(-1)) {
// convertion fail
free(wc_filename);
return -1;
}
printf("out_size: %d, wchar name: %lsn", out_size, wc_filename);
if (wcscmp (wc_filename, expected_output) != 0) {
printf("converted result is not correctn");
}
free(wc_filename);

控制台输出为:

input: C:/Users/xxxxxxxx/Desktop/αβγ.stdf, length: 37
correct out length is 34
requiredsize: 37
out_size: 37, wchar name: C:/Users/xxxxxxxx/Desktop/αβγ.stdf
converted result is not correct

只是不知道为什么expected_outputwc_filename的内容相同,但长度不同?我在这里做错了什么?

问题似乎出在您选择的区域设置名称上。替换以下内容:

setlocale(LC_ALL, "C.UTF-8");

有了这个:

setlocale(LC_ALL, "en_US.UTF-8");

修复了我的系统(Windows 10、MSVC、64 位版本)上的问题——至少,out_sizerequiredSize都是34的,并且没有显示"converted result is not correctn"消息。使用"en_GB。UTF-8"也有效。

我不确定 C 标准是否真的定义了什么是区域设置名称,但这个问题/答案可能会有所帮助:有效的区域设置名称。


注意:正如 Mgetz 的评论中所述,使用setlocale(LC_ALL, ".UTF-8");也有效——我想这将是要使用的最小和最便携的语言环境名称。

第二点:您可以通过将其返回值与NULL进行比较来检查setlocale调用是否成功。如果使用以下代码,则使用原始本地名称将给出错误消息(但如果删除前导"C",则不会:

if (setlocale(LC_ALL, "C.UTF-8") == NULL) {
printf("Error setting locale!n");
}

通用 CRT 支持 UTF-8,但 MSVCRT.DLL 不支持。 使用 MINGW 时,您需要链接到 UCRT。

最新更新