部分库函数的功能分析及模拟实现
来源:互联网 发布:苹果离线翻译软件 编辑:程序博客网 时间:2024/05/18 00:03
库函数能提供给我们最显著的作用就是提高工作效率,在我们初学阶段使用库函数来实现一些简单的算法其实是很常见的,那么了解一些库函数的功能及其实现过程就很有必要了。
首先我们来看看strcmp和strncmp的用法和区别:
函数名:strcmp
原 型:extern int strcmp (const char *s1, const char *s2)
功 能:这个函数用来比较s1和s2字符串,这个函数将返回一个值.如全部字符相同,则认为两个字符串相等; 若出现不相同的字符,则以第一对不相同的字符比较结果为准。
说 明: 当s1<s2时,返回值为负整数(注意不一定是-1);
当s1==s2时,返回值为0;
当s1>s2时,返回值为正整数(注意也不一定是1)
字符串的比较规则:将两个字符串自左至右逐个字符比较(按ASCII码值大小比较),直到出现不同的字符或遇 到'\0'为止。
特别注意:strcmp(const char*s1,const char*s2)这里只能比较字符串,不能比较数字等其他形式的参数。
模拟实现:
<strong><span style="font-size:18px;">#include<stdio.h>#include<stdlib.h>#include<assert.h>int my_strcmp(const char*arr,const char *str){assert(arr);assert(str);while(*arr==*str){if(*arr=='\0') return 0; arr++; str++;}return (*arr-*str);}int main(){char *str1="abcda";char *str2="abcde";int ret=0; ret=my_strcmp(str1,str2);if(ret==0)printf("str1==str2\n");else if(ret>0)printf("str1>str2\n");elseprintf("str1<str2\n");system("pause");return 0;}</span></strong>
函数名:strncmp
原 型:int strncmp (const char *s1, const char *s2, size_t size)
功 能: 此函数与strcmp极为类似。不同之处是,strncmp函数是指定比较size个字符。也就是说,如果字符 串s1与s2的前size个字符相同,函数返回值为0; 如果字符串s1与s2的前size个字符不等,函数返回值为 *s1-*s2;
模拟实现:
<span style="font-size:18px;"><strong>#include<stdio.h>#include<stdlib.h>#include<assert.h>int my_strncmp(const char*arr,const char *str,int k){assert(arr);assert(str);while(k--){ if(*arr==*str) { while(*arr=='\0')return 0;arr++;str++; }else return (*arr-*str);}if(k==0)return 0;}int main(){char *str1="abcde";char *str2="bcda";int k=0;int ret=0;printf("请输入要比较的字符串个数:\n");scanf("%d",&k); ret=my_strncmp(str1,str2,k);if(ret==0)printf("str1=str2\n");else if(ret>0)printf("str1>str2\n");elseprintf("str1<str2\n");system("pause");return 0;}</strong></span>
通过上述比较:strncmp还是相对比较灵活的,所需比较的字符个数可以自行输入,这是strcmp所做不到的!
接下来让我们再看看strcpy和strncpy这两个函数:
函数名:strcpy
原 型:extern char *strcpy(char *dest,char *src);
功 能:把从src地址开始且含有NULL结束符的字符串赋值到以dest开始的地址空间,返回dest(地址中存储 的为复制后的新值)。
注 意:(1)src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
(2)字符数组dest必须写成数组名的形式,字符数组src可以是字符数组名,也可以是字符串常量。例 如:strcpy(dest,"China");
(3)如果在拷贝前未对dest数组初始化或赋值,则dest各字节中的内容是无法预知的,所以记得要对其 初始化哦!
模拟实现:
<strong><span style="font-size:18px;"><strong>#include<stdio.h>#include<stdlib.h>#include<assert.h>char *my_strcpy(char *dest, const char *src){char *ret=dest;assert(dest);assert(src);while(*src){ *dest++=*src++; }return ret;}int main(){char arr[10]="\0";char str[]="China"; my_strcpy(arr, str);printf("%s",arr);system("pause");return 0;}</strong></span></strong>
函数名:strncpy
原 型:extern char *strcpy(char *dest,char *src,size_t num);
功 能:(c/c++)复制src中的内容到dest,复制多少由num的值决定,返回指向dest的指针
说 明:如果num > dest串长度,dest栈空间溢出产生崩溃异常。
1)src串长度<=dest串长度,(这里的串长度包含串尾NULL字符)
如果n = src串长度,与strcpy一致;
如果n >src串长度,dest就包含两部分,从源src复制过来的和dest原来初始化的内容(根据初始化的内 容来看,不一定为'\0')的最后num-n个字符。
2)src串长度>dest串长度
如果n =dest串长度,则dest串没有NULL字符,会导致输出会有乱码。如果不考虑src串复制完整 性,可以将dest 最后一字赋值为NULL。
一般情况下,使用strncpy时,建议将n置为dest串长度(除非你将多个src串都复制到dest数组, 并且从dest尾部反向操作),复制完毕后,为保险起见,将dest串最后一字符置NULL,避免发生输出乱码问题。当然喽,无论是strcpy还是strncpy,保证dest串容量(能容纳下src串)才是最重要的。
模拟实现:
<span style="font-size:18px;"><strong>#include<stdio.h>#include<stdlib.h>#include<assert.h>char *my_strncpy(char *dest, const char *src,int n){char *ret=dest;assert(dest);assert(src);while(n--){*dest++=*src++;}*dest='\0';return ret;}int main(){int n=0;char arr[10]="\0";char str[]="China";printf("请输入要拷贝的字符个数:\n");scanf("%d",&n); my_strncpy(arr, str,n);printf("%s",arr);system("pause");return 0;}</strong></span>
如果需要拷贝一个比较大的字符串呢,用strncpy该如何优化才能提高效率呢,我们是不是可以考虑进行多个字节一拷贝呢,当然在32位进制的计算机上通常指的是4个字节一拷贝咯。说到这,那memcpy和memmove这两个函数好像更能达到优化的效果哦!下来让我们去比较一下它们的优缺:
首先描述一下这三个相关函数strcpy/strncpy、memcpy和memmove的意义。
众所周知的,strcpy/strncpy和memcpy都是用于从一块内存复制一段连续的数据到另一块内存,区别在于终结标识不同。strcpy会比较每个字符是否为'\0'以判定是否继续复制,而memcpy就不管内存数据内容,确定复制指定的长度(不讨论源串有错误或者目的空间不够等出错的情况)。所以这两者在作用上是可以共通的,我想这两个函数最大的区别只能说是语义上的区别。而用法上,strcpy只能针对字符串,memcpy却没有这个限制,用memcpy(char *pDest,char *pSource,strlen(pSource))完全能替代strcpy的功能。
而后面两个mem系列函数,主要区别在memcpy对于重叠内存的复制支持不太好。例如对char a[10]操作的话,memcpy(a, a + 3, 5)这样的,源数据是a+3到a+7,目标位置是a到a+5,操作区域有重复,则应该用memmove。
下来简述一下memcpymemmove的区别:
原型:void *memcpy(void *dst, const void *src, size_t count);
void *memmove(void *dst, const void *src, size_t count);
功能:memcpy与memmove的目的都是将count个字节的源内存地址的内容拷贝到目标内存地址中。
但当源内存和目标内存存在重叠时,memcpy会出现错误,而memmove能正确地实施拷贝,但这也 增加了一点点开销。
memmove的处理措施:
(1)当源内存的首地址等于目标内存的首地址时,不进行任何拷贝
(2)当源内存的首地址大于目标内存的首地址时,实行正向拷贝
(3)当源内存的首地址小于目标内存的首地址时,实行反向拷贝
从功能上来说,用memcpy(char *pDest,char *pSource,strlen(pSource))完全能替代strcpy的功能,当然memmove安全性更高一些。之所以倡导这种用法,在于用memcpy/memmove函数不仅功能上比strcpy/strncpy更强大,关键在于前者效率要高很多!尽管没有这两个函数的源代码,但是单从分析上,strcpy/strncpy需要在每一步操作时都要比较字符是否为'\0',而memcpy/memmove完全不需要,甚至有更快的指令来优化块复制,所以效率肯定高很多。
关于拷贝这一块儿呢就暂且介绍到这里,然后我们进入到下一个模块:
连接函数:strcat和strncat
函数名:strcat
原 型:extern char*strcat(char *dest,coonst char *src)
功 能:把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'。
说 明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串;
返回指向dest的指针。
模拟实现:
<span style="font-size:18px;"><strong>#include<stdio.h>#include<stdlib.h>#include<assert.h>char *my_strcat(char *str,const char *dest){char *pret=str;assert(str);assert(dest);while(*str){str++;}while(*str++=*dest++){;}*str='\0';return pret;}int main(){char arr[20]="abcdef";char str[]="aac";my_strcat(arr,str);printf("%s",arr);system("pause");return 0;}</strong></span>
strncat函数
原 型:extern char *strncat(char *dest,char *src,int n);
功 能:把src所指字符串的前n个字符添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'。
说 明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串;
模拟实现:
<strong><span style="font-size:18px;">#include<stdio.h>#include<stdlib.h>#include<string.h>#include<assert.h>char *my_strncat(char *str,const char *dest,int len){char *pret=str;assert(str);assert(dest);if(*dest=='\0')return 0;while(*str){str++;}while(len--){*str++=*dest++;}*str='\0';return pret;}int main(){char arr[20]="abcdef"; int len=strlen(arr);my_strncat(arr,arr,len); //这里实现的是字符串与字符串自身进行连接printf("%s",arr);system("pause");return 0;}</span></strong>
值得注意的是:strncat能进行字符串与字符串自身连接,而strcat是没有这个功能的!
最后呢,我们再来看一下strstr这个函数:
函数名:strstr
原 型:extern char *strstr(const char *str,const char *substr)
功 能:strstr()函数搜索一个字符串在另一个字符串中的第一次出现。该函数返回字符串的其余部分 (从匹配点)。如果未找到所搜索的字符串,则返回 false。
注 释:如果该参数是数字,则搜索匹配数字ASCII值的字符。该函数对大小写敏感。如需进行大小写不 敏感的搜索,请使用 stristr()。
模拟实现:
<span style="font-size:18px;"><strong>#include<stdio.h>#include<stdlib.h>#include<assert.h>char* my_strstr(const char *str, const char *substr){const char* str1 = str;const char* str2 = substr;const char *start = NULL;assert(str);assert(substr);if(*str2 == '\0')return (char *)str1;while(*str1) {start = str1;while( *str1 && *str2 && *str1 == *str2){str1++;str2++;}if(*str2 == '\0') return (char*)start; str1 = start+1; str2 = substr;}return NULL; //函数的返回类型}int main(){char *str=NULL;str=my_strstr("abcde","bcd"); if(str!=NULL){ printf("%s\n",str);}else{ printf("matched fail\n");}system("pause");return 0;}</strong></span>
最后再提醒一句,这些都是库函数,在直接使用它们的时候记得引头文件#include<string.h>哦!
先暂时介绍这些库函数吧,作为初学者呢,希望大家多多提点啊!
函数名
- 部分库函数的功能分析及模拟实现
- 模拟实现部分库函数
- 部分库函数的自我实现
- 字符串的部分库函数的实现
- 字符串的部分库函数的实现
- 某些库函数的模拟实现(一)
- 一大波库函数的模拟实现
- 模拟库函数实现字符串的操作
- 实现部分库函数
- 模拟实现string库函数
- 模拟实现库函数Strcpy
- 模拟实现库函数strstr
- 模拟实现库函数atoi
- 模拟实现库函数strstr
- str库函数模拟实现
- Mem库函数模拟实现
- 模拟实现库函数
- 模拟实现库函数strcpy
- 【Raspberry Pi 3试用体验】+wifi的一些问题
- Miui Note源码解析
- Shell中整数比较
- jdk中密钥和证书管理工具keytool常用命令详解
- 解压版MySQL安装图解
- 部分库函数的功能分析及模拟实现
- flume-ng性能优化与架构设计
- C#—考题字符串2
- 由于不满目前CSDN的域名,现博客将搬迁重写
- 特斯拉、猎鹰9、海上回收、龙飞船、格洛航天公司、充气式太空舱、霍金、邮票航天器
- 快速打开当前窗口下的CMD窗口
- 利用Spring的AbstractRoutingDataSource解决多数据源的问题
- Android通过PendingIntent实现消息通知
- Linux:sk_buff完全剖析与理解【转】