如何在C编程中从文件读取到数组?

3

我有一个名为Players.txt的文件,其中包含以下内容:

Del Piero|3|意大利|尤文图斯 Ronaldo|0|葡萄牙|皇家马德里

我想将每个单词读入到一个独立的数组中,例如将数组players包含
players[NUM_PLAYERS][NAME_LENGTH]={ Del Piero,Ronaldo}
以及其他数组。

我知道需要使用一个叫做fgets和一些字符串函数的函数。

这是我尝试过的方法;我的问题是:是否有其他方法来解决我的问题,例如使用其他不同的程序或字符串程序?如何从该文件中获取进球数并将其存储到文件中?

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

#define NUM_PLAYERS 20
#define NAME_LENGTH 100
#define COUNTRY_NAME 20


int main (void)    
{    
    FILE *Players;    

    char player_name [NUM_PLAYERS][NAME_LENGTH] = {0};
    char team_name[NUM_PLAYERS][NAME_LENGTH] = {0};
    char country_name[NUM_PLAYERS][COUNTRY_NAME] = {0};

    char temp_buffer[NAME_LENGTH]={0};
    int goals_scored[NUM_PLAYERS] = {0};

    char *ptr1,*ptr2,*ptr3;
    int i;

    Players = fopen("Players.txt", "r");
    if (Players == NULL)
    {
        printf("File not found.\n");
    }
    else
    {
        i=0;
        while ((fgets(temp_buffer,sizeof(temp_buffer), Players) != NULL) && i < NUM_PLAYERS)

        {
            ptr1 = strchr(temp_buffer, '|');
            strncpy(player_name[i], temp_buffer, ptr1 - temp_buffer);
            printf("the name of the player is %s\n.", player_name[i]);
            i ++;

        }       
    }
  fclose(Players);

    return 0;
}
3个回答

2
您可以尝试使用fscanf代替fgets+strchr。这样您将获得更简单的代码和更安全的保障(现在您的代码很容易溢出缓冲区,导致结果不可预知)。
 if (fscanf(Players, " %*[^|]|%d|%*[^|]|%*s",
     NAME_LENGTH-1, player_name[i],
     goals_scored + i,
     NAME_LENGTH-1, team_name[i],
     NAME_LENGTH-1, country_name[i]) == 4) {
   ...
 }

注意:该模式非常特定于您的数据格式,从您的问题中我不清楚国家名称是否有分隔符。然后,最后一个字符串模式通常是%s,它在第一个空格处停止。


谢谢大家的回复! @CapelliC,您所说的分隔符是什么意思? - user2512806
@user2512806:这是用于分隔字段的字符:根据您的问题,应该是|。fscanf、sscanf和scanf都共享相同(复杂)的规范。它们是一个“家族”。 - CapelliC
最好使用fgets()sscanf(),而不是试图使用fscanf() - Jonathan Leffler

0

我建议使用内存映射:这样你就可以直接将整个文件内容加载到可寻址的内存中,让你可以随意查看数据。

作为额外的奖励,如果在调用mmap()时指定了MAP_PRIVATE,你可以将其简单地切成单独的字符串(用空字节替换'|'和' '字符),而不修改文件。这样可以避免复制字符串。剩下的就是将索引结构构建到数据中的简单问题。

这是我使用的框架:

const char* mmapInputFile(const char* path, int kernelAdvice, off_t* outLength) {
    //Open the file.
    int file = open(path, O_RDONLY);
    if(file == -1) /* error handling */;
    *outLength = lseek(file, 0, SEEK_END);  //Get its size.

    //Map its contents into memory.
    const char* contents = (const char*)mmap(NULL, *outLength, PROT_READ, MAP_PRIVATE, file, 0);
    if((intmax_t)contents == -1) /* error handling */;
    if(madvise((void*)contents, *outLength, kernelAdvice)) /* error handling */;

    //Cleanup.
    if(close(file)) /* error handling */;
    return contents;
}

请注意,存在映射时无需保持文件处于打开状态。
从性能上讲,这可能是您可以实现的最佳方案,因为整个过程可以在不复制数据的情况下完成,这既节省了 CPU 时间又节省了内存。

0

我建议使用fgets()sscanf(),而不是使用fscanf();使用fscanf()时错误报告会更加困难,非常困难。 - Jonathan Leffler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接