字符函数和字符串函数

article/2025/7/14 1:56:04

目录

1.字符分类函数

2.字符转换函数

3.strlen函数的使用和模拟实现

4.strcpy函数的使用和模拟实现

5.strcat函数的使用和模拟实现

6.strcmp函数的使用和模拟实现

7.strcnpy函数的使用和模拟实现

8.strcnat函数的使用和模拟实现

9.strncmp函数的使用

10.strstr的函数使用和模拟实现

11.strtok函数的使用

12.strerror函数的使用

12.1 perror


1.字符分类函数

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

 我们介绍其中的一个函数,其余函数类似:

         int islower ( int c );

islower是 可以判断参数部分的c是否是小写字母,如果是小写字母,则返回非0的整数,如果不是小写字母,则返回0;

练习:写一个代码,将字符串中的小写字母转成大写,其余字符不变。

#include<stdio.h>
#include<ctype.h>
int main()
{char arr[] = "hello BIT";int i = 0;while (arr[i]){if (islower(arr[i])){arr[i] -= 32;}i++;}printf("%s\n", arr);return 0;
}

2.字符转换函数

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

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

学习了上面的字符转换函数,我们就可以改写上面的练习代码:

#include<stdio.h>
#include<ctype.h>
int main()
{char arr[] = "hello BIT";int i = 0;while (arr[i]){if (islower(arr[i])){arr[i]=toupper(arr[i]);}i++;}printf("%s\n", arr);return 0;
}

3.strlen函数的使用和模拟实现

//函数原型
size_t strlen ( const char* str );

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

参数: str :指针,指向了要统计长度的字符串(一般传字符的首地址)

返回值:返回了str指向的字符串的长度,返回的长度不可能是负数,所以返回类型是size_t。

代码演示:

#include<stdio.h>
#include<string.h>
int main()
{char arr[] = "hello bit";printf("%zu\n", strlen(arr));//%zu是打印无符号类型的整数return 0;
}

模拟实现: 

//方式一 创建第三变量
size_t my_strlen(const char* str)
{const char* strat = str;while (*str){str++;}return str - strat;
}
int main()
{char arr[] = "hello bit";size_t ret = my_strlen(arr);printf("%zu\n", ret);return 0;
}//方式二 不创建其余变量
size_t my_strlen(const char* str)
{if (*str=='\0'){return 0;}else{return 1 + my_strlen(str + 1);}
}
int main()
{char arr[] = "hello bit";size_t ret = my_strlen(arr);printf("%zu\n", ret);return 0;
}

使用注意事项:

字符串必须以‘\0’作为结束标志,strlen函数返回的是在字符串中的'\0'之前的字符个数(不包含\0).

参数指向的字符串必须以'\0'结束。

注意函数的返回类型是size_t类型,是无符号类型。

strlen函数在使用的时候需要包含头文件string.h。 

练习题:

#include<string.h>
int main()
{if (strlen("abc") - strlen("abcdef") > 0){printf(">\n");}else{printf("<\n");}return 0;
}

strlen("abc")的结果是3,strlen("abcdef")的结果是6,很明显3-6<0,那strlen("abc") - strlen("abcdef")的结果就是小于0的吗?我么通过编译器运行可以发现最终打印出的是 >,这是什么原因呢?

我们知道strlen函数的返回类型是size_t类型,也就是无符号整型,计算机在进行运算的时候,是对二进制的补码进行加减运算,size_t类型它认为内存中存的(补码)就是无符号整型,32位二进制全是有效位,所以最终结果是大于0的。

4.strcpy函数的使用和模拟实现

//函数原型
char* strcpy(char* destination ,const char* source);

功能:字符串拷贝,将源头数据拷贝到目标空间,直到遇见源头数据中的 '\0'时停止拷贝。

参数:

destination : 指针,指向目的地空间;

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

返回值:

strcpy函数返回目标空间的起始地址(注意:可以是destination,也可以用变量来接收这个返回值) 

代码演示:

//strcpy
int main()
{char src[] = "hello bit";char dest[20] = { 0 };strcpy(dest, src);printf("%s\n", dest);return 0;
}

 模拟实现:

//模拟实现
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{assert(src);while (*dest++ = *src++)//1.*dest=*str  2.dest++,str++  3.判断循环条件{;}return dest;
}
int main()
{char src[] = "hello bit";char dest[20] = { 0 };my_strcpy(dest, src);printf("%s\n", dest);return 0;
}

