0


【C语言】字符串函数详解

hello~~,我是小鹿 ,这是我的第一篇博客,没有循序渐进从基础开始写,只是最近在学习这里就写了,比较随心吧。希望这一篇博客能够给你带来帮助,之后也会继续写的,只是可能没有循序渐进,会比较杂七杂八吧,需要哪些看哪些嘛(可能我太随心了吧,本人比较佛系,不想给自己太大的压力)。
有什么不对的地方希望指正,有什么不好地方可以给我些意见呀

【C语言】字符串函数

1.strlen() - 计算字符串长度

函数的声明方式:size_t strlen(const char* str);

· 字符串以’\0’作为结束标志,strlen函数返回的是字符串’\0’前面出现的字符个数(不包含’\0’);
· 参数指向的字符串必须要以’\0’结束;
· 函数的返回值为 size_t 是无符号整型(unsigned int);
· str->要计算长度的字符串。

strlen()函数代码示例

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strlen函数的头文件intmain(){char arr[]="abcdef";int len =strlen(arr);printf("%d\n", len);return0;}

运行结果:6

注意:如果char arr[]={‘a’,‘b’,‘c’};没有’\0’结尾,则strlen就会一直向后数字符,直至遇到’\0’,返回的是随机值。可以写成char arr[]={‘a’,‘b’,‘c’,‘\0’},此时strlen函数计算的是字符个数。代码如下

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strlen函数的头文件intmain(){char arr[]={'a','b','c'};int len =strlen(arr);printf("%d\n", len);return0;}

运行结果:15(随机值)

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strlen函数的头文件intmain(){char arr[]={'a','b','c','\0'};int len =strlen(arr);printf("%d\n", len);return0;}

运行结果:3

函数的返回值为 size_t 是无符号整型(unsigned int);代码示例:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strlen函数的头文件intmain(){if(strlen("abc")-strlen("abcdef")>0)printf(">\n");elseprintf("<\n");}

运行结果:>

strlen()函数的模拟实现(即自定义实现),代码示例:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<assert.h>//assert函数的头文件size_tmy_strlen(constchar* str){assert(str);//断言,确保不是空指针constchar* start = str;constchar* end = str;while(*end !='\0'){
        end++;}return end - start;//指针-指针得到两指针间元素的个数}intmain(){char arr[]="abcdef";int len =my_strlen(arr);printf("%d\n", len);return0;}

运行结果:6

2.strcpy() - 拷贝字符串

函数的声明方式:char* strcpy(char* destination,const char* source);

· 将source所指向的字符串拷贝到destination中;
· 源字符串(source)必须以’\0’结束;
· 会将源字符串中的’\0’拷贝到目标空间;
· 目标空间(destination)必须足够大,以确保能存放源字符串;
· 目标空间必须可变。

strcpy()函数代码示例:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strcpy的头文件intmain(){char arr1[20]="abc";char arr2[]="hello world";strcpy(arr1, arr2);printf("arr1=%s\n", arr1);return0;}

运行结果:arr1=hello world

注意:目标空间必须可变;若目标空间char* p=“abc”; 此时的字符串"abc"是常量字符串不可改变。代码示例:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>intmain(){char* p ="abc";char arr2[]="hello world";strcpy(p, arr2);printf("%s\n", p);return0;}

运行结果:(运行错误)

strcpy()函数的模拟实现,代码示例:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strcp的头文件#include<assert.h>//asser的头文件char*my_strcpy(char* dest,constchar* src){assert(dest);//断言,确保不是空指针assert(src);char* ret = dest;while(*src!='\0'){*dest =*src;//赋值
        dest++;//指向下一个字符
        src++;//也可以写成*dest++=*src++;}*dest =*src;//将src中的'\0'拷贝进dest中}intmain(){char arr1[20]="abc";char arr2[]="hello world";my_strcpy(arr1, arr2);printf("arr1=%s\n", arr1);return0;}

运行结果:arr1=hello world

3.strcat() - 追加字符串函数

函数的声明方式:char* strcat(char* destination,const char* source);

· 这个函数是将source指向的字符串追加到destination指向的字符串末尾;
· destination - 目标数组,source - 要追加的字符串;
· 源字符串(source)必须以’\0’结束;
· 目标空间(destination)必须有足够大,能容纳下源字符串的内容;
· 目标空间可修改。

