从多个文件读取到结构

时间:2017-02-09 06:38:53

标签: c file struct

我在分配时遇到问题,它涉及从文件读取到结构中,我对如何操作感到困惑,这是带有我必须使用的参数的函数。

// This function will read in size  struct players from filename and add these
// the players array. The function will use index  to know where to start
// writing  the players to in the array.
// Parameters
//
// filename – The name of the input file
// players – a pointer to the array of player structures
// index – The index of the array to start placing players into
// size – The number of players in the input file
// Return - Nothing

void read_from_file(char* filename, Player* players, int index, int size);

这是我必须用来从3个不同文件中读取数据的函数:

Andrew Jackson 129 33 38 30 506
Jeremy Warden 25 24 3 9 493
Jared Welch 130 1 43 27 422
Brandon Splitter 138 38 40 7 587
Joe Gwilliams 150 23 30 25 498
Ali Mohammed 119 43 13 6 598
Dheeraj Johnson 124 79 59 36 506
Bill Clinton 121 65 12 26 449
Jesse James 87 58 8 5 464
John Doe 129 100 0 12 548

我必须阅读3个文件,其中包含10个玩家,总共30个我需要阅读结构。我还没有走得太远我知道但是我很困惑该怎么做以及如何处理这个问题,非常感谢任何帮助!下面我已经完成了我已经完成的工作。请帮忙!!谢谢

//Brady Webb
//lab D
//HW1

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

typedef struct player
{
    char Fname[25];
    char Lname[25];
    int Singles;
    int Doubles;
    int Triples;
    int Homeruns;
    int At_Bats;
    float Slugging_Percentage;
} Player;

void read_from_file(char* filename, Player* players, int index, int size);

int main(int argc, char* argv[])
{
    int size= atoi(*(argv+1));
    char* file1 = *(argv+2);
    char* file2 = *(argv+3);
    char* file3 = *(argv+4);
    if (argc<6 || argc>6)
    {
        printf("Incorrect command line arguments\n");
        return 0;
    }

    return 0;
}
void read_from_file(char*filename, Player* players, int index, int size)
{
    FILE *ptr;
    int i=0;

    if ((ptr=fopen(filename, "r")) == NULL)
    {
        return 0;
    }

    while (ptr != EOF)
    {

    }

}

3 个答案:

答案 0 :(得分:2)

使用常规结构读取文件的最简单方法是使用带有复杂格式字符串的fscanf

fscanf("%s %s %d %d %d %d %d", Player.Fname, Player.Lname, 
                          &Player.Singles, &Player.Doubles, 
                          &Player.Triples, &Player.Homeruns, &Player.At_Bats);

你应该循环读取文件和文件,你可以添加以正确格式读取数据的检查,例如:

int check = fscanf("%s %s %d %d %d %d %d", Player.Fname, Player.Lname, 
                          &Player.Singles, &Player.Doubles, 
                          &Player.Triples, &Player.Homeruns, &Player.At_Bats);
if( check != 7 )
{
   // stop reading and report on wrong file format 
}

<强>更新

我提出以下代码作为可能的解决方案:

// This function will read in size  struct players from filename and add these
// the players array. The function will use index  to know where to start
// writing  the players to in the array.
// Parameters
//
// filename – The name of the input file
// players – a pointer to the array of player structures
// index – The index of the array to start placing players into
// size – The number of players in the input file
// Return - number of read players (positive number)
//          or error code (negarive number)
int read_from_file(char * filename, Player* players, int index, int size)
{
    struct player ptmp;
    FILE *fptr;
    // open the file
    if ((fptr = fopen(filename, "r")) == NULL)
    {
        fprintf(stderr, "File %s cannot be oppened\n",filename);
        return -1; // error code for "File cannot be oppened"
    }
    // reading from file 
    int position = index;
    int cnt = 0;
    while (!ferror(fptr) && cnt < size)
    {
        int check = fscanf(fptr, "%24s %24s %d %d %d %d %d", ptmp.Fname, ptmp.Lname,
            &ptmp.Singles, &ptmp.Doubles, &ptmp.Triples, &ptmp.Homeruns, &ptmp.At_Bats);
        if (feof(fptr) && check != 7)
        {
            break;
        }
        if (check != 7)
        {
            fclose(fptr);
            fprintf(stderr,"Wrong data format in line %d of file %s\n", cnt+1, filename);
            return -2; // error code for "File has wrong data format"
        }
        // copy data to players
        players[index++] = ptmp;
        cnt++;
    }
    // close the file
    fclose(fptr);
    return cnt;
}