while (*dest++ = *src++)
    {
        ;
    } 这段代码的意思是:1.执行赋值语句*dest=*src  2. dest++ src++  3.条件判断 赋值表达式的结果是被复制的值(即赋值的字符),看赋值表达式的结果是否为0.

使用注意事项:

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

会将源字符串中的‘\0’拷贝到目标空间;

目标空间必须足够大,以保证能存放原字符串,并且必须是可以修改的 ;

遇见‘\0’停止拷贝,‘\0’后面的数据不拷贝。 

5.strcat函数的使用和模拟实现

//函数原型
char* strcat(char* destination , const char* source);

功能:字符串追加,将source指向的源头字符串中的所有字符串都追加到destination指向的空间里。从目标空间中的‘\0’位置开始追加,追加到源头数据的‘\0’停止追加(如果源头数据中存在多个‘\0’则遇到最靠前的停止追加),并且将源头数据中的‘\0’也追加到目的地。

参数:
destination : 指针。指向目的地空间;

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

返回值:

strcat函数返回的是目标空间的起始地址。(该返回值可以是destination,也可以用变量来接收返回值) 

代码演示:

//strcat
int main()
{char dest[20] = "hello";char str[] = "world";//方式一//strcat(dest, str);//printf("%s\n", dest);//方式二char* ret= strcat(dest, str);printf("%s\n", ret);return 0;
}

 模拟实现:

#include<assert.h>
char* my_strcat(char* dest, const char* str)
{assert(dest && str);char* ret = dest;while (*dest){dest++;}while (*dest++ = *str++){;}return ret;
}
int main()
{char dest[20] = "hello";char str[] = "world";char* ret = my_strcat(dest, str);printf("%s\n", ret);return 0;
}

使用注意事项:

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

目标字符串中也必须要有‘\0’,否则没办法直到从哪里开始追加;

目标空间必须足够大,能容下源字符串的内容;

目标空间必须是可修改的。

6.strcmp函数的使用和模拟实现

//函数原型
int strcmp(const char* str1, const char* str2);

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

参数:

str1: 指针,指向的是要比较的第一个字符串;

str2: 指针,指向的是要比较的第二个字符串。

返回值:

如果第一个字符串大于第二个字符串,则返回大于0的数字;

如果第一个字符串小于第二个字符串,则返回小于0的数字;

如果第一个字符串等于第二个字符串,则返回0。

代码演示:

int main()
{char arr1[] = "extravgant";char arr2[] = "arrogant";int ret=strcmp(arr1, arr2);if (ret > 0){printf(">\n");}else if (ret == 0)printf("==\n");elseprintf("<\n");return 0;
}

模拟实现:

//模拟实现
#include<assert.h>
int my_strcmp(const char* str1, const char* str2)
{assert(str1 && str2);while(*str1 == *str2){if (*str1){return 0;}str1++;str2++;}if (*str1 > *str2){return 1;}elsereturn -1;
}
int main()
{char arr1[] = "extravgant";char arr2[] = "arrogant";int ret = my_strcmp(arr1, arr2);if (ret > 0){printf(">\n");}else if (ret == 0)printf("==\n");elseprintf("<\n");return 0;
}

7.strcnpy函数的使用和模拟实现

//函数原型
char* strncpy(char* destination, const char* source,size_t num);

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

参数:

destination : 指针,指向目的地空间;

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

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

返回值:

strncpy函数返回目标空间的起始地址。(可以是destination,也可以用其他变量来接收这个返回值) 

代码演示:

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

模拟实现:

#include<assert.h>
char* my_strncpy(char* dest, const char* str, size_t num)
{assert(str);while (num--){*dest = *str;dest++;str++;}return dest;
}
int main()
{char arr[10] = { 0 };char arr2[] = "hello bit";my_strncpy(arr, arr2, 5);printf("%s\n", arr);return 0;
}

注意事项:

若源头数据中的字符数不足num个,则主动用‘\0’补够num个,若拷贝不够num个,但提前遇到‘\0’,则停止拷贝,不够的用'\0'补齐。

strncpy函数指定了拷贝的长度,源字符串不一定要有'\0'。 

8.strcnat函数的使用和模拟实现

//函数原型
char* strncat(char* destination, const char* source,size_t num);

