C语言字符函数和字符串函数

前言

今天这篇博客咱们一起来认识一些特殊的函数,在编程的过程中我们经常要处理字符和字符串,为了方便字符和字符串,C语言提供了一些库函数,让我们一起看看这些函数都有什么功能吧!!!

个人主页:小张同学zkf

若有问题 评论区见

感兴趣就关注一下吧


目录

 1. 字符分类函数

2. 字符转换函数

3. strlen的使用和模拟实现

4. strcpy的使用和模拟实现

5. strcat的使用和模拟实现

 6. strcmp的使用和模拟实现

 7. strncpy,strncat, strncmp函数的使用

8. strstr的使用和模拟实现

9. strtok函数的使用

10.strerror函数的使用


1. 字符分类函数

C语言中有一系列的函数是专门做字符分类的,也就是一个字符是属于什么类型的字符的。
这些函数的使用都需要包含一个头文件是 <ctype.h>

 以上函数使用方法非常类似,我们随便列举一个,结构都非常相似

int islower ( int c );

 islower 是能够判断参数部分的 c 是否是小写字母的。
通过返回值来说明是否是小写字母,如果是小写字母就返回非0的整数,如果不是小写字母,则返回0。其他分类函数跟这个一样,满足对应条件返回非0整数,不满足条件,返回0,记住非0的整数不一定是1!!!

2. 字符转换函数
 

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

int tolower ( int c ); //将参数传进去的大写字母转小写
int toupper ( int c ); //将参数传进去的小写字母转大写

这两个函数的功能相当于对应字符ASC码值加减32来转换大小写嘛


从这个函数开始以下所有的函数以str开头的都是字符串函数,头文件<string.h>

3. strlen的使用和模拟实现
 

格式

size_t strlen ( const char * str );

这个已经很熟悉,之前博客无数次提到,它就是字符串函数其中之一strlen函数

注意几个事项:

• 字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包
含 '\0' )。
• 参数指向的字符串必须要以 '\0' 结束。
• 注意函数的返回值为size_t,是无符号的( 易错 )
• strlen的使用需要包含头文件
我们来再看看strlen用法

看以下代码:

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

通俗的说,strlen就是计算字符串中‘\0’之前字符个数

我们既然知道这个函数的功能,那怎么样模仿它实现呢

方法一:

我们分析一下,我们可以创建一个计数变量count,只要传过去的指针解引用满足不为‘\0’字符,那么count就++

以下是我创建的函数来模拟strlen的实现

//计数器方式
int my_strlen(const char * str)
{
int count = 0;
assert(str);//防止传来的函数指针是野指针,可以断言一下
while(*str)
{
count++;
str++;
}
return count;
}
 

方法二:

假如规定我们不创建临时变量,我们该怎么做哪,我们不如用函数递归的思想看可行不可行

用函数递归的方法,将它大事化小,一个字符一个字符的分离加上去,就像橘子那样一片一片的往外剥

看一下代码

//不能创建临时变量计数器
int my_strlen(const char * str)
{
assert(str);
if(*str == '\0')
return 0;
else
return 1+my_strlen(str+1);
}

方法三:

我们还可以用指针运算来模仿strlen函数,指针-指针求得偏移量就是字符个数

看下代码

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

4. strcpy的使用和模拟实现

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

这个strcpy函数功能是将第二个参数字符串拷贝一份到第一个参数,使第一个参数字符串与第二个参数字符串相同

注意:• 源字符串必须以 '\0' 结束。
• 会将源字符串中的 '\0' 拷贝到目标空间。
• 目标空间必须足够大,以确保能存放源字符串。
• 目标空间必须可修改。
 

我们来模拟实现一下这个函数

我们分析一下,简单来说,它不就是将第二个参数字符串中的字符挨个给第一个参数字符串中的字符赋值嘛,那我可以把他们分别解引用,赋完值地址再加加再解引用……循环下去直到把‘\0’也赋值过去停止

以下是模拟这个函数的代码

char* my_strcpy(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while((*dest++ = *src++))
{
;
}
return ret;
}
 

5. strcat的使用和模拟实现

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

strcat这个函数就是追加的意思,将第二个参数的字符串追加到第一个参数的字符串的后面。

注意:

• 源字符串必须以 '\0' 结束。
• 目标字符串中也得有 \0 ,否则没办法知道追加从哪里开始。
• 目标空间必须有足够的大,能容纳下源字符串的内容。
• 目标空间必须可修改

接下来模拟一下这个函数

我们仔细想,可以把它拆成两部分先将目标字符串的指针指向‘\0’,再将要追加的函数从这里进行拷贝

以下是模拟实现这个函数的代码

char *my_strcat(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while(*dest)
{
dest++;
}\\找'\0'
while((*dest++ = *src++))\\开始拷贝
{
;
}
return ret;
}
 

我们假想一下,一个字符串能自己追加自己吗

字符串要是自己追加自己,它原函数的“\0”被覆盖了,你追加函数是它本身,也没“\0”了,所以没"\0"它会死循环追加下去!!!

 6. strcmp的使用和模拟实现

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

看这个函数的格式,我们要知道它的返回值是整形

这个函数就是让字符串进行比较,若第一个参数的字符串大于第二个参数的字符串,返回大于零的数,若第一个参数的字符串小于第二个参数的字符串,返回小于零的数,若相等,返回零,比较的话这两个指针指向的字符串不能变,所以都得用const修饰

那俩字符串具体怎么比较那

就是将他们所有字符asc码值一个一个字符对应比较,直到比较出结果不再比较,‘\0’asc码值比任何字符都小

我们来模拟实现一下这个函数

这个函数简单来说就是每个字符比较呗,那我就分别解引用比较若相等,再地址加加,循环下去,若字符一直相同直到‘\0’还相同,那就返回零代表俩字符相等,若加加过程中,突然字符不相等,那就跳出这个循环,直接返回现在所指的字符之差的数。

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;
}

 7. strncpy,strncat,strncmp函数的使用

这三个跟上面的比肉眼可见多了个n,其实就是有个数限制了

怎么说那

就拿这个strncpy来说

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

发现多了个参数num,这个num的意思就是我要拷贝几个字符过去,就是这意思,拷贝几个就是几个,不带‘\0’拷贝过去,除非它将字符串全拷贝过去带上‘\0’

那strncat,strncmp也是这个意思,我要追加几个,比较几个

注意的是strncat不管追加几个都会自动再追加个‘\0‘,毕竟追加过后的字符串末尾也得有‘\0’呀

8. strstr的使用和模拟实现

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

这个就是在str1中找到str2的字符串,返回的是字符串str2在字符串str1中第⼀次出现的位置

strstr模拟实现:

这个我们先想如果我们找到了对应的第一个字符相同那我们是不是先用一个指针记录下来,假如后面也都相同那不就找到这个函数的位置了嘛,那返回是不是返回位置相同的起始位置,那就是需要记录起始位置的指针,接下来我们再想想找到了第一个相同的字符,接下来肯定需要指针继续往后指进行判断,若中间字符不相同了,那相同的起始位置的指针向后移找到下一个相同的起始位置,从而形成循环,那我是不是又要需要两个指针那,这两个指针分别从相同的起始位置往后移进行比较,所以我们需要创建三个指针,还要记住比较过程中,若中间有一个字符串指向‘\0’,那跳出循环,若是第二个参数字符串先到‘\0’,那就是找到了,返回初始相同位置的指针,若第一个参数字符串都指向‘\0’,而第二个字符串还没有指向‘\0’,那就是没找到。

char * strstr (const char * str1, const char * str2)
{
char *cp = (char *) str1;
char *s1, *s2;
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);
}

9. strtok函数的使用

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

这个函数就是分隔符将字符串分割起来,返回的指针就是这个分隔符标记的指针

哈哈什么意思那

分隔符就是一些特殊符号比如@……这个第二个参数里面存储的字符串就是第一个参数的字符串里特殊符号的集合,就是分隔符的集合

注意:

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

#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "192.168.6.111";
char* sep = ".";
char* str = NULL;
for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
{
printf("%s\n", str);
}
return 0;
}

大家看看这个for循环,初始值就是第一个标记之前的字符串,然后保存这个标记的位置,然后从这个标记的位置开始找到下一个标记,打印这个保存的标记到下一个标记之间的字符串,然后保存下一个标记……直到一个标记为空指针,循环结束

10.strerror函数的使用

char * strerror ( int errnum );

strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回来。

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

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

结果

也可以了解一下perror函数,可以直接将错误信息打印出来。perror函数打印完参数部分的字符串后,再打印一个冒号和一个空格,再打印错误信息。
 举个例子

#include <stdio.h>
#include <string.h>
#include <errno.h>
int main ()
{
FILE * pFile;
pFile = fopen ("unexist.ent","r");
if (pFile == NULL)
perror("Error opening file unexist.ent");
return 0;
}

输出

 Error opening file unexist.ent: No such file or directory

OK字符串函数与字符函数总结结束,下篇总结一些内存函数

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

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

相关文章

基础刷题50之八(数组元素积的符号)

文章目录 前言一、题目二、力扣官方解释文心一言解释总结 前言 刚上研一&#xff0c;有人劝我好好学C&#xff0c;当时用的不多就没学&#xff0c;现在毕业上班了。在此亡羊补牢了 在此感谢力扣和文心一言 一、题目 数组元素积的符号 已知函数 signFunc(x) 将会根据 x 的正负…

python读取execl里的图片

正常的读取图片 from openpyxl import load_workbook from PIL import Imagefrom openpyxl import load_workbook wb load_workbook(rC:\Users\Administrator\Downloads\output1111.xlsx) ws wb[wb.sheetnames[0]] for image in ws._images:data image.anchor._fromif image…

深耕大屏营销领域的酷开科技,为品牌方带来更多的收益

互联网作为一种新的发展趋势&#xff0c;更是为我们提供了无数的机会和无限可能性&#xff0c;从电子商务时代到社交网络时代&#xff0c;价值文化也成为了品牌与消费者之间紧密联系的关键纽带。而在此背景下&#xff0c;OTT大屏拥有着独特的优势&#xff0c;作为OTT行业内的独…

数据库三大范式设计原则

数据库三大范式 第一范式(确保每列保持原子性) 第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值&#xff0c;就说明该数据库表满足了第一范式。 第二范式(确保表中的每列都和主键相关) 第二范式在第一范式的基础之上更进一层。第二范式需要确保数据…

网络工程师——2024自学

一、怎样从零开始学习网络工程师 当今社会&#xff0c;人人离不开网络。整个IT互联网行业&#xff0c;最好入门的&#xff0c;网络工程师算是一个了。 什么是网络工程师呢&#xff0c;简单来说&#xff0c;就是互联网从设计、建设到运行和维护&#xff0c;都需要网络工程师来…

03在ESP-IDF中使用C++面向对象编程

在ESP-IDF中使用C和C进行混合编译 ESP-IDF是Espressif Systems开发的官方IoT开发框架&#xff0c;用于编程和开发ESP32系列的微控制器。虽然ESP-IDF主要使用C语言编写&#xff0c;但它也支持使用C进行开发 为什么要进行混合编译&#xff1f; C是一种功能强大的编程语言&…

【NR 定位】3GPP NR Positioning 5G定位标准解读(十五)-UL-TDOA 定位

前言 3GPP NR Positioning 5G定位标准&#xff1a;3GPP TS 38.305 V18 3GPP 标准网址&#xff1a;Directory Listing /ftp/ 【NR 定位】3GPP NR Positioning 5G定位标准解读&#xff08;一&#xff09;-CSDN博客 【NR 定位】3GPP NR Positioning 5G定位标准解读&#xff08;…

Linux:时间指令 - cal date

Linux&#xff1a;时间指令 - cal & date date指令cal指令 date指令 date用于以指定格式显示时间 我们先看看直接输入date指令的效果&#xff1a; [hxyiZ2zehtehrgzt3wqccrpyfZ CSDN]$ date Tue Mar 12 21:38:01 CST 2024直接输入date指令&#xff0c;得到了以 星期 月 日…

C#,数值计算,解微分方程的龙格-库塔二阶方法与源代码

1 微分方程 含有导数或微分的方程称为微分方程,未知函数为一元函数的微分方程称为常微分方程。 微分方程的阶数 微分方程中导数或微分的最高阶数称为微分方程的阶数。 微分方程的解 使得微分方程成立的函数称为微分方程的解。 微分方程的特解 微分方程的不含任意常数的解称…

蚂蚁集团2025届暑期实习开始啦~

