簡體   English   中英

C將數據從文本文件保存到結構數組中

[英]C Saving Data from a Text File into an Array of Structures

我想問一下C語言中的文件處理和結構。 給我一個作業,其中我需要一個.txt文件,其中包含:籃球隊的名稱,他們參加的比賽總數,他們贏得的比賽數量等。這是任務:

  1. 從用戶指定的.txt文件中獲取數據(例如“ data.txt ”)
  2. 將數據存儲在struct數組中
  3. 讓用戶能夠按姓名或獲勝總數排序

這是一個示例“ data.txt”文件:

結構:名稱,玩過的游戲,在家里贏了,在家里輸了,贏了,輸了

Fenerbahce-Dogus 25 12 0 10 3
Tofas 25 11 2 9 3
Anadolu-Efe 26 13 1 6 6
Banvit 26 9 4 8 5
Darussafaka 26 11 2 4 9

到目前為止,我一直在嘗試分配一個動態數組(結構),並將txt文件中的數據保存到所述數組中。 但是,每當我嘗試輸入所說的“ data.txt”時,程序都會立即停止響應。 作為輸入。 有人可以告訴我為什么會發生這種情況,我應該怎么做才能克服此錯誤?

這是代碼:

#include <stdio.h>
#include <stdlib.h>

typedef struct {
        char *name;
        int games;
        int winsHome, losesHome;
        int winsAway, losesAway;
        int winsTotal, losesTotal;
        int totalPoints;
} scoreboard;


void Load_Scoreboard_Table(char *, scoreboard *);

int main(){
    char fileName[40];
    FILE *inputFile;
    while (1){
        printf("Enter the file name> ");
        gets(fileName);
        inputFile = fopen(fileName,"r");
        if (inputFile != NULL){
            break;
        }
        printf("ERROR: The file %s could not be opened.\n",fileName);
        printf("Please verify that the file exists.\n");
    }
    int listLength=0;
    char curChar;
    while ((curChar=fgetc(inputFile))!=EOF){
        if (curChar=='\n'){
            listLength++;
        }
    }
    fclose(inputFile);
    scoreboard *scoreboard_table = (scoreboard *)malloc(sizeof(scoreboard) * listLength);
    Load_Scoreboard_Table(fileName,scoreboard_table);
    return 0;
}

void Load_Scoreboard_Table(char *fileName,scoreboard *scoreboard_table){
    FILE *inputFile;
    fopen(fileName,"r");
    int i=0;
    while (fscanf(inputFile, "%s %d %d %d %d %d\n", (scoreboard_table+i)->name,(scoreboard_table+i)->games,(scoreboard_table+i)->winsHome,(scoreboard_table+i)->losesHome,(scoreboard_table+i)->winsAway,(scoreboard_table+i)->losesAway)!=EOF){
        (scoreboard_table+i)->winsTotal = (scoreboard_table+i)->winsHome + (scoreboard_table+i)->winsAway;
        (scoreboard_table+i)->losesTotal = (scoreboard_table+i)->losesHome + (scoreboard_table+i)->losesAway;
        (scoreboard_table+i)->totalPoints = (((scoreboard_table+i)->winsTotal)*2) + (scoreboard_table+i)->losesTotal;
        i++;
    }
}

更新:

我設法從文件中讀取並將其保存在struct數組中。(還添加了打印功能)。 但是,一旦完成函數的打印,我仍然無法停止凍結(將數據保存到陣列之前,它將凍結)。 注意:我知道很多人警告過我不要使用gets。 但是,我的老師告訴我暫時使用它。 注意2:我決定在結構內部使用一個靜態char名稱。注意3:我今天才了解數據結構,因此對這個話題非常陌生。 因此,請不要過多解釋。 是什么導致下面的代碼凍結?

碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {                 // defining a struct here
    char name[40];               // name of the sports club
    //clubs containing multiple words should be written in the following format: 'name-name-name'
    //ex : 'Anadolu Efe' should be written as 'Anadolu-Efe' in the text file
    //This is to avoid confusion when reading from .txt file
    int games;
    int winsHome, losesHome;
    int winsAway, losesAway;
    int winsTotal, losesTotal;
    int totalPoints;
} scoreboard;