功能:字符串追加,将source指向的字符串的内容,追加到destination指向的空间,最多追加num个字符,追加完成后自动添加'\0',若源头字符串中的字符个数不足num个,则有几个就追加几个。

参数:

destination : 指针,指向目的地空间;

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

num : 从source指向的字符串中最多追加的字符个数。

返回值:

strncat函数返回目标空间的起始地址。(可以是destination,也可以用其他变量来接收这个返回值) 

 代码演示:

//strncat 在末尾追加字符串,限定字符个数
#include<string.h>
int main()
{char str[] = "how are you";char dest[30] = "good morning";strncat(dest, str, 3);printf("%s\n", dest);return 0;
}

模拟实现:

#include<assert.h>
char* my_strncat(char* dest, const char* str, size_t num)
{assert(str);char* ret = dest;while (*dest)dest++;while (num--){*dest = *str;dest++;str++;}return ret;
}
int main()
{char str[] = "how are you";char dest[30] = "good morning";my_strncat(dest, str, 3);printf("%s\n", dest);return 0;
}

9.strncmp函数的使用

//函数原型
int strncmp(const char* str1,const char* str2,size_t num);

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

参数:

str1 : 指针,指向一个比较的字符串;

str2 :指针,指向一个比较的字符串;

num :最多比较的字符个数。

返回值:

如果第一个字符串大于第二个字符串,则返回大于0的数字;

如果第一个字符串小于第二个字符串,则返回小于0的数字;

如果第一个字符串等于第二个字符串,则返回0。

代码演示:

//strncmp 比较限定前num个字符
#include<string.h>
int main()
{char arr1[] = "abcdcvknf";char arr2[] = "abc";int ret=strncmp(arr1, arr2, 4);if (ret > 0)printf(">");else if (ret < 0)printf("<");elseprintf("=");return 0;
}

10.strstr的函数使用和模拟实现

//函数原型
char* strstr(const char* str1, const char* str2);

功能:查找str2指向的字符串在str1指向的字符串中第一次出现的位置。简而言之:在一个字符串中查找子字符串。 

参数:

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

str2 :指针,指向了要查找的字符串。

返回值:

如果找到了,则返回第一次在str1中出现的起始地址;如果没找到,就返回NULL。

代码演示:

#include<string.h>
int main()
{char str1[] = "abbcdfe";char str2[] = "bbc";char* ret=strstr(str1, str2);printf("%s\n", ret);return 0;
}

模拟实现: 

#include<assert.h>
char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);const char* p = str1;const char* s1 = NULL;;const char* s2 = NULL;if (*str2 == '\0')return str1;while (*p)//寻找次数{s1 = p;s2 = str2;//找一次的匹配过程while (*s1 == *s2 && *s2 && *s1){s1++;s2++;}if (*s2 == '\0')return (char*)p;p++;}return NULL;
}
int main()
{char str1[] = "bbc";char str2[] = "abbcdfe";char* ret = my_strstr(str1, str2);if (ret == NULL)printf("找不到\n");elseprintf("找到了,%s\n", ret);return 0;
}

 

11.strtok函数的使用

//函数原型
cahr* strtok(char* str,const cahr* delim);

功能:

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

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

参数:

str:首次调用时传入待分割的字符串;后续调用传入NULL,表示继续分割同一个字符串。

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

返回值:
成功时返回指向当前子字符串的指针,若没有更多子字符串时返回NULL。

 使用步骤:

1.首次调用:传入待分割字符串和分隔符。

2.后续调用:传入NULL和相同的分隔符,继续分割。

3.结束条件:当返回NULL时,表示分割完成。

代码演示:

#include<stdio.h>
#include<string.h>
int main()
{char str1[] = "3604400378@qq.com";char str2[] = "@.";char str3[30] = { 0 };strcpy(str3, str1);char* ret = NULL;for (ret = strtok(str3, str2); ret != NULL;ret=strtok(NULL,str2)){printf("%s\n", ret);}return 0;
}

 注意事项:

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

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

空指针处理:如果输入的str为NULL且没有前序调用,行为未定义。

12.strerror函数的使用

//函数原型
char* strerror(int errnum);

功能:

1. strerror 函数可以通过参数部分的 个错误信息字符串⾸字符的地址。

2. errnum 表示错误码,得到对应的错误信息,并且返回这 strerror 函数只针对标准库中的函数发⽣错误后设置的错误码的转换。

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

