strcpy函数的C/C++实现
2013-07-05 14:07:49
本函数给出了几种strcpy与strncpy的实现,有ugly implementation,也有good implementation。并参考标准库中的implementation,最后给出了比较好的implementation。
字符串复制,一个一个字符进行判断,直到最后一个结束符。
问题:
*与++的优先级问题:
根据《C缺陷与C陷阱》上的说法,两者是同一个优先级,结合性是从右向左。但*p++的含义却是先得到*p的值,之后再对指针p加1,具体实例见文章:http://www.cnblogs.com/youngforever/p/3171283.html
因此,
while ( (*dst = *src) != '\0')
dst++;
*src++;
可简写为:
while ( (*dst = *src) != '\0') ;
又因为'\0'的ASCII值就是0,因此while ( (*dst++ = *src++) != '\0') ; 可简写为while ( *dst++ = *src++ ) ;
并注意到结束时字符串结束符'\0'已经复制,因为是先复制再判断的。
小结:
标准库函数并没有输入合法性检查,这将输入合法性检查的任务推给了函数的调用者。
对于strcpy函数,好的implementation要考虑一下几点:
- 函数src参数应为const,dst参数为非const;
- 函数要返回dst的地址,以方便嵌套使用该函数;
- 函数返回的dst的地址不要为const类型;
- 确定dst要有字符串结束符;
- 注意输入合法性检查注意输入合法性检查。
对于strncpy函数,除了以上几点外,好的implementation还要考虑一下几点:
当source的长度小于count时,应该怎么办?标准库函数的做法是,对dst大于source长度、小于count的部分赋值为\0;但在当source的长度大于count时。赋值到dst中的字符串是没有结束符的,在下面的运行结果中_strncpy_2的测试部分可以看到;这是因为代码中只这样写的:
while (count && (*dest++ = *source++)) /* copy string */
count--; if (count) /* pad out with zeroes */
while (--count)
*dest++ = '\0';
这样在当source的长度大于或等于count时,就不会执行下面的if语句,而上面的while条件判断由于是先判断count的值,后复制的,因此,在count减为0时,刚好复制完最后一个有效字符,即 \0 的前一个字符,而没有复制\0.
如果要想使得source的长度大于count时,复制到dst中的字符串也有结束符,_strncpy_3函数可以做到这一点;
注意若while中的换为(*dest++ = *source++) && count,结果就会不同,即:
while ( (*dest++ = *source++) && count )
count--;
这样写,就会在source长度大于count时,多复制一个字符,因为count为0时,*source不是\0,仍会惊醒复制曹组,之后才会判断count的值。
代码:
#include <iostream> using namespace std;
#define SIZE 100 /***
*char *strcpy(dst, src) - copy one string over another
*
*Purpose:
* Copies the string src into the spot specified by
* dest; assumes enough room.
*
*Entry:
* char * dst - string over which "src" is to be copied
* const char * src - string to be copied over "dst"
*
*Exit:
* The address of "dst"
*
*Exceptions:
*******************************************************************************/ const char * _strcpy_1(char *dst,const char *src)
{
if (NULL == src || NULL == dst)
{
return NULL;
}
char *dst_ret = dst;
//const char *dst_ret = dst;
while ( (*dst++ = *src++) != '\0') ; //*的优先级高于++,结束时'\0'已经复制
return dst_ret;
} char * _strcpy_2(char *dst,const char *src)
{
if (NULL == src || NULL == dst)
{
return NULL;
}
char *dst_ret = dst;
//const char *dst_ret = dst; //返回值不需要是const类型的
while ( (*dst++ = *src++) != '\0') ; //*的优先级高于++
return dst_ret;
} //标准库函数给出的implementation,没有输入合法性检查
char * _strcpy_3(char *dst,const char *src)
{
char *cp = dst; while ( *cp++ = *src++ )
; /* Copy src over dst */ return ( dst );
} //标准库函数给出的implementation,加上输入合法性检查
//好的implementation要考虑一下几点:
//1)函数src参数应为const,dst参数为非const
//2)注意输入合法性检查
char * _strcpy_4(char *dst,const char *src)
{
if (NULL == src || NULL == dst)
{
return NULL;
} char *cp = dst; while ( *cp++ = *src++ )
; /* Copy src over dst */ return ( dst );
} /***
*char *strncpy(dest, source, count) - copy at most n characters
*
*Purpose:
* Copies count characters from the source string to the
* destination. If count is less than the length of source,
* NO NULL CHARACTER is put onto the end of the copied string.
* If count is greater than the length of sources, dest is padded
* with null characters to length count.
*
*
*Entry:
* char *dest - pointer to destination
* char *source - source string for copy
* unsigned count - max number of characters to copy
*
*Exit:
* returns dest
*
*Exceptions:
*
*******************************************************************************/ //不好的implementation
//因为参数count为int,且在src的长度小于count时,dst后面的没有处理
char * _strncpy_1(char *dst,const char *src,int count)
{
if (NULL == src || NULL == dst)
{
return NULL;
}
char *cp = dst;
int current_count = ;
//while ( (*cp++ = *src++) != '\0' && current_count != count)
// ++current_count; //*(cp - 1) = '\0'; //结束符 while ( current_count != count && (*cp++ = *src++) != '\0')
++current_count; *cp = '\0'; //结束符 return ( dst );
} //标准库函数的implementation
char * _strncpy_2 (
char * dest,
const char * source,
size_t count
)
{
char *start = dest; while (count && (*dest++ = *source++)) /* copy string */
count--; if (count) /* pad out with zeroes */
while (--count)
*dest++ = '\0'; //在sorce的长度小于count时,后面不补'\0',只是将source的前面count个字符覆盖,后面的不变 return(start);
} //标准库函数的implementation,加上输入合法性检查
//好的implementation要考虑一下几点:
//1)输入source为const,dest为非const,count为size_t类型
//2)在sorce的长度小于count时,后面补'\0'
//3)在sorce的长度大于count时,同样有结束符'\0'
char * _strncpy_3 (
char * dest,
const char * source,
size_t count
)
{
if (NULL == source || NULL == dest)
{
return NULL;
} char *start = dest; while (count && (*dest++ = *source++)) /* copy string */
count--; //若while中的换为(*dest++ = *source++) && count,结果就会不同 //*(dest - 1) = '\0'; //结束符
*dest = '\0'; //在sorce的长度小于count时,后面补'\0' if (count) /* pad out with zeroes */
while (--count)
*dest++ = '\0'; return(start);
} //测试程序
int main()
{
//_strcpy
char src_1[SIZE] = "hello world!";
char dst[SIZE] = "\0"; cout<<"test _strcpy_1..."<<endl;
cout<<"the src string is : "<<src_1<<endl;
_strcpy_1(dst,src_1);
cout<<"the dst string is : "<<dst<<endl; char src_2[SIZE] = "hello!";
cout<<"test _strcpy_2..."<<endl;
cout<<"the src string is : "<<src_2<<endl;
_strcpy_2(dst,src_2);
cout<<"the dst string is : "<<dst<<endl; char src_3[SIZE] = "happy birthday!";
cout<<"test _strcpy_3..."<<endl;
cout<<"the src string is : "<<src_3<<endl;
_strcpy_3(dst,src_3);
cout<<"the dst string is : "<<dst<<endl; char *src_null = NULL; //不能这样赋值,报错:cannot convert from 'int' to 'char [100]'
//cout<<"test _strcpy_3(src == NULL )..."<<endl;
////cout<<"the src string is : "<<src_3<<endl;
//_strcpy_3(dst,src_null);
//cout<<"the dst string is : "<<dst<<endl; char src_4[SIZE] = "happy!";
cout<<"test _strcpy_4..."<<endl;
cout<<"the src string is : "<<src_4<<endl;
_strcpy_4(dst,src_4);
cout<<"the dst string is : "<<dst<<endl; cout<<"test _strcpy_4(src == NULL )..."<<endl;
_strcpy_4(dst,src_null);
cout<<"the dst string is : "<<dst<<endl; //_strncpy
char dst_2[SIZE] = "\0";
size_t count = ;
cout<<"test _strncpy_1..."<<endl;
cout<<"the src string is : "<<src_1<<endl;
cout<<"the number to copy is : "<<count<<endl;
_strncpy_1(dst_2,src_1,count);
cout<<"the dst_2 string is : "<<dst_2<<endl; count = ;
cout<<"test _strncpy_1..."<<endl;
cout<<"the src string is : "<<src_1<<endl;
cout<<"the number to copy is : "<<count<<endl;
_strncpy_1(dst_2,src_1,count);
cout<<"the dst_2 string is : "<<dst_2<<endl; count = ;
cout<<"test _strncpy_2..."<<endl;
cout<<"the src string is : "<<src_1<<endl;
cout<<"the number to copy is : "<<count<<endl;
_strncpy_2(dst_2,src_1,count);
cout<<"the dst_2 string is : "<<dst_2<<endl; count = ;
cout<<"test _strncpy_2..."<<endl;
cout<<"the src string is : "<<src_1<<endl;
cout<<"the number to copy is : "<<count<<endl;
_strncpy_2(dst_2,src_1,count);
cout<<"the dst_2 string is : "<<dst_2<<endl; count = ;
cout<<"test _strncpy_3..."<<endl;
cout<<"the src string is : "<<src_1<<endl;
cout<<"the number to copy is : "<<count<<endl;
_strncpy_3(dst_2,src_1,count);
cout<<"the dst_2 string is : "<<dst_2<<endl; count = ;
cout<<"test _strncpy_3..."<<endl;
cout<<"the src string is : "<<src_1<<endl;
cout<<"the number to copy is : "<<count<<endl;
_strncpy_3(dst_2,src_1,count);
cout<<"the dst_2 string is : "<<dst_2<<endl; return ;
}
运行结果(分别测试count大于、以及小于source长度的情形):
test _strcpy_1...
the src string is : hello world!
the dst string is : hello world!
test _strcpy_2...
the src string is : hello!
the dst string is : hello!
test _strcpy_3...
the src string is : happy birthday!
the dst string is : happy birthday!
test _strcpy_4...
the src string is : happy!
the dst string is : happy!
test _strcpy_4(src == NULL )...
the dst string is : happy!
test _strncpy_1...
the src string is : hello world!
the number to copy is :
the dst_2 string is : hell
test _strncpy_1...
the src string is : hello world!
the number to copy is :
the dst_2 string is : hello world!
test _strncpy_2...
the src string is : hello world!
the number to copy is :
the dst_2 string is : hello world!
test _strncpy_2...
the src string is : hello world!
the number to copy is :
the dst_2 string is : hello world!
test _strncpy_3...
the src string is : hello world!
the number to copy is :
the dst_2 string is : hell
test _strncpy_3...
the src string is : hello world!
the number to copy is :
the dst_2 string is : hello world!
请按任意键继续. . .
从运行结果可以看出,
strcpy函数的C/C++实现的更多相关文章
- strcpy函数的实现
strcpy函数的实现 大家一般认为名不见经传strcpy函数实现不是很难,流行的strcpy函数写法是: char *my_strcpy(char *dst,const char *src) { a ...
- strcpy函数实现
1,strcpy最简便实现 char * strcpy_to (char *dst, const char *src) { char *address = dst; assert((dst != NU ...
- strcpy函数和strncpy函数的区别
strcpy函数和strncpy函数的原型介绍在我的另一篇文章中介绍了,见strcpy,strncpy,strlen等函数原型 strcpy:字串复制 原型:char *strcpy(char *de ...
- memcpy、memmove、memset及strcpy函数实现和理解
memcpy.memmove.memset及strcpy函数实现和理解 关于memcpy memcpy是C和C++ 中的内存拷贝函数,在C中所需的头文件是#include<string.h> ...
- strlen() 和 strcpy()函数
strlen() 和 strcpy()函数的区别,这两个一个是返回一个C风格字符串的长度,一个是对一个C风格字符串的拷贝,两个本来功能上是不同的,此外,他们还有一些细小的区别:strlen(" ...
- strcpy函数导致release版程序崩溃
最近在写一个读取模型文件的小程序.很随意的使用了strcpy函数进行char字符数组的拷贝,这个数组是需要传递给PostMessage作为WPARAM的参数.代码部分如下: char pStrCurr ...
- strcmp函数和strcpy函数
(一)strcmp函数 strcmp函数是比較两个字符串的大小,返回比較的结果.一般形式是: i=strcmp(字符串,字符串); 当中,字符串1.字符串2均可为字符串常量或变量:i 是用于存放比 ...
- 第九十六题(编写strcpy 函数)
96.08 年中兴校园招聘笔试题 1.编写strcpy 函数 已知strcpy 函数的原型是 char *strcpy(char *strDest, const char *strSrc); 当中st ...
- strcpy函数
不调用C/C++库函数,编写strcpy()函数. char * my_strcpy(char *strDest,const char *strSrc) { char *p=strDest; whil ...
随机推荐
- NHibernate各种查询
NHibernate各种查询 NHibernate's methods of querying are powerful, but there's a learning curve. Longer t ...
- ASP.NET Web API标准的“管道式”设计
详见:http://www.cnblogs.com/artech/p/asp-net-web-api-pipeline.html http://www.codeproject.com/Articles ...
- Linux下SCP的使用
一.下载远程文件到本地 scp -i /Users/user/ssh/id_rsa root@192.168.1.8:/root/talk_server_redis/dump.rdb /Users/k ...
- 使用urllib2的HttpResponse导致内存不回收(内存泄漏)
问题出现环境:python 2.7.1(X)及以下, Windows(或CentOS) 这个问题产生在lib/urllib2.py的line 1174 (python 2.7.1),导致形成了cycl ...
- Linux tar 解压缩命令
tar -c: 建立压缩档案 -x:解压 -t:查看内容 -r:向压缩归档文件末尾追加文件 -u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个 ...
- 《WPF程序设计指南》读书笔记——第9章 路由输入事件
1.使用路由事件 路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件.通俗地说,路由事件会在可视树(逻辑树是其子集)上,上下routed,如果哪个节点上订阅了 ...
- General Palindromic Number (进制)
A number that will be the same when it is written forwards or backwards is known as a Palindromic Nu ...
- opencv学习笔记(02)——遍历图像(指针法)
#include <opencv2\core\core.hpp> #include <opencv2\highgui\highgui.hpp> #include <ope ...
- wampserver安装后的基本配置
wampserver安装后的基本配置 1.WampServer的安装 下载好安装包后,你能在保存其文件夹中找到这样一个图标: 双击它,会弹出如下提示 提示信息:不要试图从Wamp5 1.x(x代表任意 ...
- sql查找最小缺失值与重用被删除的键(转载)
转载自:http://blog.csdn.net/yanghua_kobe/article/details/6262550 在数据处理时,我们经常会使用一些“自增”的插入方式来处理数据.比如学生学号: ...