字符操作库函数以及内存操作库函数 C语言实现
字符操作库函数
strlen
strlen判断结束的标志为找到字符串中的'\0',也就是说如果字符串中间出现'\0'将会导致strlen停止 即strlen的返回值是'\0'前所出现的字符个数 然而此时字符串长度并非真实长度,但一般很少出现字符串中间会有‘\0’
size_t strlen(const char* str)
模拟实现my_strlen:
方式1:直接计数 遍历整个字符串 直至找到“\0”为止 否则计算器实现加一操作
int my_strlen(const char* str)
{int count=0;while(*str){count++;str++;}return count;
}
方式2:不引入整型计数变量,利用递归实现计数
int my_strlen(const char* str)
{if(*str=='\0'){return 0;}return 1+my_strlen(str+1);
}
方式3:指针方式实现计数,遍历不为‘\0’则向右移动指针,直至指针p移动至‘\0’前一位置,p-str即为中间不为'\0'的字符个数
int my_strlen(const char* str)
{char* p=(char*)str;while(*p!='\0'){p++;}return p-str;
}
strcpy
源字符串必须以'\0'结束,同时,目标空间必须足够大,以免源字符串拷贝空间不足,通过实际代码调试查看内存空间 注意到,拷贝过程中会将源字符串结尾的‘\0’拷贝至目标地址空间中
char* strcpy(char* destination,const char* source)
my_strcpy模拟实现:
当判断源字符串不为空,以及目标空间存在的情况下,实现从源字符串到目标空间的逐个字符拷贝,直至源字符串遇到'\0'结束拷贝
注意:while(*dest++=*src++); 当src遇到'\0',赋值给dest后,表达式结果为0,为false,则循环结束,暂停拷贝
char* my_strcpy(char* dest,const char* src)
{char* ret=dest;assert(dest!=NULL)assert(src!=NULL)while(*dest++=*src++);return ret;
}
strcat
char* strcat(char* destination,const char* source)
strcat模拟实现,可以在strcpy基础上进行,即在目标空间末尾(不包括‘\0’)进行一次strcpy即可实现,具体参见代码
char* my_strcat(char* dest,const char* src)
{char* ret=dest;assert(dest!=NULL)assert(src!=NULL)while(*dest!=NULL){dest++;}while(*dest++=*src++);return ret;
}
考虑:strcat自己给自己追加会发生什么?
自己给自己追加的过程中,源字符串末尾的‘\0’被覆盖,导致while循环进入死循环,无法再找到‘\0’停止,此时starcat将一直拷贝连接 直至目标空间溢出报错
strcmp
strcmp实现字符串比较,通过对应字符ASCll码比较大小
int strcmp(const char* src1,const char* src2)
如果第一个字符串大于第二个字符串,返回大于0的数
如果第一个字符串等于第二个字符串,返回等于0的数
如果第一个字符串小于第二个字符串,返回小于0的数
strcmp的模拟实现:
int my_strcmp(const char* src1,const char* src2)
{int ret=0;assert(src1!=NULL);assert(src2!=NULL);while(!(ret=*(unsigned char*)src1-*(unsigned char*)src2)&&*src2)//相等字符则后移比较,直至遇到‘\0’{src1++;src2++;}if(ret<0)ret=-1;else if(ret>0)ret=1;return ret;
}
strstr
strstr实现子串查找,返回子串首元素地址
char* strstr(const char*,const char*)
模拟实现my_strstr():主要难点在于一个字符一个字符逐一匹配,需要一个指针记录起始位置,每次匹配失败需要退回起始位置的下一位置处开始在次匹配
#include<stdio.h>
#include<string.h>
#include<assert.h>char* my_strstr(const char* str1,const char* str2)
{assert(str1);assert(str2);const char* s1 = str1;const char* s2 = str2;const char* cp = str1;//该指针记录每一次进行匹配的起始位置if (*str2 == '\0'){return (char*)str1;}while (*cp){//一次匹配查找的过程s1 = cp;s2 = str2;while (*s1 && *s2 && *s1 == *s2)//逐个匹配{s1++;s2++;}if (*s2 == '\0')//只有s2走完才能说明找到真正的子串 返回起始查找位置cp s1走完还没有找到匹配的子串,则返回null{return (char*)cp;}cp++;}return NULL;
}int main()
{char* str1 = "abcdef";char* str2 = "cde";char* ret = my_strstr(str1,str2);printf("%s",ret);return 0;
}
kmp算法实现字符串匹配详细可参考http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html
内存操作库函数
memcpy
函数从source拷贝nums个字节到destination中,此时拷贝字节,遇到'\0'并不会停止
void* memcpy(void* destination,const void* source,size_t nums)
memcpy拷贝过程中 源内存块和目标内存块不可以重叠
由于类型不确定,为void*类型,为了实现一字节一字节拷贝,需要强制类型转换为char*类型具体代码如下:
void* my_memcpy(void* dest,const void* str,size_t count)
{void* ret = dest;//一字节一字节拷贝,一字节一字节后移while (count--){*(char*)dest = *(char*)str;dest = (char*)dest + 1;str = (char*)str + 1;}return ret;
}
memmove
memmove与memcpy功能基本类似,都是实现内存块数据拷贝,memmove可以实现重叠内存拷贝
重叠内存拷贝 不同的拷贝方向会导致尚未拷贝的内存空间 cd被覆盖为bb 导致后续拷贝也只拷贝了bb 如图所示:
解决方案,从source后面开始拷贝,从后向前拷贝,则不会被覆盖,但情况不一定,如果红色框为dest,绿色框为source,从后向前拷贝又会被覆盖
考虑是否存在一个分界条件,使得分情况处理即可
如果拷贝的目的地址在源地址前面 则源地址从前向后拷贝到目的地址
如果拷贝的目的地址在源地址后面 则源地址从后向前拷贝到目的地址
void* my_memmove(void* dest, const void* str, size_t count)
{//避免拷贝重叠 需要分情况讨论void* ret = dest;if (dest < str)//如果拷贝的目的地址在源地址前面 则源地址从前向后拷贝到目的地址{while (count--){//依然遵循一字节一字节拷贝*(char*)dest = *(char*)str;dest = (char*)dest + 1;str = (char*)str + 1;}}else//如果拷贝的目的地址在源地址后面 则源地址从后向前拷贝到目的地址{while (count--){*((char*)dest + count) = *((char*)str + count);}}return ret;
}
字符操作库函数以及内存操作库函数 C语言实现相关推荐
- -1-4 java io java流 常用流 分类 File类 文件 字节流 字符流 缓冲流 内存操作流 合并序列流...
File类 •文件和目录路径名的抽象表示形式 构造方法 •public File(String pathname) •public File(String parent,Stringchild) •p ...
- java io--内存操作流_JavaIO——内存操作流、打印流
我们之前所做的都是对文件进行IO处理,实则我们也可以对内存进行IO处理.我们将发生在内存中的IO处理称为内存流. 内存操作流也可分为两类:字节内存流和字符内存流. (1)ByteArrayInputS ...
- 字符串转内存c语言,【一起学C】C语言面试题必考:字符串操作函数,内存操作函数实现...
本帖最后由 奉聪 于 2017-1-25 14:54 编辑 *******前言******* 我数一下,我发了几个帖子,1.2.3? 哈哈哈,没几个哈,感谢吾爱,让我学到了很多,乐于分享,共同进步! ...
- STM32学习第三课:STM32 c语言学习基础3(内存操作、指针、结构指针)
1.内存操作 在对内存操作头疼的时候我发现了这篇神奇的文章,拜读之后豁然开朗心生崇拜 数据指针 在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它 ...
- C语言——常见的字符串函数+内存操作函数的介绍及实现
文章目录 前言 一.字符串函数 1.求字符串长度 strlen 2.长度不受限制的字符串函数strcpy.strcat.strcmp 字符串拷贝 strcpy 字符串追加拷贝 strcat 字符串比较 ...
- C语言处理字符串及内存操作
字符串处理函数 1.字符串长度 strlen表示包含的字符的个数,size_t strlen(char cosnt *string), 返回的是size_t类型,它是无符号整数类型,在表达式中进行运算 ...
- C 中的内存操作函数-memcpy 等(to be continued)
文章目录 C中的内存操作函数 1.memcpy() 1.1 函数介绍 1.2 示例代码 1.3 Reference C中的内存操作函数 1.memcpy() 1.1 函数介绍 void *memcpy ...
- C语言程序设计 | 模拟实现内存操作函数:strncpy, strncat, strncmp, memcpy, memmove
模拟实现字符串和内存操作函数(二)目录: strncpy strncat strncmp strcmp memcpy memmove strncpy char* strncpy(char* dst, ...
- C#中Marshal 类的内存操作的一般功能概述
Marshal 类的内存操作的一般功能 Marshal类 提供了一个方法集,这些方法用于分配非托管内存.复制非托管内存块.将托管类型转换为非托管类型,此外还提供了在与非托管代码交互时使用的其他杂项方法 ...
最新文章
- 11月3号晚7点中科院南土所梁玉婷报告:土壤微生物功能组学与关键类群识别
- Xshell:Xshell的简介、安装、使用方法之详细攻略
- android ios web兼容,js与android iOS 交互兼容
- Spring Boot中使用@Scheduled创建定时任务
- 以后再想大数据杀熟就没那么容易了
- 6-3-1:STL之vector——vector的快速入门、常用接口
- 机器学习Machine learning in action实战相关资料
- 《Linux内核分析》(二)——从一个简单Linux内核分析进程切换原理
- CAShapeLayer
- linux 0.11 内核学习 -- sched.c,调度进程。
- 初入职场,如何快速脱颖而出?
- 根据深度优先算法(DFS)和标记数组求全排列
- Matlab返回多个值以及转化为C/C++工程
- 『网易实习』周记(五)
- 谨防!黑客是这样偷窥你的智能手机
- hackrf+portapack 组装上手体验记录
- 清理FLASH_RECOVERY_AREA
- 唯美毕业论文答辩PPT模板
- magic4.0跟harmonyos,支持升级Harmony 2.0 Magic UI 4.0 9月中旬招募公测
- 计算机主机的组成部分,计算机主机的组成是有哪些