注意更改后的函数类型read_from_file - 我在评论中描述了关于返回值的想法。

我理解中的main应该是:

int main(int argc, char* argv[])
{
    Player players[30]; // memory is allocated for particular number of data items
    // check the command line arguments
    if (argc < 3)
    {
        printf("Please run the program in the format:\n");
        printf(" %s 2 firstFile.txt secondFile.txt\n", argv[0]);
        printf(" where 2 is number of files given after 2 with data to be read\n");
        return 0;
    }
    int fileNumber = 0;
    if (!sscanf(argv[1], "%d", &fileNumber) || fileNumber <= 0)
    {
        printf("The first command line argument nust be positive number.\n");
        printf("Run program without parameters to see details\n");
        return 0;
    }
    if (fileNumber != (argc - 2))
    {
        printf("Command line arguments are inconsistent\n");
        printf("Run program without parameters to see details\n");
        return 0;
    }
    // file processing
    int i = 0;
    int total = 0;
    int max = 30;
    for (i = 0; i < fileNumber; i++)
    {
        printf("Reading from %s...\n", argv[i + 2]);
        int res = read_from_file(argv[i + 2], players, total, max); 
        if (res > 0)
        {
            total += res;
            max -= res;
        }
    }
    // check data
    for (i = 0; i < total; i++)
    {
        printf("%s %s : %d %d %d %d %d\n", players[i].Fname, players[i].Lname, players[i].Singles, players[i].Doubles, players[i].Triples, players[i].Homeruns, players[i].At_Bats);
    }
    return 0;
}

假设30个玩家可以读取任意数量的文件,而不一定是每个文件中的10个。

答案 1 :(得分:0)

循环可以返回一次读取一行,每行可以传递给辅助函数,如getPlayer

char *line;
char buffer[256]; // assuming that's the longest line size
while ((line = fgets(buffer, sizeof(buffer), ptr)) != NULL) {
    Player *pl = getPlayer(line);
    //...
}

上面的代码应该替换张贴为 while(ptr!= EOF)的代码中的循环。 getPlayer可以是以下几行(然后可以将播放器添加到列表/数组等,并确保在完成后相应地释放)

Player *getPlayer(char *line) {
        Player *iPlayer = (Player *)malloc(sizeof(Player));
        sscanf(line, "%s %s %d %d %d %d %d %f",
                iPlayer->Fname,
                iPlayer->Lname,
                &iPlayer->Singles,
                &iPlayer->Doubles,
                &iPlayer->Triples,
                &iPlayer->Homeruns,
                &iPlayer->At_Bats,
                &iPlayer->Slugging_Percentage);
         return iPlayer;
}

答案 2 :(得分:0)

struct Player PlayerArr[10];

void read_from_file(char*filename, Player* players, int index, int size)
{
    FILE *ptr;
    int i=0;
    char content[50];

    memset(content, '\0', 50);

    if ((ptr=fopen(filename, "r")) == NULL)
    {
        return 0;
    }

    while (ptr != EOF)
    {
         getline(infile,line);
         memset(content,'\0',sizeof(content));
         strcpy(content,line.c_str());
         ReadNextConfRecord(content);
    }

    return 0;
}

int ReadNextConfRecord(char *content)
{
        char str[50];
    const char delimiter[2] = " ";
    char *token;
    int count =0;
    int i =0;

    memset(str, '\0', 50);

    strcpy(str, (char*)content);

    token = strtok(str, delimiter);
    while( token != NULL )
    {
     count++;
        if(count == 1)
            {
                strcpy(PlayerArr[i].Fname, token);
            }
        else if(count == 2)
            {
                strcpy(PlayerArr[i].Lname, token);
            }
        else if(count == 3)
            {
                PlayerArr[i].Singles= atoi(token);
            }
        else if(count == 4)
            {
               PlayerArr[i].Doubles= atoi(token);
            }
        else if(count == 5)
            {
               PlayerArr[i].Triples= atoi(token);
            }
        else if(count == 6)
            {
               PlayerArr[i].Homeruns= atoi(token);
            }
        else if(count == 7)
            {
               PlayerArr[i].At_Bats= atoi(token);
            }
        else if(count == 8)
            {
               PlayerArr[i].Slugging_Percentage= atof(token);
            }
       i++;                       
      token = strtok(NULL, delimiter);
    }
    return 0;
}

使用tokenizer也可以解决上述问题