strcat()函数代码示例

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strcat的头文件intmain(){char arr1[15]="hello \0xxxxxxxx";//写出"\0xxxxxxxx",从结果可以看出追加arr2时是否追加"\0"char arr2[]="world";strcat(arr1, arr2);printf("arr1=%s\n", arr1);return0;}

运行结果:arr1=hello world

注意:strcat函数不能做到自己给自己追加;
若自己给自己追加函数:
char arr[20] = “hello”;
strcat(arr, arr);->死循环
一个字符数组只有一个内存空间,在一个内存空间中给自己的字符串追加,找到目标空间(arr)的’\0’后,将源字符串(arr)中的第一个元素’h’赋给目标空间的’\0’,则这个内存空间中的字符串就没有了字符串结束标志,就会进入死循环
图片: ![Alt](https://img-home.csdnimg.cn/images/20220524100510.png

strcat()函数的模拟实现,代码示例:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strcat的头文件#include<assert.h>//asser的头文件char*my_strcat(char* dest,constchar* src){assert(dest);//断言。确保不是空指针assert(src);char* cur = dest;while(*cur !='\0'){
        cur++;}while(*cur++=*src++)//当src为'\0'时,将'\0'赋值给cur,'\0'的ASCII码为0(假)跳出循环{;}return dest;//输出的是arr1的起始地址}intmain(){char arr1[15]="hello ";char arr2[]="world";my_strcat(arr1, arr2);printf("arr1=%s\n", arr1);return0;}

运行结果:arr1=hello world

4.strcmp() - 比较两个字符串大小

函数的声明方式:int strcmp(const char* str1,const* str2);

· 将字符串str1与字符串str2进行比较;
· 比较的是对应位置的字符大小,而非长度;
· 从字符串的第一个字符开始比较,相等则比较下一个字符,直到不相等或都为’\0’,此时比较出大小;
· 比较每一位字符 ,比较的是字符的ASCII的值;

· 该函数返回值为int类型:
若 str1 > str2 ,则返回 > 0 的数;
若 str1 < str2 ,则返回 < 0 的数;
若 str1 = str2 ,则返回 0 。

strcmp()函数代码示例

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strcmp的头文件intmain(){char arr1[]="abcdef ";//小char arr2[]="abq";//大int ret =strcmp(arr1, arr2);//比较过程:1. a=a,  2. b=b,  3. c<q  所以arr1<arr2printf("%d\n", ret);if(ret <0)printf("arr1<arr2");elseif(ret >0)printf("arr1>arr2");elseprintf("arr1=arr2");return0;}

运行结果:
-1
arr1<arr2

strcmp()函数的模拟实现,代码示例

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strcmp的头文件#include<assert.h>//assert的头文件intmy_strcmp(constchar* str1,constchar* str2){assert(str1 && str2);//断言,确保不是空指针while(*str1 ==*str2){if(*str1 =='\0'){return0;}
        str1++;
        str2++;}if(*str1 <*str2)//    因为strcmp函数返回的是 >0 或 <0 或 =0 的值return-1;//    所以直接可以写成 :   else//    return *str1-*str;return1;//}intmain(){char arr1[]="abcdef ";char arr2[]="abq";int ret =my_strcmp(arr1, arr2);printf("%d\n", ret);if(ret <0)printf("arr1<arr2");elseif(ret >0)printf("arr1>arr2");elseprintf("arr1=arr2");return0;}

运行结果:
-1
arr1<arr2

注:strcpy、strcat、strcmp 是不受长度限制的字符串;
下面要讲的 strncpy、strncat、strncmp 是受长度限制的字符串。

5.strncpy() - 拷贝字符串(受长度限制)

函数的声明方式:
char* strncpy(char* destination,const char* source,size_t num);

· 把source指向的字符串拷贝到destination中,拷贝num个字符;
· num ->指要从源字符串中拷贝出来的字符数;
· size_t ->无符号整型类型。

· 这个函数实际和strcpy函数功能相同,只是相较于strcpy函数多了一个长度限制。

strncpy()函数代码示例

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strncpy的头文件intmain(){char arr1[20]="abcdef ";char arr2[]="xxxx";strncpy(arr1, arr2,2);printf("arr1 = %s\n",arr1);return0;}

运行结果:arr1 = xxcdef

注意:当arr2的长度小于num时,剩余的会用 ‘\0’ 填充;
例如arr1[20]=“abcdefhhhh”; arr2[]=“xxxx”; 时
strncpy(arr1,arr2,8)得arr1为 xxxx\0\0\0\0hh
下面为代码示例:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strncpy的头文件intmain(){char arr1[20]="abcdefhhhhhhh";char arr2[]="xxxx";strncpy(arr1, arr2,8);printf("arr1 = %s\n",arr1);return0;}

运行结果:arr1 = xxxx

调试结果的步骤:
在这里插入图片描述
strncpy()函数的模拟实现,代码示例

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<assert.h>//assert的头文件char*my_strncpy(char* dest,constchar* src,size_t num){assert(dest && src);//断言,确保不是空指针char* ret = dest;while(num &&(*dest++=*src++)){
        num--;}while(num)//num的值 > src长度,多出来的值的地方用 '\0' 填充;{*dest++='\0';
        num--;}return ret;}intmain(){char arr1[20]="abcdefhhhhhhh";char arr2[]="xxxx";my_strncpy(arr1, arr2,8);printf("arr1 = %s\n",arr1);return0;}

