0

尝试将存储在宽字符中的日文字符转换为 UTF-8,以便使用 cJSON 库将值存储在 json 文件中。首先尝试使用wcstombs_s,但显然这不支持日文字符:

size_t len = wcslen(japanese[i].name) + 1;
char* japanese_char = malloc(len);
if (japanese_char == NULL) {
    exit(EXIT_FAILURE);
}
size_t sz;
wcstombs_s(&sz, japanese_char, len, japanese[i].name, _TRUNCATE);

然后,根据其他答案,也是在从 json UTF-8 到 Wide char 的成功转换中,尝试了如下相反的功能,但目标缓冲区dest只包含垃圾字符:

size_t wcsChars = wcslen(japanese[i].name);
size_t sizeRequired = WideCharToMultiByte(CP_UTF8, 0, japanese[i].name, wcsChars, NULL, 0, NULL, NULL);
char* dest = calloc(sizeRequired, 1);
WideCharToMultiByte(CP_UTF8, 0, japanese[i].name, wcsChars, dest, sizeRequired, NULL, NULL);
free(dest);

wchar_t我试图转换的宽字符 ( )ササササササササササササササササ存储在japanese[i].name(a wchar_t*in a struct) 中。目标是使用 cJSONcJSON_CreateString将值保存在 UTF-8 编码的 json 文件中。

问题:在 C(不是 C++)中将日语从 wchar_t 转换为 UTF-8 char 的正确方法是什么?

4

1 回答 1

0

您的wcstombs_s()代码将错误的值传递给sizeInBytes参数:

sizeInBytes

mbstr缓冲区的大小(以字节为单位) 。

您传入的字符japanese[i].name,而不是分配的字节japanese_char。它们不是相同的值。

Unicode 代码点以 UTF-16(wchar_tWindows 上的字符串编码方式)编码,每个使用 2 或 4 个字节,而在 UTF-8 中,每个使用 1-4 个字节,具体取决于它们的值。该范围内的 Unicode 代码点在U+0080..U+FFFFUTF-8 中比在 UTF-16 中占用更多字节,因此您的japanese_char缓冲区实际上可能需要分配比您的japanese[i].name数据更大的字节。就像您可以调用WideCharToMultiByte()以确定所需的目标缓冲区大小一样,您可以使用wcstombs_s().

size_t len = 0;
wcstombs_s(&len, NULL, 0, japanese[i].name, _TRUNCATE);
if (len == 0)
    exit(EXIT_FAILURE);
char* japanese_char = malloc(len);
if (!japanese_char)
    exit(EXIT_FAILURE);
wcstombs_s(&len, japanese_char, len, japanese[i].name, _TRUNCATE);
...
free(japanese_char);

由于您将显式大小传递给参数,因此您的WideCharToMultiByte()代码不会以空值终止。destcchWideChar

cchWideChar

lpWideCharStr 指示的字符串的大小(以字符为单位)。或者,如果字符串以 null 结尾,则可以将此参数设置为 -1。如果 cchWideChar 设置为 0,则函数失败。

如果此参数为 -1,则该函数处理整个输入字符串,包括终止空字符。因此,结果字符串有一个终止空字符,函数返回的长度包括这个字符。

如果此参数设置为正整数,则该函数将精确处理指定数量的字符。如果提供的大小不包含终止空字符,则生成的字符串不是空终止字符,并且返回的长度不包含此字符。

cJSON_CreateString()需要一个以 null 结尾的char*字符串。所以你需要:

  • num为参数添加 +1 以calloc()说明缺少的空终止符。
size_t wcsChars = wcslen(japanese[i].name);
size_t len = WideCharToMultiByte(CP_UTF8, 0, japanese[i].name, wcsChars, NULL, 0, NULL, NULL);
char* japanese_char = malloc(len + 1);
if (!japanese_char)
    exit(EXIT_FAILURE);
WideCharToMultiByte(CP_UTF8, 0, japanese[i].name, wcsChars, japanese_char, len, NULL, NULL);
japanese_char[len] = '\0';
...
free(japanese_char);
  • 将 +1 添加到 的返回值wcslen(),或将 的cchWideChar参数设置WideCharToMultiByte()为 -1,以在输出中包含空终止符。
size_t wcsChars = wcslen(japanese[i].name) + 1;
size_t len = WideCharToMultiByte(CP_UTF8, 0, japanese[i].name, wcsChars, NULL, 0, NULL, NULL);
if (len == 0)
    exit(EXIT_FAILURE);
char* japanese_char = malloc(len);
if (!japanese_char)
    exit(EXIT_FAILURE);
WideCharToMultiByte(CP_UTF8, 0, japanese[i].name, wcsChars, japanese_char, len, NULL, NULL);
...
free(japanese_char);
size_t len = WideCharToMultiByte(CP_UTF8, 0, japanese[i].name, -1, NULL, 0, NULL, NULL);
if (len == 0)
    exit(EXIT_FAILURE);
char* japanese_char = malloc(len);
if (!japanese)
    exit(EXIT_FAILURE);
WideCharToMultiByte(CP_UTF8, 0, japanese[i].name, -1, japanese_char, len, NULL, NULL);
...
free(dest);
于 2019-10-04T23:00:29.707 回答