欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 家装 > 【C/C++】字符函数和字符串函数

【C/C++】字符函数和字符串函数

2025/5/9 15:36:20 来源:https://blog.csdn.net/czx_163/article/details/147798586  浏览:    关键词:【C/C++】字符函数和字符串函数

文章目录

  • 前言
  • 字符函数和字符串函数
    • 1.字符分类函数
    • 2.字符转换函数
    • 3.strlen的使用和模拟实现
      • 3.1 代码演示
      • 3.2 strlen返回值
      • 3.3 strlen的模拟实现
    • 4.strcpy的使用和模拟实现
      • 4.1 代码演示
      • 4.2 模拟实现
    • 5.strcat的使用和模拟实现
      • 5.1 代码演示
      • 5.2 模拟实现
    • 6.strcmp的使用和模拟实现
      • 6.1 代码演示:
      • 6.2 模拟实现:
    • 7.strncpy函数的使用
      • 7.1 代码演示
      • 7.2 ⽐较strcpy和strncpy函数
    • 8.strncat函数的使用
      • 8.1 代码演示
      • 8.2 strcat和strncat对比
    • 9.strncmp函数的使用
      • 9.1 代码演示
      • 9.2 strcmp和strncmp⽐较
    • 10.strstr的使用和模拟实现
      • 10.1 代码演示
      • 10.2 strstr的模拟实现
    • 11.strtok函数的使用
      • 11.1 代码演示
      • 11.2 注意事项
    • 12.strerror函数的使用
      • 12.1 代码演示
      • 12.2 perror

前言

在编程的过程中,我们经常要处理字符和字符串,为了⽅便操作字符和字符串,C语⾔标准库中提供了 ⼀系列库函数,接下来我们就学习⼀下这些函数。

字符函数和字符串函数

1.字符分类函数

C语⾔中有⼀系列的函数是专⻔做字符分类的,也就是⼀个字符是属于什么类型的字符的。 这些函数的使⽤都需要包含⼀个头⽂件是 ctype.h

在这里插入图片描述

这些函数的使⽤⽅法⾮常类似,我们就讲解⼀个函数的事情,其他的⾮常类似:

int islower ( int c );

islower 是能够判断参数部分的 c 是否是⼩写字⺟的。 通过返回值来说明是否是⼩写字⺟,如果是⼩写字⺟就返回⾮0的整数,如果不是⼩写字⺟,则返回 0。

练习:

写⼀个代码,将字符串中的⼩写字⺟转⼤写,其他字符不变。

#include <stdio.h>
#include <ctype.h>
int main ()
{int i = 0;char str[] = "Test String.\n";char c;while (str[i]){c = str[i];if (islower(c)) c -= 32;putchar(c);i++;}return 0;
}

也可以写成

while(str[i]!='\0')
{if(islower(str[i])){str[i]=toupper(str[i]);}i++;
}

2.字符转换函数

C语⾔提供了2个字符转换函数:

int tolower ( int c ); //将参数传进去的⼤写字⺟转⼩写  
int toupper ( int c ); //将参数传进去的⼩写字⺟转⼤写 

上⾯的代码,我们将⼩写转⼤写,是-32完成的效果,有了转换函数,就可以直接使⽤ tolower 函 数。

#include <stdio.h>
#include <ctype.h>
int main ()
{int i = 0;char str[] = "Test String.\n";char c;while (str[i]){c = str[i];if (islower(c)) c = toupper(c);putchar(c);i++;}return 0;
}

3.strlen的使用和模拟实现

size_t strlen ( const char * str );//size_t是无符号整型

功能:统计参数 str 指向的字符串的⻓度。统计的是字符串中 ‘\0’ 之前的字符的个数。

参数:

• str :指针,指向了要统计⻓度的字符串。 返回值:返回了 str 指向的字符串的⻓度,返回的⻓度不会是负数,所以返回类型是 size_t 。

if((strlen("abc")-strlen("abcdef"))>0)//size_t为无符号整型,所以3-6一定大于0
{printf(">\n");//所以输出>
}
else
{printf("<=\n");
}

解决方案

(int)strlen("abc")-(int)strlen("abcdef")

3.1 代码演示

#include <stdio.h>
#include <string.h>
int main()
{const char* str = "abcdef";printf("%zd\n", strlen(str));return 0;
}

使⽤注意事项:

• 字符串以 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前⾯出现的字符个数(不包 含 ‘\0’ )。

• 参数指向的字符串必须要以 ‘\0’ 结束。

• 注意函数的返回值为 size_t ,是⽆符号的( 易错 )

• strlen的使⽤需要包含头⽂件

3.2 strlen返回值

#include <stdio.h>
#include <string.h>
int main()
{const char* str1 = "abcdef";const char* str2 = "bbb";if(strlen(str2) - strlen(str1) > 0)//size_t类型恒大于0{printf("str2 > str1\n");} else{printf("srt1 > str2\n");}return 0;
}

3.3 strlen的模拟实现

⽅式1:

//计数器⽅式 
int my_strlen(const char * str)
{int count = 0;assert(str);//assert断言 头文件<assert.h>while(*str){count++;str++;}return count;
}

⽅式2:

//不能创建临时变量计数器 
int my_strlen(const char * str)
{assert(str);if(*str == '\0')return 0;elsereturn 1 + my_strlen(str+1);//str+1是下一个字符的地址
}
比如
my_strlen("abcdef")=1+my_strlen("bcdef")

⽅式3:

//指针-指针的⽅式 
int my_strlen(char *s)
{assert(str);char *p = s;while(*p != '\0')p++;return p - s;
}

4.strcpy的使用和模拟实现

string copy

char* strcpy(char * destination, const char * source );

功能:字符串拷⻉,拷⻉到源头字符串中的 \0 为⽌

参数:

destination :指针,指向⽬的地空间

source :指针,指向源头数据

返回值:

strcpy 函数返回的⽬标空间的起始地址

4.1 代码演示

#include <stdio.h>
#include <string.h>
int main()
{char arr1[10] = {0};char arr2[] = "hello";strcpy(arr1, arr2);//\0也会拷贝进去printf("%s\n", arr1);return 0;
}

使⽤注意事项:

•源字符串必须以 ‘\0’ 结束.。

• 会将源字符串中的 ‘\0’ 拷⻉到⽬标空间。

• ⽬标空间必须⾜够⼤,以确保能存放源字符串。

• ⽬标空间必须可修改。(不能是常量字符串,因为常量字符串不可以修改)

4.2 模拟实现

#include <stdio.h>
#include <assert.h>
//1.参数顺序 
//2.函数的功能,停⽌条件 
//3.assert
//4.const修饰指针 
//5.函数返回值 
char* my_strcpy(char *dest, const char*src)//src不能修改
{ char *ret = dest;//dest++后变了 所以先存起来assert(dest != NULL);assert(src != NULL);while((*dest++ = *src++))//先用再++,当*src为\0时,终止循环{;}return ret;
}
int main()
{char arr1[10] = {0};char arr2[] = "hello";my_strcpy(arr1, arr2);printf("%s\n", arr1);return 0;
}
void my_strcpy(char* dest,char* src)
{
//拷贝\0前面的内容
while(*src!='\0'){*dest=*src;dest++;src++;}*dest=*src;//拷贝\0
}

5.strcat的使用和模拟实现

连接字符串

char * strcat ( char * destination, const char * source );

功能:字符串追加,把 source 指向的源字符串中的所有字符都追加到 destination 指向的空间 中。

参数:

destination :指针,指向⽬的地空间

source :指针,指向源头数据

返回值:

strcat 函数返回的⽬标空间的起始地址

5.1 代码演示

#include <stdio.h>
#include <string.h>
int main()
{char arr1[20] = "hello ";char arr2[] = "world";strcat(arr1, arr2);printf("%s\n", arr1);return 0;//输出hello world
}

使用注意事项:

• 源字符串必须以 ‘\0’ 结束。

• ⽬标字符串中也得有 \0 ,否则没办法知道追加从哪⾥开始。

• ⽬标空间必须有⾜够的⼤,能容纳下源字符串的内容。

• ⽬标空间必须可修改。

5.2 模拟实现

#include <stdio.h>
#include <assert.h>
char* my_strcat(char *dest, const char*src)
{char *ret = dest;assert(dest != NULL);assert(src != NULL);//这两行等价于assert(dest&&src)//1.找到目标空间中的\0while(*dest)//while(*dest!='\0'){dest++;}while((*dest++ = *src++)){;}return ret;
}
int main()
{char arr1[20] = "hello ";char arr2[] = "world";my_strcat(arr1, arr2);printf("%s\n", arr1);return 0;
}

那如果是自拼接呢

my_strcat(arr1,arr1)
//自拼接会:1.死循环2.系统崩溃            

在这里插入图片描述

6.strcmp的使用和模拟实现

两个字符串比较应用场景 登录: 输入 :用户名 密码

​ 数据库 用户名 密码

int strcmp ( const char * str1, const char * str2 );

功能:⽤来⽐较 str1 和 str2 指向的字符串,从两个字符串的第⼀个字符开始⽐较,如果两个字符 的ASCII码值相等,就⽐较下⼀个字符。直到遇到不相等的两个字符,或者字符串结束。

参数:

str1 :指针,指向要⽐较的第⼀个字符串

str2 :指针,指向要⽐较的第⼆个字符串

返回值:

• 标准规定:

◦ 第⼀个字符串⼤于第⼆个字符串,则返回⼤于0的数字

◦ 第⼀个字符串等于第⼆个字符串,则返回0

◦ 第⼀个字符串⼩于第⼆个字符串,则返回⼩于0的数字

6.1 代码演示:

#include <stdio.h>
#include <string.h>
int main()
{char arr1[] = "abcdef";char arr2[] = "abq";int ret = strcmp(arr1, arr2);printf("%d\n", ret);if(ret > 0)printf("arr1 > arr2\n");else if(ret == 0)printf("arr1 == arr2\n");elseprintf("arr1 < arr2\n");return 0;
}

6.2 模拟实现:

int my_strcmp (const char * str1, const char * str2)
{int ret = 0 ;assert(str1 != NULL);assert(str2 != NULL);while(*str1 == *str2){if(*str1 == '\0')return 0;str1++;str2++;}return *str1-*str2;//最后比较的ASII码值的差
}

7.strncpy函数的使用

strcpy strcat strcmp 是长度不受限的字符串比较 不安全
strncpy strncat strncmp 长度受限函数

char * strncpy ( char * destination, const char * source, size_t num );

功能:字符串拷⻉;将 source 指向的字符串拷⻉到 destination 指向的空间中,最多拷⻉ num 个字符。

参数

destination :指针,指向⽬的地空间

source :指针,指向源头数据

num :从source指向的字符串中最多拷⻉的字符个数

返回值:

strncpy 函数返回的⽬标空间的起始地址

7.1 代码演示

#include <stdio.h>
#include <string.h>
int main()
{char arr1[20] = {0};char arr2[] = "abcdefghi";char* str = strncpy(arr1, arr2, 5);printf("%s\n", arr1);printf("%s\n", str);return 0;
}

长度足够,让拷贝几个就几个,长度小于num补\0

7.2 ⽐较strcpy和strncpy函数

strcpy 函数拷⻉到 \0 为⽌,如果⽬标空间不够的话,容易出现越界⾏为。

strncpy 函数指定了拷⻉的⻓度,源字符串不⼀定要有 \0 ,同时在设计参数的时候,就会多⼀层 思考:⽬标空间的⼤⼩是否够⽤, strncpy 相对 strcpy 函数更加安全。

8.strncat函数的使用

char * strncat ( char * destination, const char * source, size_t num );

功能:字符串追加;将 source 指向的字符串的内容,追加到 destination 指向的空间,最多追 加 num 个字符。

参数

destination :指针,指向了⽬标空间

source :指针,指向了源头数据

num :最多追加的字符的个数

返回值:返回的是⽬标空间的起始地址

8.1 代码演示

#include <stdio.h>
#include <string.h>
int main()
{char arr1[20] = "hello ";char arr2[] = "world";char* str = strncat(arr1, arr2, 5);//从\0开始追加,追加万还加\0printf("%s\n", arr1);printf("%s\n", str);//若num>长度,则追加\0return 0;
}

8.2 strcat和strncat对比

• 参数不同, strncat 多了⼀个参数

• strcat 函数在追加的时候要将源字符串的所有内容,包含 \0 都追加过去,但是 strncat 函 数指定了追加的⻓度。

strncat 函数中源字符串中不⼀定要有 \0 了。

• strncat 更加灵活,也更加安全。

9.strncmp函数的使用

int strncmp ( const char * str1, const char * str2, size_t num );

功能:字符串⽐较;⽐较 str1 和 str2 指向的两个字符串的内容,最多⽐较 num 字符。

参数:

str1 :指针,指向⼀个⽐较的字符串

str2 :指针,指向另外⼀个⽐较的字符串

num :最多⽐较的字符个数

返回值:

• 标准规定:

◦ 第⼀个字符串⼤于第⼆个字符串,则返回⼤于0的数字

◦ 第⼀个字符串等于第⼆个字符串,则返回0

◦ 第⼀个字符串⼩于第⼆个字符串,则返回⼩于0的数字

在这里插入图片描述

9.1 代码演示

#include <stdio.h>
#include <string.h>
int main()
{char arr1[] = "abcdef";char arr2[] = "abcqw";int ret1 = strncmp(arr1, arr2, 3);printf("%d\n", ret1);int ret2 = strncmp(arr1, arr2, 4);printf("%d\n", ret2);return 0;
}

9.2 strcmp和strncmp⽐较

• 参数不同

• strncmp可以⽐较任意⻓度了

• strncmp函数更加灵活,更加安全

10.strstr的使用和模拟实现

char * strstr ( const char * str1, const char * str2);

功能:strstr 函数,查找 str2 指向的字符串在 str1 指向的字符串中第⼀次出现的位置。 简⽽⾔之:在⼀个字符串中查找⼦字符串。 strstr 的使⽤得包含<string.h>

参数:

str1 :指针,指向了被查找的字符串

str2 :指针,指向了要查找的字符串
返回值:

• 如果str1指向的字符串中存在str2指向的字符串,那么返回第⼀次出现位置的指针

• 如果str1指向的字符串中不存在str2指向的字符串,那么返回NULL(空指针)

10.1 代码演示

/* strstr example */
#include <stdio.h>
#include <string.h>
int main ()
{char str[] ="This is a simple string";char * pch;pch = strstr (str,"simple");if (pch != NULL)printf("%s\n", pch);elseprintf("查找的字符串不存在\n");return 0;
}
int main()
{char arr1[]="this is an apple\n";const char* p="is";//放的是i的地址char* ret = strstr(arr1,p);printf("%s\n",ret);return 0;
}

10.2 strstr的模拟实现

char * strstr (const char * str1, const char * str2)//str1 str2不希望被修改
{char *cp = (char *) str1;char *s1, *s2;//特殊情况:str2是空字符串时,直接返回str1 if ( !*str2 )return((char *)str1);while (*cp){s1 = cp;s2 = (char *) str2;while ( *s1 && *s2 && !(*s1-*s2) )s1++, s2++;if (!*s2)return(cp); //返回第⼀次出现的起始 cp++;}return(NULL); //找不到则返回NULL 
}

先来一种简单情况 在abcdef 中找 bcd

在这里插入图片描述

str1指向a时,不符合,所以++指向b,此时与*str2相等,然后str2++,再str1++,直到str2指向\0时结束

再来一种复杂情况

在这里插入图片描述

从第一个b开始时没有
可能存在多次匹配
还得有两个指针变量 存放他们两个的起始变量 然后对他们++ 让起始位置向后平移
char* my_strstr(const char* str1,const char* str2)
{const char* s1=NULL;const char* s2=NULL;const char* cur=str1;while(*cur){s1=cur;s2=str2;while(*s1!='\0'&&*s2!='\0'&&*s1==*s2){s1++;s2++;}if(*s2=='\0'){return char* cur;}cur++;}return NULL;
}

strstr函数的实现有多种,可以暴⼒查找,也有⼀种⾼效⼀些的算法:KMP,有兴趣的可以去学习。

11.strtok函数的使用

char *strtok(char *str, const char *delim);
//delim参数指向了一个字符串,定义了用作分隔符的字符的集合

功能

• 分割字符串:根据delim 参数中指定的分隔符,将输⼊字符串str 拆分成多个⼦字符串。

• 修改原始字符串: strtok 会直接在原始字符串中插⼊’\0’ 终⽌符,替换分隔符的位置,因 此原始字符串会被修改。

参数

1.str :⾸次调⽤时传⼊待分割的字符串;后续调⽤传⼊NULL ,表⽰继续分割同⼀个字符串。

2.delim :包含所有可能分隔符的字符串(每个字符均视为独⽴的分隔符)。

返回值

• 成功时返回指向当前⼦字符串的指针。

• 没有更多⼦字符串时返回NULL 。

使⽤步骤

  1. ⾸次调⽤:传⼊待分割字符串和分隔符。
  2. 后续调⽤:传⼊NULL 和相同的分隔符,继续分割。
  3. 结束条件:当返回NULL 时,表⽰分割完成。

11.1 代码演示

int main()
{char arr[]="fnianxu@yeah.net";char arr2[30]={0};//"fnianxu\0yeah\0net"strcpy(arr2,arr);const char* sep="@.";//传入NULL在\0之后继续进行char* ret=NULL;//初始化ret = strtok(arr2,sep);printf("%s\n",ret);ret = strtok(NULL,sep);printf("%s\n",ret);ret = strtok(NULL,sep);printf("%s\n",ret);
}

运行结果如下:

在这里插入图片描述

但一直传入空指针有些麻烦,所以看以下示例

#include <stdio.h>
#include <string.h>
int main()
{char arr[] = "192.168.6.111";const char* sep = ".";const char* str = NULL;char buf[30] = {0};strcpy(buf, arr); //将arr中的字符串拷⻉到buf中,对buf的内容进⾏切割 for (str = strtok(buf, sep); str != NULL; str = strtok(NULL, sep)){printf("%s\n", str);}return 0;
}

11.2 注意事项

• 破坏性操作: strtok 会直接修改原始字符串,将其中的分隔符替换为’\0’ 。如果需要保留原字符串,应先拷⻉⼀份。

• 连续分隔符:多个连续的分隔符会被视为单个分隔符,不会返回空字符串。

• 空指针处理:如果输⼊的str 为NULL 且没有前序调⽤,⾏为未定义。

12.strerror函数的使用

char* strerror ( int errnum );

功能

1.strerror 函数可以通过参数部分的errnum 表示错误码,得到对应的错误信息,并且返回这个错误信息字符串⾸字符的地址

2.strerror 函数只针对标准库中的函数发⽣错误后设置的错误码的转换。

3.strerror 的使⽤需要包含<string.h>

在不同的系统和C语⾔标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头⽂件中说 明的,C语⾔程序启动的时候就会使⽤⼀个全局的变量 errno 来记录程序的当前错误码,只不过程序启动的时候errno 是0,表⽰没有错误,当我们在使⽤标准库中的函数的时候发⽣了某种错误, 就会将对应的错误码,存放在 errno 中,⽽⼀个错误码的数字是整数,很难理解是什么意思,所 以每⼀个错误码都是有对应的错误信息的。strerror函数就可以将错误码对应的错误信息字符串的地 址返回。

参数:

errnum :表示错误码

这个错误码⼀般传递的是 errno 这个变量的值,在C语⾔有⼀个全局的变量叫: errno ,当库函数 的调⽤发⽣错误的时候,就会讲本次错误的错误码存放在 errno 这个变量中,使⽤这个全局变量需要 包含⼀个头⽂件 errno.h 。

返回值:

函数返回通过错误码得到的错误信息字符串的⾸字符的地址。

12.1 代码演示

#include <errno.h>
#include <string.h>
#include <stdio.h>
//我们打印⼀下0~10这些错误码对应的信息 
int main()
{int i = 0;for (i = 0; i <= 10; i++) {printf("%d: %s\n", i, strerror(i));}return 0;
}

在Windows11+VS2022环境下输出的结果如下:

0: No error
1: Operation not permitted
2: No such file or directory
3: No such process
4: Interrupted function call
5: Input/output error
6: No such device or address
7: Arg list too long
8: Exec format error
9: Bad file descriptor
10: No child processes

举例:

#include <stdio.h>
#include <string.h>
#include <errno.h>
int main ()
{FILE * pFile = NULL;//fopen函数以读的形式打开⽂件,如果⽂件不存在,则打开失败。 pFile = fopen ("unexist.ent", "r");if (pFile == NULL){printf ("错误信息是:%s\n", strerror(errno));return 1;//错误返回 }//读文件 fclose(pf);//关闭文件return 0;//空指针不能解引用
}

输出:

错误信息是:No such file or directory

12.2 perror

也可以了解⼀下 perror 函数, perror 函数相当于⼀次将上述代码中的第11⾏完成了,直接将错误 信息打印出来。 perror 函数打印完参数部分的字符串后,再打印⼀个冒号和⼀个空格,再打印错误 信息。

perror有能力直接打印错误信息,打印的时候,先打印传给perror的字符串,然后打印冒号,再打印空格,最后打印错误码对应信息

perrpr=printf+strerror

#include <stdio.h>
#include <string.h>
#include <errno.h>
int main ()
{FILE * pFile = NULL;pFile = fopen ("unexist.ent", "r");if (pFile == NULL){perror("错误信息是");return 1;}return 0;
}

输出:

错误信息是: No such file or directory

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词