字符串函数-C语言

介绍

字符串函数,简单说,就是处理字符串的函数,头文件是string.h,以下是今天的讲解中会讲到的一系列字符串函数

  • 头文件:#include<string.h>
  • strlen:求字符串长度
  • strcpy:拷贝字符串
  • strcat:追加字符串
  • strcmp:比对字符串
  • strstr:一个字符串中找一个字符串
  • strncpy:拷贝字符串(拷贝指定字符串个数)
  • strncmp:比对字符串(比较指定个数字符个数)
  • strncat:追加字符串(追加指定个数个字符)
  • strtok:提取被分隔字符分隔字符串
  • strerror:可将参数部分错误码对应的错误信息返回

strlen

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

功能:求字符串长度

使用条件:字符串以'\0'结尾

//函数自实现
#include <assert.h>
int my_strlen(const char* str)
{assert(str);int count = 0;while (*str != '\0') {count++;str++;}return count;
}

在库函数实现strlen时,是以'\0'为结尾判断标识的,如果在字符串中间混入了'\0',那么字符串长度的计算就会提前结束,计算的结果也会随之错误;反之,如果字符串结尾没有遇到'\0'那么在计时函数会一直顺着地址找下去,直到找到'\0'为止,这时候strlen返回的结果就是不可预测的了。

此处注明一下sizeof和strlen的区别,首先,sizeof是一个操作符,不是函数,其返回的值是数据类型所占内存大小,可处理的不只是字符串。而strlen恰相反,其只能用来处理字符串并计算其长度。

同时,也要注意到,strlen函数的返回值为size_t:无符号整型。

下面我举一个关于size_t易错的题

//问以下代码的输出结果
#include<stdio.h>
#include<string.h>
int main()
{if(strlen("abc") - strlen("abcd") > 0)printf("大于\n");else printf("小于\n");return 0;
}

大家的第一反应是什么呢?我猜应该是输出小于。但仔细想一想,size_t作为无符号整型,相减会产生负数吗?不会的,所以最后的结果是打印大于。

//函数使用样例
#include<stdio.h>
#inlcude<string.h>
int main()
{char arr[] = "abcdef";int la = strlen(arr);printf("%s\n", la);//打印6return 0;
}

strcpy

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

功能:将参数source字符串拷贝至参数destination所指的地址

返回值:字符串destination起始地址

使用条件:源字符串必须以'\0',结尾

                目标空间必须大于等于拷贝过去字符所占的空间:包括'\0'

//自实现
#include<assert.h>
char* my_strcpy(char* str1, const char* str2)
{assert(str1 && str2);char* ret = str1;while (*str1++ = *str2++);*str1 = *str2;return ret;
}
//使用样例
#include<stdio.h>
#include<string.h>
int main() {char arr1[20] = "abcdef";char arr2[20] = { 0 };char* p1 = strcpy(arr2, arr1);printf("%s\n", arr2);//打印abcdefreturn 0;
}

strcat

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

功能:将source字符串追加到destination字符串末尾

返回值:destination字符串起始地址 

使用条件:两字符串均以'\0'结尾

                目标空间可被修改

                destination末尾'\0'会被覆盖

                目标空间足够大

注(追加位置):destination字符串'\0'及其后面

//自实现
char* my_strcat(char* dest, const char* src)
{char* ret = dest;while (*dest) dest++;while (*dest++ = *src++);return ret;
}
//样例使用
#inlude<stdio.h>
#inclue<string.h>
int main() {char arr1[20] = "abcdef";char arr2[] = "cd";printf("%s\n",strcat(arr1, arr2));//打印abcdefcdreturn 0;
}

 strcmp

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

功能:比较字符串

返回值:两字符串相同返回0

               前一个字符串在字典排序靠前返回负数

               后一个字符串在字典排序靠前返回正数

注:区分大小写比较,如果不希望区分可参考stricmp

//自实现
int my_strcmp(const char* s1, const char* s2)
{while (*s1 == *s2) {if (*s1 == '\0')return 0;s1++;s2++;}if (*s1 > *s2)return 1;else return -1;
}
//代码使用样例
#include<stdio.h>
#include<string.h>
int main() {char arr1[] = "abcdef";char arr2[] = "cd";printf("%d\n", strcmp(arr1, arr2));//打印一个负数return 0;
}

strstr

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

功能:检索str2在str1中第一次出现的位置

返回值: 返回子串str2在str1中第一次出现的位置,找不到返回空指针

