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

字符函数与字符串函数

字符函数与字符串函数

  • 1、 strcmp 函数
    • 1.1、使用
    • 1.2、模拟实现
  • 2、字符分类函数和字符转换函数
    • 2.1、字符分类函数
    • 2.1、字符转换函数
    • 2.3、实践
  • 3、strlen 函数
    • 3.1、使用
    • 3.1、模拟实现
  • 4、`strcpy()`函数
    • 4.1、使用
    • 4.2、模拟实现
  • 5、`strcat()`函数
    • 5.1、使用
    • 5.2、模拟实现
  • 6、`strncpy()`
    • 6.1、使用
  • 7、`strncat()`
    • 7.1、使用
  • 8、`strncmp()`
    • 8.1、使用
  • 9、`strstr()`
    • 9.1、使用
    • 9.2、模拟实现
  • 10、`strtok()`
    • 10.1、使用
  • 11、`strerror()`
    • 11.1、使用
    • 11.2、`perror()`

1、 strcmp 函数

1.1、使用

strcmp 函数的声明:

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

使用函数时,包含头文件string.h。返回类型是 int 类型,输入参数都是 char* 类型。

函数开始时,从每个字符串的第一个字符出发,比较其ASCII值的大小,若相等,则分别进行至下一个,直到出现ASCII值不相等,或转义字符\0的出现。

不同情况下的返回值:

返回值情况
大于0第一个字符串中字符的ASCII值大于对应第二个字符串的
0所有字符相匹配相匹配
小于0第一个字符串中字符的ASCII值小于对应第二个字符串的

比如,我们来比较两个字符串:

#include<stdio.h>
#include<string.h>int main()
{char ch1[] = "abq";char ch2[] = "abcdef";int ret = strcmp(ch1, ch2);if (ret > 0)printf("ch1 > ch2");//语句1else if (ret < 0)printf("ch1 < ch2");//语句2elseprintf("ch1 == ch2");//语句3return 0;
}

结果输出语句1。

1.2、模拟实现

模拟实现,要达到函数的返回类型、参数、功能与原函数一致。

在设计的函数中,我们接收到两个字符串首元素的地址。若要挨个进行比较,我们可以使用while循环。循环的条件是两个字符相等
当两个字符串不相等时,我们可以返回对应两个地址解引用后做差的差值。当两个字符串相等,即进行到最后都出现\0时,我们可以在while循环中直接返回0

设计的代码如下:

#include<stdio.h>
#include<assert.h>int my_strcmp(const char* str1, const char* str2)
{assert(str1 && str2);while (*str1 == *str2){if (*str1 == '\0')return 0;str1++;str2++;}return *str1 - *str2;
}int main()
{char ch1[] = "abq";char ch2[] = "abcdef";int ret = my_strcmp(ch1, ch2);	if (ret > 0)printf("ch1 > ch2");else if (ret < 0)printf("ch1 < ch2");elseprintf("ch1 == ch2");return 0
}

2、字符分类函数和字符转换函数

都要包含头文件<ctype.h>

2.1、字符分类函数

islower()为例:

int islower(int c);

如果是小写字母,返回非0值;如果不是,返回0

2.1、字符转换函数

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

int toupper(int c);//小写转大写
int tolower(int c);//大写转小写

2.3、实践

比如,将一个字符串中的小写字母,全部转换成大写字母:

