目录
C语言中对字符和字符串的操作很是频繁,C语言中本身是没有字符串类型的,但是其给我们提供了一系列的操作字符和字符串的库函数,下面来一一进行介绍。
1、strlen
——求字符串长度的函数
strlen函数的功能即统计字符串中 \0 之前出现的字符串的个数,头文件为 #include<sting.h> 。
#include<stdio.h>
#include<sting.h>
int main()
{
char arr[]="abcdef";
int len=strlen(arr); //string length
printf("%d\n",len); //6
return 0;
}
但如果将代码中 char arr[]="abcdef"; 一行改为 char arr[]={'a','b','c','d','e','f'}; 此时打印结果如下:
#include<stdio.h>
#include<sting.h>
int main()
{
char arr[]={'a','b','c','d','e','f'};
int len=strlen(arr); //string length
printf("%d\n",len); //23
return 0;
}
可以发现,此时打印结果变为23,这是为什么呢?
原来,char arr[]="abcdef"; 中,arr实际为“a b c d e f \0”,这样,strlen函数统计\0之前的字符的个数,可以得知为6;而当char arr[]={'a','b','c','d','e','f'}时;arr实际为“a b c d e f ”,strlen函数统计\0之前的字符的个数,当到f时,由于f之后不知道什么位置处才回遇到\0,所以最后打印随机值(这里的打印的是23)。
所以在使用strlen库函数时,要注意:
1.参数指向的字符串必须要以‘\0’结束。
2.注意函数的返回值为size_t,是无符号的。
2、strcpy
——字符串拷贝函数
看下面所示代码,strcpy函数可将源字符串的内容拷贝到目标字符串,头文件 #include<sting.h> 。
#include<stdio.h>
#include<sting.h>
int main()
{
char arr1[20]={0};
char arr2[]="abcdef";
strcpy(arr1,arr2);
printf("%s\n",arr1); //abcdef
return 0;
}
但如果改为:
#include<stdio.h>
#include<sting.h>
int main()
{
char arr1[20]={0};
char arr2[]={'a','b','c'};
strcpy(arr1,arr2);
printf("%s\n",arr1); //越界崩溃,拷贝不成功
return 0;
}
可以发现拷贝不成功。
strcpy函数可以将源字符串的内容拷贝到目标字符串,其中包括源字符串后面的\0。
如果源字符串为char arr2[]="abcdef"; 由于f后面还隐藏了有\0,所以可以正常拷贝;
而如果char arr2[]={'a','b','c'}; 由于在c后面不知何时才能有\0,在此过程中有可能会造成越界访问,所以会造成程序崩溃。
所以在使用strcpy函数时,要注意:
1.源字符串必须以'\0'结束。
2.strcpy函数也会将'\0'拷贝到目标空间。
3.目标空间必须足够大,以确保能存放源字符串。
4.目标空间必须可变。
3、strcat
——字符串追加函数
看如下代码,strcat函数可以将一个字符串(源字符串)追加在另一个字符串(目标字符串)的后面:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20]="hello";
char arr2[]="boy";
strcat(arr1,arr2);
printf("%s\n",arr1); //helloboy
return 0;
}
所以在使用strlen库函数时,要注意:
源字符串必须以'\0'结束。
目标字符串也要以'\0'结束。
目标字符串必须有足够的大,能容纳下源字符串的内容。
目标字符串必须可修改。
4、strcmp
——字符串比较函数
strcmp函数比较的不是字符串的长度,而是比较字符串中对应位置上的字符的大小,如果相同,就比较下一对儿,直到不同或者都遇到'\0'。
如下列所示代码:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[]="abcdef";
char arr2[]="abq";
int ret=strcmp(arr1,arr2);
printf("%d\n",ret); //-1
return 0;
}
VS环境下strcmp函数的返回值:
对strcmp(arr1,arr2):
如果 arr1 < arr2,返回 -1
如果 arr1 > arr2,返回 1
如果 arr1 == arr2,返回 0
而标准规定strcmp函数的返回值:
对strcmp(arr1,arr2):
如果 arr1 < arr2,返回一个小于0的数
如果 arr1 > arr2,返回一个大于0的数
如果 arr1 == arr2,返回0
所以,注意以下写法是错误的:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[]="abcdef";
char arr2[]="abq";
int ret=strcmp(arr1,arr2);
if(ret == 1)
{
printf(">\n");
}
else if(ret == 0)
{
printf("==\n");
}
else if(ret == -1)
{
printf("<\n");
}
//这种写法是错误的。
return 0;
}
正确的写法应为:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[]="abcdef";
char arr2[]="abq";
int ret=strcmp(arr1,arr2);
if(ret > 0)
{
printf(">\n");
}
else if(ret == 0)
{
printf("==\n");
}
else
{
printf("<\n");
}
return 0;
}
以上介绍的strcpy、strcat、strcmp都是长度不受限制的字符串函数,所以这些函数在使用的时候会有由于目标空间不够大而使得程序崩溃的风险,如下列代码:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[]="abcdef";
char arr2[]="qwerrwrds";
strcpy(arr1,arr2); //仍然是可以拷贝的,只不过程序会崩溃
return 0;
}
可以发现,编译器仍然是可以实现字符串的拷贝的,但会提示程序崩溃。
那么为了使得程序变得相对安全,接下来介绍一组长度受限制的字符串函数:
5、strncpy
——拷贝count个字符从源字符串到目标字符串。
对比与strcpy函数的区别:
char *strcpy( char *strDestination, const char *strSource );
char *strncpy( char *strDest, const char *strSource, size_t count );
可以发现,strncpy函数相较于strcpy函数多了一个参数count,指的就是要拷贝的源字符串中字符个数,观察下列所示代码:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[]="abcdef";
char arr2[]="yyds";
strncpy(arr1,arr2,3); //yyddef
return 0;
}
特殊情况下,如果拷贝的源字符串的个数大于源字符串的长度时,默认将'\0'拷贝过去,但拷贝的字符串的个数不能大于目标字符串的个数,要不然会造成越界访问:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[]="abcdef";
char arr2[]="yys";
strncpy(arr1,arr2,5); //yys\0\0f
return 0;
}
6、strncat
——在目标字符串后面追加count个源字符串中的字符。
同理,strncat函数相较于strcat函数多一个参数count,指的就是要追加的源字符串中字符的个数,观察下列所示代码:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20]="abcdefxxxxxxxx";
char arr2[]="qwertyuiop";
strncat(arr1,arr2,5); //abcdefqwert\0xx
return 0;
}
在这个代码中,当从源字符串追加了5个字符到目标字符串后,在后面又会自动加一个'\0'。
7、strncmp
——对前count个源字符串和目标字符串进行比较(比较方法与strcmp一样)
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[]="abcdef";
char arr2[]="asdfghgfh";
int ret=strncmp(arr1,arr2,3);
printf("%d\n",ret); //-1
int ret=strncmp(arr1,arr2,1);
printf("%d\n",ret); //0
int ret=strncmp(arr2,arr1,3);
printf("%d\n",ret); //1
return 0;
}
所以在C语言中,比较两个字符串时有专门的比较函数,如果直接写成两个字符串的比较,这是比较的是两个字符串首字母的地址:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[]="abcdef";
char arr2[]="abc";
if(arr1<arr2) //直接写成这样字符串的比较,比的是这两个数组的地址
{
}
if("abc" < "abcdef") //比较的是两个a的地址
{
}
return 0;
}
8、strstr
——在一个字符串中找另一个字符串的函数。
char *strstr( const char *str1, const char *str2 );
看str2是否在str1里,如果有,返回str2在str1里第一次出现的位置的地址。
看如下所示的代码:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[]="abcdefcd";
char arr2[]="cd";
char* ret=strstr(arr1,arr2);
if(NULL == ret) //在arr1里找不到arr2
{
printf("找不到子串\n");
}
else
{
printf("%s\n",ret); //cdefcd
}
return 0;
}
9、strtok
——字符串切割函数
strtok函数可以识别由不同分隔符分开的字符串。
char *strtok( char *str, const char *sep );
看下面所示代码:
#include<stdio.h>
#include<string.h>
int main()
{
char arr[]="jiayouba@gogogo.net";
char buf[20]={0};
strcpy(buf,arr);
const char* sep = "@.";
//strtok
//"@."
printf("%s\n",strtok(buf,sep));//只找第一个标记
printf("%s\n",strtok(NULL,sep));//是从保存好的位置开始继续往后找
printf("%s\n",strtok(NULL,sep));//是从保存好的位置开始继续往后找
//到这里,再往后找就返回空指针了。
/*
打印结果:
jiayouba
gogogo
net
*/
return 0;
}
在使用strtok函数时,同时要注意以下几点:
1、sep参数是个字符串,定义了用作分隔符的字符集合。
2、第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。3、strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
4、strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置;strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记;5、如果字符串中不存在更多的标记,则返回NULL指针。
10、strerror
——返回错误码所对应的错误信息。
就像我们日常在浏览网页的时候,有时候网页出错会提示404的错误信息,同样,在使用库函数的时候,如果某一个库函数调动失败,会返回一个错误码,strerror函数会返回错误码所对应的错误信息。如下列所示代码:
#include<stdio.h>
#include<string.h>
#include<malloc.h>
#include<limits.h>
#include<errno.h>
int main()
{
int* p=(int*)malloc(INT_MAX); //向堆区申请内存的,如果申请失败了,返回空指针
//void *malloc( size_t size );
if(p == NULL)
{
printf("%s\n",strerror(errno)); //打印Not enough space
return 1;
}
return 0;
}
malloc函数表示向堆区申请内存,上述代码中由于申请空间过大导致申请失败,返回空指针。这时利用strerror函数可以将此时对应的错误信息打印出来:Not enough space