2012-08-09 59 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