不使用库函数实现strcpy,源代码如下:
|
#include <assert.h>
/* * Function : strcpy * Description: The strcpy() function shall copy the string pointed to * by src (including the terminating null byte) into the * array pointed to by dst. If copying takes place * between objects that overlap, the behavior is undefined. * Parameters : char *dst -- destination address * const char *src -- source address * Return : The strcpy() function shall return dst; no return value is * reserved to indicate an error. */ char *strcpy(char *dst, const char *src) { assert((dst != NULL) && (src != NULL)); char *tmp = dst;
while ((*dst++ = *src++) != '\0') { /* nothing */; }
return tmp; }
|
需要注意几个方面的问题:
1、注意编程风格。比如,使用dst、src这样增强可读性的名字。
2、使用断言来检验输入参数的有效性。
3、使用const来约束src,表明src对应的内容不能被修改。
4、返回dst,以便实现链式表达式这样的机制。
下面给出一个测试驱动程序。
 |
| 文件: |
strcpy.tar.gz |
| 大小: |
2KB |
| 下载: |
下载 | |
2007-10-30
这个版本算是比较好的一个了。也许是受林锐博士的《高质量C/C++编程》的影响,这个函数实现被用来作为面试/笔试的试题,有点滥用了。
在CU上面有贴子讨论strcpy为什么要返回值,通读了该贴,感觉还是flw的看法有道理,如下:
这是一种哲学,基于两种思想:
1、返回值和不返回值效率相差无几。
2、返回了值,可以不用它(返回值),也可以用它。想不用,就不用,想用,也可以,给了用户更多的选择。而如果不返回值,就只能选择“不用”了,因为你想用也用不着。
总而言之,就是尽可能给用户更多的选择,因为你无法预期用户将来会如何使用你的程序。引用 Perl 界的一句谚语,就是“There is more than one way to do it”。
下面再举个例子:
在C或者Perl以及其它的一些语言中,赋值运算有返回值,并且该返回值可以参与其它运算。比如我们经常见到的:
if ( (fp = fopen( "/path/to/foo", "r" )) == NULL ){
}
类似的语句,就是利用了这一特性。现在有许多“编程规范”明文禁止这种写法,认为可读性不好,本人也是非常支持的。然而作为语言本身来讲,它提供这种功能,只是你可以不用它。
和 C/Perl 相反的例子是 Pascal、Basic、Python。就拿 Python 来说,Python 的作者认为这种做法经常会造成把
if ( ret == -1 ){
}
误写为
if ( ret = -1 ){
}
之后,程序仍然能够继续运行、并且造成难以察觉的错误(类似的讨论本版已经有过多次,许多人提到他们采用把常量写左边的方法。然而,大家都是 C 程序员,因此早就适应了前述的哲学,因而从来没有人想到这其实是因为罪恶的赋值语句返回值造成的错误,-1 == ret 只是亡羊补牢)。在 Python 中,if ( ret = -1 ) 就是错误的写法,是不能编译运行的,也自然就不会造成 BUG。我个人非常赞许这一做法。
说到这里,就触摸到了不同哲学之间的冲突问题来了。有些人认为,我们给用户提供更多的功能,更多的选择,然后由他们决定哪一种才是最好的。并据此进行取舍。而另一些认为,我们应该仅仅给用户提供最优的功能,然后强制用户采用这种选择,从而避免因为过于自由而带来的各种问题。Python 的强制缩进便是如此:几乎所有的语言都在强调缩进所带来的弊端,然而很少有语言像 Python 这样激进。因此格式混乱的代码在各种语言中都能见到,相比起来 Python 代码就要整齐的多。(自然也就没有资格参加混乱代码大赛了 ^_^)