部分库函数的功能分析及模拟实现

来源:互联网 发布:苹果离线翻译软件 编辑:程序博客网 时间:2024/05/18 00:03

库函数能提供给我们最显著的作用就是提高工作效率,在我们初学阶段使用库函数来实现一些简单的算法其实是很常见的,那么了解一些库函数的功能及其实现过程就很有必要了。

首先我们来看看strcmpstrncmp的用法和区别:

函数名: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所做不到的!



接下来让我们再看看strcpystrncpy这两个函数


函数名: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);
功能:
memcpymemmove的目的都是将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完全不需要,甚至有更快的指令来优化块复制,所以效率肯定高很多。


关于拷贝这一块儿呢就暂且介绍到这里,然后我们进入到下一个模块:

连接函数strcatstrncat

函数名: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的字符串;
            返回指向dest的指针。

模拟实现:

<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>哦!

先暂时介绍这些库函数吧,作为初学者呢,希望大家多多提点啊!



函数名






  

  

     
0 0