#include<stdio.h>
#include<ctype.h>int main()
{char ch[] = "Hello World";char c;int i = 0;while (ch[i] != '\0'){c = ch[i];if (islower(ch[i]))//判断小写{c = toupper(ch[i]);//改成大写}putchar(c);i++;}return 0;
}

3、strlen 函数

size_t strlen(const char* p1);

3.1、使用

#include<stdio.h>
#include<string.h>int main()
{printf("%zd\n", strlen("abc"));return 0;
}

3.1、模拟实现

可利用指针遍历。

1、使用计数器

#include<stdio.h>
#include<assert.h>size_t my_strlen(const char* p)
{size_t count = 0;//计数器char* s = p;assert(s && p);while (*s != '\0'){count++;s++;}return count;
}int main()
{char ch[] = "abc";printf("%zd\n", my_strlen(ch));return 0;
}

2、使用指针运算

#include<stdio.h>
#include<assert.h>size_t my_strlen(const char* p)
{char* s = p;assert(s && p);while (*s != '\0'){s++;}return s - p;//指针运算
}int main()
{char ch[] = "abc";printf("%zd\n", my_strlen(ch));return 0;
}

3、使用函数递归

#include<stdio.h>
#include<assert.h>size_t my_strlen(const char* p)
{char* s = p;assert(s && p);if (*s == '\0')return 0;elsereturn 1 + my_strlen(p + 1); 
}int main()
{char ch[] = "abc";printf("%zd\n", my_strlen(ch));return 0;
}

4、strcpy()函数

声明

char* strcpy(char* dest, const char* src);

strcpy()函数输入的参数为destination(目的地,相当于粘贴上的地方)和source(源头,相当于拷贝的地方),都为各自字符串数组首元素的地址。返回值是目的地字符串数组首元素的地址。

4.1、使用

#include<stdio.h>
#include<string.h>int main()
{char ch1[] = "abc";char ch2[30] = "xxxxxxxxxxxx";printf("%s\n", ch2);char* ret = strcpy(ch2, ch1);printf("%s\n", ret);return 0;
}

注意:

  1. 源字符串必须以'\0'结束。
  2. 会将源字符串中的'\0'拷贝到目标空间。
  3. 目标空间必须足够大可修改

4.2、模拟实现

#include<stdio.h>
#include<assert.h>char* my_strcpy(char* dest, const char* src)
{char* ret = dest;assert(dest && src);while ((*dest++ = *src++)){;}return ret;
}int main()
{char ch1[] = "abc";char ch2[30] = "xxxxxxxxxxxx";printf("%s\n", ch2);char* ret = my_strcpy(ch2, ch1);printf("%s\n", ret);return 0;
}

解释关键点:

  1. 语句char* ret = dest;用来保证函数最后返回的是拷贝后目标字符串(数组)首元素的地址。
  2. 语句*(dest++ = *src++)可以理解为,先分别进行取地址操作,然后赋值,再分别跳到下一个字符的地址
  3. while循环内什么都不干,空语句。

5、strcat()函数

strcat()函数,是用来添加字符串的。

5.1、使用

char* strcat(char* dest, const char* src);

strcpy()函数类似,只不过拷贝变成了加在后面。
比如:

#include<stdio.h>
#include<string.h>int main()
{char ch1[30] = "abc";char ch2[] = "def";printf("%s\n", ch1);printf("%s\n", strcat(ch1, ch2));return 0;
}

注意:

  1. 源字符串必须以'\0'结束。
  2. 目标字符串也得有'\0',否则不知道在哪里追加。
  3. 目标空间必须足够大可修改

5.2、模拟实现

#include<stdio.h>
#include<assert.h>char* my_strcat(char* dest, const char* src)
{char* ret = dest;assert(dest && src);while (*dest){dest++;}while ((*dest++ = *src++)){;}return ret;
}int main()
{char ch1[30] = "abc";char ch2[] = "def";printf("%s\n", ch1);printf("%s\n", my_strcat(ch1, ch2));return 0;
}

解释关键点:

  1. 第一个while循环是找到目标字符串的'\0'
  2. 第二个while循环,相当于拷贝

6、strncpy()

从源字符串拷贝num个字符到目标空间(从目标空间的首地址开始)

6.1、使用

声明:

char* strncpy(char* destination, const char* source);
  1. destination: 指向目标空间。
  2. source: 指向原字符串。
  3. num: 要拷贝的字符数。
  4. 该函数返回拷贝后目标空间起始地址。

代码实现:

#include<stdio.h>
#include<string.h>int main()
{char dest[100] = { "xxxxxxxxxxxxxxxxxxxx" };char src[] = "abcde";char* ret = strncpy(dest, src, 4);printf("%s\n", ret);return 0;
}

注意:

  1. 目标空间必须足够大,不然报错。
  2. 拷贝时不会将原字符串的'\0'拷贝进来,也就是说原字符串无需包含'\0'
  3. 若原字符串个数小于num,补’\0’;若大于num,拷贝到num个字符串为止。

7、strncat()

将源字符串首地址开始num个字符,添加到到目标空间(从目标空间的首地址开始)

7.1、使用

char* strncat(char* destination, const char* source);
  1. destination: 指向目标空间。
  2. source: 指向原字符串。
  3. num: 要添加的字符数。
  4. 该函数返回添加后目标空间起始地址。

代码实现:

#include<stdio.h>
#include<string.h>int main()
{char dest[100] = { "xxxxxxxxx\0xxxxxxxxxxx" };char src[] = "abcd";char* ret = strncat(dest, src, 6);printf("%s\n", ret);return 0;
}

注意:

  1. 目标空间必须足够大。
  2. 添加时,会识别目标空间中\0的位置,并在其首地址处添加原字符串,之后以\0结尾。
  3. 若原字符串个数小于num,只会将原字符串到\0的内容整个拷贝过去,不会另外添加任何东西。

8、strncmp()

strcmp()类似,只不过限定了要比较字符的个数

8.1、使用

声明:

int strncmp(const char* str1; const char* str2; size_t num);
  1. str1: 指向第一个字符串。
  2. str2: 指向第二个字符串。
  3. num: 要比较的字符数。

返回类型的情况:

返回值Value
大于0指定字符数下,第一个字符串比第二个大
0指定字符数下,相匹配
小于0指定字符数下,第一个字符串比第二个小

代码实现:

#include<stdio.h>
#include<string.h>int main()
{char ch1[] = "abcdef";char ch2[] = "abcfer";int ret = strncmp(ch1, ch2, 3);if (ret > 0)printf(">\n");else if (ret < 0)printf("<\n");elseprintf("==\n");return 0;
}

9、strstr()

在str1指向的字符串中,找到str2指向的字符串的位置。

9.1、使用

声明:

char* strstr(const char* str1, const char* str2);
  1. str1: 指向被查找的字符串。
  2. str2: 指向要查找的内容。
  3. 该函数返回被查找内容中,要查找字符串的起始地址。

代码实现:

#include<stdio.h>
#include<string.h>int main() 
{char ch1[1000] = "This is a sample string.";printf("%s\n", ch1);char ch2[] = "sample";char* ret1 = strstr(ch1, ch2);printf("%s\n", ret1);char* ret2 = strncpy(ret1, "simple", 6);printf("%s\n", ch1);return 0;
}

注意:

  1. 若找到,返回的是第1次出现的位置;若未找到,返回NULL
  2. 字符串的比较,不包括’\0’,以’\0’为结束标志。

9.2、模拟实现

代码及详解如下:

#include<stdio.h>char* my_strstr(const char* str1, const char* str2)
{char* p = (char*)str1;//正确位置的标记char* s1 = (char*)str1;//可移动的匹配指针char* s2 = (char*)str2;//可移动的匹配指针if (*s2 == '\0')//当要查找的内容为空,直接返回被查找内容首地址return (char*)str1;while (*p != '\0')//对于被查找内容,从开始到'\0'结束,挨个查找{s1 = p;//对于被查找内容的匹配指针,未匹配成功的每一次匹配,最后都要返回至跳过一个字节后的pchar* s2 = (char*)str2;//未匹配成功的每一次匹配后,都要返回起始位置while ((*s1 != '\0') && (*s2 != '\0') && (*s1 == *s2))//一个字节匹配成功,再匹配下一个{s1++, s2++;}if (*s2 == '\0')//要找内容遍历完了,找到了return(p);p++; //若有匹配不成功,跳出循环,p跳过一个字节,重复过程}return(NULL);//其他任何情况,都视为未找到
}int main()
{char ch1[] = "abbcd";char ch2[] = "bbc";char* ret = my_strstr(ch1, ch2);printf("%s\n", ret);return 0;
}

10、strtok()

将字符串中特定的字符,转换为\0

10.1、使用

声明:

char* strtok(char* str, const char* sep);
  1. str: 指向要被分隔的字符串。
  2. sep: 指向分隔符。
  3. 函数返回\0前字符串的首地址

代码实现:

#include<stdio.h>
#include<string.h>int main()
{char ch[] = "145440@qq.com";char sep[] = "@.";printf("%s\n", strtok(ch, sep));return 0;
}

注意:

  1. strtok()会直接改变原字符串,所以使用时应先复制
  2. 若想得到所有被分割的部分,只需在下次调用函数时,将第一个参数改为NULL
  3. 若可转换的标记已经没有了,再调用函数,就返回NULL

根据(2),可以有以下代码:

#include<stdio.h>
#include<string.h>int main()
{char ch1[] = "1404406905@qq.com";char ch2[10000];char* ret = strcpy(ch2, ch1);//clonechar sep[] = "@.";char* str;for (str = strtok(ret, sep); str != NULL; str = strtok(NULL, sep)){printf("%s\n", str);}return 0;
}

11、strerror()

找到错误码对应的错误信息。

11.1、使用

声明:

char* strerror(int errnum);
  1. 输入参数为错误码。
  2. 函数返回错误信息字符串首地址。

看看几个错误码:

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

代码示例:

#include<stdio.h>
#include<string.h>
#include<errno.h>int main() {FILE* pFile;pFile = fopen("Data.txt", "r");if (pFile == NULL)printf("Error opening file Data.txt: %s\n", strerror(errno));return 0;
}

补充:

  1. C语言可以打开文件。
  2. 打开文件用fopen()函数。如果以读的形式打开,文件又不存在,fopen()函数将错误码存放在errno中,并返回NULL

如果不想像上面代码中printf()部分那么麻烦,可以使用perror()函数。

11.2、perror()

在该函数中,输入说明信息,函数将在屏幕上打印信息、冒号、一个空格,以及错误码对应的错误信息:

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

使用该函数,使代码更简洁,但也丧失了灵活性。

http://www.dtcms.com/a/392123.html

相关文章:

  • 酷9 1.7.3 | 支持自定义添加频道列表,适配VLC播放器内核,首次打开无内置内容,用户可完全自主配置
  • Slurm sbatch 全面指南:所有选项详解
  • 使用SCP命令在CentOS 7上向目标服务器传输文件
  • Kindle Oasis 刷安卓系统CrackDroid
  • 最新超强系统垃圾清理优化工具--Wise Care 365 PRO
  • JeecgBoot权限控制系统解析:以具体模块为例
  • 2025年职场人AI认证与学习路径深度解析
  • 硬件开发_基于STM32单片机的智能垃圾桶系统2
  • CSS Display Grid布局 grid-template-columns grid-template-rows
  • 在 Spring Boot 中,针对表单提交和请求体提交(如 JSON) 两种数据格式,服务器端有不同的接收和处理方式,
  • NL2SQL简单使用
  • 数据结构:二叉树OJ
  • 【Linux手册】生产消费者模型的多模式实践:阻塞队列、信号量与环形队列的并发设计
  • Python + Flask + API Gateway + Lambda + EKS 实战
  • 【OpenGL】openGL常见矩阵
  • DeepSeek大模型混合专家模型,DeepSeekMoE 重构 MoE 训练逻辑
  • 450. 删除二叉搜索树中的节点
  • 实用工具:基于Python的图片定位导出小程序
  • 滚珠螺杆在工业机器人关节与线性模组的智能控制
  • 【AI】coze的简单入门构建智能体
  • Python数据分析:函数定义时的装饰器,好甜的语法糖。
  • Java数据结构——包装类和泛型
  • 【C++进阶】C++11的新特性 | 列表初始化 | 可变模板参数 | 新的类功能
  • 广东省省考备考(第一百零三天9.20)——言语(强化训练)
  • 面试编程题(四)
  • OpenHarmony之充电振动定制
  • 前端单元测试入门:使用 Vitest + Vue 测试组件逻辑与交互
  • 泛英国生物样本库全基因组关联分析
  • 【LeetCode 每日一题】2785. 将字符串中的元音字母排序
  • 游戏开发中的友好提示,错误信息,异常描述等数据管理的必要性