2012-08-09 61 views
1

我有一个文件,其中包含学生的姓名和成绩,我想编写一个程序,可以根据用户选择对他们的成绩进行排序(如中期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

考虑什么可能是一个有点自由格式的文本文件(基于所示的代码),它可能是有意义的只是读取整个文件(有点像你已经这样做),并只使用部分,你需要。如果文本文件具有固定偏移量的非常特定的格式,则可以寻找文件中的特定位置并读取特定的列值,然后查找下一个偏移量并从下一行读取列值。但是这可能比它的价值更麻烦,而且效率也不会更高(如果有的话)。

话虽如此,要对结果进行排序,无论如何您可能需要整个文件。例如,如果您只是阅读并对“期中1”值进行排序,那么结果只是排序的成绩,没有任何关联的姓名和学号。因此,如果不了解更多关于目标的信息,您可以考虑创建一个可容纳一行(学号,姓名,中期1等)的struct。然后创建一个数组,并将每行读入数组的一个元素中。如果您知道预先存在多少行,则可以将该数组分配到一个块中,否则在扩展它时可能需要重新分配该行。

一旦您已经阅读整个数组,你可以来挑选基于期望的值(例如,与qsort

已经提到,存在与现有的显示代码的一些问题/问题:

  • 第二个printf具有较少的格式说明(%S)比参数
  • 第三的printf与“你想怎么办”的问题是缺少闭括号
  • 的fprintf中是不正确;它应该^ h将一个文件句柄作为第一个参数。不过,我怀疑这可能是printf
  • 最终while环具有一个外来分号(;)以下其关闭括号,这意味着它有一个空体,而不是预期的明显和printf声明switch
  • switch陈述有点奇怪,如书面。我认为这是“未完成”的部分。但包括fclose在内,似乎很奇怪。它可能应该在主要的else的末尾。
  • 使用system("PAUSE");可能不是最佳选择。也许使用getch会更有意义暂停输入。

编辑这里是为了响应您的评论要求更多一些细节上的附加信息。这听起来像是对我的功课,所以它只是给出答案似乎不正确。但在这里是做这件事:

  • 定义与6项是文件(基本上是摆在那,你目前已经被定义为局部变量的6个变量)在struct
  • 声明一个局部变量(例如,,grades)作为pointer来结构你定义的。
  • 使用malloc分配内存并将其分配给刚才提到的指针。内存的数量也许是整个事情中最棘手的部分。尺寸参数为malloc将类似于numRecs * sizeof(yourstruct)。问题是numRecs应该是什么。如果这是一项任务,并且您被告知会有多少记录(最多),那么就使用它。但如果它是“未知的”,那么有几种方法可以解决这个问题。一个是猜测一个数字(例如100),然后在循环中读取它们时使用realloc,如果超过100个。另一种替代方法(可能效率较低)将使用两个循环 - 一次读取它们而不保存它们但只需数它们,然后分配已知大小并再次读取它们。我会使用realloc版本。
  • 用数组替换本地变量的使用(即malloc ed)。例如,您可以使用grades[arraypos].studentnumber而不是studentnumber。当你阅读它们时,请记下它有多少。然后可以使用qsort对数组进行排序。

编辑2

  • 你的结构定义相貌端正除了FILE *cfPtr;成员不应该是它。它应该仍然是一个局部变量。
  • 为便于使用,您可以将结构定义为typedef struct { ... } Student;。这样你就可以在代码中使用Student而不是struct Student。请注意,我大写了名字(个人偏好命名,使其看起来不像变量名称)。
  • 对于malloc,你就近了。但正如所写,它正在为单个记录分配空间。您需要是这样的:。如果你改变它使用的typedef name = malloc(50 * sizeof(struct student));(或malloc(50 * sizeof(Student));这假设不会有50个或更少的记录从文件中读取
+0

我的问题是,我真的不知道知道如何阅读记录到一个数组我开始与第一部分; INT选择,studentnumber,midterm1,midterm2,midterm3; 焦炭名[30]; 焦姓[30]; FILE * cfPtr; 这实际上意味着是结构进入数组部分,但失败了。任何指导呢?对不起,我是一个起动器,并且是一个非常糟糕的:D。谢谢 – dawsonrose 2012-08-10 15:50:25

+0

我已经编辑了原始帖子,感谢您的建议。我定义编辑结构部分,认为我已经获得声明局部变量作为指针部分(可能不是:D),但我真的不熟悉“malloc”函数。我已经搜遍了,是我写的对吗? – dawsonrose 2012-08-10 19:26:19

+0

@dawsonrose:我添加了一些更多细节的“编辑2”。 – 2012-08-10 19:38:13