运行结果:arr1 = xxxx

调试结果的步骤:
在这里插入图片描述

6.strncat() - 追加字符串函数(受长度限制)

函数的声明方式:
char* strncat(char* destination,const char* source,size_t num);

· 这个函数是将source指向的字符串追加到destination指向的字符串末尾,追加num个字符;
· num ->指要从源字符串中要追加的字符数;
· size_t ->无符号整型类型。

strncat()函数代码示例:

intmain(){char arr1[20]="abcdef";char arr2[]="xxxx";strncat(arr1, arr2,2);printf("arr1 = %s\n", arr1);return0;}

运行结果:arr1 = abcdefxx

我们可以验证一下追加字符串(arr2)时是否追加了一个\0:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strncat的头文件intmain(){char arr1[20]="abcdef\0hhhhh";char arr2[]="xxxx";strncat(arr1, arr2,2);printf("arr1 = %s\n", arr1);return0;}

运行结果:arr1 = abcdefxx

调试过程:
在这里插入图片描述在这里插入图片描述
证明追加字符串时还追加了一个’\0’

上面讲的strcat函数,说到了自己追加自己会导致死循环;现在我们知道了strncat函数,有长度限制,可以知道自己追加自己时可以使用strncat函数,strncat函数追加字符串(有限长度)时还会在后面追加’\0’。下面我们用strncat函数写一个自己追加自己的函数:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strncat的头文件intmain(){char arr1[20]="abc";strncat(arr1, arr1,3);//这里的3也可以写成strlen(arr1)printf("arr1 = %s\n", arr1);return0;}

运行结果:arr1 = abcabc

strncat()函数的模拟实现,代码示例:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strncat的头文件#include<assert.h>//assert的头文件char*my_strncat(char* dest,constchar* src,size_t num){assert(dest && src);//断言,确保不是空指针char* ret = dest;while(*dest !='\0')//找到目标字符串的末尾{
        dest++;}while(num&&(*src!='\0'))//开始追加源函数{*dest++=*src++;
        num--;}*dest ='\0';//追加字符串后还需追加一个'\0'return ret;}intmain(){char arr1[20]="abcdef";char arr2[]="xxxx";my_strncat(arr1, arr2,2);printf("arr1 = %s\n", arr1);return0;}

运行结果:arr1 = abcdefxx

7.strncmp() - 比较字符串大小(受长度限制)

函数的声明方式:
int strncmp(const char* str1,const char* str2,size_t n);

· 将字符串str1与字符串str2进行比较,最多比较前n个字符;
· 比较的是对应位置的字符大小,而非长度;
· 从字符串的第一个字符开始比较,相等则比较下一个字符,直到不相等或在第n个字符依旧相同时,此时比较出大小(在前n个字符内);
· 比较每一位字符 ,比较的是字符的ASCII的值;

· 该函数返回值为int类型:
若 str1 > str2 ,则返回 > 0 的数;
若 str1 < str2 ,则返回 < 0 的数;
若 str1 = str2 ,则返回 0 。

