字符操作库函数

  • 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. -1-4 java io java流 常用流 分类 File类 文件 字节流 字符流 缓冲流 内存操作流 合并序列流...

    File类 •文件和目录路径名的抽象表示形式 构造方法 •public File(String pathname) •public File(String parent,Stringchild) •p ...

  2. java io--内存操作流_JavaIO——内存操作流、打印流

    我们之前所做的都是对文件进行IO处理,实则我们也可以对内存进行IO处理.我们将发生在内存中的IO处理称为内存流. 内存操作流也可分为两类:字节内存流和字符内存流. (1)ByteArrayInputS ...

  3. 字符串转内存c语言,【一起学C】C语言面试题必考:字符串操作函数,内存操作函数实现...

    本帖最后由 奉聪 于 2017-1-25 14:54 编辑 *******前言******* 我数一下,我发了几个帖子,1.2.3? 哈哈哈,没几个哈,感谢吾爱,让我学到了很多,乐于分享,共同进步! ...

  4. STM32学习第三课:STM32 c语言学习基础3(内存操作、指针、结构指针)

    1.内存操作 在对内存操作头疼的时候我发现了这篇神奇的文章,拜读之后豁然开朗心生崇拜 数据指针 在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它 ...

  5. C语言——常见的字符串函数+内存操作函数的介绍及实现

    文章目录 前言 一.字符串函数 1.求字符串长度 strlen 2.长度不受限制的字符串函数strcpy.strcat.strcmp 字符串拷贝 strcpy 字符串追加拷贝 strcat 字符串比较 ...

  6. C语言处理字符串及内存操作

    字符串处理函数 1.字符串长度 strlen表示包含的字符的个数,size_t strlen(char cosnt *string), 返回的是size_t类型,它是无符号整数类型,在表达式中进行运算 ...

  7. C 中的内存操作函数-memcpy 等(to be continued)

    文章目录 C中的内存操作函数 1.memcpy() 1.1 函数介绍 1.2 示例代码 1.3 Reference C中的内存操作函数 1.memcpy() 1.1 函数介绍 void *memcpy ...

  8. C语言程序设计 | 模拟实现内存操作函数:strncpy, strncat, strncmp, memcpy, memmove

    模拟实现字符串和内存操作函数(二)目录: strncpy strncat strncmp strcmp memcpy memmove strncpy char* strncpy(char* dst, ...

  9. C#中Marshal 类的内存操作的一般功能概述

    Marshal 类的内存操作的一般功能 Marshal类 提供了一个方法集,这些方法用于分配非托管内存.复制非托管内存块.将托管类型转换为非托管类型,此外还提供了在与非托管代码交互时使用的其他杂项方法 ...

最新文章

  1. 11月3号晚7点中科院南土所梁玉婷报告:土壤微生物功能组学与关键类群识别
  2. Xshell:Xshell的简介、安装、使用方法之详细攻略
  3. android ios web兼容,js与android iOS 交互兼容
  4. Spring Boot中使用@Scheduled创建定时任务
  5. 以后再想大数据杀熟就没那么容易了
  6. 6-3-1:STL之vector——vector的快速入门、常用接口
  7. 机器学习Machine learning in action实战相关资料
  8. 《Linux内核分析》(二)——从一个简单Linux内核分析进程切换原理
  9. CAShapeLayer
  10. linux 0.11 内核学习 -- sched.c,调度进程。
  11. 初入职场,如何快速脱颖而出?
  12. 根据深度优先算法(DFS)和标记数组求全排列
  13. Matlab返回多个值以及转化为C/C++工程
  14. 『网易实习』周记(五)
  15. 谨防!黑客是这样偷窥你的智能手机
  16. hackrf+portapack 组装上手体验记录
  17. 清理FLASH_RECOVERY_AREA
  18. 唯美毕业论文答辩PPT模板
  19. magic4.0跟harmonyos,支持升级Harmony 2.0 Magic UI 4.0 9月中旬招募公测
  20. 计算机主机的组成部分,计算机主机的组成是有哪些

热门文章

  1. python在财务方面的应用-财务数据分析与Python
  2. 龙芯板卡内存压力测试方法
  3. 部分Discuz!论坛刷分方法总结
  4. c语言竞赛算法编程题目,[C语言编程接龙竞赛]第一题 设计一个N!的算法
  5. 土壤科学系的李博士,你还好么
  6. C语言如何写二进制文件,C语言 读写二进制文件
  7. 论文学习——基于循环神经网络的电信行业容量数据预测方法
  8. HIS医院EMR电子病历系统源码
  9. android studio jar 包添加 的 三种方法
  10. MySql 拼接查询 CONCAT