简体   繁体   English

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

[英]making program read certain parts of the file

I've a file which contains names and grades of students, and I'd like to write a program which can sort their grades (like midterm 1,midterm 2) according to user choice. 我有一个包含学生姓名和成绩的文件,并且我想编写一个程序,该程序可以根据用户选择对他们的成绩进行排序(如期中1,期中2)。 I wrote as far as the choice part and opening the file, yet I don't know how to make program read only certain part of the file (like only Midterm 1 grades for example) and sort them only. 我写了关于选择部分并打开文件的内容,但我不知道如何使程序仅读取文件的某些部分(例如,仅中期1年级)并仅对它们进行排序。 Here's what I've wrote so far; 到目前为止,这是我写的内容。

#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;
    }

Given what might be a somewhat free form text file (based on the shown code), it probably makes sense just to read the entire file (somewhat like you are already doing) and only use the parts that you need. 鉴于可能是某种形式的自由文本文件(基于显示的代码),仅读取整个文件(就像您已经在做的那样)并且仅使用所需的部分可能是有意义的。 If the text file has a very specific format with fixed offsets, you could seek to certain locations in the file and read a specific column value, then seek to the next offset and read the column value from the next row. 如果文本文件具有固定偏移量的非常特定的格式,则可以查找文件中的某些位置并读取特定的列值,然后查找下一个偏移量并从下一行读取列值。 But that is probably more trouble than it is worth and would not be much more efficient (if at all). 但这可能是麻烦多于其应有的价值,并且效率不会更高(如果有的话)。

Having said that, to sort the results, you probably need the entire file anyway. 话虽如此,为了对结果进行排序,您可能仍然需要整个文件。 For example, if you just read and sort the "midterm 1" value, then the result would just be sorted grades without any associated name and student number. 例如,如果您仅读取“期中1”值并对其进行排序,则结果将仅按成绩进行排序,而无需任何关联的名称和学生编号。 So without knowing more about the goal, you might consider creating a struct that can hold a single row (student number, name, surname, midterm1, etc.). 因此,没有更多地了解目标,则可以考虑创建一个struct ,可容纳单行(学号,姓名,midterm1等)。 Then create an array of those and read each row into an element of the array. 然后创建一个数组,并将每一行读入数组的元素。 If you know how many rows exist up front, you can allocate the array in one chunk, otherwise you might need to reallocate it as you go to grow it. 如果知道前面有多少行,则可以将数组分配为一个块,否则在增长数组时可能需要重新分配它。

Once you have read the entire array, you could sort based on the desired value (eg, with qsort . 阅读完整个数组后,您可以根据所需的值进行排序(例如,使用qsort

Having mentioned that, there a few problems/issues with the existing shown code: 提到了这一点,现有显示的代码存在一些问题/问题:

  • The second printf has fewer format specifiers (%s) than parameters. 第二个printf的格式说明符(%s)少于参数。
  • The third printf with the "What would you like to do" question is missing the closing paren. 问题为“您想做什么”的第三个printf缺少结尾括号。
  • The fprintf is incorrect; fprintf不正确; it should have a file handle as the first parameter. 它应该具有文件句柄作为第一个参数。 I suspect, though, that it was maybe meant to be printf ? 但是,我怀疑这可能是printf吗?
  • The final while loop has an extraneous semicolon (;) following its closing paren, which means that it has an empty body rather than the apparently intended printf and switch statement. 最后的while循环在其结束括号后有一个多余的分号(;),这意味着它的主体为空,而不是表面上预期的printfswitch语句。
  • The switch statement is a bit odd as written. switch语句有点奇怪。 I assume that is the "unfinished" part. 我认为这是“未完成”的部分。 But including the fclose in it seems strange. 但是将fclose包括在内似乎很奇怪。 It should probably be at the end of the main else . 它可能应该在else主体的末尾。
  • Using system("PAUSE"); 使用system("PAUSE"); is maybe not the best choice. 也许不是最佳选择。 Perhaps using getch would make more sense to pause for input. 也许使用getch暂停输入会更有意义。

Edit Here is some additional information in response to your comment asking for more details. 编辑这里是一些其他信息,以回应您的评论,要求提供更多详细信息。 This sounds like homework to me, so it doesn't seem right just to give the answer. 在我看来,这听起来像是功课,因此仅给出答案似乎并不正确。 But here is one way to do it: 但这是一种方法:

  • Define a struct with the 6 items that are in the file (basically put in the 6 variables that you currently have defined as local variables). 用文件中的6个项目定义一个struct (基本上放入您当前已定义为局部变量的6个变量中)。
  • Declare a local variable (eg, grades ) as a pointer to struct that you defined. 声明一个局部变量(例如, grades )作为您定义的结构的pointer
  • Use malloc to allocate memory and assign it to the pointer just mentioned. 使用malloc分配内存并将其分配给刚刚提到的指针。 The amount of memory is perhaps the trickiest part of this whole thing. 内存量可能是整个过程中最棘手的部分。 The size parameter to malloc will be something like numRecs * sizeof( yourstruct ) . malloc的size参数类似于numRecs * sizeof( yourstruct ) The question is what numRecs should be. 问题是numRecs应该是什么。 If this is an assignment and you were told how many records there would be (a maximum), then just use that. 如果这是一项任务,并且您被告知会有多少条记录(最多),那么就使用它。 If, though, it is "unknown", then there are a couple of ways of dealing with that. 但是,如果它是“未知的”,则有两种处理方法。 One is to just guess at a number (eg, 100) and then while reading them in a loop use realloc if you exceed 100. The other alternative (probably less efficient) would be to use two loops - read through them once without storing them but just count them and then allocate the known size and read them again. 一种是猜测一个数字(例如100),然后在循环中读取它们(如果您超过100,则使用realloc 。另一种选择(可能效率较低)将使用两个循环-一次读取它们而不存储它们但只需计算它们,然后分配已知大小并再次读取即可。 I would use the realloc version. 我会使用realloc版本。
  • Replace the use of the local variables with the array (that was malloc ed). 将局部变量的使用替换为数组(已malloc )。 For example, instead of studentnumber you would use grades[arraypos].studentnumber . 例如,而不是studentnumber你会用grades[arraypos].studentnumber While you read them in, keep a counter of how many there are. 当您阅读它们时,请记下它们的数量。 You can then use qsort to sort the array. 然后,您可以使用qsort对数组进行排序。

Edit 2 编辑2

  • Your struct definition looks correct except that the FILE *cfPtr; 您的结构定义看起来正确,除了FILE *cfPtr; member should not be in it. 成员不应该在其中。 It should still be a local variable. 它仍然应该是局部变量。
  • For ease of use, you can define the struct as typedef struct { ... } Student; 为了易于使用,您可以将结构定义为typedef struct { ... } Student; . That way you can just use Student instead of struct Student in the code. 这样,您可以只在代码中使用Student而不是struct Student Note that I capitalized the name (personal preference in naming to make it not look like a variable name). 请注意,我将名称大写(命名时出于个人喜好,使其看起来不像变量名)。
  • For the malloc, you are close. 对于malloc,您很接近。 But as written, it is allocating space for a single record. 但是按照书面规定,它正在为单个记录分配空间。 You would need something like this: name = malloc( 50 * sizeof( struct student )); 您将需要这样的name = malloc( 50 * sizeof( struct student ));name = malloc( 50 * sizeof( struct student )); (or malloc( 50 * sizeof( Student )); if you change it to use the typedef. That assumes there would not be 50 or fewer records to read from the file. (或malloc( 50 * sizeof( Student ));如果将其更改为使用typedef,则假定从文件中读取的记录不超过50条。

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

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