strncmp()函数代码示例:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strncmp的头文件intmain(){char arr1[20]="abcdef";//前4个字符为 abcdchar arr2[]="abc";//前4个字符为 abc\0int ret =strncmp(arr1, arr2,4);//比到第四个字符时 d>'\0',所以arr1>arr2,返回值为 1printf("%d\n", ret);if(ret <0)printf("arr1<arr2");elseif(ret >0)printf("arr1>arr2");elseprintf("arr1=arr2");return0;}

运行结果:
1
arr1>arr2

strncmp()函数的模拟实现,代码示例:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strncmp的头文件#include<assert.h>//assert的头文件intmy_strncmp(constchar* s1,constchar* s2,size_t n){assert(s1 && s2);//断言,确保不是空指针while((--n)&&(*s1 ==*s2)){if(*s1 =='\0'){return0;}
        s1++;
        s2++;}if(*s1 >*s2)return1;elseif(*s1 ==*s2)return0;elsereturn-1;}intmain(){char arr1[20]="abcdef";char arr2[]="abc";int ret =my_strncmp(arr1, arr2,4);printf("%d\n", ret);if(ret <0)printf("arr1<arr2");elseif(ret >0)printf("arr1>arr2");elseprintf("arr1=arr2");return0;}

运行结果:
1
arr1>arr2

8.strstr() - 在一个字符串中找另一个字符串

函数是声明方式:char* strstr(const char* str1,const char* str2);

· 在一个字符串中(str1)找另外一个字符串(子串str2)是否存在;存在:则返回子串所在的起始位置;不存在:返回NULL;

strstr()函数代码示例:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strstr的头文件intmain(){char arr1[20]="abcdef";char arr2[]="bcd";char* p =strstr(arr1, arr2);if(p =="NULL")printf("不存在");elseprintf("%s\n", p);return0;}

运行结果:bcdef

strstr()函数的模拟实现:
原理: 举个例子来说明:在字符串"abbbcdef",中找子串"bbc"。
在这里插入图片描述
当s1(指针)指向第二个字符(‘b’)时,此时发现这个字符与子串第一个字符相同,将s1指针赋给p(p是子串的起始地址),让s1与s2向前移动一个字符的位置,此时s1指向字符’b’,s2也指向字符’b’,再次向前移动,此时s1指向字符’b’,s2指向字符’c’,‘b’!=‘c’;然后需要从开始比对的字符位置(也就是p指向的位置)的下一个字符再次开始比对,此时需p++,然后s1=p,还需将s2返回起始位置,再次开始比对,
在这里插入图片描述
此时s1指向字符’b’,s2指向字符’b’,相同,让p指针留在这个位置,让s1指针向前移动一个字符,指向字符’b’,s2也向前移动一个字符,指向字符’b’,再次同时向前移动,此时s1指向字符’c’,s2也指向字符’c’,继续向前移动,此时s1指向字符’d’,s2指向字符’\0’(字符串结束标志:‘\0’)。子串指向’\0’时,说明已经在目标字符串(“abbbcdef”)中找到子串(“bbc”)。返回这个子串所在的起始位置。
代码示例:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>char*my_strstr(constchar* str1,constchar* str2){constchar* s1 = str1;constchar* s2 = str2;constchar* p = str1;while(*p){
        s1 = p;
        s2 = str2;while(*s1 !='\0'&&*s2 !='\0'&&(*s1 ==*s2)){
            s1++;
            s2++;}if(*s2 =='\0'){return(char*)p;//此时找到了子串}
        p++;}returnNULL;//找不到了}intmain(){char arr1[20]="abbbcdef";char arr2[]="bbc";char* p =my_strstr(arr1, arr2);if(p =="NULL")printf("不存在");elseprintf("%s\n", p);return0;}

9.strtok() - 切割字符串

函数的声明方式:char* strtok(char* str,const char* sep);

· strtok作用是为了分解字符串的;
· sep参数是个字符串,定义了用作分隔符的字符集合;
· 第一个参数指定一个字符串,它包含0个或者多个sep字符串中一个或多个分隔符分割的标记;
· strtok函数找到str中的下一个标记,并将其用’\0’结尾,返回一个指向这个标记的指针;(注:strtok会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改)
· strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置;
· strtok的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始查找下一个标记;
· 如果字符串中不存在更多的标记,则返回NULL指针。

举个例子来说明:
分解字符串"xiaolu@qq.com"
此时sep为"@."(分隔符字符的集合)
代码示例:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strtok的头文件intmain(){char arr[]="[email protected]";char buf[20]={0};//strtok会改变被操作的字符串,所以使用临时拷贝的内容strcpy(buf, arr);constchar* p ="@.";char* str =strtok(buf, p);//strtok函数返回的是地址printf("%s\n", str);
    str =strtok(NULL, p);printf("%s\n", str);
    str =strtok(NULL, p);printf("%s\n", str);return0;}

可以写成循环语句:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strtok的头文件intmain(){char arr[]="[email protected]";char buf[20]={0};//strtok会改变被操作的字符串,所以使用临时拷贝的内容strcpy(buf, arr);constchar* p ="@.";char* str =strtok(buf, p);while(str !=NULL){printf("%s\n", str);
        str =strtok(NULL, p);}return0;}

运行结果:
xiaolu
qq
com

10.strerror()-将错误码转化为错误信息

函数的声明方式:char* strerror(int errnum);

· errnum是错误码(C语言中库函数报错时的错误码);
· 返回值为字符串,即错误码对应的错误信息;

一些错误码所对应的错误信息为(代码示例 ):

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strerror的头文件intmain(){printf("%s\n",strerror(0));//No error 没有错误printf("%s\n",strerror(1));//Operation not permitted 操作不允许printf("%s\n",strerror(2));//No such file or directory 没有这个文件printf("%s\n",strerror(3));//No such process 进程不存在printf("%s\n",strerror(4));//Interrupted function call 中断系统的调用return0;}

运行结果:
No error
Operation not permitted
No such file or directory
No such process
Interrupted function call

函数的运用:代码示例
注:打开文件的函数为 fopen()
关闭文件的函数为 fclose()
errno:C语言提供的全局的错误变量,将错误码记录到错误码变量(errno)中,
errno的头文件是#include <errno.h>

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>//strerror的头文件#include<errno.h>//errno的头文件intmain(){//此时我的电脑中没有test.txt文件
    FILE* pf =fopen("test.txt","r");//打开 test.txt 文件,以读(r)的形式if(pf ==NULL)//如果打开为空指针,则打开失败{printf("%s\n",strerror(errno));return1;}fclose(pf);
    pf =NULL;return0;}

运行结果:No such file or directory

也可以写成:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>intmain(){
    FILE* pf =fopen("test.txt","r");//打开 test.txt 文件,以读(r)的形式if(pf ==NULL)//如果打开为空指针,则打开失败{perror("fopen");return1;}fclose(pf);
    pf =NULL;return0;}

运行结果:fopen: No such file or directory

perror(“fopen”) 打印的依然是errno变量中错误码对应的错误信息
perror相当于printf+strerror

11.toupper()-字符转换,小写转大写

函数的声明方式:int toupper(int c);

toupper的头文件为#include <ctype.h>

函数的代码示例

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<ctype.h>//toupper的头文件intmain(){char ch ='w';printf("%c",toupper(ch));return0;}

运行结果:W

tolower()-字符转换,大写转小写

函数的声明方式:int tolower(int c);

tolower的头文件为#include <ctype.h>

函数的代码示例

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<ctype.h>//tolower的头文件intmain(){char ch ='W';printf("%c",tolower(ch));return0;}

运行结果:w

运用:代码示例
将"Are you ok?"这个字符串中的字母都转为大写
注:判断字母是否为小写的函数为islower(),头文件为#include <ctype.h>

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<ctype.h>intmain(){char arr[]="Are you ok?";char* p = arr;while(*p){if(islower(*p))//判断函数是否为小写{*p =toupper(*p);}
        p++;}printf("%s", arr);return0;}

运行结果:ARE YOU OK?

好啦,文章到这里就结束啦,有需要可以期待一些我的下一篇博客呀~

**第一次写,实在不知道表情包怎么插 (*꒦ິ⌓꒦ີ),跪求个三连(*꒦ິ⌓꒦ີ)实在不行点个赞也行呀~,关注更好啦,欸嘿(/≧▽≦)/**

标签: c语言

本文转载自: https://blog.csdn.net/mmmocen/article/details/127075300
版权归原作者 ~小鹿 所有, 如有侵权,请联系我们删除。

“【C语言】字符串函数详解”的评论:

还没有评论