void Load_Scoreboard_Table(char *, scoreboard *); // reads the .txt file and saves the contents into scoreboard_table
void Display_Scoreboard_Table(scoreboard *, int); // displays scoreboard_table, also takes it's size as input

int main(void){
    char fileName[40]; // the name of the file will be stored here (ex: data.txt)
    FILE *inputFile;   // creating a stream to read from .txt file
    while (1){         // Ask user for the name of the file until said file is opened for reading
            printf("Enter the file name> ");
            gets(fileName); // get string input from user that supports space characters (eg: "data.txt")
            inputFile = fopen(fileName,"r"); // try opening file in read mode
            if (inputFile != NULL){ //if the file has succesfully opened, then break from the loop
                    break;
            }
            printf("ERROR: The file %s could not be opened.\n",fileName); //if the file was not succesfully opened, then print appropriate error message
            printf("Please verify that the file exists.\n");
    }
    int listLength=0; //will be used to dynamically allocate memory for scoreboard_table array (array of structs)
    int curChar;   // I figured that fgetc returns an integer value
    while ((curChar=fgetc(inputFile))!=EOF){  //get a character until EOF
            if (curChar=='\n'){               //if it's a newline character then we need to allocate more memory for scoreboard_table array
                    listLength++;
            }
    }
    fclose(inputFile); // close the file as it's job is done
    scoreboard *scoreboard_table = malloc(sizeof(scoreboard) * listLength); // allocating enough memory to store the contents of .txt file
    Load_Scoreboard_Table(fileName,scoreboard_table); //save the contents of file on scoreboard_table 
    while (1){
        Display_Scoreboard_Table(scoreboard_table,listLength);
        break;
    }
    free(scoreboard_table); //freeing memory allocated for scoreboard_table
    return 0;
}

void Load_Scoreboard_Table(char *fileName,scoreboard *scoreboard_table){
    FILE *inputFile = fopen(fileName,"r"); // creating stream to read from file
    if(inputFile == NULL ) {               //checking again just in case there is a problem opening the file
        printf("ERROR: The file %s could not be opened.\n",fileName);
        exit(1);
    }
    int i=0,j,k;
    //the loop below gets data from .txt file line by line until EOF and stores it in scoreboard_table array
    while (fscanf(inputFile,"%s %d %d %d %d %d", (scoreboard_table+i)->name,&(scoreboard_table+i)->games,&(scoreboard_table+i)->winsHome,&(scoreboard_table+i)->losesHome,&(scoreboard_table+i)->winsAway,&(scoreboard_table+i)->losesAway) != EOF){
            (scoreboard_table+i)->winsTotal = (scoreboard_table+i)->winsHome + (scoreboard_table+i)->winsAway;
            (scoreboard_table+i)->losesTotal = (scoreboard_table+i)->losesHome + (scoreboard_table+i)->losesAway;
            (scoreboard_table+i)->totalPoints = (((scoreboard_table+i)->winsTotal)*2) + (scoreboard_table+i)->losesTotal;
            i++;
    }
    //the loop below replaces the '-' characters with ' ' in the name of every scoreboard_table array
    for (j=0;j<i;j++){
        for (k=0;k<40;k++){
            if ((scoreboard_table+i)->name[k] == '-'){
                (scoreboard_table+i)->name[k] = ' ';
            }
        }
    }
    printf("Score records file has been successfully loaded!\n");
}

void Display_Scoreboard_Table(scoreboard *scoreboard_table,int size){
    printf("Team                                        G     WH     LH     WA     LA     Won     Lost     Points\n");
    int i;
    for (i=0;i<=size;i++){
        printf("%-40s%5d  %5d  %5d  %5d  %5d   %5d    %5d      %5d\n",(scoreboard_table+i)->name,(scoreboard_table+i)->games,(scoreboard_table+i)->winsHome,(scoreboard_table+i)->losesHome,(scoreboard_table+i)->winsAway,(scoreboard_table+i)->losesAway,(scoreboard_table+i)->winsTotal,(scoreboard_table+i)->losesTotal,(scoreboard_table+i)->totalPoints);
    }
}

謝謝。

更新2(帶有工作代碼):