参数:

errnum: 表示错误码

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

返回值:

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

代码演示:

#include<string.h>
int main()
{FILE* pf = fopen("data.txt", "r");if (pf == NULL){printf("%s\n", strerror(errno));return 1;}return 0;
}

strerror函数是将错误码翻译成错误信息,然后通过printf函数将错误信息打印出来,不知道有没有小伙伴感到有一点麻烦?有没有一种函数可以自己找到错误信息,然后自己打印出来呢?当然是有的。

12.1 perror

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

代码演示:

#include<string.h>
int main()
{FILE* pf = fopen("data.txt", "r");if (pf == NULL){perror("fopen");return 1;}return 0;
}

输出:

完结~ 


http://www.hkcw.cn/article/IxZYymxuuA.shtml

相关文章

苹果电脑深度清理,让老旧Mac重焕新生

在日常使用苹果电脑的过程中&#xff0c;随着时间推移&#xff0c;系统内会积累大量冗余数据&#xff0c;导致电脑运行速度变慢、磁盘空间紧张。想要让设备恢复流畅&#xff0c;苹果电脑深度清理必不可少。那么&#xff0c;如何进行苹果电脑深度清理呢&#xff1f;接下来为你详…

android binder(1)基本原理

一、IPC 进程间通信&#xff08;IPC&#xff0c;Inter-Process Communication&#xff09;机制&#xff0c;用于解决不同进程间的数据交互问题。 不同进程之间用户地址空间的变量和函数是不能相互访问的&#xff0c;但是不同进程的内核地址空间是相同和共享的&#xff0c;我们可…

2025年ESWA SCI1区TOP,改进成吉思汗鲨鱼算法MGKSO+肝癌疾病预测,深度解析+性能实测

1.摘要 本文针对肝癌&#xff08;HCC&#xff09;早期诊断难题&#xff0c;提出了一种基于改进成吉思汗鲨鱼优化算法&#xff08;MGKSO&#xff09;的计算机辅助诊断系统。由于HCC在早期症状不明显且涉及高维复杂数据&#xff0c;传统机器学习方法易受噪声和冗余特征干扰。为提…

性能测试实例(http和ldap协议压测)

一、某授权服务器生成授权码效率验证&#xff08;http协议&#xff09; 测试背景 在存量数据23万条的情况下&#xff0c;生成一条授权数据&#xff0c;需要10秒左右&#xff0c;用户反应数据生成效率太差&#xff0c;需要优化。初步判断是由于在授权数据生成时&#xff0c;有查…

解锁设计师创意魔法:Onlook赋能你的Web创作

在数字时代的今天&#xff0c;设计和开发的界限正在逐步模糊。无论是经验丰富的程序员&#xff0c;还是初出茅庐的设计师&#xff0c;能在统一的环境中高效实现创意是任何设计工具的理想。而Onlook&#xff0c;不仅是一个开源的视觉编码编辑器&#xff0c;更是一座连接设计与开…

智慧零工平台前端开发实战:从uni-app到跨平台应用

智慧零工平台前端开发实战:从uni-app到跨平台应用 本文将详细介绍我如何使用uni-app框架开发一个支持微信小程序和H5的零工平台前端应用,包含技术选型、架构设计、核心功能实现及部署经验。 前言 在当今移动互联网时代,跨平台开发已成为提高开发效率的重要手段。本次我选择…

用go从零构建写一个RPC(4)--gonet网络框架重构+聚集发包

在追求高性能的分布式系统中&#xff0c;RPC 框架的底层网络能力和数据传输效率起着决定性作用。经过几轮迭代优化&#xff0c;我完成了第四版本的 RPC 框架。相比以往版本&#xff0c;这一版本的最大亮点在于 重写了底层网络框架 和 实现了发送端的数据聚集机制&#xff0c;这…

云服务器突发宕机或无响应怎么办

当云服务器突发宕机或无响应时&#xff0c;需快速定位问题并恢复服务。以下是分步骤的解决方案&#xff1a; 1. 初步确认问题 检查网络连接 本地网络是否正常&#xff1f;尝试 ping 其他网站 排除本地问题。 使用 ping <服务器IP> 或 traceroute <IP> 测试网络连通…

掌握HttpClient技术:从基础到实战(Apache)

