gpt4 book ai didi

c++ - Solaris 上的 UCS-4 到多字节转换

转载 作者:行者123 更新时间:2023-11-27 23:24:33 27 4
gpt4 key购买 nike

为什么这段代码:

char a[10]; 
wchar_t w[10] = L"ä"; // German a Umlaut
int e = wcstombs(a, w, 10);

返回 e == -1?

我在 Solaris 11 上使用 Oracle Solaris Studio 10。语言环境是 Latin-1,其中包含德语变音符号。我发现的所有文档都表明(对我而言)转换应该成功。

如果我这样做:
char a[10] = "ä"; // German a Umlaut
wchar_t w[10];
int e = mbstowcs(w, a, 10);
e = wcstombs(a, w, 10);

没有错误,但结果是错误的。 (上 A 的一些变体。)

我也尝试了类似结果的 wstostr。

最佳答案

1) 验证进入 wchar_t 的值是否正确。生成宽字符串文字的编译器必须转换 L"ä"从源代码编码到广泛的执行字符集。

2) 验证程序的语言环境是否正确。您可以使用 printf("%s\n", setlocale(LC_ALL, NULL));
我怀疑问题是 1) 因为对我来说,即使程序的语言环境设置不正确,我仍然可以获得预期的输出。为避免源代码编码出现问题,您可以转义非 ascii 字符,如 L"\x00E4" .

 1  #include <iostream>
2 #include <clocale>
3
4 int main () {
5 std::printf("%s\n", std::setlocale(LC_ALL, NULL)); // prints "C"
6
7 char a[10];
8 wchar_t w[10] = L"\x00E4"; // German a Umlaut
9 std::printf("0x%04x\n", (unsigned)w[0]); // prints "0x00e4"
10
11 std::setlocale(LC_ALL, "");
12 printf("%s\n", std::setlocale(LC_ALL, NULL)); // print something that indicates the encoding is ISO 8859-1
13 int e = std::wcstombs(a, w, 10);
14 std::printf("%i 0x%02x\n", e, (unsigned char)a[0]); // print "1 0xe4"
15 }
16



C 和 C++ 程序中的字符集

在您的源代码中,您可以使用“源字符集”中的任何字符,它是“基本源字符集”的超集。编译器会将字符串和字 rune 字中的字符从源字符集中转换为执行字符集(或宽字符串和字 rune 字的宽执行字符集)。

问题是源字符集依赖于实现。通常,编译器只需要知道您对源代码使用什么编码,然后它将接受来自该编码的任何字符。 GCC 具有用于设置源编码的命令行参数,Visual Studio 将假定源在用户的代码页中,除非它检测到 UTF-8 或 UTF-16 的所谓 Unicode 签名之一,并且 Clang 当前始终使用 UTF- 8.

一旦编译器为您的代码使用正确的源字符集,它将在“执行字符集”中生成字符串和字 rune 字。执行字符集是基本源字符集的另一个超集,也依赖于实现。 GCC 采用命令行参数来设置执行字符集,VS 使用用户的语言环境,Clang 使用 UTF-8。

因为源字符集依赖于实现,所以在基本集之外写入字符的可移植方式是使用十六进制编码直接指定要在执行中使用的数值,或者(如果您不使用 C89/90)使用通用字符名称 (UCN),将其转换为执行字符集(或用于宽字符串和字 rune 字时的宽执行字符集)。 UCN 看起来像\uNNNN 或\UNNNNNNNN,并使用代码点值 NNNN 或 NNNNNNNN 指定 Unicode 字符集中的字符。 (请注意,C99 和 C++11 禁止您使用代理代码点,如果您想要来自 BMP 外部的字符,只需使用\U 直接写入该字符的值。)

源和执行字符集是在编译时确定的,不会根据运行程序的系统的语言环境而改变。也就是说,程序语言环境使用了另一种不一定与执行字符集匹配的编码。但是,宽执行字符集应与支持的语言环境使用的宽字符编码相对应。

Solaris Studio 的行为

Oracle 的 Solaris 编译器具有非常简单的行为。对于窄字符串和字 rune 字,没有指定特定的源编码,源代码中的字节直接用作执行文字。这实际上意味着执行字符集与源文件的编码相同。对于宽字 rune 字,源字节使用系统语言环境进行转换。这意味着您必须使用语言环境编码保存源文件才能获得正确的宽文字。

我怀疑你的源代码被保存在一个不是由语言环境指定的编码中,所以你的编译器无法从 L"ä" 生成正确的宽字符串文字。 .您的编辑器可能正在使用 UTF-8。您可以使用以下程序进行检查。
 1  #include <iostream>
2 #include <clocale>
3
4 int main () {
5 wchar_t w[10] = L"ä"; // German a Umlaut
6 std::printf("0x%04x 0x%04x\n", (unsigned)w[0], (unsigned)w[1]);
7 }
8

由于 wcstombs 可以正确地将宽字符 0x00E4 转换为 'ä' 的 latin-1 编码,因此您希望上面显示 0x00E4 0x0000 .如果源代码编码是 UTF-8,那么您应该看到 0x00C3 0x00A4 .

关于c++ - Solaris 上的 UCS-4 到多字节转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10319810/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com