繁体   English   中英

使程序读取文件的某些部分

[英]making program read certain parts of the file

我有一个包含学生姓名和成绩的文件,并且我想编写一个程序,该程序可以根据用户选择对他们的成绩进行排序(如期中1,期中2)。 我写了关于选择部分并打开文件的内容,但我不知道如何使程序仅读取文件的某些部分(例如,仅中期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;
    }

鉴于可能是某种形式的自由文本文件(基于显示的代码),仅读取整个文件(就像您已经在做的那样)并且仅使用所需的部分可能是有意义的。 如果文本文件具有固定偏移量的非常特定的格式,则可以查找文件中的某些位置并读取特定的列值,然后查找下一个偏移量并从下一行读取列值。 但这可能是麻烦多于其应有的价值,并且效率不会更高(如果有的话)。

话虽如此,为了对结果进行排序,您可能仍然需要整个文件。 例如,如果您仅读取“期中1”值并对其进行排序,则结果将仅按成绩进行排序,而无需任何关联的名称和学生编号。 因此,没有更多地了解目标,则可以考虑创建一个struct ,可容纳单行(学号,姓名,midterm1等)。 然后创建一个数组,并将每一行读入数组的元素。 如果知道前面有多少行,则可以将数组分配为一个块,否则在增长数组时可能需要重新分配它。

阅读完整个数组后,您可以根据所需的值进行排序(例如,使用qsort

提到了这一点,现有显示的代码存在一些问题/问题:

  • 第二个printf的格式说明符(%s)少于参数。
  • 问题为“您想做什么”的第三个printf缺少结尾括号。
  • fprintf不正确; 它应该具有文件句柄作为第一个参数。 但是,我怀疑这可能是printf吗?
  • 最后的while循环在其结束括号后有一个多余的分号(;),这意味着它的主体为空,而不是表面上预期的printfswitch语句。
  • switch语句有点奇怪。 我认为这是“未完成”的部分。 但是将fclose包括在内似乎很奇怪。 它可能应该在else主体的末尾。
  • 使用system("PAUSE"); 也许不是最佳选择。 也许使用getch暂停输入会更有意义。

编辑这里是一些其他信息,以回应您的评论,要求提供更多详细信息。 在我看来,这听起来像是功课,因此仅给出答案似乎并不正确。 但这是一种方法:

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

编辑2

  • 您的结构定义看起来正确,除了FILE *cfPtr; 成员不应该在其中。 它仍然应该是局部变量。
  • 为了易于使用,您可以将结构定义为typedef struct { ... } Student; 这样,您可以只在代码中使用Student而不是struct Student 请注意,我将名称大写(命名时出于个人喜好,使其看起来不像变量名)。
  • 对于malloc,您很接近。 但是按照书面规定,它正在为单个记录分配空间。 您将需要这样的name = malloc( 50 * sizeof( struct student ));name = malloc( 50 * sizeof( struct student )); (或malloc( 50 * sizeof( Student ));如果将其更改为使用typedef,则假定从文件中读取的记录不超过50条。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM