当前位置: 首页 > news >正文

字符函数和字符串函数 last part

前提

我们接下来要说的的函数是:strncpy、strncat、strncmp,这三个之间和strcpy、strcat和strcmp有啥不同呢?

差别在于strcpy、strcat、strcmp只有两个参数,而strncpy、strncat、strncmp有三个参数,那么多了哪个参数呢?

这两者之间的区别是一个没有限制字符长度,一个有限制字符的长度

strncpy的使用

有字符限制的字符复制函数,可以指定num个字符复制到目标字符串,若字符串长度小于num,则在拷贝玩字符串后在目标的后面加上'\0',直到num个

函数结构:

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

返回值:

返回目标字符串的内容

代码:

int main()
{char arr1[] = "abcdef";char arr2[20] = "xxxxxxxxx";strncpy(arr2, arr1, 5);printf("%s\n", arr2);return 0;
}

运行结果:

strncat的使用

有字符限制的字符追加函数,可以指定源字符串追加几个字符到目标字符串中再追加一个'/0',若是源字符串的数量小于num,之会将字符串中的'\0'追加到目标字符串的末尾

函数结构:

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

返回值:

返回目标字符串的内容

代码:

int main()
{char arr1[] = "heil";char arr2[20] = "sieg";strncat(arr2, arr1, 3);printf("%s\n", arr2);return 0;
}

运行结果:

strncmp的使用

有字符限制的字符比较函数,如果str1==str2,则会返回0,若是str1>str2,则会返回1,反之返回-1

函数结构:

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

返回值:

str1==str2返回值为0
str1>str2返回值为正值
str1<str2返回值为负值

代码:

int main()
{char arr1[] = "abcdef";char arr2[] = "abs";int s = strncmp(arr2, arr1, 2);printf("%d\n", s);return 0;
}

运行结果:

strstr的使用与模拟实现

strstr函数专门在字符串中找子字符串的函数,不包含'\0',但是遇到'\0'时会停止

函数结构:

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

返回值:

str1==str2返回str2中str1的指针
str1!=str2返回NULL

代码:

int main()
{char arr1[] = "abcdef";char arr2[] = "cd";const char* ret = strstr(arr1, arr2);  //一定需要有接收值if (ret == NULL)printf("没找到");elseprintf("%s\n", ret);return 0;
}

运行结果:

接下来进行模拟实现

模拟实现前会有好几种情况

第一种:寻找字符串在前头

第二种:需要寻找的字符串在中间

第三种:cur必须移动才能找到匹配的字符


第四种:找不到匹配的字符

第五种特殊情况:arr2为空语句

现在开始写代码,我们用两个字符串来举例来举例

我们看到cur = str1,cur等于str1

cur不等于’\0‘,进入循环,进入循环后看到s1=cur,cur等于s1;s2 = str2,str2等于s2

在看向下一个while循环,条件为*s1 !='\0' && s2 !='\0' && *s1==s2,先看向字符串首字符s1的字符为a,s2的字符为b,s1和s2!='\0',s1和s2不相等,故不进入循环

再看向if语句,我们看到s2不等于'\0',故不返回cur,cur和s1往后一位

再看向while循环s1和s2!='\0',s1==s2,进入循环,s1和s2往后一位

再进行循环s1和s2!='\0',s1==s2,进入循环s1和s2往后一位

再进入循环s1和s2!='\0',s1和s2不相等,不进入循环,s2不等于'\0',不返回cur,cur往后一位

cur!='\0'重新进入循环,s1重置到cur位置,s2重置到首位字符

s1和s2!='\0'且s1==s2,进入循环s1和s2各往后一位

再进行循环,s1和s2!='\0',s1==s2,再各往后一位

再进入循环,s1和s2!='\0'且s1==s2,s1和s2再往后一位

再进入循环,s1!='\0',s2=='\0'且s1!=s2,不进入循环,s2==‘\0’返回cur,循环到此结束

虽然s2=='\0'了,可是s1还没找到‘\0’,当s1找到'\0'是我们可以再函数中加上return NULL来返回空指针

const char* mien_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 cur;cur++;}return NULL;
}

除此之外,还有一种特殊场景,就是子字符串没有字符的(第五种情况),我们可以让它返回str1并加上assert来防止空指针,下面是全部的代码

const char* mien_strstr(const char*str1,const char*str2)
{const char* s1 = NULL;const char* s2 = NULL;const char* cur = str1;assert(str1 && str2);if (str2 == '\0')return str1;while (*cur){s1 = cur;s2 = str2;while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2){s1++;s2++;}if (*s2 == '\0')return cur;cur++;}return NULL;
}
int main()
{char arr1[] = "abbbcdef";char arr2[] = "bbc";const char* ret =mien_strstr(arr1, arr2);if (ret == NULL)printf("没找到");elseprintf("%s\n", ret);return 0;
}

现在来运行看看能不能找到字符串

运行结果:

strtok的使用

strtok(字符切割函数)是用于提取字符串中被分割符号分割的的字符串函数

函数结构:

char * strtok ( char * str, const char * sep );

sep会指向一个字符串,定义用作分隔符号的字符集合

str指定一个字符串,里面包含了0个或多个由sep字符串中一个或多个分割符号分割的标记

strtok会在str中找到下一个分割标记并用'\0'结尾,并返回指向这一个标记的指针

返回值:

如过返回的不是NULL,函数会找str的第一个标记,strtok将他保存在字符串中的位置

如果返回的是NULL,函数会在字符中被保存的位置开始,查找下一个标记

如果不存在其他标记,则返回NULL

代码:

