C将文本文件中的数据保存到结构数组中

时间:2018-05-08 18:34:39

标签: c arrays memory-management struct

我想问一下C语言中的文件处理和结构。我得到一个任务,我需要一个.txt文件,其中包含:篮球队的名字,他们总共参加的比赛,他们赢得的比赛数量等等。 这是任务:

  1. 从用户指定的 .txt 文件中获取数据(例如" data.txt ")
  2. 将数据存储在 struct of struct
  3. 让用户能够按名称排序或获得总胜利。
  4. 这是一个例子," 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
    

    到目前为止,我一直在尝试分配动态数组(struct)并将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 array中。(还添加了一个print函数)。但是,一旦完成打印功能,我仍然无法停止冻结(在将数据保存到数组之前会冻结)。 注意:我知道很多人警告我不要使用获取;但是,我的老师告诉我现在就用它。 注2:我决定在struct中有一个静态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行。 我再次更新了代码。它现在正在工作......(在大多数情况下,除非输入了意外输入(例如输入空文件,或者用户输入更多字符)。) 这段代码对于我的任务来说已经足够了,因为我的老师没有要求更详细的程序(事实上,如果我们提交更复杂的程序,他们会生气,因为我们还没有在课堂上了解它们 - 这就是为什么我和#39 ; m使用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;
                    }
                }
            }
        }
    }
    

2 个答案:

答案 0 :(得分:0)

特别注意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

答案 1 :(得分:0)

你的代码中有很多问题,比如。

首先,使用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()将继续存储超过缓冲区末尾的字符,所以使用起来非常危险。它有          曾被用来破坏计算机安全。改为使用fgets()。