【c语言】字符函数与字符串函数(上)

news/2024/11/17 19:48:00/

大家好呀,今天给大家分享一下字符函数和字符串函数,说起字符函数和字符串函数大家会想到哪些呢??我想到的只有求字符串长度的strlen,拷贝字符串的strcpy,字符串比较相同的strcmp,今天,我要分享给大家的是我们一些其他的字符函数和字符串函数,跟着小张一起去看看吧!

文章目录

  • 前言
  • 长度不受限制的字符串函数
    • strcat
  • 长度受限制的字符串函数
    • strncpy
    • strncat
    • strncmp
  • 字符串查找
    • strstr
    • strtok
  • 错误信息报告
    • strerror
  • 模拟实现
    • strcat的模拟实现
    • strstr的模拟实现
  • 总结

前言

C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串中或者字符数组 中.字符串常量 适用于那些对它不做修改的字符串函数


长度不受限制的字符串函数

strcat

功能:可以在一个字符串后面追加字符
函数声明:char *strcat( char *strDestination, const char *strSource );
头文件:string.h
参数解释以及返回值解释:第一个参数接收被追加字符串数组的地址,第二个参数是追加的内容字符串数组,返回的是追加后字符串数组的地址
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
#include <string.h>int main()
{char arr1[20] = "abcdef";char arr2[] = "gh";strcat(arr1, arr2);printf("%s", arr1);}

注意:源字符串必须以 ‘\0’ 结束。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。

int main()
{char arr1[20] = "abcdef";char arr2[] = {'a','b','c'};strcat(arr1, arr2);printf("%s", arr1);
}

在这里插入图片描述
程序发生崩溃,arr2数组如果没有’\0’的话,他会在后面地址上找到\0,在追加到arr1数组的时候,会越界放不下

字符串strcat函数不能自己给自己追加

追加前在这里插入图片描述
追加后
在这里插入图片描述
追加的时候把源数组中的‘\0’被追加字符所覆盖


长度受限制的字符串函数

strncpy

功能:拷贝num个字符从源字符串到目标空间
函数声明:char * strncpy ( char * destination, const char * source, size_t num );
头文件:string.h
参数:第一个参数为接收目标空间地址,第二个参数接收是源空间地址,返回参数是目标地址,size_t是无符号整数类型,num是拷贝字符的数目

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
#include <string.h>int main()
{char arr1[40] = "hered ";char arr2[] = "ll";strncpy(arr1,arr2,2);printf("%s",arr1);
}

在这里插入图片描述

如果源字符小于要拷贝的个数会怎么样??

int main()
{char arr1[40] = "hered+++++++++ ";char arr2[] = "ll";strncpy(arr1, arr2, 10);printf("%s", arr1);
}

在这里插入图片描述
在这里插入图片描述

注意:拷贝num个字符从源字符串到目标空间。
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。


strncat

功能:追加num个字符从源字符串到目标空间。
声明:char * strncat ( char * destination, const char * source, size_t num );
头文件:string.h
参数:第一个参数为接收目标空间地址,第二个参数接收是源空间地址,返回参数是目标地址,size_t是无符号整数类型,num是追加字符的数目

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{char arr1[40] = "hello ";char arr2[13] = "shuxiansheng";strncat(arr1, arr2, 3);printf("%s",arr1);
}

在这里插入图片描述

strncat可以追加自己

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{char arr1[40] = "hello ";char arr2[13] = "shuxiansheng";strncat(arr1, arr1, 5);printf("%s",arr1);
}

在这里插入图片描述


strncmp

功能:可以比较指定个数的字符串比较
声明:int strncmp ( const char * str1, const char * str2, size_t num );
头文件:string.h
参数:第一个参数接收第一个字符串地址,第二个参数接收第二个字符串地址,第三个参数为比较字符的个数,比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{char arr1[6] = "hello";char arr2[] = "helld";int ret=strncmp(arr1, arr2, 4);printf("%d", ret);
}

在这里插入图片描述

比较前四个字符,由于前四个字符相同,返回0,比较五个字符,o的ascll码值大于d的ascll码值返回1;


字符串查找

strstr

