🍁🍁🍁 猛戳订阅 👉 详解数据结构专栏 👈 深度解析 🍁🍁🍁
📋个人简介
- 💬大家好,我是_奇奇,一名C/C++博主。河牧院大一在读。
- 🔔欢迎一起交流学习
- 💬我会将大一学的数据结构和C语言深度解析写成笔记记录下来。后期会慢慢推进。感兴趣可以
订阅
以下专栏。 - 📌详解数据结构专栏🍁
- 📌深度理解C语言专栏🍁
- 🔑 个人主页🌳
- 💡编程的前途是光明的,道路是曲折的。
这不是目录
❄️前言
C语言中对字符和字符串的处理很是频繁,不仅如此在以后的校招面试中字符串的题目也会涉及不少,这点在LeetCode中就能体现到,在刷题时经常会遇到处理字符串的内容,字符串还和指针相关联,对字符串的深入理解也会增加对指针的理解。
字符串函数
📌strlen
❄️功能:求字符串长度
❄️函数原型
size_t strlen ( const char* str );
🍁注意:
- 字符串以 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )。
- 参数指向的字符串必须要以 ‘\0’ 结束。
- 注意函数的返回值为
size_t
,是无符号整型,也就是不是负数。(易错!!!
)
函数模拟
1.指针-指针的方式
注意:这种方式只适用于同一个数组
intmy_strlen(char*s){char*p = s;while(*p != ‘\0’ )
p++;return p-s;}
2.计数器方法
intmy_strlen(constchar* str){int count =0;while(*str){
count++;
str++;}return count;}
3.递归方法(
面试官最爱考
)
//不能创建临时变量计数器intmy_strlen(constchar* str){if(*str =='\0')return0;elsereturn1+my_strlen(str+1);}
📌strcpy
❄️函数功能:拷贝源字符串到目的地空间,
包括"\0"也拷贝过去
。
❄️函数原型
char *strcpy( char *strDestination, const char *strSource );
🍁注意:
- 源字符串必须以 ‘\0’ 结束。
- 会将源字符串中的 ‘\0’ 拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变,
原字符串不可变!
函数模拟
注意点:
- assert断言
- const修饰
char*my_strcpy(char*dest,constchar*src){char*ret = dest;assert(dest !=NULL);assert(src !=NULL);while((*dest++=*src++)){;}return ret;}
📌strcat
❄️函数功能:
- 将源字符串和目标字符串连接起来。
❄️函数原型
char * strcat ( char * destination, const char * source );
🍁注意:
- 源字符串必须以 ‘\0’ 结束。
- 目标空间必须有足够的大,能容纳下源字符串的内容。
- 目标空间必须可修改。
- 返回的是目标字符串的首元素的地址。
函数模拟
注意:
后
置++是先使用后++。
char*my_strcat(char*dest,constchar*src){char*ret = dest;assert(dest !=NULL);assert(src !=NULL);while(*dest){
dest++;}while((*dest++=*src++)){;}return ret;}
📌strcmp
❄️函数功能:
- 比较两个字符串的大小,按照每个字符的ASCII码值依次往后比较,一个字符一个字符的比较,只要遇到字符不同,就返回。
❄️函数原型
char * strncpy ( char * destination, const char * source, size_t num );
🍁注意:
并
不是大于返回1,小于返回-1,没有这个规定
规定如下
- 第一个字符串大于第二个字符串,则返回大于0的数字
- 第一个字符串等于第二个字符串,则返回0
- 第一个字符串小于第二个字符串,则返回小于0的数字
函数模拟
🍁注意;
while的循环条件&&操作符,左操作数为假时,有操作数就不用执行了。
int my_strcmp (constchar* src,constchar* dst){int ret =0;assert(src !=NULL);assert(dest !=NULL);while(!(ret =*(unsignedchar*)src-*(unsignedchar*)dst)&&*dst){++src;++dst;}if( ret <0)
ret =-1;elseif( ret >0)
ret =1;return( ret );}
📌strncpy
❄️函数功能:
拷贝num个字符从源字符串到目标空间。
❄️函数原型
char * strncpy ( char * destination, const char * source, size_t num );
🍁注意:
- 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
- 目标空间必须足够大。
- 和strcpy函数唯一区别就是拷贝的个数受限制。
📌strncat
❄️函数功能:
将num个源字符串和目标字符串连接起来。
❄️函数原型
char * strncat ( char * destination, const char * source, size_t num );
🍁注意:
- 目标字符串足够大
📌strstr
函数功能:
在目标字符串str1里找到源字符串,并返回这个源字符串的首元素的地址。
函数原型
char * strstr ( const char *str1, const char * str2);
🍁注意:
- 重点在函数模拟的实现
函数模拟
- 如果str2为空,不用照了。直接返回str1。
如图包含了找字符串的所有情况。
思考问题要考虑全面。
我认为下面代码是最优的代码了。但是需要自己细看
。描述的话太麻烦了。
#include<stdio.h>#include<assert.h>char*my_strstr(constchar* str1,constchar* str2){assert(str1 && str2);if(!*str2){return((char*)str1);}char* cp = str1;char* s1 =0;char* s2 =0;while(*cp !='\0'){
s1 = cp;
s2 = str2;while(*s2 !='\0'&&*s1 !='\0'&&*s2 ==*s1){
s1++;
s2++;if(!*s2){return cp;}}
cp++;}returnNULL;}intmain(){char arr[]="hworld";char arr1[]="world";char* p =my_strstr(arr, arr1);printf("%s", p);return0;}
📌strtok
❄️函数功能:将字符串分割。
❄️函数原型
char * strtok ( char * str, const char * sep );
🍁
注意
- sep参数是个字符串,定义了用作分隔符的字符集合
- 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记
- strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
- strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
- strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
- 如果字符串中不存在更多的标记,则返回 NULL 指针。
如图例子
📌streeor
❄️函数功能:返回错误码所对应的错误信息。
❄️函数原型
char * strerror ( int errnum );
例子
/* strerror example : error list */#include<stdio.h>#include<string.h>#include<errno.h>//必须包含的头文件int main (){
FILE * pFile;
pFile = fopen ("unexist.ent","r");if(pFile ==NULL)
printf ("Error opening file unexist.ent: %s\n",strerror(errno));//errno: Last error numberreturn0;}
Edit & Run
📌字符分类函数
函数如果他的参数符合下列条件就返回真isspace空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’isdigit十进制数字 09isxdigit十六进制数字,包括所有十进制数字,小写字母af,大写字母A ~ Fislower小写字母azisupper大写字母AZisalpha字母a~ z或AZisalnum字母或者数字,a ~ z,A Z,0~9ispunct标点符号,任何不属于数字或者字母的图形字符(可打印)isgraph任何图形字符isprint任何可打印字符,包括图形字符和空白字符iscntrl任何控制字符
内存函数
📌memcpy
❄️函数功能:
- 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置
❄️函数原型
void * memcpy ( void * destination, const void * source, size_t num );
🍁注意:
- 注意是以字节为单位的拷贝。
- 这个函数在遇到 ‘\0’ 的时候并不会停下来。
- 如果source和destination有任何的重叠,复制的结果都是未定义的。
函数模拟实现
- 因为不知道数据是哪种类型所以需要
进行强制类型转换
。
void* memcpy (void* dst,constvoid* src, size_t count){void* ret = dst;assert(dst);assert(src);while(count--){*(char*)dst =*(char*)src;
dst =(char*)dst +1;
src =(char*)src +1;}return(ret);}
📌memmove
❄️函数功能:
- 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
❄️函数原型
void * memmove ( void * destination, const void * source, size_t num );
🍁注意:
- 如果源空间和目标空间出现
重叠
,就得使用memmove函数处理。
函数模拟
🍁注意
- 如果src > dest ,或者det > src+ count 从
前往后拷贝
就可以了 - 否则
从后往前拷贝
- 不遵循这个规则的话就会覆盖,导致拷贝错误。
void*memmove(void* dst,constvoid* src, size_t count){void* ret = dst;if(dst <= src ||(char*)dst >=((char*)src + count)){while(count--){*(char*)dst =*(char*)src;
dst =(char*)dst +1;
src =(char*)src +1;}}else{
dst =(char*)dst + count -1;
src =(char*)src + count -1;while(count--){*(char*)dst =*(char*)src;
dst =(char*)dst -1;
src =(char*)src -1;}}return(ret);}
📌memcmp
❄️函数功能:
- 比较从ptr1和ptr2指针开始的num个字节
- 和strcmp函数功能相同。
❄️函数原型
int memcmp ( const void * ptr1,
const void * ptr2,
size_t num );
函数返回值
版权归原作者 _奇奇 所有, 如有侵权,请联系我们删除。