3

を含む Players.txt というファイルがあります

デル・ピエロ|3|イタリア|ユベントス・ロナウド|0|ポルトガル|レアル・マドリード

各病棟を個別の配列に読み込みたいのですが、配列プレーヤーが含まれる
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;
}
4

3 に答える 3

2

fgets+strchr の代わりに fscanf を使用してみてください。そうすれば、コードが単純になり、安全性が高まります (これで、コードはバッファを簡単にオーバーフローし、予期しない結果になります)。

 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) {
   ...
 }

注:パターンはデータ形式に非常に固有のものであり、あなたの質問から、country_nameの区切り文字(ある場合)が明確ではありません。最後の文字列パターンは、%s最初に停止する通常の です。space

于 2013-07-09T16:50:57.687 に答える
0

mmapping をお勧めします: そうすれば、ファイルの内容全体をアドレス指定可能なメモリに直接取得して、自由にデータを調べることができます。

追加のボーナスとして、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;
}

マッピングが存在する間、ファイルを開いたままにしておく必要はないことに注意してください。

データのコピーを 1 つも作成せずにプロセス全体を実行できるため、CPU 時間とメモリの両方を節約できるため、パフォーマンスに関してはおそらくこれが達成できる最善の方法です。

于 2013-07-09T17:01:56.847 に答える