蚂蚁集团2025届暑期实习开始啦&#xff5e;欢迎大家投递信贷事业群-风险管理部的算法岗&#xff0c;找我内推哦&#xff5e;社招也有hc&#xff0c;欢迎大家沟通&#xff01;

STM32CubeIDE基础学习-STM32CubeIDE软件代码编写格式问题

STM32CubeIDE基础学习-STM32CubeIDE软件代码编写格式问题 前言 代码编写最好就是规定一个格式&#xff0c;或者建立一个偏好&#xff0c;这样写出来的代码就方便自己管理了&#xff0c;不然代码乱放下次打开工程就很难找到具体位置&#xff0c;如果规定了格式&#xff0c;那么…

Git 系列:简介安装以及配置管理

文章目录 简介安装简介Centos安装 配置管理[git help](https://www.git-scm.com/docs/git-help)概要选项示例git-doc [git config](https://www.git-scm.com/docs/git-config)概要选项变量示例 初始化配置 简介安装 简介 https://git-scm.com/ Git是一个开源的分布式版本控制…

理论学习:Softmax层和全连接层 全连接层之前的数据

Softmax层和全连接层 Softmax层和全连接层在深度学习模型中通常是紧密相关的&#xff0c;经常一起使用。 全连接层&#xff08;也称为线性层或密集连接层&#xff09;是深度学习模型中常见的层之一&#xff0c;它将输入张量与权重矩阵相乘&#xff0c;并添加偏置项&#xff0c;…

酒店宾馆医院IPTV电视系统质保期满后怎样进行维护?-酒店宾馆医院IPTV电视系统质保期满常年巡检售后服务攻略

酒店宾馆医院IPTV电视系统质保期满后怎样进行维护&#xff1f;-酒店宾馆医院IPTV电视系统质保期满常年巡检售后服务攻略 北京海特伟业任洪卓发布于2024年3月11日 一、酒店IPTV电视系统简述 酒店IPTV电视系统&#xff0c;是新时代“互联网”在酒店领域的重要应用之一&#xff…

15双体系Java学习之数组的声明和创建

数组的声明 ★小贴士 可以使用int[] a;或者int a[];建议使用第一种风格&#xff0c;因为它将元素类型int[]&#xff08;整型数组&#xff09;与变量名清晰分开了。 在Java中声明数组时不能指定其长度。这种定义是非法的&#xff1a;int a[5]; 注意&#xff1a;上图显示的内存…

JDBC连接MysqL

import java.sql.*;public class Demo {public static void main(String[] args) throws ClassNotFoundException, SQLException {//1.注册驱动&#xff0c;加载驱动&#xff1b;Class.forName("com.mysql.jdbc.Driver");//2.获得连接,返回connection类型的对象&…

重学SpringBoot3-集成Thymeleaf

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-集成Thymeleaf 1. 添加Thymeleaf依赖2. 配置Thymeleaf属性&#xff08;可选&#xff09;3. 创建Thymeleaf模板4. 创建一个Controller5. 运行应用并访问页…

数学建模-模糊性综合评价模型

中医药是中国传统文化的重要组成部分&#xff0c;凝聚了中华民族千百年来智慧的结晶。作为中医的发源地&#xff0c;中国政府一直致力于保护、发展和推广中医药&#xff0c;采取了一系列政策措施[]。目前&#xff0c;中国面临着老龄化日益加剧&#xff0c;老年人群中慢性疾病和…

在家不无聊,赚钱有门道:5个正规线上赚钱平台,轻松开启副业

随着网络技术的快速发展&#xff0c;越来越多的人开始寻求通过网络来探索兼职副业的可能性&#xff0c;期望实现额外的收入。在这个过程中&#xff0c;选择一个正规且可靠的线上兼职平台显得尤为关键。 为此小编精心网上盘点了5个正规且靠谱的线上兼职副业平台。这些平台不仅安…

双环PID控制详细讲解

参考博客&#xff1a; &#xff08;1&#xff09;PID双环控制&#xff08;速度环和位置环&#xff09; &#xff08;2&#xff09;PID控制&#xff08;四&#xff09;&#xff08;单环与双环PID&#xff09; &#xff08;3&#xff09;内外双环pid算法 0 单环PID 目标位置→系…