修改 我只能使用stdio.h和stdlib.h
我想遍历一个充满字符的字符数组。
然而,像ä,ö这样的字符占用了两倍的空间并使用了两个元素。 这就是我的问题所在,我不知道如何访问这些特殊的字符。
在我的例子中,char“ä”将使用hmm [0]和hmm [1]。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* hmm = "äö";
printf("%c\n", hmm[0]); //i want to print "ä"
printf("%i\n", strlen(hmm));
return 0;
}
谢谢,我试图在Eclipse中运行我附加的代码,它可以工作。我假设因为它使用64位而“ä”有足够的空间来适应。 strlen确认每个“ä”仅计为一个元素。 所以我想我可以以某种方式告诉它为每个字符分配更多的空间(所以“ä”可以适合)?
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* hmm = "äüö";
printf("%c\n", hmm[0]);
printf("%c\n", hmm[1]);
printf("%c\n", hmm[2]);
return 0;
}
答案 0 :(得分:3)
char总是使用一个字节。
在你的情况下,你认为“ä”是一个字符:错误。 使用十六进制查看器打开.c源代码,您将看到ä正在使用2个char,因为该文件是以UTF8编码的
现在问题是你想使用宽字吗?
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
int main()
{
const wchar_t hmm[] = L"äö";
setlocale(LC_ALL, "");
wprintf(L"%ls\n", hmm);
wprintf(L"%lc\n", hmm[0]);
wprintf(L"%i\n", wcslen(hmm));
return 0;
}
答案 1 :(得分:2)
您的数据采用多字节编码。因此,您需要使用多字节字符处理技术来分割字符串。例如:
#include <stdio.h>
#include <string.h>
#include <locale.h>
int main(void)
{
char* hmm = "äö";
int off = 0;
int len;
int max = strlen(hmm);
setlocale(LC_ALL, "");
printf("<<%s>>\n", hmm);
printf("%zi\n", strlen(hmm));
while (hmm[off] != '\0' && (len = mblen(&hmm[off], max - off)) > 0)
{
printf("<<%.*s>>\n", len, &hmm[off]);
off += len;
}
return 0;
}
在我的Mac上,它产生了:
<<äö>>
4
<<ä>>
<<ö>>
致电setlocale()
至关重要;没有它,该程序在“C”语言环境而不是我的en_US.UTF-8
语言环境中运行,并且mblen()
处理不当:
<<äö>>
4
<<?>>
<<?>>
<<?>>
<<?>>
出现问号是因为就UTF-8终端而言,正在打印的字节是无效的单字节。
您还可以使用宽字符和宽字符打印,如benjarobin的answer所示。
答案 2 :(得分:1)
很抱歉将其拖动。虽然我认为重要的是突出一些问题。据我所知,OS-X能够将默认的操作系统代码页设置为UTF-8,因此答案主要针对引擎盖下使用UTF-16的Windows,其默认的ACP代码页依赖于指定的操作系统区域。
首先你可以打开角色地图,然后找到
AO
两者都驻留在代码页1252(西方)中,因此不是 MBCS问题。它可能是MBCS问题的唯一方法是使用MBCS(Shift-JIS,Big5,Korean,GBK)编码保存文件。
答案,使用
setlocale(LC_ALL,“”)
无法深入了解äö在命令提示符窗口中错误呈现的原因。
命令提示符确实使用自己的代码页,即OEM代码页。 Here是对以下(OEM)代码页的引用及其字符映射。
进入命令提示符并键入以下命令(Chcp)将显示命令提示符正在使用的当前OEM代码页。
使用setlocal(LC_ALL,“”)跟踪Microsoft文档后,它详细说明了以下行为。
setlocale(LC_ALL,“”);
将语言环境设置为默认值,即从操作系统获取的用户默认ANSI代码页。
您可以手动执行此操作,使用chcp并传递所需的代码页,然后运行您的应用程序,它应该完全输出文本。
如果这是一个多字节字符集问题,那么就会有一整套其他问题:
在MBCS下,字符以一个或两个字节编码。在双字节字符中,第一个或“前导字节”表示它和后续字节都被解释为一个字符。第一个字节来自一系列保留用作前导字节的代码。哪个字节范围可以是前导字节取决于使用的代码页。例如,日语代码页932使用范围0x81到0x9F作为前导字节,但是韩语代码页949使用不同的范围。
查看情况,并且长度为4而不是2.我会说文件格式已经保存在UTF-8中(事实上它可以保存在UTF-16中,尽管你会遇到问题早于编译器的问题)。您使用的字符不在0到127的ASCII范围内,UTF-8将Unicode代码点编码为两个字节。您的编译器打开文件并假设它是您的默认操作系统代码页或ANSI C.在解析您的字符串时,它将字符串解释为ANSI C字符串1字节= 1个字符。
为了解决这个问题,在Windows下将UTF-8字符串转换为UTF-16并使用wprintf打印。目前,对Ascii / MBCS stdio功能没有本机UTF-8支持。
对于Mac OS-X,其默认操作系统代码页为UTF-8,我建议遵循Jonathan Leffler解决方案,因为它更优雅。虽然如果稍后将其移植到Windows,您会发现需要使用以下示例将字符串从UTF-8转换为UTF-16。
在任一解决方案中,您仍然需要将命令提示符代码页更改为操作系统代码页以正确打印ASCII以上的字符。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
#include <locale>
// File saved as UTF-8, with characters outside the ASCII range
int main()
{
// Set the OEM code page to be the default OS code page
setlocale(LC_ALL, "");
// äö reside outside of the ASCII range and in the Unicode code point Western Latin 1
// Thus, requires a lead byte per unicode code point when saving as UTF-8
char* hmm = "äö";
printf("UTF-8 file string using Windows 1252 code page read as:%s\n",hmm);
printf("Length:%d\n", strlen(hmm));
// Convert the UTF-8 String to a wide character
int nLen = MultiByteToWideChar(CP_UTF8, 0,hmm, -1, NULL, NULL);
LPWSTR lpszW = new WCHAR[nLen];
MultiByteToWideChar(CP_UTF8, 0, hmm, -1, lpszW, nLen);
// Print it
wprintf(L"wprintf wide character of UTF-8 string: %s\n", lpszW);
// Free the memory
delete[] lpszW;
int c = getchar();
return 0;
}
UTF-8 file string using Windows 1252 code page read as:äö
Length:4
wprintf wide character of UTF-8 string: äö
答案 3 :(得分:0)
我会检查你的命令提示字体/代码页,以确保它可以显示你的os单字节编码。 note命令提示符有自己的代码页,与您的文本编辑器不同。