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

字符函数和字符串函数

字符函数:

1.字符分类函数

C语言中有一系列的函数是专门做字符分类的,也就是一个字符是属于什么类型的字符的。

这些函数的使用都需要包含一个头文件:<ctype.h>

函数                       如果他返回下列条件就返回

iscntrl                     任何控制字符

isspace                  任何字符:空格 ‘’,换页 ‘\f’ ,换行  '\n',回车 ‘\r’,制表符'\t'或者垂直制表符‘\v’

isdigit                     十进制数字 ‘0’ ~ ‘9’ 字符

isxdigit                   十进制数字,包括所有十进制数字字符,小写字母 a~f ,大写字母 A~F

islower                   小写字母 a~z

isupper                  大写字母 A~Z

isalpha                  字母 a~z 或 字母 A~Z     

isalnum                 字母或者数字,a~z ,A~Z ,0~9

ispunct                  标点符号,任何不属于数字或者字母的图形字符(可打印)

isgraph                  任何图形字符

isprint                     任何可打印字符,包括图形字符和空白字符     

islower 是能够判断参数部分的 c 是否是小写字母的。

通过返回值来说明是否是小写字母,如果是小写字母就返回非0的整数,如果不是小写字母,则返回0。    

//判断字母的大小写
int main()
{int ch = getchar();//getchar()接受一个字符,直接返回来,会让我们输入一个值if (ch >= 'a' && ch <= 'z'){printf("小写\n");}else if (ch >= 'A' && ch <= 'Z'){printf("大写\n");}//putchar(ch);//直接输出(打印)上面getchar输入的值//在ASCII码中0-31这32个字符是不可打印字符return 0;
}

#include<ctype.h>
int main()
{int ch = getchar();if (islower(ch)){printf("小写\n");}else if (isupper(ch)){printf("大写\n");}return 0;
}

2.字符转换函数

例子:将字符串中的小写字母转换成大写字母,其余的字符不变。

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

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