//自实现
char* my_strstr(const char* str1,const char* str2)
{const char* cur = str1;const char* s1 = NULL;const char* s2 = NULL;if (!*str2)return (char*)str1;while (*cur) {s1 = cur;s2 = str2;while (*s1 == *s2) {s1++;s2++;}if (*s2 == '\0')return (char*)cur;cur++;}return NULL;
}

以上自实现代码是一份暴力查找版,算法和时间复杂度并不像库函数中那样是最优的,如果想了解真正的内部实现可以去了解KMP算法,此代码只是想让读者更容易了解此函数的功能。

//使用样例
#include<stdio.h>
#include<string.h>
int main() {char arr1[20] = "abcdef";char arr2[] = "cd";printf("%s\n",strstr(arr1, arr2));//打印cdefreturn 0;
}

strncpy 

 函数声明:char* strncpy(char* destination,const char* source,size_t mun);

功能:与strcpy很相似,只是多累个参数,拷贝指定个数的字符串

返回值:字符串destination起始地址

使用条件:源字符串必须以'\0',结尾

                目标空间必须大于等于拷贝过去字符所占的空间:包括'\0'

注:在拷贝完指定个数字符后,不会在串的末尾再拷贝'\0'

//自实现
#include<assert.h>
char* my_strcpy(char* str1, const char* str2,size_t num)
{assert(str1 && str2);char* ret = str1;while ((*str1++ = *str2++)&&num!=0) num--;*str1 = *str2;return ret;
}

strncmp

函数声明:int strcmp(const char* str1,const char* str2,size_t num);

功能:和strcmp很相似,但是多了个参数,比较的是指定个数的字符

返回值:两字符串相同返回0

               前一个字符串在字典排序靠前返回负数

               后一个字符串在字典排序靠前返回正数

注:返回值描述的字符串比较的比较是用num个数截掉后的字符串,具体可参考自实现

//自实现
#include<assert.h>
int my_strncmp(const char* arr1, const char* arr2, size_t num)
{assert(arr1 && arr2);for (int i = 0; i < num; i++) {if (*(arr1 + i) == *(arr2 + i));else if (*(arr1 + i) > *(arr2 + i)) return 1;else return -1;}return 0;
}
//使用样例
#include<stdio.h>
#include<string.h>
int main()
{char arr1[] = "abcdefg";char arr2[] = "abcdfea";int ret =strncmp(arr1, arr2, 4);printf("%d\n", ret);//打印0ret = strncmp(arr1, arr2, 5);printf("%d\n", ret);//打印一个负数return 0;
}

strncat

函数声明: char* strcat(char* destination,const char* source,size_t num);

功能:与strcat功能相似,将source指定个数的字符串追加到destination字符串末尾

返回值:destination字符串起始地址 

使用条件:两字符串均以'\0'结尾

                目标空间可被修改

                destination末尾'\0'会被覆盖

                目标空间足够大

注:destination字符串'\0'及其后面

        追加num个字符后会自动添加'\0'        

//自实现
#include<assert.h>
char* my_strncat(char* arr1, const char* arr2, size_t num)
{assert(arr1 && arr2);char* ret = arr1;while (*arr1)arr1++;for (int i = 0; i < num; i++) {*(arr1 + i) = *(arr2 + i);}*(arr1 + num) = '\0';return ret;
}
//使用样例
#include<stdio.h>
#include<string.h>
#include<assert.h>
int main()
{char arr1[20] = "abcdefg";char arr2[20] = "rhmotyi";char* pc = strncat(arr1, arr2, strlen(arr2));printf("%s\n", pc);    //打印abcdefgrhmotyipc = strncat(arr1, arr2, strlen(arr2) - 2);printf("%s\n", pc);    //打印abcdefgrhmotyirhmotreturn 0;
}

strtok

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

功能:提取被分隔字符分隔字符串

           其中:sep里面放的是分隔符;str里面放的是带分隔符的字符串

           调用一次,将最首先找到的分隔符变成'\0',并标记下一个位置

返回值:上一次标记位置(如第一次调用则返回str首元素地址)

               如果字符串中不存在更多标记,则返回NULL

注:strtok第一个参数不为NULL时,函数找到str中第一个标记,保存在其字符串中的位置

       strtok第一个参数为NULL时,函数将从被保存的位置开始,寻找下一个标记

       strtok内部其实存在静态变量,运行结束后上一次运行数据会有存留(也就是标记地址)

//使用样例
#include <stdio.h>
#include <string.h>
int main()
{const char* p = "@.";char arr[] = "zhangsan@1623.com";char* s = strtok(arr, p);printf("%s\n", s);//zhangsans = strtok(NULL, p);printf("%s\n", s);//1623s = strtok(NULL, p);printf("%s\n", s);//comreturn 0;
}