目录 前言 一、Apache HttpClient简介 二、HttpClient基础使用 1. 添加依赖 2. 创建HttpClient实例 3. 发送GET请求 4. 发送POST请求 三、HttpClient高级配置与实战案例 1. 连接池优化 2. 超时与重试配置 3. 文件上传&#xff08;Multipart&#xff09; 总结 前言 …

EXCEL--累加,获取大于某个值的第一个数

一、函数 LET(data,A1:A5,cumSum,SCAN(0,data,LAMBDA(a,b,ab)),idx,MATCH(TRUE,cumSum>C1,0),INDEX(data,idx)) 二、函数拆解 1、LET函数&#xff1a;LET(name1, value1, [name2, value2, ...], calculation) name1, name2...&#xff1a;自定义的变量名&#xff08;需以字…

D. Gellyfish and Camellia Japonica【Codeforces Round 1028 (Div. 2)】

D. Gellyfish and Camellia Japonica 思路 贪心构造&#xff08;其实是思维题&#xff09; 先找必要性&#xff0c;再验证充分性&#xff1a; 倒着求出每个位置的下界作为这个位置的值&#xff0c;再正着验证构造出的这个数列是否合法。 代码非常短&#xff0c;这个题如果当时…

GODOT引擎学习日志

最近在学习使用GODOT引擎&#xff0c;发现这个东西很好很强大。此为背景。 刚开始学习&#xff0c;在使用camera3D的时候&#xff0c;发现使用鼠标滚轮进行视角缩放的时候&#xff0c;网上有些内容不全&#xff0c;于是找了一下。其实很简单&#xff1a; Camera3D有个属性是siz…

普通二叉树 —— 最近公共祖先问题解析(Leetcode 236)

&#x1f3e0;个人主页&#xff1a;尘觉主页 文章目录 普通二叉树 —— 最近公共祖先问题解析&#xff08;Leetcode 236&#xff09;&#x1f9e0; 问题理解普通二叉树与 BST 的区别&#xff1a; &#x1f4a1; 解题思路关键思想&#xff1a;&#x1f4cc; 举个例子&#xff1a…

Dify 部署问题处理

Dify介绍 Dify 是一款开源的大语言模型(LLM) 应用开发平台。它融合了后端即服务&#xff08;Backend as Service&#xff09;和 LLMOps 的理念&#xff0c;使开发者可以快速搭建生产级的生成式 AI 应用。即使你是非技术人员&#xff0c;也能参与到 AI 应用的定义和数据运营过程…

《操作系统真相还原》——中断

可以毫不夸张的说&#xff0c;操作系统离不开中断 此时我们将中断处理程序放在了汇编文件中了&#xff0c;很显然我们不能很方便的编写中断处理程序&#xff0c;不如在汇编程序里调用c函数。 在这个感觉过可以在c语言中直接内联汇编完成这些。 定时器 将时钟中断的频率提高后…

腾讯位置商业授权沿途搜索服务开发指南

概述 通过本服务检索某段道路附近的POI信息&#xff0c;可配合路线规划&#xff0c;为用户提供沿途服务区、加油站等搜索功能。 注&#xff1a; 1、本服务属于高级付费服务&#xff0c;如需试用请提交商务合作开通服务试用。 2、本接口有大小限制&#xff0c;接口长度不能超…

内容中台的实施基石是什么?

标准化流程体系构建 在企业内容中台建设中&#xff0c;标准化流程体系是确保内容生产、管理和分发效率的核心框架。通过定义元数据规范、内容分类规则及跨部门协作机制&#xff0c;能够实现从内容创建到归档的全链路标准化运作。例如&#xff0c;Baklib作为支持团队协作与权限…

信息安全管理与评估2024山东卷WAF答案

需要其他赛题解析的可联系博主

[免费]微信小程序网上花店系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序网上花店系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序网上花店系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…

定制开发开源AI智能名片驱动下的海报工厂S2B2C商城小程序运营策略——基于社群口碑传播与子市场细分的实证研究

摘要 本文聚焦“定制开发开源AI智能名片S2B2C商城小程序”技术与海报工厂业务的融合实践&#xff0c;探讨其如何通过风格化海报矩阵的精细化开发、AI技术驱动的用户体验升级&#xff0c;以及S2B2C模式下的社群裂变机制&#xff0c;实现“工具功能-社交传播-商业变现”的生态…