//将一个字符串转换全小写
int main()
{char arr[] = "I Am A Student";int i = 0;while (arr[i]){if (isupper(arr[i])){arr[i] = arr[i] + 32;// a 对应的ASCII码值:97// A 对应的ASCII码值:65}putchar(arr[i]);i++;}return 0;
}

字符串函数:

3.strlen 的使用和模拟实现

size_t strlen ( const char * str );

  • 字符串以 ' \0 ' 作为结束标志,strlen函数返回的是在字符串中 ' \0 ' 之前的字符的个数(不包含' \0 ') 
  • 参数指向的字符串必须以 ' \0 ' 结束
  • 注意函数返回的类型是 size_t , 是无符号的(易错)
  • strlen的头文件是<string.h>
#include<string.h>
//strlen() 函数  求字符串长度的函数
int main()
{//char arr[] = "zxcvbn";// 数组内容:z x c v b n \0//char arr[] = { 'z','x','c' };//随机值 没有找到 \0char arr[] = { 'z','x','c','\0'};// 3size_t len = strlen(arr);printf("%zd\n", len);return 0;
}

看个有趣的代码:

int main()
{   //			3-7=-4 ??if (strlen("asd") - strlen("asdfghj") > 0){printf("大于\n");}else{printf("小于等于");}return 0;
}

运行出的结果: 

 

为什么上面显示的是 “大于”??

strlen 返回的值是 无符号类型的整数,无符号类型的整数的加减的结果也是无符号类型的整数,所以不会出现负数

strlen 函数的多种模拟实现方法:

#include<assert.h>//方法1:size_t my_strlen1(char * str)
{assert(str);size_t count = 0;while (*str){count++;str++;}return count;
}//方法2:size_t my_strlen2(char* str)
{assert(str);char *start = str;while (*str){str++;}return str-start;//指针减指针的应用
}//方法3://不创建变量实现 strlen()函数的实现 ---- 递归的方法来实现
size_t my_strlen3(char* str)
{assert(str);if (*str == '\0')return 0;elsereturn  1 + my_strlen3(str + 1);}// ch arr[]="zxcvbn" --> [z x c v b n \0]
//1+my_srtrlen("xcvbn")
//1+1+my_srtrlen("cvbn")
//1+1+1+my_srtrlen("vbn")
//1+1+1+1+my_srtrlen("bn")
//1+1+1+1+1+my_srtrlen("n")
//1+1+1+1+1+1+my_srtrlen("")int main()
{char arr[] = "abc";//size_t len = my_strlen1(arr);//size_t len = my_strlen2(arr);size_t len = my_strlen3(arr);printf("%zd\n", len);return 0;
}

4.strcpy 的使用和模拟实现

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

  • 源字符串必须以 ' \0 ' 结束
  • 会将源字符串中的 ' \0 ' 拷贝到目标空间
  • 目标空间必须足够大,以确保能存放源字符串
  • 目标空间必须可以修改 
int main()
{char arr1[] = "xxxxxxxxxxxxxxxxxx";char arr2[] = "hehehe";strcpy(arr1, arr2);printf("%s\n", arr1);return 0;
}

调试看看是否将arr2的内容拷贝到了arr1中,同样也将arr2中的 '\0' 也拷贝到了arr1中??

确实是:将arr2的内容拷贝到了arr1中,同样也将arr2中的 '\0' 也拷贝到了arr1中 

int main()
{char arr1[3] = { 0 };//目标空间必须足够大,否则会出现错误char arr2[] = "hello hello world";strcpy(arr1, arr2);printf("%s\n", arr1);return 0;
}
int main()
{char* pch = "abcdefghiasdfg";//常量字符串是不可修改的char arr[] = "hello world";strcpy(pch, arr);printf("%s\n", pch);//目标空间必须是可以修改的return 0;
}

strcpy 的模拟实现:

char * my_strcpy(char* str1,const char* str2)
{char* ret = str1;while (*str2 !='\0'){*str1 = *str2;str1++;str2++;}*str1 = *str2;return ret;
}//优化如下:#include <assert.h>
char* my_strcpy(char* str1, const char* str2)
{assert(str1 && str2);char* ret = str1;while (*str1++ = *str2++){;}return ret;
}int main()
{char arr1[20] = {0};char arr2[] = "hello world";printf("%s\n",my_strcpy(arr1, arr2));return 0;
}

 5.strcat 的使用和模拟实现

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

  • 源字符串必须以 ' \0 ' 结束
  • 目标空字符串中也得有 ' \0 ',否则没办法知道从哪里开始追加
  • 目标空间必须足够大,能容下源字符串的内容
  • 目标空间必须可修改
  • 字符串自己给自己追加,是什么情况?? 
int main()
{char arr1[25] = "Hello ";char arr2[] = "World";char *ret=strcat(arr1, arr2);printf("%s\n", ret);return 0;
}

模拟实现strcat函数:

char* my_strcat(char* dest, const char* sour)
{char* ret = dest;assert(dest && sour);//1.找到目标空间中的\0while (*dest){dest++;}//2.拷贝sour中的内容到dest中while (*dest++ = *sour++){;}return ret;
}int main()
{char arr1[25] = "Hello ";char arr2[] = "World";char* ret = my_strcat(arr1, arr2);printf("%s\n", ret);return 0;
}

字符串自己给自己追加的情况:

#include <assert.h>
char* my_strcat(char* dest, const char* sour)
{char* ret = dest;assert(dest && sour);//1.找到目标空间中的\0while (*dest){dest++;}//2.拷贝sour中的内容到dest中while (*dest++ = *sour++){;}return ret;
}int main()
{char arr1[25] = "Hello ";char* ret = my_strcat(arr1, arr1);printf("%s\n", ret);return 0;
}

6.strcmp 函数的使用

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

标准规定:

  • 第一个字符串大于第二个字符串,则返回大于0的数字
  • 第一个字符串等于第二个字符串,则返回0
  • 第一个字符串小于第二个字符串,则返回小于0的数字
  • 是根据两个字符串上对应的字符ASCII码值的大小的比较
int main()
{int ret = strcmp("bbq", "abcdef");printf("%d\n", ret);return 0;
}
int main()
{int ret = strcmp("bbq", "abcdef");if (ret > 0){printf("大于\n");}else if (ret < 0){printf("小于\n");}elseprintf("等于\n");return 0;
}

 strcmp函数的模拟实现:

int my_strcmp(const char* dest, const char* sour)
{while (*dest == *sour){if (*dest == '\0')return 0;dest++;sour++;}if (*dest - *sour > 0)return 1;elsereturn -1;}//方法二:
int my_strcmp(const char* dest, const char* sour)
{while (*dest == *sour){if (*dest == '\0')return 0;dest++;sour++;}return *dest - *sour;}
int main()
{int ret = my_strcmp("bbq", "abcdef");if (ret > 0){printf("大于\n");}else if (ret < 0){printf("小于\n");}elseprintf("等于\n");return 0;
}

7.strncpy 函数的使用

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

  •  Copies the first num characters of source to destination. If the end of the source C string(which is signaled by a null-character) is found before num characters have been copied,destination is padded with zeros until a total of num characters have been written to it.
  • 拷⻉num个字符从源字符串到⽬标空间。
  • 如果源字符串的⻓度⼩于num,则拷⻉完源字符串之后,在⽬标的后边追加0,直到num个。 

 8.strncat 函数的使用

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

  • Appends the first num characters of source to destination, plus a terminating null-character(将source指向字符串的前num个字符追加到destination指向的字符串末尾,再追加⼀个 \0 字符)。
  • If the length of the C string in source is less than num, only the content up to the terminatingnull-character is copied.(如果source 指向的字符串的⻓度⼩于num的时候,只会将字符串中到\0 的内容追加到destination指向的字符串末尾)。 
//strncat 比strcat多了一个参数:可以限制追加的字符的个数
int main()
{char arr1[20] = "xxxxxxxxxx";char arr2[] = "world";strncat(arr1, arr2, 7);//调试就会发现:看不出是否追加arr2的\0return 0;
}
int main()
{char arr1[20] = "hello\0xxxxxxxx";char arr2[] = "world";strncat(arr1, arr2, 7);//将w o r l d \0拷贝到了arr1中,是从arr1中的第一个\0开始拷贝//可以看出是要将arr2中的\0追加到arr1中的return 0;
}

 

9.strncmp函数的使用

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

比较str1和str2的前num个字符,如果相等就继续往后⽐较,最多比较num个字⺟,如果提前发现不⼀样,就提前结束,⼤的字符所在的字符串⼤于另外⼀个。如果num个字符都相等,就是相等返回0。

int main()
{char arr1[] = "abcdef";char arr2[] = "abcq";int ret = strncmp(arr1, arr2, 3);//将arr1和arr2中的前3个字母进行比较,有字母长度的限制printf("%d\n", ret);return 0;
}

10.strstr 函数的使用

  • Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.(函数返回字符串str2在字符串str1中第⼀次出现的位置)。
  • The matching process does not include the terminating null-characters, but it stops there.(字符串的⽐较匹配不包含 \0 字符,以 \0 作为结束标志)。
int main()
{char arr1[] = "abbbbcdebbehig";char arr2[] = "bbe";char* ret = strstr(arr1, arr2);if (ret != NULL)printf("%s\n", ret);elseprintf("找不到\0");return 0;
}

strstr函数的模拟实现:


//暴力求解 char* my_strstr(const char* str1, const char* str2)
{const char* cur = str1;char* s1 = NULL;char* s2 = NULL;assert(str1 && str2);//特殊规定的处理:if (*str2 == '\0')return (char *)str1;while (*cur){s1 = cur;s2 = str2;while (*s1&&*s2&&*s1 == *s2){s1++;s2++;}if (*s2 == '\0'){return (char*)cur;}cur++;}return NULL;
}//测试用例1
//abbbbcdebbehig
//bbe//测试用例2
//abbbbcdebbehig
//abb//测试用例3
//abbbbcdebbehig
//bbf//测试用例4
//abbbbcdebbehig
//abbbbcdebbehig//测试用例越多,功能越齐全,不容易漏掉其他的情况
//bug也不容易出现int main()
{char arr1[] = "abbbbcdebbehig";char arr2[] = "bbe";char* ret = my_strstr(arr1, arr2);if (ret != NULL)printf("%s\n", ret);elseprintf("找不到\0");return 0;
}

 11.strtok 函数的使用

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

 

 

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>
#include<string.h>
//strtok 函数
int main()
{char arr1[] = "zhangsan@163.com#hehhe";char arr2[30] = {0};strcpy(arr2, arr1);const char* p = "@.#";char* s = NULL;//for循环优点:初始化部分只执行一次for (s = strtok(arr2, p); s != NULL; s = strtok(NULL, p)){printf("%s\n", s);}//char* s = strtok(arr2, p);//printf("%s\n", s);//s = strtok(NULL, p);//printf("%s\n", s);//s = strtok(NULL, p);//printf("%s\n", s);//s = strtok(NULL, p);//printf("%s\n", s);//繁琐、冗余return 0;
}

12.strerror 函数的使用

  • strerror 函数可以把参数部分错误码对应的错误信息的字符串地址返回来。
  • 在不同的系统和C语⾔标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头⽂件中说明的,C语⾔程序启动的时候就会使⽤⼀个全局的变量errno来记录程序的当前错误码,只不过程序启动 的时候errno是0,表⽰没有错误,当我们在使⽤标准库中的函数的时候发⽣了某种错误,就会将对应 的错误码,存放在errno中,⽽⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是 有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址回。
int main()
{int i = 0;for (i = 0; i < 10; i++){printf("%d:%s\n", i, strerror(i));}return 0;
}

在vs下输出结果为:

 

 

#include<errno.h>//C语言是可以进行文件操作的
//打开文件:
//FILE* pf=fopen(...)
//如果文件打开成功,则返回一个地址
//如果文件打开失败,则返回一个NULL
int main()
{FILE* pFile;pFile = fopen("unexist.ent", "r");if (pFile == NULL)//printf("Error opening file unexist.ent: %s\n", strerror(errno));//strerror    头文件:<string.h>//errno       头文件:<errno.h>perror("Error opening file unexist.ent");//perror 函数自动加上:和空一格return 0;
}

输出结果:

http://www.xdnf.cn/news/357949.html

相关文章:

  • MKS RGA 校准调试MKS eVision和Vision 1000p RGA步骤(图文并茂)
  • 使用 Spring 和 Redis 创建处理敏感数据的服务
  • 4.2【LLaMA-Factory实战】金融财报分析系统:从数据到部署的全流程实践
  • 20250509 哲学上的真空和哲学上的虚无是一个概念吗
  • 量子计算在软件开发中的兴起
  • Baklib智能内容推荐中台是什么?
  • canvas坐标系转webgl坐标系
  • 数字化转型-4A架构之数据架构
  • selenium替代----playwright
  • XML Forms Data Format (XFDF) 工作原理、数据结构、使用场景以及与缓冲区的交互方式
  • 【身份证识别表格】批量识别身份证扫描件或照片保存为Excel表格,怎么大批量将身份证图片转为excel表格?基于WPF和腾讯OCR的识别方案
  • 从 JMS 到 ActiveMQ:API 设计与扩展机制分析(一)
  • 37-智慧医疗服务平台(在线接诊/问诊)
  • Windows系统下【Celery任务队列】python使用celery 详解(二)
  • Jsoup与HtmlUnit:两大Java爬虫工具对比解析
  • PostgreSQL逻辑复制(logic replication)
  • 《内存单位:解锁数字世界的“度量衡”》
  • TIME - MoE 模型代码 3.2——Time-MoE-main/time_moe/datasets/time_moe_dataset.py
  • android 媒体框架
  • Android Handler 机制面试总结
  • 力扣刷题 每日四道
  • pandas中的数据聚合函数:`pivot_table` 和 `groupby`有啥不同?
  • 【项目中的流程管理(十一)】
  • MongoDB 创建索引原则
  • 设计模式-策略模式(Strategy Pattern)
  • 前端指南——项目代码结构解析(React为例)
  • 系统文件夹迁移与恢复
  • 系分论文《论多云架构治理的分析和应用》
  • 为人类文明建一座“永不遗忘”的数字博物馆:Funes 技术解析
  • 【计算机视觉】OpenCV项目实战:get_inverse_perspective:基于OpenCV的透视图转化为不同平面