但是上面的代码似乎有点冗杂,你完全可以写在循环中,见代码

//使用样例(循环版)
#include <stdio.h>
#include <string.h>
int main()
{const char* p = "@.";char arr[] = "zhangsan@1623.com";//char* s = strtok(arr, p);//printf("%s\n", s);//zhangsan//s = strtok(NULL, p);//printf("%s\n", s);//1623//s = strtok(NULL, p);//printf("%s\n", s);//comfor (char* s = strtok(arr, p); s != NULL; s = strtok(NULL, p))printf("%s\n", s);return 0;
}

这两份代码打印出来的结果是相同的

strerror

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

功能:可以将参数部分错误码对应的错误信息字符串返回 

 C语言规定了一些错误码,放在errno.h这个头文件中说明

//样例使用
#include <stdio.h>
#include <string.h>
int main()
{for (int i = 0; i < 10; i++)printf("%d:%s\n",i, strerror(i));return 0;
}

下面是输出结果

 结语

那么本篇博客到这里就要结束了,我们介绍了大部分在平时coding中可能运用到的字符串函数,以及一些函数的自实现,大家可以看看,更利于对函数的了解。如果觉得这篇博客对你有帮助的话,还请点个小赞收藏一下再走啊,如果本篇博客有任何错误也欢迎在评论区讨论或者私我哦--比心♥

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/184618.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用自动化测试获取手机短信验证码

目前在职测试开发,,写一些脚本,个人认为这职业不科学不应该有的职业,测试就是测试,开发就是开发,运维还是老鸟,这行业总能折腾些莫名其妙的东西出来,刚做这行时学的第一门语言是bash shell, 去新去单位上班直接写了个一键搭建测试环境的测试脚本,本来不想干测试了,好好做微信小…

夜莺项目发布 v6.4.0 版本,新增全局宏变量功能

大家好&#xff0c;夜莺项目发布 v6.4.0 版本&#xff0c;新增全局宏变量功能&#xff0c;本文为大家简要介绍一下相关更新内容。 全局宏变量功能 像 SMTP 的配置中密码类型的信息&#xff0c;之前都是以明文的方式在页面展示&#xff0c;夜莺支持全局宏变量之后&#xff0c;可…

kibana安装

kibana安装下载注意事项 地址&#xff1a;curl -O https://artifacts.elastic.co/downloads/kibana/kibana-7.16.3-linux-x86_64.tar.gz 下载后直接解压启动即可 1. 但需要使用非root用户启动 &#xff0c;root用户启动会报错 2. kibana需要和elasticsearch版本一致 不然…

vue3通过el-dropdown实现动态菜单切换页面

这是效果图 首先是主页index.vue <template><el-row><el-col :span"20"><!-- 顶部菜单 --><div v-if"showTop"><topmenu /></div><!-- 右侧下方区域动态切换的内容 --><div style"flex: 1;&quo…

css浮动属性学习

在此文&#xff0c; html菜单的基本制作-CSDN博客 已经看到css 浮动属性的效果&#xff1b;下面单独看一下浮动属性&#xff1b; 做4个div&#xff0c;设置不同的背景色&#xff0c;不为div添加float属性&#xff1b;效果如下&#xff1b; 因为div是块级元素&#xff0c;默认…

上海震坤行:水泥行业数字化采购的趋势、策略与实践

上海震坤行&#xff1a;水泥行业数字化采购的趋势、策略与实践 在中国水泥协会发布的《2023年上半年水泥行业经济运行及下半年展望》中提到了水泥行业的发展现状——2023年上半年&#xff0c;在全球经济增长放缓、国内经济延续恢复态势、但市场需求不足的宏观环境下&#xff0…

【Windows】解决Windows11错误0x80190001

1. 安装Fiddler网络调试工具 下载链接&#xff1a;Fiddler Classic 注&#xff1a;获取安装包的过程中可能要获取邮箱信息&#xff0c;但不用验证邮箱&#xff0c;大概是给你的邮箱发广告信息&#xff0c;问题不大。 在“开始”界面找到Fiddler Classic&#xff0c;点击运行…

办公用品领用管理系统能做什么?如何优化企业运营管理工作?

办公用品相对于公司其他的固定资产来说&#xff0c;大多数都属于低值易耗品&#xff0c;东西虽小但必须要有&#xff0c;且种类较多&#xff0c;因此制定适当的制度对于日常管理来说是十分必要的流程&#xff0c;行政人员也需要根据不同的需求去进一步的完善。然而&#xff0c;…

maven 常用命令解析