int main()
{char arr[] = "derek@gmail.com";char tmp[40] = {0};strcpy(tmp, arr);const char* sep = "@ .";char * p = strtok(tmp, sep);printf("%s\n", p);p = strtok(NULL, sep);printf("%s\n", p);p = strtok(NULL, sep);printf("%s\n", p);return 0;
}

运行结果:

其实这个代码很冗余,可以使用for循环来完善代码

int main()
{char arr[] = "derek@gmail.com";char tmp[40] = { 0 };strcpy(tmp, arr);const char* sep = "@ .";char* p = NULL;for (p = strtok(tmp, sep); p != NULL;p = strtok(NULL,sep)){printf("%s\n", p);}return 0;
}

运行结果:

还可以再加上其他的字符串,而除了字符串其他的地方都不用改

int main()
{char arr[] = "derek@gmail.com.ch";char tmp[40] = { 0 };strcpy(tmp, arr);const char* sep = "@ .";char* p = NULL;for (p = strtok(tmp, sep); p != NULL;p = strtok(NULL,sep)){printf("%s\n", p);}return 0;
}

运行结果:

第一个代码每多一个字符串就需要增加一行代码

int main()
{char arr[] = "derek@gmail.com.ch";char tmp[40] = {0};strcpy(tmp, arr);const char* sep = "@ .";char * p = strtok(tmp, sep);printf("%s\n", p);p = strtok(NULL, sep);printf("%s\n", p);p = strtok(NULL, sep);printf("%s\n", p);p = strtok(NULL, sep);printf("%s\n", p);return 0;
}

运行结果:

strerror的使用

strerror可以将参数部分的错误码和对应的错误信息传返回

int main()
{for (int a = 0; a < 10; a++){char* p = strerror(a);printf("%d,%s\n", a, p);}return 0;
}

win11+vs2022的运行结果:

在不同的系统中C语言的表准库的实现中都规定一些错误码,一般都是在errno.h这个头文件中解释,C语言启动时就会使用一个全局的变量errno来记录当前的错误码,不过启动的时候为0,表示没有错误,当我们在使用标准库时出现了某种错误就会将对应的错误码存放在errno中,而一个数字是很难理解是啥意思,所以每一个错误码都是有信息的,而strerror就是专门将这些错误信息返回

范例1:

int main()
{FILE* pf = fopen("test.txt","r");if (pf == NULL){printf("%s\n", strerror(errno));return 1;}return 0;
}

运行结果:

也可以了解下perror函数,perror会直接将错误信息打印出来,perror会打印参数中的字符串,再打印一个冒号最后才打印错误信息

范例2:

int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL){perror("hehe");return 1;}return 0;
}

输出结果:


文章转载自:

http://xPsvyHNS.hxsdh.cn
http://eZpxtIPC.hxsdh.cn
http://duA7z2nm.hxsdh.cn
http://D3AiwOcp.hxsdh.cn
http://s6rBcMYl.hxsdh.cn
http://RkKbZGTO.hxsdh.cn
http://9mstaDp0.hxsdh.cn
http://UpLzze7m.hxsdh.cn
http://0cxgElhN.hxsdh.cn
http://yvyi9X0f.hxsdh.cn
http://BL2o1AHs.hxsdh.cn
http://TFSdayld.hxsdh.cn
http://rq9Jsewy.hxsdh.cn
http://yDoOQIzN.hxsdh.cn
http://Djy16IUy.hxsdh.cn
http://UIJb4pEj.hxsdh.cn
http://2281eGvp.hxsdh.cn
http://WtPB9woY.hxsdh.cn
http://zUbelKxN.hxsdh.cn
http://6k7s7nfG.hxsdh.cn
http://ex68DVYL.hxsdh.cn
http://9oO9DnIL.hxsdh.cn
http://WAj7WSSk.hxsdh.cn
http://5KPcWHo0.hxsdh.cn
http://53JCAq0r.hxsdh.cn
http://SmFnSoYP.hxsdh.cn
http://YYAEzAnP.hxsdh.cn
http://hTYdQuEQ.hxsdh.cn
http://I72bLIAS.hxsdh.cn
http://szEzMBjn.hxsdh.cn
http://www.dtcms.com/a/375844.html

相关文章:

  • win安装多个mysql,免安装mysql
  • 开源项目_强化学习股票预测
  • Shell 脚本基础:从语法到实战全解析
  • Nginx如何部署HTTP/3
  • 解一元三次方程
  • A股大盘数据-20250909分析
  • 05-Redis 命令行客户端(redis-cli)实操指南:从连接到返回值解析
  • shell函数+数组+运算+符号+交互
  • 群晖Lucky套件高级玩法-——更新证书同步更新群晖自带证书
  • 照明控制设备工程量计算 -图形识别超方便
  • Matlab通过FFT快速傅里叶变换提取频率
  • iis 高可用
  • 有趣的数学 贝塞尔曲线和毕加索
  • 基于STM32的智能宠物小屋设计
  • STM32之RS485与ModBus详解
  • DCDC输出
  • GitHub 项目提交完整流程(含常见问题与解决办法)
  • Day39 SQLite数据库操作与文本数据导入
  • python常用命令
  • 广东省省考备考(第九十五天9.9)——言语、资料分析、判断推理(强化训练)
  • MySQL问题8
  • 【AI】Jupyterlab中关于TensorFlow版本问题
  • Java 运行时异常与编译时异常以及异常是否会对数据库造成影响?
  • CosyVoice2简介
  • 新机快速搭建java开发环境过程记录
  • std::enable_shared_from_this
  • Spring Boot--Bean的扫描和注册
  • Pytorch基础入门3
  • ARM-指令集全解析:从基础到高阶应用
  • ARM 汇编学习