該問題是由於我為名為scoreboard_table的結構數組分配了錯誤的內存量引起的。 更具體地說,我為數組分配的內存可能比文件少1行。 我已經再次更新了代碼。 現在可以正常工作了...(在大多數情況下,除非輸入了意外的輸入(例如,輸入空文件或用戶在gets中輸入了更多字符)。)對於我作為我的任務的工作,此代碼已綽綽有余老師們並沒有要求提供更詳細的程序(事實上,由於我們還沒有在課堂上了解到它們,因此如果我們提交更復雜的程序,他們會很生氣-這就是為什么我使用的是gets()而不是fgets() )。 但是,我很好奇您對此事的看法。 您認為我應該怎么做才能改善這一點? 順便說一句,我知道代碼中的語法拼寫錯誤。 這只是因為我們需要嚴格遵守分配中的輸入輸出格式,而以不同方式鍵入內容則意味着丟分。 碼:

/* -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
                                          ~ ~ ~ ~ VERY IMPORTANT ~ ~ ~ ~
        The text file containing the data should be written in the following format:
        "%s %d %d %d %d %d\n" where
        %s is the name of the club
        If the name of the club contains more than one word, it should be written without any space characters ' '; instead place dash characters '-'
        Example: 'Anadolu Efe' should be written as 'Anadolu-Efe' in the text file
        complete line example:
        "Anadolu-Efe 26 13 1 6 6"

   -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-        */

//including required libraries
#include <stdio.h>  
#include <stdlib.h> //used to dynamically allocate memory
#include <string.h> //used for some string manipulation functions

typedef struct {                 // defining a struct here
    char name[40];               // name of the sports club
    //clubs containing multiple words should be written in the following format: 'name-name-name'
    //ex : 'Anadolu Efe' should be written as 'Anadolu-Efe' in the text file
    //This is to avoid confusion when reading from .txt file
    int games;
    int winsHome, losesHome;
    int winsAway, losesAway;
    int winsTotal, losesTotal;
    int totalPoints;
} scoreboard;

void Load_Scoreboard_Table(char *, scoreboard *); // reads the .txt file and saves the contents into scoreboard_table
void Display_Scoreboard_Table(scoreboard *, int); // displays scoreboard_table, also takes it's size as input
void Search(scoreboard *, int, char *);           // searches if a team exists in the scoreboard array and if there is; it prints the stats of the team
void interactive_board(scoreboard *, int, int);   // sorts the scoreboard array depending on user input, (sort by: games, points)

/*
This program reads data from a txt data, stores it in an array of structs
The program has the ability to sort the array based on either points or games
It also can search for the name inside said array of structs
*/

int main(){
    char fileName[40];   // the name of the file will be stored here (ex: data.txt)
    char searchTerm[40]; // search term will be stored here
    FILE *inputFile;     // creating a stream to read from .txt file
    int i;               // will be used later in a loop
    while (1){           // Ask user for the name of the file until said file is opened for reading
            printf("Enter the file name: ");
            gets(fileName); // get string input from user that supports space characters (eg: "data.txt")
            inputFile = fopen(fileName,"r"); // try opening file in read mode
            if (inputFile != NULL){ //if the file has succesfully opened, then break from the loop
                    break;
            }
            printf("ERROR: The file %s could not be opened.\n",fileName); //if the file was not succesfully opened, then print appropriate error message
            printf("Please verify that the file exists.\n");
    }
    int listLength=1; //will be used to dynamically allocate memory for scoreboard_table array (array of structs)
    int curChar;   // I figured that fgetc returns an integer value
    while ((curChar=fgetc(inputFile))!=EOF){  //get a character until EOF
            if (curChar=='\n'){               //if it's a newline character then we need to allocate more memory for scoreboard_table array
                    listLength++;
            }
    }
    fclose(inputFile); // close the file as it's job is done
    scoreboard *scoreboard_table = malloc(sizeof(scoreboard) * (listLength)); // allocating enough memory to store the contents of .txt file
    if (scoreboard_table == NULL){
        printf("ERROR: There has been an error allocating memory for scoreboard table array.\n");
        exit(1);
    }
    Load_Scoreboard_Table(fileName,scoreboard_table); //save the contents of file on scoreboard_table 
    Display_Scoreboard_Table(scoreboard_table,listLength);
    while (1){
        printf("Enter the name of the team (Exit - X, Sort -S): ");
        gets(searchTerm);
        i=0;
        while (searchTerm[i]!='\0'){
            searchTerm[i]=toupper(searchTerm[i]);
            i++;
        }
        if (strcmp(searchTerm,"X")==0){
            printf("Bye!\n");
            free(scoreboard_table); //freeing memory allocated for scoreboard_table
            return 0;
        }
        else if (strcmp(searchTerm,"S")==0){
            printf("Sort by (G: games, P: points): ");
            gets(searchTerm);
            i=0;
            while (searchTerm[i]!='\0'){
                searchTerm[i]=toupper(searchTerm[i]);
                i++;
            }
            if (strcmp(searchTerm,"G")==0){
                interactive_board(scoreboard_table,listLength,1);
                Display_Scoreboard_Table(scoreboard_table,listLength);
            }
            else if (strcmp(searchTerm,"P")==0){
                interactive_board(scoreboard_table,listLength,2);
                Display_Scoreboard_Table(scoreboard_table,listLength);
            }
            else{
                printf("ERROR: Invalid input. There is no sort term for '%s'\n",searchTerm);
            }
        }
        else{
            Search(scoreboard_table,listLength,searchTerm);
        }
    }
}

void Load_Scoreboard_Table(char *fileName,scoreboard *scoreboard_table){
    FILE *inputFile = fopen(fileName,"r"); // creating stream to read from file
    if(inputFile == NULL ) {               //checking again just in case there is a problem opening the file
        printf("ERROR: The file %s could not be opened.\n",fileName);
        exit(1);
    }
    int i=0,j,k;
    //the loop below gets data from .txt file line by line until EOF and stores it in scoreboard_table array
    while (fscanf(inputFile,"%s %d %d %d %d %d", (scoreboard_table+i)->name,&(scoreboard_table+i)->games,&(scoreboard_table+i)->winsHome,&(scoreboard_table+i)->losesHome,&(scoreboard_table+i)->winsAway,&(scoreboard_table+i)->losesAway) != EOF){
            (scoreboard_table+i)->winsTotal = (scoreboard_table+i)->winsHome + (scoreboard_table+i)->winsAway;
            (scoreboard_table+i)->losesTotal = (scoreboard_table+i)->losesHome + (scoreboard_table+i)->losesAway;
            (scoreboard_table+i)->totalPoints = (((scoreboard_table+i)->winsTotal)*2) + (scoreboard_table+i)->losesTotal;
            i++;
    }
    //the loop below replaces the '-' characters with ' ' in the name of every scoreboard_table array
    for (j=0;j<i;j++){
        for (k=0;k<40;k++){
            if (*(((*(scoreboard_table+j)).name)+k) == '-' ){  //if the value of name[k] inside scoreboard_table[j] is equal to '-' character
                *(((*(scoreboard_table+j)).name)+k) = ' ';     //replace the value of scoreboard_table[j].name[k] to ' ' character
            }
        }
    }
    fclose(inputFile); // close the file as it's job is done
    printf("Score records file has been successfully loaded!\n"); // notify the user that reading from the file has been successful
}

void Display_Scoreboard_Table(scoreboard *scoreboard_table,int size){
    printf("\nTeam                                        G     WH     LH     WA     LA     Won     Lost     Points\n\n"); // the variables to be shown in table
    int i;
    for (i=0;i<size;i++){//for every element in scoreboard_table, print the variables stored
        printf("%-40s%5d  %5d  %5d  %5d  %5d   %5d    %5d      %5d\n",(scoreboard_table+i)->name,(scoreboard_table+i)->games,(scoreboard_table+i)->winsHome,(scoreboard_table+i)->losesHome,(scoreboard_table+i)->winsAway,(scoreboard_table+i)->losesAway,(scoreboard_table+i)->winsTotal,(scoreboard_table+i)->losesTotal,(scoreboard_table+i)->totalPoints);
    }
}

