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,则可以使用等号。