目录
开门见山,直接进入讲解。
一:字符串函数:
字符串函数有:
strcpy strcat strcmp
strncpy strncat strncmp //第二行的函数近比第一行的函数都多加一个n,它们 的使用方法也相似
strlen strstr strtok strerror
1.strlen函数
函数原型:size_t strlen(const char *str);
头文件:string.h
功能:计算给定字符串(const char *str)的长度,不包括'\0'在内。
返回值:返回字符串的长度,返回值为size_t类型
代码示例:
#include<stdio.h>
#include<string.h>
int main()
{
char arr[]="abcdef";//创建字符串arr
printf("%d",strlen(arr));//打印arr的长度
return 0;
}
接下来我们来尝试模拟strlen的实现,来增强我们对函数的掌握。
模拟strlen函数
可以用三种方式来模拟实现strlen函数。
第一种方法:计数器方式
1.计数器方式
int my_strlen(const char* arr)
{
assert(arr);//判断arr是否为野指针
int count=0;//创建变量count来计数
while (*arr++)//当字符串循环到'\0'时停下来,此时count就是字符串的长度
{
count++;
}
return count;//返回count的值
}
int main()
{
char arr[] = "abcdefghijk";//创建字符串arr
int ret=my_strlen(arr);//创建一个函数,参数为字符串首地址,返回值为int
printf("%d", ret);
return 0;
}
第二种方法:递归方式(不会递归的话可以不选择这种方式)
int my_strlen(char* arr)
{
assert(arr);
if (*arr == '\0')
{
return 0;
}
else
return 1 + my_strlen(arr + 1);
}
int main()
{
char arr[] = "abcdefghijk";
int ret=my_strlen(arr);
printf("%d", ret);
return 0;
}
第三种方法:指针减去指针的方式
int my_strlen(char* arr)
{
assert(arr);
char* pt = arr;
while (*arr++)//当循环到'\0'时停止,此时的arr指向的是'\0'的下一位
;
return arr-1 - pt;//因此应该先减去1后再减去首地址,得到的字符尾部相对于字符首地址的偏移量。
}
int main()
{
char arr[] = "abcdefghijk";
int ret=my_strlen(arr);
printf("%d", ret);
return 0;
}
当然,不管这三种用哪种方式,最终程序运行的结果都会是:
strlen函数讲解结束。
2.strcpy函数
函数原型:char *strcpy(char* dest, const char *src);
头文件:#include <string.h>
功能:把从src地址开始且含有结束符的字符串复制到以dest指向的地址空间
返回值:字符串dest的地址
注意:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
返回指向dest的指针。
代码示例:
#include<stdio.h>
#include<string.h>
//strcpy使用
int main()
{
char arr1[20] = "abcdefg";
char arr2[] = "hijklm";
strcpy(arr1, arr2);
printf("%s", arr1);
return 0;
}
运行结果:
我们可以看到原先arr1中的字符串内容已经全部被 arr2所替换。
在知道了如何使用strcpy后,我们来尝试一下模拟strcpy函数功能的实现。
#include<stdio.h>
char* my_strcpy(char* arr1, char* arr2)
{
char* pa = arr1;//把arr1的首地址存在pa中
while (*arr1++ = *arr2++)当(*arr2)为'\0'时,赋给(*arr1)后循环会停止,此时arr1的长度和内容就
和arr2一样了。
;
return pa;//返回pa(arr1)的地址
}
int main()
{
char arr1[20]="xxxxxxxxxxxx";
char arr2[] = "abcdefg";
char*p=my_strcpy(arr1, arr2);
printf("%s", p);//打印被覆盖后的字符串arr1
return 0;
}
运行结果:
strcpy函数的讲解结束。
3.strcat函数
函数原型:extern char *strcat(char *dest, const char *src);
头文件:string.h
功能:把src所指向的字符串(包括“\0”)复制到dest所指向的字符串后面(删除*dest原来末尾的“\0”)。*src中原有的字符不变。返回指向dest的指针。
返回值:指向字符串dest地址的指针
注意:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
代码示例:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20] = "abcdefg";
char arr2[] = "hijklmn";
strcat(arr1, arr2);
printf("%s", arr1);
return 0;
}
运行结果:
在知道strcat函数如何使用后,我们来尝试模拟strcat函数功能的实现。
#include<stdio.h>
char* my_strcat(char* arr1, char* arr2)
{
char* pa = arr1;
while (*++arr1)//当*arr1为'\0'时循环停止
;
while (*arr1++ = *arr2++)//用循环把*arr2的值一个个赋给*arr1,直到*arr2为'\0'时停止循环
;
return pa;
}
int main()
{
char arr1[20] = "abcdefg";
char arr2[] = "hijklmn";
char* p = my_strcat(arr1, arr2);
printf("%s", p);
return 0;
}*/
运行结果:
strcat函数讲解结束。
4.strcmp函数
函数原型:extern int strcmp(const char *s1,const char *s2);
头文件:string.h
功能:比较s1字符串和s2字符串,两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇'\0'为止。
返回值:
当s1<s2时,返回为负数;
当s1=s2时,返回值为0;
当s1>s2时,返回正数。
代码示例:
#include<stdio.h>
#include<string.h>
int main()
{
char arr[]="abcdef";
char arr1[]="abcdes";
int ret=strcmp(arr,arr1);
if(ret>0)
printf("arr>arr1");
else if(arr<0)
printf("arr<arr1");
else
printf("arr==arr1");
return 0;
}
在这里不展示运行结果了,如果感兴趣可以自己尝试。
在了解strcmp如何使用后,我们可以尝试模拟strcmp的功能实现。
代码示例:
#include<stdio.h>
#include<assert.h>
int my_strcmp(char* arr1, char* arr2)
{
assert(arr1 && arr2);//判断指针是否为野指针
while (*arr1++ == *arr2++)//如果在循环过程中arr1!=arr2,则跳出循环执行return。
{
if (*arr1 == '\0')如果在循环过程中arr1为'\0',则arr2也为'\0',则直接返回0.
{
return 0;
}
}
return *(arr1 - 1) - *(arr2 - 1);
}
int main()
{
char arr1[] = "abcde";
char arr2[] = "abcd";
int ret = my_strcmp(arr1, arr2);
printf("%d", ret);
return 0;
}
运行结果:
strcmp函数讲解结束。
5.strncpy函数
函数原型:char *strncpy(char *destinin, char *source, int n);
头文件:string.h
功能:把source指向的字符串的前n个字符(不包括\0,\0得自己手动加在*destin被复制之后)复制到destin指向的字符串中。如果要复制的*source的部分有\0,就把\0复制进去,之后就提前结束,即使没复制到第n个字符也是。
返回值:指向destin的地址的指针
注意: 如果复制source的n个字符不含NULL字符,则结果不会以NULL字符结束,会导致 为乱码。因此,如果不考虑source串复制完整性,可以将destin 最后一字符置为'\0'。
如果n > destin串长度,destin栈空间溢出产生崩溃异常。
综上,一般情况下,使用strncpy时,建议将n置为destin串长度,复制完毕后,为保险起见,将destin串最后一字符置NULL,避免发生输出乱码问题。当然喽,无论是strcpy还是strncpy,保证destin串容量(能容纳下source串)才是最重要的。
代码示例:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcde";
char arr2[] = "xxxxx";
strncpy(arr1, arr2, 4);
printf("%s", arr1);
return 0;
}
运行结果:
在知道如何使用strncpy后,我们模拟一下strncpy函数的功能实现来加深理解。
char* my_strncpy(char* arr2, const char* arr1, int sz)
{
char* pa = arr2;
while (sz--)
{
*arr2++= *arr1++;
}
return pa;
}
int main()
{
int sz = 0;
char arr1[] = "abcdefghijk";
char arr2[20] = { 0 };
scanf("%d", &sz);
char* p = my_strncpy(arr2, arr1, sz);
printf("%s", p);
return 0;
}
因为代码比较简单易懂,因此没有添加注释。strncpy函数讲解结束。
6.strncat函数
函数原型:char * strncat(char *dest, const char *src, size_t n);
头文件:string.h
功能:把src所指字符串的前n个字符添加到dest所指字符串的结尾处,并覆盖dest所指字符串结尾的'\0',从而实现字符串的连接
返回值:指向dest的地址的指针
代码示例:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[10] = "abcde";
char arr2[] = "fgh";
strncat(arr1, arr2, 2);
printf("%s", arr1);
return 0;
}
运行结果:
学会如何使用strncat函数后,我们来尝试模拟实现strncat函数的功能。
代码示例:
char* my_strncat(char* arr1, const char* arr2, int sz)
{
char* pa = arr1;
while (*++arr1)//当arr1为'\0'时循环停止
;
while (sz--)
{
*arr1++ = *arr2++;//把arr2中sz个字符衔接到arr1的后面,覆盖住'\0'.
}
return pa;
}
int main()
{
int a = 0;
char arr1[20] = "abcde";
char arr2[] = "fghijk";
scanf("%d", &a);
char* p = my_strncat(arr1, arr2, a);
printf("%s\n", p);
return 0;
}
运行结果:
strncat函数讲解结束。
7.strncmp函数
函数原型:int strncmp(const char *str1, const char *str2, size_t n)
头文件:string.h
功能:用来比较s1和s2字符串的前n个字符。如果两个字符串相等的话,strncmp将返回0。如果s1是s2的一个子串的话,s1小于s2。
返回值:返回指向str1的地址
由于strcmp与strncmp的使用用法与模拟实现方法极其相似,只是多了选择比较字符数量的功能,因此,在此处不再详细讲解。
8.strstr函数
函数原型:extern char *strstr(char *str1, const char *str2);
头文件:string.h
返回值:若str2是str1的子串,则返回str2在str1的首次出现的地址;如果str2不是str1的子串,则返回NULL。
代码示例:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[10] = "abcdefg";
char arr2[] = "def";
char* ret = strstr(arr1, arr2);
printf("%s", ret);
return 0;
}
运行结果:
接下来尝试模拟一下strstr函数功能的实现。
#include<stdio.h>
char* my_strstr(const char* arr1, const char* arr2)
{
const char* s1 = NULL;//创建两个空指针变量s1、s2
const char* s2 = NULL;
const char* start = arr1;//把arr1的地址存在start中
while (*start)
{
s1 = start;//再把start里存的地址赋给s1
s2 = arr2;//把arr2的地址赋给s2
while(*s1!='\0'&& *s1 == *s2)当循环停下时,说明*s1不等于*s2,或者*s1等于'\0'
{
s1++;
s2++;
}
if (*s2 == '\0')此时判断s2是否等于'\0'
{
return (char*)start;//如果等于则返回此时start指向的arr1的地址
}
start++;如果不等于则start(arr1)++,继续判断
}
return NULL;当没有在arr1中找到arr2时,则返回NULL
}
int main()
{
char arr1[] = "abcdefghk";
char arr2[] = "cdefg";
char* ret = my_strstr(arr1, arr2);
if (ret == NULL)
{
printf("找不到");
}
else
printf("%s", ret);
return 0;
}
strstr的模拟有点困难,需要画图+看代码来理解。
9.strtok函数
函数原型:char *strtok(char*s, const char *delim);
解释:
头文件:string.h
功能:用来将字符串分割成一个个片段。参数s指向欲分割的字符串,参数delim则为分割字符串中包含的所有字符。strtok()在参数s的字符串中发现参数delim中包含的分割字符时,则会将该字符改为\0 字符。
注意:
例如:strtok(123,234,567",")
strtok()函数第一次调用需设置两个参数。第一次分割的结果,返回串中第一个 ',' 之前的字符串123,也就是上面的程序第一次输出123,再把标记设置为\0.
第二次调用该函数strtok(\0,","),返回第一个NULL后面且下一个','前的字符串234,然后再把第二个标记置为\0
一直调用到字符串中不存在更多的标记。因此想要彻底把字符串分割完需要多次调用strtok
返回值:
从s开头开始的一个个被分割的串。当s中的字符查找到末尾时,返回NULL。
如果查找不到delim中的字符时,返回当前strtok的字符串的指针。
所有delim中包含的字符都会被滤掉,并将被滤掉的地方设为一处分割的节点。
代码示例:
#include<stdio.h>
#include<string.h>
int main()
{
//strtok使用
const char str[] = "aaa-bbb-ccc@";
const char s[] = "-@";
char* p = NULL;
for (p = strtok(str, s); p != NULL; p = strtok(NULL, s))
{
printf("%s\n", p);
}
return 0;
}
10.strerror
函数原型:char * strerror ( int errnum );
errnum为错误码
头文件:string.h和errno.h
功能:strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回来。 在不同的系统和C语言标准库的实现中都规定了一些错误码,⼀般是放在 errno.h 这个头⽂件中说明 的,C语言程序启动的时候就会使⽤⼀个全⾯的变量errno来记录程序的当前错误码,只不过程序启动 的时候errno是0,表示没有错误,当我们在使用标准库中的函数的时候发生了某种错误,就会讲对应 的错误码,存放在errno中,而⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是 有对应的错误信息的。
返回值:strerror函数就可以将错误对应的错误信息字符串的地址返回。
函数示例:
#include<stdio.h>
#include<errno>
#include<string.h>
int main()
{
int i = 0;
for (i = 0; i <= 10; i++)
{
printf("%s\n", strerror(i));
}
return 0;
}
使用结果:
至此,字符串函数全部讲解完毕。
二:字符函数
C语言中有⼀系列的函数是专门做字符分类的,也就是⼀个字符是属于什么类型的字符的。这些函数的使用都需要包含⼀个头文件是ctype.h
1.字符分类函数
2.字符转换函数
C语言提供了两个字符转换函数:
int tolower ( int c ); //将参数传进去的大写字母转小写
int toupper ( int c ); //将参数传进去的小写字母转大写
我们可以联立字符分类函数和字符转换函数写一个代码:
#include<stdio.h>
#include<ctype.h>
int main()
{
int i = 0;
int j = 0;
char arr[] = "abcdefg";
char arr1[] = "JFDKSKJ";
while ( arr[i])
{
if (islower(arr[i]))//判断是否为小写
{
int c = toupper(arr[i]);//利用toupper函数将小写转换为大写
putchar(c);
}
i++;
}
printf("\n");
while (arr1[j])
{
if (isupper(arr1[j]))//判断arr1是否为大写
{
int a = tolower(arr1[j]);//利用tolower函数将大写转换为小写
putchar(a);
}
j++;
}
return 0;
}
运行结果:
由于字符函数太多且不复杂,在此就不把剩下的字符函数一个个代码举例了,大家可以自己去实践
至此,字符和字符串函数内容已经全部讲解结束。
制作不易,如果本章内容对你有所帮助的话不妨留个赞再走。