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

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

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

函数名:strcmp

原   型:extern  int  strcmp (const char *s1, const char *s2)  

功   能:这个函数用来比较s1和s2字符串,这个函数将返回一个值.如全部字符相同,则认为两个字符串相等;                 若出现不相同的字符,则以第一对不相同的字符比较结果为准。

说   明: 当s1注意不一定是-1);

               当s1==s2时,返回值为0;

               当s1>s2时,返回值为正整数(注意也不一定是1

字符串的比较规则:将两个字符串自左至右逐个字符比较(按ASCII码值大小比较),直到出现不同的字符或遇                                   到'\0'为止。

特别注意:strcmp(const char*s1,const char*s2)这里只能比较字符串,不能比较数字等其他形式的参数。

模拟实现:

#include
#include
#include
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");
	else
		printf("str1


函数名strncmp

原   型:int strncmp (const char *s1, const char *s2, size_t size) 

功   能: 此函数与strcmp极为类似。不同之处是,strncmp函数是指定比较size个字符。也就是说,如果字符                  串s1与s2的前size个字符相同,函数返回值为0; 如果字符串s1与s2的前size个字符不等,函数返回值为              *s1-*s2; 

模拟实现:

#include
#include
#include
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");
	else
		printf("str1

通过上述比较: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各字节中的内容是无法预知的,所以记得要对其                      初始化哦!

模拟实现:

#include
#include
#include
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;
}


函数名: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串)才是最重要的。

模拟实现:

#include
#include
#include
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;
}


到这里我们是不是应该思考一个问题

如果需要拷贝一个比较大的字符串呢,用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的指针。

模拟实现:

#include
#include
#include
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;
}

strncat函数

原 型:extern char *strncat(char *dest,char *src,int n);

功 能:把src所指字符串的前n个字符添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'。

说 明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串;
            返回指向dest的指针。

模拟实现:

#include
#include
#include
#include
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;
}

值得注意的是:strncat能进行字符串与字符串自身连接,而strcat是没有这个功能的!


最后呢,我们再来看一下strstr这个函数:

函数名:strstr

原  型:extern char *strstr(const char *str,const char *substr)

功  能:strstr()函数搜索一个字符串在另一个字符串中的第一次出现。该函数返回字符串的其余部分        (从匹配点)。如果未找到所搜索的字符串,则返回 false。

注  释:如果该参数是数字,则搜索匹配数字ASCII值的字符。该函数对大小写敏感。如需进行大小写不        敏感的搜索,请使用 stristr()。 

模拟实现:

#include
#include
#include
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;

}

最后再提醒一句,这些都是库函数,在直接使用它们的时候记得引头文件#include哦!

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



函数名






  

  

     

你可能感兴趣的:(C语言,函数,库)