C/C++面试常考题目讨论-之一strcpy()函数

1.1 功能


strcpy是C语言里的标准库函数,strcpy把从src地址开始且含有’\0’结束符的字符串复制到以dest开始的地址空间,返回值的类型为char*。原型为
char strcpy(char dset,const char *srcstr);
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
返回指向dest的指针。

1.2 实现

一种完整的写法如下:

char * strcpy( char *strDest, const char *strSrc ) 
{
 assert( (strDest != NULL) && (strSrc != NULL) );
 char *address = strDest; 
 while( (*strDest++ = * strSrc++) != ‘\0’ ); 
 return address;

一种典型的被喷写法:

void strcpy( char *strDest, char *strSrc )
{
  while( (*strDest++ = * strSrc++) != ‘\0’ );
}

这种方式只能说明会写代码,但是只能得2分。 和上面的想对比就知道为什么了。
1.strSrc传输的形式应该写成const char *strSrc。这是C++里的一个好习惯,如果只读数据strSrc被修改,会提示错误。
2.未判断输入的数据的合法性。这里可以使用断言来实现。 assert((des != NULL) && (source != NULL));
这里有一种错误是检查指针的有效性时使用((!strDest)||(!strSrc))或(!(strDest&&strSrc)),这样其实是将char*类型隐式转换成bool类型了。这种方式虽然灵活,但更多的是导致出错概率增大和维护成本升高。所以C++专门增加了bool、true、false三个关键字以提供更安全的条件表达式。
这里还有一种容易忽视的错误,将循环写成while (*strSrc!=’\0’) *strDest++=*strSrc++;,说明答题者对边界条件的检查不力。循环体结束后,strDest字符串的末尾没有正确地加上’\0’。
3.实现链式操作,也就是 char *address = strDest; 该方式的优点是能够保证每次调用都使用独立的地址空间,链式操作时将其连接到一起即可。如果只使用strDest则连续操作无法进行。
4.(A)针对返回值,容易有两种错误,return new string(“Invalid argument(s)”);这里新开辟了一个空间,放的是错误信息。这从函数中返回函数体内分配的内存是十分危险的做法,他把释放内存的义务抛给不知情的调用者,绝大多数情况下,调用者不会释放内存,这导致内存泄漏。
(B)return 0;一般而言,返回0不代表有异常信息,调用者有可能忘记检查返回值,调用者还可能无法检查返回值(见后面的链式表达式)。妄想让返回值肩负返回正确值和异常值的双重功能,其结果往往是两种功能都失效。应该以抛出异常来代替返回值,这样可以减轻调用者的负担、使错误不会被忽略、增强程序的可维护性。

1.3 使用时容易犯的错

1.指出下面的错误

void test1()
{
 char string[10];
 char* str1 = "0123456789";
 strcpy( string, str1 );
}

错误:str1需要11个字节来存储,因为需要末尾’\0’;如果不修改,在qt调试时会发现string中有正确的数据,但是无法正确打印。
2.分析下面的代码的错误:

void test2() 
{ 
char string[10], str1[10]; 
int i; 
for(i=0; i<10; i++) 
{ 
str1 = ‘a’; 
} 
strcpy( string, str1 ); 
}

这里的错误有:
首先,代码根本不能通过编译。因为str1为数组名,因此这里应该写成str1[i]=’a’。即使想对数组的第一个元素赋值,也要使用 *str1 = ‘a’;
其次,对字符数组赋值后,使用库函数strcpy进行拷贝操作,strcpy会从源地址一直往后拷贝,直到遇到’\0’为止。所以拷贝的长度是不定的。如果一直没有遇到’\0’导致越界访问非法内存,程序就崩了。正确的程序为:

void test2() 
{ 
char string[10], str1[10]; 
int i; 
for(i=0; i<9; i++) 
{ 
str1[i] = ‘a’; 
} 
str1[9] = ‘\0’; 
strcpy( string, str1 ); 
}

3下面的代码有什么问题

void test3(char* str1) 
{ 
if(str1 == NULL){ 
return ; 
} 
char string[10]; 
if( strlen( str1 ) <= 10 ) 
{ 
strcpy( string, str1 ); 
} 
} 

这里的问题是 if( strlen( str1 ) <= 10 )应该改成 if( strlen( str1 ) <10 ),这里考察的是sizeof与strlen的区别。
区别是sizeof()会统计最后的\0,而strlen不会。如果要使用sizeof,则可以使用等号。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纵横千里,捭阖四方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值