将字符串复制到 *struct 成员

Posted

技术标签:

【中文标题】将字符串复制到 *struct 成员【英文标题】:Copy a string to a *struct member 【发布时间】:2022-01-14 18:00:24 【问题描述】:

我浏览了类似的主题,但没有找到解决问题的方法。我有一个类似

的结构
typedef struct 
    int number;
    char *string;
 mystruct;
    
//Then define a pointer to the struct:
mystruct *data;
    
// Allocate memory:
data = malloc(sizeof(mystruct));
    
//Assign some number, let's say 5:
(*data).number = 5;
    
//So far ok, works (checked: 5 can be retrieved from the struct somewhere else) but:
    
strcpy((*data).string = "Hello!");
//This line fails with segmentation fault.

我不明白为什么?有人可以解释一下我做错了什么吗?

【问题讨论】:

因为成员char *string; 也需要分配内存来复制字符串。但是你可以通过data->string = "Hello!" 来分配指针。 strcpy() 需要两个参数。 当您编写问题时,请使用编辑器中的正确工具将文本格式化为代码。插入 html 换行符比突出代码并按下 按钮要费力得多。而后者实际上会产生一些不会灼伤我们眼睛的东西。 顺便说一句,我们通常写pointer->member而不是(*pointer).member 我怀疑你实际上写了strcpy((*data).string, "Hello!");,否则它甚至不会编译。在这种情况下,请参阅@WeatherVane 的评论。 【参考方案1】:

如 cmets 中所述,您尝试的 strcpy 调用的问题在于您的目的地(datastring 成员)不是指向有效内存的指针。 (我假设您的无效语法 strcpy((*data).string = "Hello!") 是一个错字,并且您的真实代码具有类似 strcpy((*data).string, "Hello!") 的内容 - 否则,它甚至不会编译,因此您不会遇到分段错误。 )

有几种方法可以解决此问题,具体取决于您实际想要发生的情况。首先,正如 cmets 中也提到的,您可以将 指针 复制到目的地,如下所示1

data->string = "Hello!";

然而,这可能不是你想要的,因为,如果源实际上不是一个文字,而是一个可修改的字符串,那么,在赋值之后,对源的任何更改也将适用到您的副本。

如果你想要一份源数据的副本,你需要为其分配足够的空间,然后调用strcpy;像这样:

#include <stdlib.h> // For malloc

const char* src = "Hello!";
data->string = malloc(strlen(src) + 1); // Add 1 for the required nul-terminator
strcpy(data->string, src);

然而,the strdup function2 一举完成了上述mallocstrcpy 调用的工作:

data->string = strdup("Hello!");

在上述两种情况下,请务必在完成后致电free(data-&gt;string)


1 请注意,您可以使用“通过指针访问成员”(-&gt;)运算符,而不是取消引用然后使用. 运算符:data-&gt;number = 5 相当于您的@ 987654338@.

2 一些编译器/平台可能不支持 strdup 函数,但它是 C23 的 ISO C 标准的一部分

【讨论】:

嗨,阿德里安,感谢您的长篇回答。事实上,问题是不同的,请查看原始帖子的评论。【参考方案2】:

正如其他用户所说,您需要为字符串分配空间。

我会使用一个灵活的数组成员并且只有一个分配给结构和字符串。

typedef struct 
    int number;
    char string[];
 mystruct;


mystruct *create(const char *str)

    mystruct *ms = NULL;

    if(str)
    
        ms = malloc(sizeof(*ms) + strlen(str) + 1);
        if(ms)
        
            strcpy(ms -> string, str);
            ms -> number = 0;
        
    
    return ms;


int main(void)

    mystruct *ms = create("Hello");

    if(ms)
    
        printf("ms -> string = `%s`\n", ms -> string);
    
    free(ms);

【讨论】:

【参考方案3】:

我不太清楚这一行

strcpy((*data).string = "Hello!");

你是说

strcpy((*data).string, "Hello!");

我认为问题在于您的结构包含一个指针char * string,它没有指向有效的分配内存。 您可以尝试多种解决方案

    具有预定义大小的结构
typedef struct 
    int number;
    char string[100];
 mystruct;

    您可以在初始化期间为字符串分配内存
data = malloc(sizeof(mystruct));
data->string = malloc(sizeof(char) *100));

【讨论】:

2 是错误的。它应该是data-&gt;string,因为data 是一个指针。

以上是关于将字符串复制到 *struct 成员的主要内容,如果未能解决你的问题,请参考以下文章

struct 的字符串成员正在附加其他字符串成员,均使用 scanf 解析

如何将interface 转成struct数组

将一种结构复制到另一种结构

golang中struct成员变量的标签(Tag)说明和获取方式

为啥 &mut self 允许借用 struct 成员,但不允许将 self 借用到不可变方法?

C中的字符串链表