除了另一个答案,你还有一些额外的问题,使你的列表逻辑非常混乱和脆弱。首先,您正在对循环迭代进行硬编码,这些迭代可能会或可能不匹配您的输入。链表的全部用途是提供一个灵活的数据结构,使您可以存储一个未知的节点数量。 for(i = 0; i < 7; ++i)
完全失败了这个目的。
它是什么你想存储?你的意见是什么? (note
字符串)。为什么不在输入有效的note
时创建附加节点?它可以是简单:
char tmp[MAXC] = "";
...
while (scanf ("%3s", tmp) == 1) {
...
strcpy (newp->note, tmp); /* set note and linkp */
...
}
您也留下自己敞开到整个代码处理无效值。为什么?您无法验证您的用户输入和内存分配。如果任一失败,您将继续盲目地使用未定义的值。总是验证所有用户输入和内存分配。这很简单,例如
if (!(scalep = malloc (sizeof *scalep))) { /* allocate/validate */
fprintf (stderr, "error: virtual memory exhausted, scalep.\n");
return 1;
}
if (scanf ("%3s", scalep->note) != 1) { /* validate ALL input */
fprintf (stderr, "error: invalid input, scalep->note\n");
return 1;
}
最后,不需要prevp
。这只在删除或交换节点时需要(在删除或交换节点后,您必须重新指定prev
指针指向next
(您的linkp
)),您在代码中都不执行任何操作,也不需要int
值你迭代current node = next node;
来遍历你的列表(有几个变化如何做到这一点)。把所有的拼在一起,并试图走出打好代码在一个稍微更合乎逻辑的方式,你可以做类似下面的东西:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXC 4
typedef struct scale_node_s {
char note[MAXC];
struct scale_node_s *linkp;
} scale_node_t;
int main (void)
{
scale_node_t *scalep, *newp, *walker;
char tmp[MAXC] = "";
if (!(scalep = malloc (sizeof *scalep))) { /* allocate/validate */
fprintf (stderr, "error: virtual memory exhausted, scalep.\n");
return 1;
}
if (scanf ("%3s", scalep->note) != 1) { /* validate ALL input */
fprintf (stderr, "error: invalid input, scalep->note\n");
return 1;
}
scalep->linkp = NULL;
while (scanf ("%3s", tmp) == 1) {
if (!(newp = malloc (sizeof *newp))) { /* allocate/validate */
fprintf (stderr, "error: virtual memory exhausted, newp.\n");
break;
}
strcpy (newp->note, tmp); /* set note and linkp */
newp->linkp = NULL;
walker = scalep; /* set walker to scalep */
while (walker->linkp) /* find last node */
walker = walker->linkp; /* linkp !NULL move to next node */
walker->linkp = newp;
}
walker = scalep; /* output list */
while (walker) {
printf ("%s\n", walker->note);
walker = walker->linkp;
}
walker = scalep; /* free list memory */
while (walker) {
scale_node_t *victim = walker; /* save victim address */
walker = walker->linkp;
free (victim); /* free victim */
}
return 0;
}
示例使用/输出
$ echo "a b c d e" | ./bin/llhelp
a
b
c
d
e
内存使用/错误检查
在您编写的动态分配内存的代码中,您有2 的责任(1)总是保留一个指向内存块的起始地址的指针,所以,(2)当它不再需要时,它可以被释放为。
这是你必须使用一个内存错误检查程序,以确保你不要试图超越写/你分配的内存块的边界之外,尝试读取或底座上未初始化值条件跳转,最后,确认你释放了你分配的所有内存。
对于Linux valgrind
是正常的选择。每个平台都有类似的内存检查器。它们都很简单,只需通过它运行你的程序。
$ echo "a b c d e" | valgrind ./bin/llhelp
==25758== Memcheck, a memory error detector
==25758== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==25758== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==25758== Command: ./bin/llhelp
==25758==
a
b
c
d
e
==25758==
==25758== HEAP SUMMARY:
==25758== in use at exit: 0 bytes in 0 blocks
==25758== total heap usage: 5 allocs, 5 frees, 80 bytes allocated
==25758==
==25758== All heap blocks were freed -- no leaks are possible
==25758==
==25758== For counts of detected and suppressed errors, rerun with: -v
==25758== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
总是确认您已释放所有分配的内存,并且没有内存错误。
如果您有任何其他问题,请仔细查看并告诉我们。
'prevp-> linkp = newp;'复制'newp'的值,它并不指向它 –