除了另一個答案,你還有一些額外的問題,使你的列表邏輯非常混亂和脆弱。首先,您正在對循環迭代進行硬編碼,這些迭代可能會或可能不匹配您的輸入。鏈表的全部用途是提供一個靈活的數據結構,使您可以存儲一個未知的節點數量。 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'的值,它並不指向它 –