從註釋繼續,你爲什麼用鏈表處理這個問題?您可以使用鏈接列表,但開銷和代碼複雜度超過要求。直接的解決方案是一個簡單的動態數組,類型爲students
。數組或重要的好處。直接訪問所有的學生,簡單的排序與一個調用qsort
,簡單的加法,等等。
不要誤會我的意思,如果你的任務是使用鏈表,通過各種手段做,但你應該看看動態數組student
,在那裏你可以根據需要添加realloc
以添加儘可能多的學生。
例如:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { MAXC = 30, MAXS = 60, MAXLN = 128 };
typedef struct students {
char first[MAXC];
char last[MAXC];
char class[MAXC];
} students;
int main (int argc, char **argv) {
students *array = NULL;
size_t i, idx = 0, maxs = MAXS;
char buf[MAXLN] = "";
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
/* allocate/validate maxs students in array */
if (!(array = malloc (maxs * sizeof *array))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1;
}
while (fgets (buf, MAXLN, fp)) { /* read each line into buf */
/* separate in to struct members */
if (sscanf (buf, "- %s %s %s", array[idx].first,
array[idx].last, array[idx].class) != 3)
continue;
if (++idx == maxs) { /* check against current allocations */
void *tmp = realloc (array, (maxs + MAXS) * sizeof *array);
if (!tmp) { /* valdate realloc array succeeded */
fprintf (stderr, "error: realloc memory exhausted.\n");
break; /* or break and use existing data */
}
array = tmp; /* assign reallocated block to array */
maxs += MAXS; /* update current allocations size */
}
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
printf ("\nstudents:\n\n"); /* output formatted data */
for (i = 0; i < idx; i++) {
char tmp[2 * MAXC + 2] = "";
strcpy (tmp, array[i].last);
strcat (tmp, ", ");
strcat (tmp, array[i].first);
printf (" %-60s %s\n", tmp, array[i].class);
}
putchar ('\n');
free (array); /* free all allocated memory */
return 0;
}
(注:如果你的數據文件確實不開始每個符合'- '
,然後只需刪除從sscanf
格式字符串)
示例輸入
$ cat dat/studentclass.txt
- John Johnson Math
- Eric Smith Biology
- etc.
示例使用/輸出
$ ./bin/structstudents <dat/studentclass.txt
students:
Johnson, John Math
Smith, Eric Biology
內存錯誤/檢查
在動態分配內存的任何代碼你寫的,你有關於分配的任何內存塊2個responsibilites:(1)總保留一個指向內存塊起始地址的指針,(2)當不再需要時可以釋放它。
您必須使用內存錯誤檢查程序來確保您沒有超出/分配您分配的內存塊,嘗試讀取或基於未初始化值的跳轉,並最終確認您已釋放所有分配的內存。
對於Linux valgrind
是正常的選擇。例如
$ valgrind ./bin/structstudents <dat/studentclass.txt
==14062== Memcheck, a memory error detector
==14062== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==14062== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==14062== Command: ./bin/structstudents
==14062==
students:
Johnson, John Math
Smith, Eric Biology
==14062==
==14062== HEAP SUMMARY:
==14062== in use at exit: 0 bytes in 0 blocks
==14062== total heap usage: 1 allocs, 1 frees, 5,400 bytes allocated
==14062==
==14062== All heap blocks were freed -- no leaks are possible
==14062==
==14062== For counts of detected and suppressed errors, rerun with: -v
==14062== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)
務必確認所有堆塊被釋放 - 無泄漏是可能同樣重要錯誤摘要:0誤差爲0的上下文。
查看一下讓我知道如果數組方法適合您的需求,如果您有任何問題。
排序由class
構件
爲了的struct students
由class
,最簡單的方法對數組進行排序是使用qsort
功能。它是C庫提供的標準排序功能(包括stdio.h
)。您可以按students
結構的任何成員進行排序。你甚至可以按照課程和名稱進行排序。
唯一的問題新程序員有qsort
被寫入比較功能傳遞給qsort
纔能有它的排序所需的順序。 比較函數將接收一個指向你的結構student數組中的兩個元素的指針。參數傳遞爲void *
(實際上爲const void *
)。就像任何void
指針一樣,您必須將其轉換爲適當的類型,然後才能對其進行解引用。 (在這種情況下爲students *
)因此,您只需要一個將void
指針轉換爲students *
並將值傳遞給strcmp
的函數。例如:
int compare (const void *a, const void *b)
{
return strcmp (((students *)a)->class, ((students *)b)->class);
}
唯一剩下的(在代碼fclose
後)調用qsort
:
qsort (array, idx, sizeof *array, compare);
你的輸出繼而被類排序。
然後,如果您想進一步排序由last
名稱由class
排序,而不是在strcmp
返回爲class
,試驗後,如果結果不等於零,並返回結果。如果strcmp
的結果爲class
爲零,那麼您只需return strcmp (((students *)a)->last, ((students *)b)->last);
即可首先按class
排序,但如果該類相同,則進一步排序last
。例如:
int compare (const void *a, const void *b)
{
int r;
if ((r = strcmp (((students *)a)->class, ((students *)b)->class)))
return r;
return strcmp (((students *)a)->last, ((students *)b)->last);
}
示例輸入
$ cat dat/studentclass.txt
- Wade Williams Biology
- John Johnson Math
- Eric Smith Biology
- etc.
實施例使用/輸出
$ ./bin/structstudents <dat/studentclass.txt
students:
Smith, Eric Biology
Williams, Wade Biology
Johnson, John Math
採取學習qsort
的時間。
您顯示的代碼看起來並不像真正的努力。你有沒有嘗試讀取文件?以任何方式?在那裏有很多例子,當然你可以進一步發展,而不僅僅是打開文件。或者至少做一些嘗試。 – kaylum
我正在嘗試'while(fgets(name,MAX,in)!=(int)(EOF))'用指針做一些事情,但是我從編譯器得到了寫訪問衝突,我想我錯了。 –
你更好地服務於創建學生數組並放下'next'指針。鏈表會使您的項目不必要地複雜化。 –