简体   繁体   English

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

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

I want to ask about file processing and struct in C language. 我想问一下C语言中的文件处理和结构。 I am given an assignment where I need to have a .txt file containing: the names of basketball teams, the games they have played in total, the amount of games they have won, etc.. Here is the task: 给我一个作业,其中我需要一个.txt文件,其中包含:篮球队的名称,他们参加的比赛总数,他们赢得的比赛数量等。这是任务:

  1. Get data from user-specified .txt file (eg " data.txt ") 从用户指定的.txt文件中获取数据(例如“ data.txt ”)
  2. Store the data in array of struct 将数据存储在struct数组中
  3. Let the user have the ability to sort by name or the total amount of wins they have. 让用户能够按姓名或获胜总数排序

Here is an example, "data.txt" file: 这是一个示例“ data.txt”文件:

Structure : name, games played, won at home, lost at home, won away, lost away 结构:名称,玩过的游戏,在家里赢了,在家里输了,赢了,输了

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

So far, I have been trying to allocate a dynamic array (of struct) and save the data from the txt file into said array. 到目前为止,我一直在尝试分配一个动态数组(结构),并将txt文件中的数据保存到所述数组中。 However, the program stops responding immediately whenever I try to enter the said "data.txt". 但是,每当我尝试输入所说的“ data.txt”时,程序都会立即停止响应。 as input. 作为输入。 Could anybody inform me why this is happening and what should I do to get past this error? 有人可以告诉我为什么会发生这种情况,我应该怎么做才能克服此错误?

Here is the code: 这是代码:

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

Update: 更新:

I have managed to read from the file and save it in struct array.(Also added a print function). 我设法从文件中读取并将其保存在struct数组中。(还添加了打印功能)。 However I still cannot get it to stop freezing once it finishes printing the function (it would freeze after saving data into the array before). 但是,一旦完成函数的打印,我仍然无法停止冻结(将数据保存到阵列之前,它将冻结)。 Note: I know many people have warned me not to use gets; 注意:我知道很多人警告过我不要使用gets。 but, my teacher told me to use it for now. 但是,我的老师告诉我暂时使用它。 Note2: I decided to have a static char name inside the struct Note3: I have only learned about data structures today, so I'm VERY new to the topic; 注意2:我决定在结构内部使用一个静态char名称。注意3:我今天才了解数据结构,因此对这个话题非常陌生。 therefore, please explain things without going into too much detail. 因此,请不要过多解释。 What could be causing the code below to freeze? 是什么导致下面的代码冻结?

Code: 码:

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

Thank you. 谢谢。

Update 2 (With working code): 更新2(带有工作代码):

The issue was caused by me allocating wrong amount of memory for the array of structs called scoreboard_table . 该问题是由于我为名为scoreboard_table的结构数组分配了错误的内存量引起的。 To be more specific, I was allocating memory for array that could hold 1 less line than the file. 更具体地说,我为数组分配的内存可能比文件少1行。 I have updated the code again. 我已经再次更新了代码。 It is working now... (For the most part, except when an unexpected input is entered(such as being fed an empty file, or user entering more characters into gets).) This code is more than enough for my assignment as my teachers have not asked for a more detailed program(infact, they do get angry if we submit more complicated programs since we have not yet learnt about them in class - which is why I'm using gets() and not fgets() for example). 现在可以正常工作了...(在大多数情况下,除非输入了意外的输入(例如,输入空文件或用户在gets中输入了更多字符)。)对于我作为我的任务的工作,此代码已绰绰有余老师们并没有要求提供更详细的程序(事实上,由于我们还没有在课堂上了解到它们,因此如果我们提交更复杂的程序,他们会很生气-这就是为什么我使用的是gets()而不是fgets() )。 However I'm curious to hear your opinions on the matter. 但是,我很好奇您对此事的看法。 What do you think I should do to improve this? 您认为我应该怎么做才能改善这一点? By the way, I am aware of the grammar-spelling mistakes in the code. 顺便说一句,我知道代码中的语法拼写错误。 It's just because we need to strictly obey the input-output format in our assignments and typing things differently means losing points. 这只是因为我们需要严格遵守分配中的输入输出格式,而以不同方式键入内容则意味着丢分。 Code: 码:

/* -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
                                          ~ ~ ~ ~ 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;
                }
            }
        }
    }
}

Pay special attention to contents of your fscanf() . 要特别注意fscanf() Addresses of int variables have to be passed it's the one of crashing reason of the code. 必须传递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){

Moreover, you should give ear to the other comments like not using gets() 此外,您应该注意其他注释,例如不使用gets()

char fileName[40], *p;

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

By the way, an allocated memory is needed for char *name in the struct, it's the another reason for crashing, and not forget to free it. 顺便说一句,结构中的char *name需要分配的内存,这是崩溃的另一个原因,并且不要忘记free它。

you have lot of problems in your code like. 您的代码中有很多问题,例如。

Firstly , use fgets() instead of gets() . 首先 ,使用fgets()代替gets() for eg 例如

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

Secondly , name is pointer member of scoreboard , allocate memory for it first. 其次namescoreboard指针成员,首先为其分配内存。 for eg 例如

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

Thirdly , fgetc() return type is int . 第三fgetc()返回类型为int check the manual page of fgetc() . 检查fgetc()的手册页。 So char curChar; 所以char curChar; should be int curChar; 应该是int curChar;

Finally, in fscanf() while storing integers you need to provide the & address to each argument. 最后,在fscanf()存储整数时,需要为每个参数提供&地址。 for eg 例如

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

I try to explain in the comments. 我试图在评论中解释。 Here is the sample code 这是示例代码

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

From man 3 gets Why one shouldn't use gets() reason is here. 从第man 3 gets为什么不应该使用gets()原因就在这里。

Never use gets(). 永远不要使用gets()。 Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. 因为无法不事先知道数据就无法知道将读取多少个字符gets(),并且因为gets()将继续存储超过缓冲区末尾的字符,所以使用它非常危险。 It has been used to break computer security. 它已被用来破坏计算机的安全性。 Use fgets() instead. 使用fgets()代替。

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

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