void Search(scoreboard *scoreboard_table, int size, char *searchTerm){ //search for name of team in scoreboard_table
    int i,j; //i = index of scoreboard_table array, j = index of name array inside scoreboard_table array
    char table_name[40]; //  will be used to convert scoreboard_table->name to uppercase and store it
    for (i=0;i<size;i++){  // for every element in scoreboard_table
        for (j=0;j<40;j++){  // for every character in the name of scoreboard_table[i]->name
            table_name[j]=toupper(*(((*(scoreboard_table+i)).name)+j)); //store the upper-case letter of scoreboard_table[i]->name[j] in table_name[j]
        }
        if (strcmp(table_name,searchTerm)==0){ 
        //if the search term is equal to table_name (which is uppercase version of scoreboard_table[i]->name), then print the statistics and break from the loop.
            printf("%s has %d win, %d lost and a total of %d points!\n",(scoreboard_table+i)->name,(scoreboard_table+i)->winsTotal,(scoreboard_table+i)->losesTotal,(scoreboard_table+i)->totalPoints);
            break;
        }
        else if(i==(size-1)){ 
        //   if it's the last element of scoreboard_table array and the search term is not equal to scoreboard_table[i]->name
        //   notify the user that their search term is not found in the scoreboard_table array
            printf("That team is unknown! Please try again!\n");
        }
    }
}

void interactive_board(scoreboard *scoreboard_table, int size, int sort){
    //this function sorts the scoreboard_table array using selection sort algorithm
    /*
    selection sort algorithm sorts an array by repeatedly finding the maximum element from unsorted part and putting it at the beginning.
    */
    int i,j,index;
    /*
    i is used in a for loop to get ith element of scoreboard_table
    j is used to determine when the sorting is complete
    (ie: if you have a list containing 5 elements, you need to sort the array 4 times at most(in this case, which is selection sort algorithm); 
    therefore j is used in a for loop : for (j=0;j<(sizeofArray-1);j++)
    j is also used to write into jth element of scoreboard_table
    */
    int max; //store the max value here
    scoreboard temp; //declare a struct named temp, will store temporary data when swapping variables of scoreboard_table array
    if (sort==1){ // if sorting based on games
        for (j=0;j<size-1;j++){ // explained above, iterate the code below (array) size-1 times
            max=(scoreboard_table+size-1)->games; //set max to the last element of the array since this is the unsorted part of array...
            index=size-1;                         //set index to index of last element of the array...
            for (i=j;i<size;i++){                 //no need to search elements with index less than j since they are already sorted
                                                  //therefore start searching elements from j till the last element
                if (max<((scoreboard_table+i)->games)){ 
                //if the value of current element > max, then the max value becomes this value and the index of the new max value is stored in index
                    max=(scoreboard_table+i)->games;
                    index=i;
                }
                if (i==(size-1)){ // swap the variables of scoreboard_table[index] with the variables of scoreboard_table[j]
                    //where j stands for the next unsorted member and index stands for the index of the largest variable
                    //copy contents of scoreboard_table[j] into temp (BACKUP)
                    strcpy(temp.name,(scoreboard_table+j)->name);
                    temp.games=(scoreboard_table+j)->games;
                    temp.losesAway=(scoreboard_table+j)->losesAway;
                    temp.losesHome=(scoreboard_table+j)->losesHome;
                    temp.losesTotal=(scoreboard_table+j)->losesTotal;
                    temp.totalPoints=(scoreboard_table+j)->totalPoints;
                    temp.winsAway=(scoreboard_table+j)->winsAway;
                    temp.winsHome=(scoreboard_table+j)->winsHome;
                    temp.winsTotal=(scoreboard_table+j)->winsTotal;
                    //copy contents of scoreboard_table[index] into scoreboard_table[j]
                    strcpy((scoreboard_table+j)->name,(scoreboard_table+index)->name);
                    (scoreboard_table+j)->games=(scoreboard_table+index)->games;
                    (scoreboard_table+j)->losesAway=(scoreboard_table+index)->losesAway;
                    (scoreboard_table+j)->losesHome=(scoreboard_table+index)->losesHome;
                    (scoreboard_table+j)->losesTotal=(scoreboard_table+index)->losesTotal;
                    (scoreboard_table+j)->totalPoints=(scoreboard_table+index)->totalPoints;
                    (scoreboard_table+j)->winsAway=(scoreboard_table+index)->winsAway;
                    (scoreboard_table+j)->winsHome=(scoreboard_table+index)->winsHome;
                    (scoreboard_table+j)->winsTotal=(scoreboard_table+index)->winsTotal;
                    //copy contents of temp (BACKUP) into scoreboard_table[index]
                    strcpy((scoreboard_table+index)->name,temp.name);
                    (scoreboard_table+index)->games=temp.games;
                    (scoreboard_table+index)->losesAway=temp.losesAway;
                    (scoreboard_table+index)->losesHome=temp.losesHome;
                    (scoreboard_table+index)->losesTotal=temp.losesTotal;
                    (scoreboard_table+index)->totalPoints=temp.totalPoints;
                    (scoreboard_table+index)->winsAway=temp.winsAway;
                    (scoreboard_table+index)->winsHome=temp.winsHome;
                    (scoreboard_table+index)->winsTotal=temp.winsTotal;
                }
            }
        }
    }
    else{ // if sorting based on points
        for (j=0;j<size-1;j++){ // explained above, iterate the code below (array) size-1 times
            max=(scoreboard_table+size-1)->totalPoints; //set max to the last element of the array since this is the unsorted part of array...
            index=size-1;                         //set index to index of last element of the array...
            for (i=j;i<size;i++){                 //no need to search elements with index less than j since they are already sorted
                                                  //therefore start searching elements from j till the last element
                if (max<((scoreboard_table+i)->totalPoints)){ 
                //if the value of current element > max, then the max value becomes this value and the index of the new max value is stored in index
                    max=(scoreboard_table+i)->totalPoints;
                    index=i;
                }
                if (i==(size-1)){ // swap the variables of scoreboard_table[index] with the variables of scoreboard_table[j]
                    //where j stands for the next unsorted member and index stands for the index of the largest variable
                    //copy contents of scoreboard_table[j] into temp (BACKUP)
                    strcpy(temp.name,(scoreboard_table+j)->name);
                    temp.games=(scoreboard_table+j)->games;
                    temp.losesAway=(scoreboard_table+j)->losesAway;
                    temp.losesHome=(scoreboard_table+j)->losesHome;
                    temp.losesTotal=(scoreboard_table+j)->losesTotal;
                    temp.totalPoints=(scoreboard_table+j)->totalPoints;
                    temp.winsAway=(scoreboard_table+j)->winsAway;
                    temp.winsHome=(scoreboard_table+j)->winsHome;
                    temp.winsTotal=(scoreboard_table+j)->winsTotal;
                    //copy contents of scoreboard_table[index] into scoreboard_table[j]
                    strcpy((scoreboard_table+j)->name,(scoreboard_table+index)->name);
                    (scoreboard_table+j)->games=(scoreboard_table+index)->games;
                    (scoreboard_table+j)->losesAway=(scoreboard_table+index)->losesAway;
                    (scoreboard_table+j)->losesHome=(scoreboard_table+index)->losesHome;
                    (scoreboard_table+j)->losesTotal=(scoreboard_table+index)->losesTotal;
                    (scoreboard_table+j)->totalPoints=(scoreboard_table+index)->totalPoints;
                    (scoreboard_table+j)->winsAway=(scoreboard_table+index)->winsAway;
                    (scoreboard_table+j)->winsHome=(scoreboard_table+index)->winsHome;
                    (scoreboard_table+j)->winsTotal=(scoreboard_table+index)->winsTotal;
                    //copy contents of temp (BACKUP) into scoreboard_table[index]
                    strcpy((scoreboard_table+index)->name,temp.name);
                    (scoreboard_table+index)->games=temp.games;
                    (scoreboard_table+index)->losesAway=temp.losesAway;
                    (scoreboard_table+index)->losesHome=temp.losesHome;
                    (scoreboard_table+index)->losesTotal=temp.losesTotal;
                    (scoreboard_table+index)->totalPoints=temp.totalPoints;
                    (scoreboard_table+index)->winsAway=temp.winsAway;
                    (scoreboard_table+index)->winsHome=temp.winsHome;
                    (scoreboard_table+index)->winsTotal=temp.winsTotal;
                }
            }
        }
    }
}

要特別注意fscanf() 必須傳遞int變量的地址,這是代碼崩潰的原因之一。

 while (fscanf(inputFile, "%s %d %d %d %d %d\n", 
 (scoreboard_table+i)->name, &(scoreboard_table+i)->games,
 &(scoreboard_table+i)->winsHome, &(scoreboard_table+i)->losesHome,
 &(scoreboard_table+i)->winsAway,&(scoreboard_table+i)->losesAway)!=EOF){

此外,您應該注意其他注釋,例如不使用gets()

char fileName[40], *p;

fgets(fileName, sizeof fileName, stdin);
if ((p = strchr(fileName, '\n')) != NULL) { 
    *p = '\0'; /* remove newline */
}

順便說一句,結構中的char *name需要分配的內存,這是崩潰的另一個原因,並且不要忘記free它。

您的代碼中有很多問題,例如。

首先 ,使用fgets()代替gets() 例如

fgets(fileName,sizeof(fileName),stdin);

其次namescoreboard指針成員,首先為其分配內存。 例如

scoreboard_table->name = malloc(SIZE); /* define SIZE */

第三fgetc()返回類型為int 檢查fgetc()的手冊頁。 所以char curChar; 應該是int curChar;

最后,在fscanf()存儲整數時,需要為每個參數提供&地址。 例如

fscanf(inputFile,"%d",&(scoreboard_table+i)->games)

我試圖在評論中解釋。 這是示例代碼

void Load_Scoreboard_Table(char *, scoreboard *);
int main(void){
        char fileName[40], *ret = NULL;
        FILE *inputFile;
        while (1){
                printf("Enter the file name> ");
                /* make sure fileName gets correctly stored in buffer as expected  */
                ret = fgets(fileName,sizeof(fileName),stdin); /* use fgets() instead of gets() */
                if(ret == NULL) { /* if failed, check again */
                        continue;
                }
                else {
                        printf("%s",ret); /* if fgets() result is as expected, control comes here */
                        fileName[strlen(fileName)-1] ='\0';
                }
                inputFile = fopen(fileName,"r");
                if (inputFile != NULL){
                        break;
                }
                printf("ERROR: The file %s could not be opened.\n",fileName);
                printf("Please verify that the file exists.\n");
        }
        int listLength=0;
        int curChar; /*return type of fgetc() is int */
        while ((curChar=fgetc(inputFile))!=EOF){
                if (curChar=='\n'){
                        listLength++;
                }
        }
        fclose(inputFile);
        scoreboard *scoreboard_table = malloc(sizeof(scoreboard) * listLength);/* no need to cast the result of malloc() */
        scoreboard_table->name = malloc(100);/*name is pointer member, allocate memory for it. must */
        Load_Scoreboard_Table(fileName,scoreboard_table);

        /* don't forget to free dynamically allocated memory here  @TODO */
        return 0;
}

void Load_Scoreboard_Table(char *fileName,scoreboard *scoreboard_table){
        FILE *inputFile = fopen(fileName,"r");
        if(inputFile == NULL ) {
                /* some mesage,, error handling  @TODO*/
        }
        int i=0;
        while (fscanf(inputFile,"%s %d %d %d %d %d", (scoreboard_table+i)->name,&(scoreboard_table+i)->games,&(scoreboard_table+i)->winsHome,&(scoreboard_table+i)->losesHome,&(scoreboard_table+i)->winsAway,&(scoreboard_table+i)->losesAway) > 0){
                (scoreboard_table+i)->winsTotal = (scoreboard_table+i)->winsHome + (scoreboard_table+i)->winsAway;
                (scoreboard_table+i)->losesTotal = (scoreboard_table+i)->losesHome + (scoreboard_table+i)->losesAway;
                (scoreboard_table+i)->totalPoints = (((scoreboard_table+i)->winsTotal)*2) + (scoreboard_table+i)->losesTotal;
                i++;
        }
        for(int j =0 ;j<i;j++) {
                printf("%d %d %d \n",(scoreboard_table+j)->winsTotal,(scoreboard_table+j)->losesTotal,(scoreboard_table+j)->totalPoints);
        }
}

從第man 3 gets為什么不應該使用gets()原因就在這里。

永遠不要使用gets()。 因為無法不事先知道數據就無法知道將讀取多少個字符gets(),並且因為gets()將繼續存儲超過緩沖區末尾的字符,所以使用它非常危險。 它已被用來破壞計算機的安全性。 使用fgets()代替。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM