在C/C++中有字符和字符数组,分别对应char和char[]。其中字符数组也称字符串。
查阅头文件stdint.h可以看到如下两句关键的语句:
typedef signed char int8_t;
typedef unsigned char uint8_t;
那么char对应的是哪一个?网上找不到确切说法,据说这个和编译器有关。经过实验表明,在MSVC中char对应signed char,范围-128~127。
由以上头文件定义可以看出,char类型变量可以是一个有符号八位整数,也可以是一个带有单引号的字符。如“char s=39;”或者“char s='a';”。所以在输出int_8变量时,如果用cout,它会被当作一个字符来输出,导致得不到预期结果,得使用printf配合%d来指定输出格式,wcout也可以。
那么wchar_t呢?经过实验表明,在MSVC中其对应于uint16_t,范围0~65535。而且不存在signed wchar_t或者unsigned wchar_t这两种类型。对于其输出,要使用wcout,并且还要在输出之前配合一句代码“setlocale(LC_ALL, "zh-CN");”才能正常显示。若使用cout,则会被当做一个整数来输出。
字符数组在初始化时有两种方式:
char s[]={'a','b','c','\0'};//必须手动添加\0
char s[]="abc";//其结尾会自动添加\0
以上两种方式的数组长度都是4,因为包含结尾的\0。
若想操作字符数组,需要使用string.h中提供的字符数组函数:
strlen(s1); 返回字符串 s1 的长度(不包括\0)。
strcmp(s1, s2); 如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回小于 0;如果 s1>s2 则返回大于 0。
strcat(s1, s2); 连接字符串 s2 到字符串 s1 的末尾,并返回s1。
strcpy(s1, s2); 复制字符串 s2 到字符串 s1,并返回s1。
strncat(s1, s2, n); 连接字符串 s2 的前n个字符到字符串 s1 的末尾,并返回s1。
strncpy(s1, s2, n); 复制字符串 s2 的前n个字符到字符串 s1,并返回s1。
strchr(s1, ch); 返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。
strstr(s1, s2); 返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。
对于宽字符数组,将以上所有函数名中的str换成wcs即可。
由于C语言对于字符串的操作很繁琐且容易出错,尽可能使用C++标准库类型string,它会负责处理所有的内存管理问题,从而提高安全性,效率也能得到提高。
string类型的初始化如下:
string s1; 默认构造函数,s1为空串
string s2(s1); 将s2初始化为s1的一个副本
string s3("value") 将s3初始化为一个字符串字面值副本
string s4(n,'c') 将s4初始化为字符'c'的n个副本
string s5="value" 此初始化必须使用双引号,不能是单引号
其操作和char[]相比容易很多:
s.empty() 若s为空串,则返回true,否则返回false
s.size() 返回s中字符的个数
s[n] 返回s中位置为n的字符,位置从0开始计数
s1+s2 返回连接两字符串后生成的新字符串
s1=s2 s1内容替换为s2的副本
注意“副本”的含义,比如“string b=a;”,对b的修改不会影响到a。另外一个需要注意的地方是s1=s2存在效率上的问题,它会先把s1占用的内存释放掉,然后再分配给s1足够存放s2副本的内存空间,最后再将s2副本复制到新分配的空间。
鉴于效率问题,最好优先考虑以下针对string的函数:
1. append() -- 在字符串的末尾添加字符
2. find() -- 在字符串中查找字符串
4. insert() -- 插入字符
5. length() -- 返回字符串的长度
6. replace() -- 替换字符串
7. substr() -- 返回某个子字符串
宽字符串的类型是wstring。
最后补充,普通字符使用ANSI编码,宽字符使用Unicode编码。其中使用ANSI编码时,0x00~0x7F之间的字符是1个字节代表一个字符(ASCII编码),而这之外的字符通常是使用0x80~0xFF范围内的两个字节来表示一个字符,对于不同的语言它代表的编码不同,如在简体中文系统下,ANSI 编码代表 GB2312 编码;在繁体中文系统下,ANSI 编码代表 Big5 编码;在日文操作系统下,ANSI 编码代表 JIS 编码。
所以如果一个程序没有合理地选择编码方式,在运行时就会出现问题。如:源码页使用GB2312,定义变量时使用宽字符,两者不统一就会显示乱码。综上所述,是否使用宽字符变量请根据源码页的编码来决定;对于必须使用宽字符的函数,源码页编码务必设置为Unicode。