实现
金山面试的问题之一,比较简单。
需要注意两点:1.字符串空间检测判断2.字符串末尾记得加'0'
第一种写法:
也是我的答案:
char *strcat(char *str1, char *str2)
{
if((str1==NULL)||(str2==NULL)) throw "Invalide arguments!";
int len1=strlen(str1),len2=strlen(str2);
for(int i=strlen(str1);i<len1+len2;i++){
str1[i]=str2[i-len1];
}
str1 [len1+len2]= '\0';
return str1;
}
当时少写了 str1 [len1+len2]= '0';
第二种写法:
char *strcat(char *str1, char *str2)
{
if((str1==NULL)||(str2==NULL)) throw "Invalide arguments!";
char *pt = str1;
while(*str1!='\0') str1++;
while(*str2!='\0') *str1++ = *str2++;
*str1++ = '\0';
return pt;
}
切不可写成return str1;
因为此时函数体内的str1指针已经被移动到字符串结尾,指向'0'。
所以只能返回一开始pt保存的原始str1。返回值错误!
由于函数strcat的参数str1是形参,所以主函数的数组a的指针不会变化。
但是最好的写法还是不要直接对str1做修改:
char *strcat(char *str1, char *str2)
{
if((str1==NULL)||(str2==NULL)) throw "Invalide arguments!";
char *pt = str1;
while(*pt!='\0') pt++;
while(*str2!='\0') *pt++ = *str2++;
*pt = '\0';
return str1;
}
应用
参考:http://www.blog.chinaunix.net...
声明:使用gcc和vc++(VS2010)编译
函数定义:char *strcat (char *dest,const char *src)
函数说明:strcat()
会将参数src字符串拷贝到参数dest所指的字符串尾,第一个参数dest要有足够的空间来容纳要拷贝的字符串;
返回值: 返回dest字符串参数的起始地址;
接下来分三种情况来看strcat()
函数:
方案一:两个参数都是数组
#include <string.h>
#include <stdio.h>
int main(void)
{
char dest[30] = "Hello";
char src[] = "World";
strcat(dest, src);
printf("dest:[%s]\n", dest);
return 0;
}
GCC/VC++:dest:[HelloWorld]
方案二:两个参数都是指针
-
dest为空
#include <stdio.h> #include <string.h> int main(void) { char *dest = NULL; char *src = "World"; strcat(dest, src); printf("dest:[%s]", dest); return 0; }
GCC:Segmentation fault (core dumped)竟然是段错误,为什么呢?
dest没有足够的空间来存储src中的内容;
VC++:
cmd:空 弹出:.exe已停止工作。
修改之后的:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char *dest = NULL; dest = (char *)malloc(1024); *dest='\0';//显式将首地址指向结束符。非常必要。否则1024个字节的字符串会充满随机的字符。 char *src = "World"; strcat(dest, src); printf("dest:[%s]", dest); return 0; }
GCC/VC++:dest:[World]
如果没有*dest='\0';
,GCC通过,VC++不通过。
猜测:gcc在malloc后,新分配的空间自动补全了'0'。 -
dest非空
但此时的dest是空字符串,如果想要在非空字符串(比如"aaa")后strcat怎么办?
直接把char *dest = NULL;
改成char *dest = "aaa";
吗?#include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char *dest = "aaa"; dest = (char *)malloc(1024); *(dest+3)='\0'; char *src = "World"; strcat(dest, src); printf("dest:[%s]", dest); return 0; }
VC++:
cmd: dest:[屯蚖orld]
gcc:
dest[World]
VC++中, "aaa"被新分配的内存地址的值覆盖。由于新分配的内存地址的值并未初始化(除了dest+3位置上赋值为'0'), 所以出现乱码。"World"的第一个字母W(1字节)被a的第三个字符组合成了汉字“蚖”(2字节)。
那么,先分配内存,然后赋值:
char *dest = (char *)malloc(1024);dest = "aaa";
?
一样不可以!
VC++:cmd:空 弹出:.exe已停止工作!
gcc:Segmentation fault (core dumped)
原因相同:"aaa"将分配的空间覆盖,也就是说a指向新的字符串"aaa",它的大小为4,无法放下a和b。正确的做法是对a先申请内存,然后用strxxx函数对a开始几位进行修改。比如用strcpy:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main () { char *dest=(char *)malloc(1024); char *src="World"; strcpy (dest,"aaa"); strcat (dest,src); printf("dest:[%s]", dest);//puts (dest); return 0; }
vc++:
cmd:dest:[aaaWorld]
gcc:
dest:[aaaWorld]
OK!
方案三:第一个是数组,第二个是指针
#include <stdio.h>
#include <string.h>
int main(void)
{
char dest[6] = "Hello";
char *src = "World";
strcat(dest, src);
printf("dest:[%s]\n", dest);
return 0;
}
gcc:
dest:[HelloWorld]
*** stack smashing detected ***: ./1 terminated
Aborted (core dumped)
为什么会这样呢?不是说要空间足够的时候才可以拷贝成功的么?
很明显,这属于数组越界的问题,在C语言中,c不检查也不提示,所以这里的拷贝用到了dest[6]后面紧挨着的几个存储单元;
VC++:
cmd:dest:[HelloWorld]
弹出:stack around the variable “XX” was corrupted!
方案四:第一个指针,第二个数组
#include <stdio.h>
#include <string.h>
int main(void)
{
char *dest;
char src[] = "World";
strcat(dest, src);
printf("dest:[%s]\n", dest);
return 0;
}
看到这里,都会知道肯定是dest的空间不足,无法拷贝src中的内容;
所以输出结果是:
gcc:
dest:[�Ax�World]
//原文说他的结果是Segmentation fault (core dumped)
vc++:
cmd:空。
弹出:dest未初始化就被使用。
更改之后:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *dest;
dest = (char *)malloc(1024);
*dest='\0';
char src[] = "World";
strcat(dest, src);
printf("dest:[%s]\n", dest);
return 0;
}
OK输出结果是
GCC/vc++:dest:[World]
如果没有*dest='\0';
,GCC通过,VC++不通过。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。