今天刷题时遇到了这个问题,记录一下。

strcpy比较简单,就是拷贝字符串,遇到'\0'时结束拷贝。

memcpy用来做内存拷贝,可以拷贝任何数据类型的对象并指定拷贝数据的长度:char a[100],b[50]; memcpy(b, a, sizeof(b));

总结一下:

strcpy和memcpy主要有以下3方面的区别。
            复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
            复制的方法不同。strcpy不需要指定长度,它遇到字符串结束符"\0"便结束。memcpy则是根据其第3个参数决定复制的长度。
            用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy。

//注意:如果用的是sizeof(a),则会造成内存泄露。

比较复杂点的是memset,用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为‘ ’或‘\0’,比如:

char a[100];memset(a, '\0', sizeof(a));

另外比较方便的是对结构体的操作, memset可以方便的清空一个结构类型的变量或数组:

比如有结构体struct sample_strcut  stTest,一般清空结构体的话得用如下方式:

struct sample_struct
{
char csName[];
int iSeq;
int iType;
}; stTest.csName[0]='\0';
stTest.iSeq=0;
stTest.iType=0;

而如果用memset就非常方便了:

memset(&stTest,0,sizeof(struct sample_struct));

参考:http://www.cppblog.com/junfeng568/archive/2006/03/11/4022.html

http://blog.chinaunix.net/uid-23922099-id-3555928.html

今天遇到的笔试题是实现strcpy和memcpy,当时没做出来,网上一搜才发现是零几年淘宝就出过的题目,好吧。。

参考:http://blog.sina.com.cn/s/blog_4d3a41f40100cvz8.html#cmt_1557675

char *strcpy(char *des, const char *src){
assert((des != NULL) && (src != NULL));//如果值为假,打印输出错误
char *add = des;
while ((*des++ = *src++ ) != ‘\’) ;
return add;
} void *memcpy(void *pvTo, const void *pvFrom, size_t size) {
assert((pvTo != NULL) && (pvFrom != NULL)); // 使用断言
byte *pbTo = (byte *) pvTo; // 防止改变pvTo的地址
byte *pbFrom = (byte *) pvFrom; // 防止改变pvFrom的地址
while(size -- > )
*pbTo = *pbFrom ;
return pvTo;
}

下面看笔试题的得分点:

char* strcpy(char* strDest,const char* strSrc)
{
if((strDest == NULL) || (strSrc == NULL)) //[1]
throw "Invalid Arguments"; //[2]
char* strDestCopy = strDest; //[3]
while((*strDest = *strSrc ) != '\0')//[4]
;
return strDestCopy;
}

[1] 参数检查
    (A)不检查指针的有效性,说明设计者不注重程序的健壮性
   (B)检查指针的有效性时使用((!strDest) || (!strSrc))或(!(strDest && strSrc)),说明对C语言中类型隐式转换没有深刻认识,

在本例中char*转换为bool即是类型隐式转换,这种功能虽然灵活,但是更多的是导致出错概率的增大和维护成本的增高
   (C)检查指针的有效性时使用((strDest==0)||(strSrc==0))说明答题者不知道使用常量的好处。直接使用字面常量(如本例中的0)

会减少程序的可维护性。0虽然简单,但程序中可能出现很多处对指针的检查,万一出现笔误,编译器不能发现,生成的程序内含逻辑错

误,很难排除。而使用NULL代替0,如果出现拼写错误,编译器就会检查出来。

[2] 返回值
(A)return new string("Invalid arguments");,说明答题者根本不知道返回值得用途,并且它对内存泄露也没有警惕心,从函数体中

返回函数体内分配的内存是十分危险的做法,他把释放内存的义务抛给不知情的调用者,绝大多数情况下,调用者不会释放内存,这导致内存泄露
(B)return 0;,说明答题者没有掌握异常机制。调用者有可能忘记检查返回值,调用者还可能无法检查返回值(见后面的链式表达式)。妄想让返回

值肩负返回正确值和异常值的双重功能,其结果往往是两种功能都失效。应该以抛出异常来代替返回值,这样可以减轻调用者的负担、使错误不会被忽略、

增强程序的可维护性。

[3] 细节
(A)忘记保存原始的strDest值,说明答题者逻辑思维不严密。

[4] 细节
(A)循环写成while (*strDest =*strSrc );,同[1](B)。
(B)循环写成while (*strSrc!='\0') *strDest =*strSrc ;,说明答题者对边界条件的检查不力。循环体结束后,strDest字符串的末尾没有正确地加上'\0'。

最后,为啥要返回char *?

返回strDest的原始值使函数能够支持链式表达式,增加了函数的“附加值”。同样功能的函数,如果能合理地提高的可用性,

自然就更加理想。链式表达式的形式如:

int iLength=strlen(strcpy(strA,strB));
又如:
char * strA=strcpy(new char[10],strB);
返回strSrc的原始值是错误的。其一,源字符串肯定是已知的,返回它没有意义。其二,不能支持形如第二例的表达式。

其三,为了保护源字符串,形参用const限定strSrc所指的内容,把const char *作为char *返回,类型不符,编译报错。

最新文章

  1. 01.WAMP搭建 [Win7+Apache2.4+MySQL5.7+PHP7
  2. pic计数
  3. SQL Server 数据导入Mysql详细教程
  4. 小生功能贴<一> --- 动态添加应用 具有长按删除功能
  5. PHP执行过程
  6. js在本地预览图片
  7. Android 颜色渲染(三) Shader颜色渲染
  8. hdu1171 Big Event in HDU 01-背包
  9. vector的内存分配与释放
  10. 利用js制作异步验证ajax方法()
  11. No grammar constraints (DTD or XML schema).....两种解决方法
  12. ssh三大框架集成后,jsp中采用forword标签提交时会报错的解决方案
  13. 轻量级.Net Core服务注册工具CodeDi发布啦
  14. php curl Problem with the SSL CA cert (path? access rights?)
  15. DAY15、模块
  16. CentOS7.0小随笔——指令基本操作(Part.A)
  17. Python全栈之路----进制运算
  18. There is no session with id XXX
  19. pta7-18奥运排行榜(模拟)
  20. canvas-圆弧形可拖动进度条

热门文章

  1. 用户缓冲式I/O
  2. 【CF438E】The Child and Binary Tree(多项式运算,生成函数)
  3. secureCRT mac 下破解
  4. spark streaming (一)
  5. linux下ffmpeg安装(转)
  6. 手脱PEncrypt 4.0
  7. vue使用插件 使用库
  8. numpy数组中冒号和负号的含义
  9. 封装-python
  10. Jquery中find与each方法使用详解