功能:查找子串
声明: char * strstr ( char * str1, const char * str2 );
头文件string.h
参数:第一个参数接收被查找的字符串的首地址,第二个参数疑似子串的字符串的首地址
如果是子串的话,返回字符串中子串的首地址,不是子串的话返回空指针在这里插入图片描述

代码

int main()
{char arr1[] = "abcdefg";char arr2[] = "fg";char *p=strstr(arr1,arr2);//保存返回子串的首地址if (p){printf("是子串:%s", p);}else{printf("不是子串");}}

编译运行

在这里插入图片描述
在这里插入图片描述


strtok

功能:分隔子串
声明:char * strtok ( char * str, const char * sep );
头文件:string.h
参数:第一个参数接收被分解字符串的地址,第二个参数中接收的是字符串中分隔符的地址,返回被分隔子串的首地址

代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{char arr1[20] = "hello@qq.com";char arr2[] = "@.";strtok(arr1, arr2);printf("%s", arr1);
}

编译运行
在这里插入图片描述

第一个参数指定一个字符串,它包含了0个或者多个由arr2字符串中一个或者多个分隔符分割的标记。
strtok函数找到arr1中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。
strtok函数的第一个参数不为 NULL ,函数将找到arr1中第一个标记,strtok函数将保存它在字符串中的位置(strtok函数在内部维护了一个静态变量保存这个位置)。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回 NULL 指针

代码展示

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{char arr1[20] = "hello@qq.com";char arr2[] = "@.";printf("%s\n", strtok(arr1, arr2));printf("%s\n", strtok(NULL, arr2));printf("%s\n", strtok(NULL, arr2));}

编译运行
在这里插入图片描述

修改:我们可以将字符串arr1传给strtok函数,第一个@分隔符。strtok函数返回字符串中第一个遇到分隔符之前的字符串首地址,”hello’',然后在循环中继续调用strtok函数,第一个参数传NULL,strtok自己维护的静态变量,记住上次分隔的地方,不用在传arr1.

代码实现

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{char arr1[20] = "hello@qq.com";char arr2[] = "@.";char* p =NULL;for (p = strtok(arr1, arr2); p != NULL; p = strtok(NULL, arr2)){printf("%s\n",p);}}

编译运行
在这里插入图片描述


错误信息报告

strerror

功能:可以返回指向错误信息字符串地址
声明:char *strerror( int errnum );
头文件:string.h errno.h
参数:errnum是错误码,就像404页面,每个错误码对应着错误信息,返回值是指向错误信息字符串地址

int main()
{printf("%s\n", strerror(0));printf("%s\n", strerror(1));printf("%s\n", strerror(2));printf("%s\n", strerror(3));}

在这里插入图片描述

当我们向内存申请空间时,我们会使用malloc函数,如果申请的内存太大,是否会报错呢??它会将错误码放在整型全局变量errno中,使用errno时引用头文件errno.h

代码展示:

`#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{int *p=malloc(4000000000);//malloc申请内存失败会返回空地址if (p == NULL){printf("%s\n", strerror(errno));}}`

在这里插入图片描述

注意:遇到多个错误时,errno会不断赋新的错误码


模拟实现

strcat的模拟实现

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* mystrcat(char* p, char* q)
{assert(p && q);char* k = &p;//随着p++,会丢失目标字符串首地址先保存while (*p){p++;}//将p指针移动到目标字符串'\0'位置while ((*p++=*q++))//将*q的值先给*p,然后两个q++;p++;赋值后的ascll值不为0,继续循环,当*q=='\0',赋值后ascll码值为'\0',退出循环{}return k;//返回目标字符串首地址
}
int main()
{char arr1[20] = "abcde";char arr2[5] = "qqq";mystrcat(arr1, arr2);printf("%s", arr1);}

在这里插入图片描述


strstr的模拟实现

char* mystrstr(char* str1, char* str2)
{char* s1 = str1;//两个遍历指针分别指向两个字符串的首地址char* s2 = str2;char* cur = s1;//两个字符串开始匹配的指针while (*cur)//每循环一次,就是重新匹配的过程{s1 = cur;//s1移动到下一个开始匹配的位置s2 = str2;//子串要从头开始匹配while (*s1&&*s2&&(*s1 == *s2))//匹配的循环{s1++;s2++;}//不匹配退出循环if (*s2 == '\0')//当匹配循环完,s2的指针指向子串的末尾'\0';{return cur;//保存的是匹配成功时,字符串中匹配到的第一个字符首地址}cur++;                       //此时cur指向的位置不能作为开始匹配的位置,cur++;开始新一轮的匹配}return NULL;//当cur遍历完字符串,则说明没有该子串
}
int main()
{char arr1[] = "abcdecdfg";char arr2[] = "cdf";char *p=mystrstr(arr1,arr2);//如果找到子串返回字符串中和子串匹配的首字符首地址不为空if (p){printf("是子串");}else{printf("不是子串");}}

编译运行
在这里插入图片描述
在这里插入图片描述


总结

字符串函数,字符函数在处理字符问题特别的方便,使得问题简单化,本章还未讲到的内存操作函数放在下一篇讲,如果你觉得这篇文章对你有帮助的话,别忘了给小张点赞,收藏加关注,哪里不对的话还望大佬们指教,谢谢大家!!我会持续分享给大家自己学到的知识,也是在好好的做总结


http://www.ppmy.cn/news/1028526.html

相关文章

【枚举+推式子】牛客小白月赛 63 E

登录—专业IT笔试面试备考平台_牛客网 题意&#xff1a; 思路&#xff1a; 首先是个计数问题&#xff0c;考虑组合数学 组合数学就是在考虑枚举所有包含1和n的区间 这个典中典就是枚举1和n的位置然后算贡献 双指针超时&#xff0c;考虑推式子&#xff1a; Code&#xff1a…

redis在java中的使用

redis在java中的使用 Redis是一个基于内存的key-value结构数据库&#xff0c;spring data redis是spring的一部分&#xff0c;对redis底层开发包进行了封装&#xff0c;可以直接使用Spring Data Redis简化操作。 5种常见的数据类型 Redis中key是字符串类型&#xff0c;value…

分布式文件存储系统-FastDFS

前言&#xff1a;FastDFS 是一个分布式文件存储系统&#xff0c;主要用于存储和管理大规模的文件数据&#xff0c;如图片、视频、文档等&#xff0c;是淘宝前架构师为了存储图片用C语言开发出来的系统。 服务端有两个组件 Tracker Server 与 Storage Server &#xff0c;对应两…

登录验证码实现

Hutool代码改造 Hutool 有参考文档&#xff1b;很多工具类&#xff1b;把一些功能都封装好&#xff1b;都不用你自己去写&#xff1b;直接调用它的工具类 它这里会详细告诉你引入方式Hutool <dependency><groupId>cn.hutool</groupId><artifactId>hu…

化工行业案例 | 甄知科技助力万华化学重构IT服务价值,打造信息中心ERP!

随着科技的发展&#xff0c;新材料的应用领域与日俱增&#xff0c;近年来&#xff0c;全球化工新材料产业发展整体步入高技术引领、产品迭代速度快、产业规模和需求不断扩大的阶段。一体化协同与数字化转型策略是实现化工新材料生产原料自给、节能降耗、降低排放和物料成本的重…

tomcat服务七层搭建动态页面查看

一个服务器多实例复制完成 配置tomcat多实例的环境变量 vim /etc/profile.d/tomcat.sh配置tomcat1和tomcat2的环境变量 进入tomcat1修改配置 测试通信端口是否正常 连接正常 toncat 2 配置修改 修改这三个 端口配置修改完成 修改tomcat1 shudown 分别把启动文件指向tomcat1…

04 mysql innodb record

前言 最近看到了 何登成 大佬的 "深入MySQL源码 -- Step By Step" 的 pdf 呵呵 似乎是找到了一些 方向 之前对于 mysql 方面的东西, 更多的仅仅是简单的使用[业务中的各种增删改查], 以及一些面试题的背诵 这里会参照 MySQL Internals Manual 来大致的看一下 i…

【Matlab智能算法】Elman神经网络-遗传算法(Elman-GA)函数极值寻优——非线性函数求极值

往期博客&#x1f449; 【Matlab】BP神经网络遗传算法(BP-GA)函数极值寻优——非线性函数求极值 【Matlab】GRNN神经网络遗传算法(GRNN-GA)函数极值寻优——非线性函数求极值 【Matlab】RBF神经网络遗传算法(RBF-GA)函数极值寻优——非线性函数求极值 本篇博客将主要介绍Elman神…