目录 maven 是什么 Maven 目录结构 maven 常用命令解析 mvn clean mvn validate mvn compile mvn test mvn package mvn verify mvn install mvn site mvn deploy maven 是什么 Maven 是一个流行的项目管理和构建工具&#xff0c;用于帮助开发人员管理 Java 项目的…

【产品经理】AI在SaaS产品中的应用及挑战

随着ChatGPT大模型在全球的爆火&#xff0c;AI迅速在各个行业内&#xff0c;助力于各行业的效率提升。而SaaS领域&#xff0c;AI同样也大有可为。 AI&#xff08;人工智能&#xff0c;Artificial Intelligence的缩写&#xff09;近一年来一直处于舆论风口&#xff0c;随着ChatG…

「Linux」进程等待与替换

&#x1f4bb;文章目录 &#x1f4c4;前言进程等待进程等待的概念进程等待的方法 进程替换进程替换的概念替换方式 &#x1f4d3;总结 &#x1f4c4;前言 在如今的时代&#xff0c;多进程编程已经变成了必不可少的一部分&#xff0c;而进程等待、进程替换这两个概念都是作为多进…

【matlab程序】图像最大化填充画布

【matlab程序】图像最大化填充画布 不做任何修饰&#xff1a; 修饰&#xff1a; 图片 往期推荐 图片 【python海洋专题一】查看数据nc文件的属性并输出属性到txt文件 【python海洋专题二】读取水深nc文件并水深地形图 【python海洋专题三】图像修饰之画布和坐标轴 【Pytho…

2023-简单点-树莓派-camera module 3介绍

Raspberry Pi Camera Module 3 介绍开头先说&#xff0c;注意事项libcamera感光芯片和驱动的兼容图额外&#xff1a;不同module的对应的参数图用bullseye系统测试摄像头预览窗口拍摄静态图片bayer raw图像获取超长曝光视频流raw视频流 ref 介绍 树莓派镜像在Bullseye版本之后&…

高效的将两个文件夹中多余的文件删除

高效的将两个文件夹中多余的文件删除 解决方案 之前使用的是这个方法&#xff0c;但是图像太多&#xff0c;需要删除的有70W张&#xff0c;得删10多天。。 将两个文件夹中重复的图象删除 解决方案 先将image图像复制一份&#xff0c;然后改名为txt import osdef change_file…

论文笔记:Confidential Assets

Confidential Assets 描述了一种称为“保密交易”的方案&#xff0c;该方案模糊了所有UTXO的金额&#xff0c;同时保持了不创建或销毁硬币的公共可验证性。进一步将此方案扩展到“保密资产”&#xff0c;一种单一的基于区块链的分类帐可以跟踪多种资产类型的方案。将保密交易扩…

Attention机制(笔记)

参考&#xff1a;2.3.2注意力机制-part1_哔哩哔哩_bilibili 什么是attention&#xff1f; 答&#xff1a;注意力放在事物最有辨识度的部分 attention计算机制&#xff1a; 为什么用这个公式可以得到attention&#xff1f; 补充说明&#xff08;chatGPT给出的解释&#xff09;&…

值得收藏的15 个好用的 iPad/iPhone 数据恢复工具

有时您需要从移动或平板设备恢复关键数据。 许多人已经开始在手机上存储重要文件&#xff0c;因为他们可以在旅途中或现在几乎在任何情况下轻松访问数据。 不言而喻; 您只需在手机上轻轻一按&#xff0c;即可轻松访问电子邮件、共享图片、编辑和共享文档、支付账单等。一般来…

【Openstack Train安装】七、glance安装

Glance是为虚拟机的创建提供镜像的服务&#xff0c;我们基于Openstack是构建基本的IaaS平台对外提供虚拟机&#xff0c;而虚拟机在创建时必须为选择需要安装的操作系统&#xff0c;Glance服务就是为该选择提供不同的操作系统镜像。Glance提供Restful API可以查询虚拟机镜像的me…

Flutter创建TabBar

使用TabBar和TabBarView来创建一个包含"首页"、"分类"和"我的"的TabBar。每个Tab对应一个Tab控件&#xff0c;TabBarView中的每个页面对应一个Widget。 1.Tab使用自定义图标和颜色 一般UI设计的图会带渐变色之类的&#xff0c;应该保持图片的原…

【实战教程】PHP如何轻松对接阿里云直播?

1. 配置阿里云直播的推流地址和播放地址 使用阿里云直播功能前&#xff0c;首先需要在阿里云控制台中创建直播应用&#xff0c;然后获取推流地址和播放地址。 推流地址一般格式为&#xff1a; rtmp://{Domain}/{AppName}/{StreamName}?auth_key{AuthKey}-{Timestamp}-{Rand…