我尝试解析文本并在其中找到一些字符.我使用下面的代码.它适用于普通字符,如abcdef,但它不适用于öçşğüı. GCC提供编译警告.我该怎么做才能与öçşğüı合作?
代码:
#include <stdio.h> #include <ctype.h> #include <string.h> int main() { char * text = "öçşğü"; int i=0; text = strdup(text); while (text[i]) { if(text[i] == 'ö') { printf("ö \n"); } i++; } return 0; }
警告 :
warning: multi-character character constant [-Wmultichar] warning: comparison is always false due to limited range of data type [-Wtype-limits]
在while循环中打印char的地址时有10个地址
printf("%d : %p \n",i,text[i]);
输出:
0 : 0xffffffc3 1 : 0xffffffb6 2 : 0xffffffc3 3 : 0xffffffa7 4 : 0xffffffc5 5 : 0xffffff9f 6 : 0xffffffc4 7 : 0xffffff9f 8 : 0xffffffc3 9 : 0xffffffbc
而strlen是10.
但是如果我使用abcde:
0 : 0x61 1 : 0x62 2 : 0x63 3 : 0x64 4 : 0x65
而strlen是5.
如果我使用wchar_t进行文本输出
0 : 0xa7c3b6c3 1 : 0x9fc49fc5 2 : 0xbcc3
而strlen是10,wcslen是3.
解决方法
要浏览字符串中的每个字符,可以使用mblen.您还需要设置正确的语言环境(多字节字符串表示的编码),以便mblen可以正确解析多字节字符串.
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <locale.h> int main() { char * text = "öçşğü"; int i=0,char_len; setlocale(LC_CTYPE,"en_US.utf8"); while ((char_len = mblen(&text[i],MB_CUR_MAX)) > 0) { /* &text[i] contains multibyte character of length char_len */ if(memcmp(&text[i],"ö",char_len) == 0) { printf("ö \n"); } i += char_len; } return 0; }
有两种类型的字符串表示,使用多字节(8位字节)或宽字节(大小取决于平台).多字节表示具有可以使用char *(在代码中通常使用c字符串)表示的优点,但缺点是多个字节表示字符.宽字符串使用wchar_t *表示. wchar_t的优点是一个wchar_t是一个字符(但正如@anatolyg所指出的,在wchar_t无法表示所有可能的字符的平台上,这个假设仍然可能出错).
您是否使用十六进制编辑器查看了源代码?字符串“öçşğü”实际上由存储器中的多字节字符串c3 b6 c3 a7 c5 9f c4 9f c3 bc(UTF-8编码)表示,当然具有零终止.您只看到5个字符,因为您的UTF-8感知查看器/浏览器正确呈现了字符串.很容易意识到strlen(text)为此返回10,而上面的代码只循环5次.
如果使用宽字节字符串,可以按照@WillBriggs的说明完成.