从注释继续,你为什么用链表处理这个问题?您可以使用链接列表,但开销和代码复杂度超过要求。直接的解决方案是一个简单的动态数组,类型为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'指针。链表会使您的项目不必要地复杂化。 –