我有一个包含学生姓名和成绩的文件,我想编写一个程序,可以根据用户的选择对他们的成绩进行排序(如期中1,中期2)。我写了选择部分并打开文件,但我不知道如何使程序只读取文件的某些部分(例如只有Midterm 1年级)并仅对它们进行排序。这是我到目前为止所写的内容;
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int number;
char name[30];
char surname[30];
int midterm1,midterm2,midterm3;
} Student;
int main()
{
int choice,studentnumber,midterm1,midterm2,midterm3;
char surname;
FILE *cfPtr;
struct student *name;
name = malloc( 10 * sizeof(Student));
if ((cfPtr = fopen("grades.txt", "r")) == NULL)
printf("File cannot be opened.\n");
else {
const int STUDENTSMAX = 100;
Student students[STUDENTSMAX];
int i = 0;
while (!feof(cfPtr))
{
fscanf(cfPtr, "%d%s%s%d%d%d", &students[i].number, &students[i].name,&students[i].surname, &students[i].midterm1, &students[i].midterm2, &students[i].midterm3);
printf("%4d%15s%15s%10d%10d%10d\n", students[i].number, students[i].name,students[i].surname, students[i].midterm1, students[i].midterm2, students[i].midterm3);
i++;
}
printf("What would you like to do? \n"
"1- Sort according to midterm 1\n"
"2- Sort according to midterm 2\n"
"3- Sort according to midterm 3\n"
"4- Exit\n");
scanf("%d",&choice);
while (choice != 4);{
switch (choice) {
case 1:
qsort(students,10,sizeof(int),comp);
for (i=0; i<9; i++)
printf("%4d%15s%15s%10d%10d%10d\n", students[i].number, students[i].name,students[i].surname, students[i].midterm1);
fclose(cfPtr);
}
system("PAUSE");
return 0;
}
答案 0 :(得分:0)
鉴于什么可能是一个有点自由形式的文本文件(基于显示的代码),它可能只是读取整个文件(有点像你已经在做)并且只使用你需要的部分。如果文本文件具有固定偏移的非常特定的格式,您可以搜索文件中的某些位置并读取特定的列值,然后搜索下一个偏移量并从下一行读取列值。但这可能比它的价值更麻烦,效率也不高(如果有的话)。
话虽如此,要对结果进行排序,您可能还需要整个文件。例如,如果您只是读取“midterm 1”值并对其进行排序,那么结果将只是排序等级而没有任何关联的名称和学号。因此,如果不了解更多关于目标的信息,您可以考虑创建一个可以容纳一行的struct
(学生编号,姓名,姓氏,中期1等)。然后创建一个数组并将每行读入数组的元素。如果你知道前面有多少行,你可以在一个块中分配数组,否则你可能需要在增长它时重新分配它。
读完整个数组后,您可以根据所需的值进行排序(例如,使用qsort
。
提到这一点后,现有代码存在一些问题/问题:
printf
? while
循环在其关闭paren之后有一个无关的分号(;),这意味着它有一个空的主体而不是明显意图的printf
和switch
语句。 switch
语句写得有点奇怪。我认为这是“未完成”的部分。但是包含fclose
似乎很奇怪。它可能应该在主else
。system("PAUSE");
可能不是最佳选择。也许使用getch
会更有意义暂停输入。修改以下是一些其他信息,以回应您的评论,询问更多详情。这听起来像是家庭作业,所以只是给出答案似乎不对。但这是一种方法:
struct
(基本上放在您当前定义为局部变量的6个变量中)。grades
)声明为您定义的结构pointer
。malloc
分配内存并将其分配给刚才提到的指针。记忆量可能是整个事情中最棘手的部分。 malloc
的尺寸参数类似于numRecs * sizeof( yourstruct )
。问题是numRecs
应该是什么。如果这是一个作业,并且你被告知会有多少记录(最多),那么就使用它。但是,如果它“未知”,那么有几种方法可以解决这个问题。一个是猜测一个数字(例如,100),然后在循环中读取它们,如果超过100则使用realloc
。另一个替代方案(可能效率较低)将使用两个循环 - 读取它们一旦没有存储它们但只计算它们然后分配已知的大小并再次读取它们。我会使用realloc版本。malloc
ed)。例如,您可以使用studentnumber
代替grades[arraypos].studentnumber
。当你阅读它们时,请保留一个计数器。然后,您可以使用qsort
对数组进行排序。修改2
FILE *cfPtr;
成员不在其中之外,您的结构定义看起来是正确的。它应该仍然是一个局部变量。 typedef struct { ... } Student;
。这样,您就可以在代码中使用Student
代替struct Student
。请注意,我将名称大写(命名中的个人偏好使其看起来不像变量名)。name = malloc( 50 * sizeof( struct student ));
(或malloc( 50 * sizeof( Student ));
如果您将其更改为使用typedef。这假设从文件中读取的记录不会有50个或更少。