前言
在函数那篇中我们介绍过了关于库函数的相关部分,库函数我们知道的有:IO函数、字符函数、字符串函数、内存函数、时间日期函数、数学函数等等。这次主要详细介绍字符和字符串函数。
函数介绍
strlen()函数
作用:strlen()函数是用来求字符串的长度的函数。 形式:size_t strlen( const char *string ) 解释:将一个字符地址传给函数,strlen()函数进行搜寻,直到找到“\0”停止,计算字符个数(不包含“\0”)。 我们看例子:
#include<stdio.h>
#include<string.h>
int main()
{
size_t sz = strlen("abcdef");
printf("%u\n", sz);
return 0;
}
size_t表示的是strlen()函数的返回类型,也就是说计算一个字符串的字符个数时会返回字符的个数,那么我们用一个变量接收,size_t表示的是无符号整型,也就是unsigned int,因此,用unsigned int定义sz也是可以的。所以在打印是我们也用%u来打印无符号整型。
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "abcdef";
size_t sz = strlen(arr);
printf("%u\n", sz);
return 0;
}
当然,我们也可以用字符数组来储存一个字符串,那么我们只需要将数组名传给函数就可以实现字符元素个数的计算。因为这里的数组名就表示首字符的地址,当找到“\0”就会停止。 我们来看一个错误的用法:
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = { 'a','b','c' };
size_t sz = strlen(arr);
printf("%u\n", sz);
return 0;
}
我们可以看到,arr[]也是一个字符数组,但是和上面例子不一样的是没有了以“\0”结尾的结束标志,这就导致strlen()函数,一直在后方内存中寻找,直到找到“\0”为止。所以此时打印结果不可知,是一个随机值。 易错:
- 字符串已经 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )。
- 参数指向的字符串必须要以 ‘\0’ 结束。
- 注意函数的返回值为size_t,是无符号的。
strcpy()函数
作用:strcpy()函数是用于字符串拷贝。 形式:char* strcpy(char* destination,const char*source) 解释:拷贝source字符串到destination字符串中,包含“\0”字符。 我们看这个例子:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "xxxxxxxxxxxx";
char arr2[] = "hello";
strcpy(arr1, arr2);
printf("%s", arr1);
return 0;
}
这段代码中我们将arr2的内容拷贝到arr1中,但是我们发现打印结果是: 我们发现hello后面的“xxx”不见了,这就表明strcpy()函数实现过程中是寻找“\0”将“\0”前面所有的字符包括“\0”一起拷贝到arr1中,因此打印时打印到“\0”就发生了停止,所以后面的“xxx”也就消失不见了(其实并不是真正意义上的消失,只是不被打印出来)。 我们来看两个错误的例子: 错误1
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "xxx";
char arr2[] = "hello";
strcpy(arr1, arr2);
printf("%s", arr1);
return 0;
}
在这个代码中我们发现将arr2的内容拷贝到arr1中是不行的,因为arr1中不够将arr2中的字符都拷贝过来,因此会放生数组越界的访问。这是不被允许的,所以会报错。 错误2
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "xxxxxxxxxxx";
char arr2[] = {'a','b','c'};
strcpy(arr1, arr2);
printf("%s", arr1);
return 0;
}
这段代码没有错误1中的毛病,但是我们看到arr2数组中并没有“\0”,这就导致strcpy()函数会无限制的向下寻找“\0”,并将前面的字符拷贝到arr1中,这也是不被编译器所允许的,因此同样会报错。 易错:
- 源字符串必须以 ‘\0’ 结束。
- 会将源字符串中的 ‘\0’ 拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变。
strcat()函数
作用:strcat()函数是用于字符串追加和字符串连接。 形式:char* strcat(char* strDestanation,const char* strSource) 解释:strcat函数将strSource追加到strDestination,并用空字符终止结果字符串。strSource的初始字符覆盖strDestination的终止空字符。复制或追加字符串时不执行溢出检查。 我们来看一个例子:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20] = "abc";
strcat(arr1, "def");
printf("%s\n", arr1);
return 0;
}
这段代码中我们可以清楚的看到打印结果为abcdef,这就是strcat()函数的作用。 我们来看错误例子: 错误1:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abc";
strcat(arr1, "def");
printf("%s\n", arr1);
return 0;
}
这段代码和上述的代码只相差了数字“20”,但是这段代码时跑不过去的,因为我们知道,在数组初始化时,如果没有给数组元素个数,那么系统会分配给数组刚好大小的空间,也就是说arr1[]被分配了4个字节(还有“\0”),但是在追加时,将“def”追加给arr1[]会导致数组的越界访问,因此这段代码无法通过编译器。 错误2
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20] = "abc";
char arr2[] = { 'd','e','f' };
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
这段代码中,我们创建arr1,其中有足够大小的空间,但是当进行追加时,我们发现arr2没有了结束的标志“\0”,这就导致不知道何时停止追加。因此导致不能通过编译。 易错
- 原字符串必须以“\0”结束。
- 目标空间必须足够大。
- 目标空间必须可修改。
strcmp()函数
作用:strcmp()函数用于字符串比较,比较的是字符串的内容不是长度。 形式:int strcmp(const char* str1, const char* str2) 解释:strcmp函数按字典顺序比较string1和string2,并返回一个值,指示它们之间的关系。 我们来看例子:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abq";
int ret = strcmp(arr1, arr2);
printf("%d\n", ret);
return 0;
}
在这段代码中,通过strcmp()函数的比较,我们将返回值用ret接收,如果arr1中字符(Ascll码值)<arr2字符,将返回一个小于0的值(通常为-1),如果arr1中字符(Ascll码值)>arr2字符,将返回一个大于0的值(通常为1),如果arr1中字符(Ascll码值)=arr2字符,将返回0,直到遇到“\0”停止上述过程,在这个例子中,前两个字符“ab”相等,在第三个字符中“c”<“q”,所以返回-1,打印结果为-1。
strncpy()函数、strncat()函数、strncmp()函数
细心的同学可能发现,这三个函数跟上诉我们学习的三个函数很相似,是的,原因就在于上述中 strcpy()函数、strcat()函数、strcmp()函数其实是不够安全的,什么意思呢?我们可以发现,这三个函数是不受字符串长度的限制,在使用时,不管三七二十一,直接就是用找到“\0”才会停止,这样往往会导致一些不必要的问题,因此我们在这三个函数的基础上做出了改进,是的改进后的strncpy()函数、strncat()函数、strncmp()函数受到长度的限制。 形式: char *strncpy( char *strDest, const char *strSource, size_t count ); char *strncat( char *strDest, const char *strSource, size_t count ); int strncmp( const char *string1, const char *string2, size_t count ); 我们看到,这三个函数相对于一开始的函数增加了一个参数,这个参数就是用来记录操作字符的个数的。举个例子:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20] = "abcefghi";
char arr2[] = "xxxx";
strncpy(arr1, arr2, 2);
printf("%s\n", arr1);
return 0;
}
我们可以看到打印结果是“xxcdefghi”,而函数strncpy(arr1, arr2, 2)中所用的数字“2”,就是操作arr2数组中两个字符,也就是“xx”,同理,strncat()函数、strncmp()函数也是如此。
strstr()函数
作用:strstr()函数作用于字符串查找。 形式:char *strstr( const char *string, const char *strCharSet ); 解释:strstr函数返回一个指针,指向字符串中第一个出现的strCharSet。搜索不包括终止空字符。 我们来看例子:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "i am a good student,hehe student";
char arr2[] = "student";
char* ret = strstr(arr1, arr2);
if (ret == NULL)
{
printf("找不到\n");
}
else
{
printf("%s\n",ret);
}
return 0;
}
函数strstr()在找到对应匹配的字符时,会返回该字符的首字符地址,例子中我们用ret接收并打印,因此会从第一个“student”起打印直到“\0”。如果没有找到对应匹配的字符,那么返回NULL指针。
strtok()函数(了解即可)
作用:strtok()函数用于字符串的切割。 形式:char *strtok( char *str, const char *sep); 解释:strtok函数在str中查找下一个令牌。sep中的字符集指定在当前调用的str中找到的令牌的可能分隔符。 我们看例子:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "zjt@bdsaitedu.tedch" ;
char arr2[100] = { 0 };
char sep[] = "@.";
strcpy(arr2, arr1);
char* ret = NULL;
for (ret = strtok(arr2, sep); ret != NULL; ret=strtok(NULL,sep))
{
printf("%s\n", ret);
}
return 0;
}
这段代码有些许复杂,我们创建3个数组分别为arr1[],arr2[],sep[]数组,我们将arr1的内容拷贝到arr2中,进入for循环,第一次我们用sep[]数组中的符号分割出“zjt”,此时函数返回分割出字符的首字符地址,也就是“z”的地址,并赋值给ret,判断ret是否为NULL指针,显然不为空指针,打印出“zjt”,第二次循环,ret=strtok(NULL,sep)(此函数的特点:进行一次分割后,该函数会将分割位置作为标记,就像第一次分割时,会将“@”转化为“\0”,并记下分割的位置,再次进行分割时,从记住的位置再次进行分割),当第一个参数为NULL指针时函数,将在同一个字符串中被保存的位置开始,查找下一个标记。因此分割出“bdsaitedu”,以此类推,最后打印结果: 特点:
- sep参数是个字符串,定义了用作分隔符的字符集合
- 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
- strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
- strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
- strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
- 如果字符串中不存在更多的标记,则返回 NULL 指针。
关于常见的字符和字符串函数介绍就到这里,如果有错误或者不正确的地方欢迎各位指正,谢谢大家!
|