从链接列表中的指针存储字符串
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->s, str)
之前,您没有为结构 node
的 s
变量分配内存。
所以,为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”类型的空指针内的成员访问