【发布时间】:2017-05-23 06:37:43
【问题描述】:
我知道这个问题可能非常初级。如果这是显而易见的事情,请原谅。 考虑以下程序:
#include <stdio.h>
int main(void) {
// this is a string in English
char * str_1 = "This is a string.";
// this is a string in Russian
char * str_2 = "Это строковая константа.";
// iterator
int i;
// print English string as a string
printf("%s\n", str_1);
// print English string byte by byte
for(i = 0; str_1[i] != '\0'; i++) {
printf(" %c ",(char) str_1[i]);
}
printf("\n");
// print numerical values of English string byte by byte
for(i = 0; str_1[i] != '\0'; i++) {
printf("%03d ",(int) str_1[i]);
}
printf("\n");
// print Russian string as a string
printf("%s\n", str_2);
// print Russian string byte by byte
for(i = 0; str_2[i] != '\0'; i++) {
printf(" %c ",(char) str_2[i]);
}
printf("\n");
// print numerical values of Russian string byte by byte
for(i = 0; str_2[i] != '\0'; i++) {
printf("%03d ",(int) str_2[i]);
}
printf("\n");
return(0);
}
输出:
This is a string.
T h i s i s a s t r i n g .
084 104 105 115 032 105 115 032 097 032 115 116 114 105 110 103 046
Это строковая константа.
▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ .
-48 -83 -47 -126 -48 -66 032 -47 -127 -47 -126 -47 -128 -48 -66 -48 -70 -48 -66 -48 -78 -48 -80 -47 -113 032 -48 -70 -48 -66 -48 -67 -47 -127 -47 -126 -48 -80 -48 -67 -47 -126 -48 -80 046
可以看出,英文(ASCII)字符串可以打印为字符串或使用数组索引访问并逐字符(逐字节)打印,但是俄语字符串(我相信编码为 UTF-8)可以以字符串形式打印,但不能逐字符访问。
我知道原因是在这种情况下,俄语字符使用两个字节而不是一个字节进行编码。
我想知道是否有任何简单的方法可以通过正确声明数据类型或通过以某种方式标记字符串来使用标准 C 库函数逐个字符(在本例中为两个字节乘两个字节)打印 Unicode 字符串或通过设置语言环境或其他方式。
我尝试在俄语字符串前面加上“u8”,即char * str_2 = u8"...",但这不会改变行为。我想避免使用宽字符来假设所使用的语言,例如每个字符恰好两个字节。任何建议将不胜感激。
【问题讨论】:
-
它没有什么基本的东西——这类问题与国际化代码非常相关,而且一点也不明显。在 Web 浏览器的另一端,我们面临的一个问题是字符串几乎不可避免地会以 UTF-8 编码。但是,如果您使用不同的代码集(例如 ISO 8859-5 等西里尔文代码集),您磁盘上的内容可能与我们在网络上看到的不同。假设您在磁盘上确实有 UTF-8,最好确保以十六进制打印“无符号字符”值(显然,在您的机器上签名了普通的
char)。 -
可能有它的库,但我不知道标准 C 中的方法(除了编写自己的 UTF-8 解析器)。
标签: c string unicode-string