从链接列表中的指针存储字符串

Posted

技术标签:

【中文标题】从链接列表中的指针存储字符串【英文标题】:Storing strings from pointers in Linked lists 【发布时间】:2022-01-20 23:16:51 【问题描述】:

最近开始练习链表。我知道基本的算法和概念,并想到了实现 LL 来存储用户输入的一堆字符串。

但显然我不断收到Segmentation fault

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

typedef struct _node
    char *s;
    struct _node *next;

node;

int main()

    node *head = NULL;
    int a = 0;
    char ch;
    char *str = malloc(10);
    do
    
        printf("\nDude %i:", a);
        fgets(str, 10, stdin);

        node *n = malloc(sizeof(node));
        if(n == NULL)
        
            printf("\ninsufficient memory");
            return 1;
        
        
        if(a == 0)
        
            strcpy(n->s, str);
            n->next = NULL;
            head = n;
        

        else
        
            strcpy(n->s, str);
            n->next = head;
            head = n;
        
        
        a++;
        printf("\n continue?(y/n): ");
        scanf("\n%c", &ch);
        
    while(ch == 'y');
    
    for(node *temp = head; temp != NULL; temp = temp -> next)
    
        printf("\n%s", temp->s);
    
    return 0;

我确实知道我的逻辑/代码在某个地方存在缺陷,因为我正在触摸我不应该触摸的内存,但似乎无法指出哪里,因为这是我第一次处理链表。

【问题讨论】:

您的调试器会准确地告诉您段错误发生的位置。在尝试学习 C 时,学习使用调试器不是可选的,尤其是 C 中的内存引用数据结构。投票结束这个问题是因为缺少调试信息——但我保证,一旦你启动调试器在您的程序中,您将很快能够自己找出问题所在,或者您可以在这里提出更好的问题! @MarcusMüller 是对的,只要在调试器中运行代码,调试器肯定会告诉你哪一行触发了分段错误。 ... 这与我必须做的事情完全相同,甚至试图弄清楚你的代码是做什么的。所以,不管是我们还是你这样做,不同的是你的任务是成为一个有能力的 C 开发者 我明白了。谢谢您的帮助!我将从现在开始使用调试器。 @acertainwanderer 当我学会这样做时,真的让我的生活变得轻松多了:) 【参考方案1】:

当您为malloc 分配struct 的空间时,您只是为指向_node 结构中的字符串的指针分配空间。在执行strcpy 之前,您需要分配一些内存来存储字符串并将指针s 指向它。 即

n->s = malloc(sizeof(char)*100);

请记住,您还需要制定策略来取消分配此内存。

正如其他人所暗示的,这些错误通常很容易通过使用gdb 查看/调试来发现。请记住,使用-g 标志进行编译以获得有用的调试信息很有用。

【讨论】:

只有在存储字符串时才需要分配一些内存吗? 不一定。当您使用指针(尤其是内部结构)时,您需要malloc。如果要静态分配,则需要使用值。因此,例如,您可以通过执行char x[10] 之类的操作来静态分配一些字符。此内存在超出范围时被释放。 啊,我指的是如果我存储数值,我只需要为指向结构的指针分配内存。因为,到目前为止,为结构成员单独分配内存对我来说是全新的,所以我认为只有字符串是这种情况。虽然看到我需要创建一个单独的块来释放这个有点特殊的指针(给我)让我重新考虑使用指针而不是数组,因为很明显,动态性伴随着它的权衡。 您可以通过在作用域中声明结构和字符串来静态分配它们。您需要将 struct 中的内容类型从指向实际值的指针更改。这当然会带来空间成本。很高兴您开始就这些事情提出问题。 C 中的编程就是权衡这类问题并进行权衡。 哦!我不敢相信我忘记了这个基本概念-感谢您跟上我的愚蠢怀疑并简洁地解释它。所以权衡这种权衡也是可取的。我明白了。【参考方案2】:

您捕获“分段错误”的原因是因为在复制实际字符串 strcpy(n-&gt;s, str) 之前,您没有为结构 nodes 变量分配内存。 所以,为s分配内存:

n->s = (char *) malloc(10 * sizeof(char));

【讨论】:

【参考方案3】:

请注意,您不能将任何内容写入未分配的空间,因此您需要为每个节点中的字符串调用malloc。 如果字符串长度是固定的,那么可以在struct node的定义中指定长度,避免malloc的问题。

此外,建议始终free 将不再引用的对象。

经过一些修改,下面的代码可能会有所帮助:

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

#define LEN 10

typedef struct node 
    char str[LEN];
    struct node *next;
 Node;

int main() 
    Node *head = NULL;
    int n = 0;
    char c = 'y';
    while (c == 'y') 
        Node *node = malloc(sizeof(Node));
        printf("Node #%d: ", n);
        scanf(" ");

        /* Store the string directly into the node. */
        fgets(node->str, 10, stdin);
        /* Remove the newline character. */
        node->str[strcspn(node->str, "\n")] = 0;

        node->next = head;
        head = node;
        ++n;
        printf("Continue? (y/N): ");
        scanf("%c", &c);
    ;

    Node *curr = head;
    while (curr != NULL) 
        printf("%s\n", curr->str);
        Node *temp = curr;
        curr = curr->next;

        /* Remember to free the memory. */
        free(temp);
    

    return 0;

【讨论】:

将输入存储在他的节点中肯定更有效,而且我似乎完全忘记了释放我的记忆。真的有必要删除换行符吗?虽然如果需要这样做是有道理的。

以上是关于从链接列表中的指针存储字符串的主要内容,如果未能解决你的问题,请参考以下文章

链接列表中的运行时错误:“ListNode”类型的空指针内的成员访问

链接的字符串列表对于每个节点具有相同的字符串

从存储为熊猫数据框中的字符串的列表中提取项目

克隆链接列表会导致分段错误

使用指向链接列表的指针存储 NSMutableDictionary 一个 C 结构

将字符串a中的数字取出存储到b中,用C语言指针怎么实现