一、C语言中的字符串
字符串是一种重要的数据类型,但是C语言并没有显示的字符串数据类型,不像java有String ,OBC有NSString等等。所以C语言中的字符串一般以字符串常量的形式出现或者存储与字符数组中。
每个字符串的末尾都添加了代码值为0的特殊字符,这个字符称为空字符(不要和NULL搞混C中的字符串),写作\0。字符串,总是由\0字符结束,所以字符串的长度永远比字符串中的字符数多1。可以将\0字符添加到字符串的结尾,但是这会使字符串的末尾有两个\0的字符。\0 即是字符串结束的标志。
二、字符数组存储字符串
声明如:char str[4];初始化如:str="abc";
例子1:
int main(void)
{
char str[3]=“123”;
printf("%s",str);
return 1;
}
这样的程序,编译的时候直接不能让通过,会报下面的错误:
: array bounds overflow。
因为,这样的写法就是声明并初始化一个字符串,而字符串必须使用\0结尾,所以数组才会越界。如果像下面:
例子2:
int main(void)
{
char str[3]={'1','2','3'};
printf("%s",str);
return 1;
}
这样写,就是声明并初始化一个字符数组,当然不会报错,可是看输出
结果却和奇怪,其实一点也不用奇怪,用%s的形式输出一个字符数组,那么就会把这个字符数组当字符串输出,可是他并不是一个正确的字符串格式,所以只能根据数组指针的后移,一直不断的输出,直到遇到内存中随机的出现的\0才会结束,所以才会有这样的结果。
所以在声明和初始化一个字符串的时候一定要注意。一般可以这样去声明和初始化一个字符串:
char str[]="123123asda";
数组的长度自己并不指定,而是有系统自己确定,这样就不会出现数组越界的问题了。
三、使用库函数操作字符串
字符串函数在<string.h>头文件中声明,所以如果要使用它们,需要在程序的开始处使用include包含进来。
1、复制字符串
strcpy
函数原型:char *strcpy(char *destin, char *source);
参数类型为字符数组名,destin为目标字符串,source为源字符串。将字符串source的内容复制到destin,注意该函数不检查数组长度,所以要确保destin的数组能够容纳source中的所有字符。
另一个可用的函数strncpy
函数原型;char * strncpy(char *dest, char *src, size_t n);
将字符串src中最多n个字符复制到字符数组dest中(它并不像strcpy一样遇到NULL才停止复制,而是等凑够n个字符才开始复制),返回指向dest的指针。第三个参数是一个size_t类型的整数。它指定了要复制的字符数n,举例:
2、检测字符串的实际长度
strlen
函数原型: size_t strlen(conset char *s);
功能: strle函数求的是字符串的长度,它求得方法是从字符串的首地址开始到遇到第一个'\0'停止计数,如果你只定义没有给它赋初值,这个结果是不定的,它会从字符串首地址一直记下去,直到遇到'\0'才会停止。
sizeof(string)可以输出一个字符串占的字节数,因为一个char是一个字节,在加上结束符\0(可能不止一个\0),所以sizeof得出的结果比字符串实际的长度大。
而是用strlen(string) 则可以得出字符串的实际长度。
size_t数据类型
类型size_t在标准库头文件<stddef.h>中定义,它也是运算符sizeiof()的返回类型。类型size-t定义了一个无符号的整数类型unsigned int。之所以要这么做,是考虑到代码的可移植性。在各种C语言中,sizeof()和strlen()函数的返回类型互不相同。这是由编译器的作者来决定的。把这个类型定义为size_t,并把size_t定义放在头文件中,非常便于在代码中包容这种依赖性。
所以,要正确的使用size_t类型,因为它是一个无符号整数,在表达式中使用无符号数可能导致不可预料的结果,如下:
if(strlen(x) >= strlen(y))
if(strlen(x) - strlen(y)>=0)
上面这两个表达式看起来是相当的,实际上它们是不等的。第一条语句会按照预想的工作,但是第二条语句就永远都是成立的,因为两个无符号整数的运算结果是一个无符号整数,永运都是>=0的。
所以要注意了,可以将得到的size_t强转为int类型,在用于计算。
3、连接字符串
strcat
函数原型: char *strcat(char *destin, char *source);
它会将字符串source连接到字符串destin的末尾,并且返回destin
也可以使用strncat
函数原型:用 法: char *strcat(char *destin, char *source,size_t n);
第三个参数也是size_t的类型,这个函数是表示将字符串source的前面n个字符连接到destin的末尾
4、比较字符串
strcmp
函数原型:int strcmp(char *str1, char *str2);
如果str1>str2 返回值>0,如果str1=str2 返回值=0,如果str1<str2 返回值<0。
strncmp
函数原型: int strncmp(char *str1, char *str2, unsigned maxlen);
比较两个字符串的前maxlen个字符
strnicmp
函数原型: int strnicmp(char *str1, char *str2, unsigned maxlen);
比较两个字符串的前maxlen个字符,不区分大小写。
5、搜索字符串
strchr
函数原型:char *strchr(char *str, char c);
第一个参数是要搜素的字符串(是char数组的地址),第二个参数是要查找的字符。这个函数会从字符串的开头开始搜索,返回在字符串中找到的第一个给定字符的地址。这是一个在内存中的地址,其类型为char*,表示“char的指针”,所以要存储返回值,必须创建一个能存储字符地址的变量。如果没有找到给定的字符,函数就会返回NULL,他相当于0,表示这个指针没有指向任何对象。
举例:
strtchr和strchr非常类似,只不过是从字符串末尾开始查找。
strstr
函数原型;_CRTIMP char * __cdecl strstr(const char *, const char *);
它查找一个字符串中的子字符串,返回找到的第一个子字符串的位置指针。如果找不到匹配的字符串串,就返回NULL。
6、分析和检测字符串
islower() 小写字符
isupper() 大写字母
isalpha() 大写或小写字母
isalnum() 大写或小写字符,或数字
isprintf() 可打印字符,包括空格
isgraph() 可打印字符,不包括空格
isdigit() 十进制数字的字符('0'~'9')
isxdigit() 十六进制数字的字符('0'~'9'、‘A’~'F','a'~'f')
isblank() 标准空白字符(空格、'\t')
isspace() 空白字符(空格、'\n','\t','\'v','r\','\f')
ispunct() isspace()和isalnum返回false的可打印字符
toupper() 转变为大写字符
tolower() 转变为小写字符
atof() 从字符串中生成double类型的值
atoi() 从字符串中生成int类型的值
atol() 从字符串中生成long类型的值
atoll() 从字符串中生成long long类型的值
四、使用宽字符
使用宽字符串与使用前面的字符串一样简单。宽字符串存储在wchar_t类型的数组中,宽字符串常量只需要在前面加上L修饰符。举例:
wchar_t proverb[]=L"A kls a";
wchar_t字符占用2个字节。proverb字符串包含7个字符和终止空字符,所以占用16个字节。
如果要使用printf()将字符串输出到屏幕上,必须使用%S格式指定符,而不是用于ASCII字符串的%s,
如果使用了%s,printf()函数就假定字符串包含单字节字符,这样结果就不正确了。
宽字符的操作函数:
<wchar.h>头文件声明了一些函数来操作宽字符串,它们对应于处理一般字符串的函数。