字符串连接。C语言

4

以下所有代码均为C语言。

下面的两段代码片段都被编译了,但不同之处在于第二个程序在启动时崩溃了。

第一段:

#include <stdio.h>
#include <string.h>

void main() {
    char *foo = "foo";
    char *bar = "bar";
    char *str[80];;
    strcpy (str, "TEXT ");
    strcat (str, foo);
    strcat (str, bar);
}

二:

#include <stdio.h>
#include <string.h>

void main() {
    char *foo = "foo";
    char *bar = "bar";
    char *str="";
    strcpy (str, "TEXT ");
    strcat (str, foo);
    strcat (str, bar);
}

区别在于第一种情况中,str字符串的大小被指定了,而第二种情况没有。如何在没有直接指定字符串str大小的情况下进行字符串拼接呢?


能否在没有直接指定字符串 str 的大小的情况下进行字符串拼接? - user3340536
你必须管理C语言字符串的内存分配和释放。这是一个无法避免的要求。 - R Sahu
@user3340536 不,你必须事先指定数组的大小。如果你为数组动态分配内存,那么你可以使用realloc函数重新调整数组的大小。 - ajay
7个回答

3
区别在于第一个例子中提到了字符串str的大小,而第二个例子没有。在第一个程序中,以下语句...
char *str[80];

定义str为一个包含80个指向字符的指针数组。您需要的是一个字符数组 -

char str[80];

在第二个程序中,
char *str="";

定义str为指向字符串字面量""的指针,而不是数组。数组和指针是不同的类型。

现在,第二个程序崩溃是因为

char *str="";

str定义为指向字符串字面量的指针。 strcpy的第一个参数应该是一个指向足够大以容纳其第二个参数指向的字符串的缓冲区的指针。

然而,str指向分配在只读内存中的字符串字面量""。通过将str传递给strcpy,它会引发未定义行为,因为strcpy试图修改它是非法的。未定义行为意味着行为是不可预测的,从程序崩溃到由于段错误(非法内存访问)或硬盘被格式化等任何事情都可能发生。您应始终避免调用未定义行为的代码。

如何进行字符串拼接而无需直接指定字符串str的大小?

目标字符串必须足够大以存储源字符串,否则strcpy将越过其第一个参数指向的缓冲区并引发未定义行为,因为存在非法内存访问。同样,目标字符串必须具有足够的空间以附加源字符串,否则strcat将越过缓冲区并再次导致未定义行为。在这种情况下,您应确保指定字符串str的正确大小。


2

修改为:

一:

#include <stdio.h>
#include <string.h>

void main() {
    char *foo = "foo";
    char *bar = "bar";
    char str[80];
    strcpy (str, "TEXT ");
    strcat (str, foo);
    strcat (str, bar);
}

第二点:

#include <stdio.h>
#include <string.h>

void main() {
    char *foo = "foo";
    char *bar = "bar";
    char str[80]="";
    strcpy (str, "TEXT ");
    strcat (str, foo);
    strcat (str, bar);
}

1
在第二个版本中,您设置了 char *str = ""; 这相当于在堆栈上分配了一个空字符串,其中包含一个字节的 null 以表示字符串结束。如果您编写了 char* str="0123456789",则会在堆栈上分配 11 个字节,其中前 10 个字节将是 "0123456789",而第 11 个字节将是 null。如果您尝试复制超过已分配字节数的数据到 str 中,则可能导致程序崩溃。因此,请动态分配足够的内存或静态分配内存。

1

1
#include <stdio.h>
#include <string.h>

void main() {
    char *foo = "foo";
    char *bar = "bar";
    char *str=NULL;
    size_t strSize = strlen(foo)+strlen(bar)+strlen("TEXT ")+1;

    str=malloc(strSize);
    if(NULL==str)
       {
       fprintf(stderr, "malloc() failed.\n");
       goto CLEANUP;
       }

    strcpy (str, "TEXT ");
    strcat (str, foo);
    strcat (str, bar);

CLEANUP

    if(str)
       free(str);        
    }

1
size_t len1 = strlen(first);
size_t len2 = strlen(second);

char * s = malloc(len1 + len2 + 2);
memcpy(s, first, len1);
s[len1] = ' ';
memcpy(s + len1 + 1, second, len2 + 1); // includes terminating null

我做得好吗?


1
两个程序都是错误的,第一个会引起未定义的行为,就像第二个程序一样。char *str[80];是指针数组,你将其作为函数(strcpystrcat)的第一个参数传递,而这些函数的第一个参数应该是char *。解决此问题的可能方法是将str定义为char str[80]; 第二个程序的问题在于char *str = "";是指向只读内存块的指针,无法更改。在这种情况下,可能的解决方案之一是:
 char* str = malloc(80);
 strcpy(str,"");
 strcpy (str, "TEXT ");
 strcat (str, foo);
 strcat (str, bar);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接