提问人:Calmarius 提问时间:3/23/2023 最后编辑:Calmarius 更新时间:3/24/2023 访问量:39
当我使用 newlocale() 和 uselocale() 而不是 setlocale() 时,mbrtowc() 无法转换
mbrtowc() fails to convert when I'm using newlocale() and uselocale() instead of setlocale()
问:
我想转换 UTF-8 字符串宽字符表示以使用代码点。为此,我在 Linux 上调用 uselocale() 以仅更改当前线程的区域设置。但出于某种原因,它似乎没有达到我的期望。这是一个最小的程序:
#define _XOPEN_SOURCE 700
#include <locale.h>
#include <wchar.h>
#include <stdio.h>
#include <assert.h>
int main()
{
locale_t loc = newlocale(LC_ALL, "en_US.UTF-8", (locale_t)0);
assert(loc);
locale_t prevLocale = uselocale(loc);
assert(prevLocale);
wchar_t res;
char src[] = "á";
mbstate_t mbs = {0};
int v = (int)mbrtowc(&res, src, sizeof(src), &mbs);
printf("%d\n", v);
perror("Failed to convert char");
return 0;
}
我希望它能够拾取 UTF-8 语言环境并转换字符,但是当我运行它时,我得到:
-1
Failed to convert char: Invalid or incomplete multibyte or wide character
源文件编码为 UTF-8。所以这不是问题。
如果我改为调用进程范围,如下所示:setlocale
#define _XOPEN_SOURCE 700
#include <locale.h>
#include <wchar.h>
#include <stdio.h>
#include <assert.h>
int main()
{
setlocale(LC_ALL, "en_US.UTF-8");
wchar_t res;
char src[] = "á";
mbstate_t mbs = {0};
int v = (int)mbrtowc(&res, src, sizeof(src), &mbs);
printf("%d\n", v);
perror("Failed to convert char");
return 0;
}
转换成功:
2
Failed to convert char: Success
我只想为线程设置区域设置,以避免干扰进程范围的设置,然后稍后我会将其还原为原始区域设置。
我发现 uselocale() 覆盖了进程范围的区域设置,因此在调用 uselocale() 后,setlocale() 在使用线程级区域设置时将不起作用。所以uselocale()确实有一些影响。但它的行为似乎像“C”语言环境。
我在这里做错了什么?
答:
3赞
KamilCuk
3/24/2023
#1
newlocale()
采用_MASK而不是区域设置。请参见手册页。
locale_t loc = newlocale(LC_ALL_MASK, "en_US.UTF-8", (locale_t)0);
评论
0赞
Calmarius
3/24/2023
确实是这样。出于某种原因,我认为LC_ALL已经是一个位掩码了!
评论
newlocale()