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 ...
随机推荐
- javascript 事件的学习
1.事件绑定: addEventListener , removeEventListener.是dom2级别的事件绑定 attachEvent , detachEvent 是IE的事件绑定. 2. 事 ...
- [Linux] Linux学习笔记(5)-文件与目录管理
1.Linux目录结构为树状结构,最顶层的目录为跟目录"/",其它目录通过挂载可以将它添加到目录树中,通过解除挂载移除它们. 2.绝对路径与相对路径 绝对路径写法:由根目录&quo ...
- TImage 的一些操作
//给 image上写数字. Image1.Picture.Bitmap.Height:= Image1.Height; Image1.Picture.Bitmap.Width:= Image1.Wi ...
- Pandas简易入门(四)
本节主要介绍一下Pandas的另一个数据结构:DataFrame,本文的内容来源:https://www.dataquest.io/mission/147/pandas-internals-dataf ...
- 获取股票历史数据和当前数据的API
关键字:股票,stock,API,接口 1.获取股票当前数据 新浪数据接口:http://hq.sinajs.cn/list={code}.{code}替换为股票代码,沪市股票代码加前缀sh,深市股票 ...
- CR0,CR3寄存器
驱动在hook系统函数的时候通常要将只读属性暂时的屏蔽掉,主要有三种方法 1.修改CR0寄存器的WP位,使只读属性失效(这是网上用的最多的方法),切忌使用完之后立马修改回来 2.只读的虚拟地址,通过C ...
- Microsoft Office Excel 不能访问文件
问题描述: Microsoft Office Excel 不能访问文件“XX.xls”.可能的原因有: 1 文件名称或路径不存在.2 文件正被其他程序使用.3 您正要保存的工作簿与当前打开的工作簿同名 ...
- 在一个工程管理多个应用-b
Demo:http://download.csdn.net/detail/u012881779/9166527 本文的产生是因产品经理提出的特殊需求: 一个针对多所学校的应用,对不同学校需要分别使用一 ...
- iOS 本地存储四种方法
在iOS开发过程中,不管是做什么应用,都会碰到数据保存的问题.将数据保存到本地,能够让程序的运行更加流畅,不会出现让人厌恶的菊花形状,使得用户体验更好.下面介绍⼀一下数据保存的方式: 1.NSKeye ...
- HighCharts 根据spline-plot-bands图,定制自己的图(区间里显示多个数据)
公司项目里有这样一个需求,根据数据绘图,但是数据很多,不可能每个点每个点的去画,这样显示的数据太密集非常的难看(更显得技术不专业),如图: 所以我和项目经理商量如何显示这个图形,按照他的意思是,按照范 ...