2

重複の可能性:
C、ファイルから構造体への読み取り

大きなテキスト ファイルを読み取ってから、メーリング リストのデータ構造を埋める必要があります。

データ構造は次のとおりです。

typedef struct mentry {
    char *surname;
    int house_number;
    char *postcode;
    char *full_address;
} MEntry;

テキストファイル形式は次のとおりです。

Bloggs, Joe  
1 Street Name, City  
M53 3JK  
Surname, Firstname  
University of Nowhere, City  
G44 3GB

そして、データ構造体の私のコンストラクタ:

/* me_get returns the next file entry, or NULL if end of file*/
MEntry *me_get(FILE *fd);

これは、メーリング リスト エントリを含む MEntry 構造体へのポインタを返します。

これまでのところ、ファイルを1行ずつ読み取ることしかできませんでした。

#define MAXLINE 1024

int main(){
    char line[MAXLINE];
    FILE *fp = fopen("S.txt","r");

    while(fgets(line,MAXLINE,fp))
        {
        printf("%s %d",line,linecount);
    }

    fclose(fp);
    return 0;
}

現時点での主な問題は、データ構造を正しく埋めるために行を分割する方法がわからないことです。fgetc を使用して一度に文字を読み取る方が、行全体を読み取ってから分割するよりも簡単かどうか疑問に思っていますか?

4

3 に答える 3

2

おそらくstrtokを使用する必要があります

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

int main ()
{
    char str[] ="Elizarraras, Salvador, UG";
    char *token = NULL;
    int n_tokens = 0;

    printf ("Get tokens from string \"%s\"\n",str);
    printf("%s\n", "*********************************************");

   // Split the string into tokens delimited by spaces and commas
   token = strtok (str," ,");
   while (token != NULL)
   {
       printf("%s\n", token);
       // Different call
       token = strtok (NULL, " ,");
       n_tokens++;
   }

  return 0;
}

出力:

Get tokens from string "Elizarraras, Salvador, UG"

*********************************************
Elizarraras

Salvador

UG

このトピックに関する興味深い記事Finding Tokens in a String があります。

于 2012-10-18T15:54:26.943 に答える
0

あなたの例では、2 番目のアドレスにはhouse_number.

つまり、データ形式に頼って盲目的にファイルを読み取ることはできません。

データを読み取ってから解析するしかありません。

が指定される前に住所に 2 行のテキストがある場合、他の問題が発生する可能性がpostcodeあります。

入力ファイルの信頼性を知っているのはあなただけであり、したがって、エラーなしで解析するにはどのようなルールを適用する必要があるかを知っています。

メソッドに関しては、ファイルを1行ずつ読み取り、各レコードの が見つかるまで、テキストの各行を解析してその場で解釈しますpostcode(これはレコードの終わりのマーカーのようです)。

解析とは、line[]文字を見て、読み取ったデータを分類することを意味します (つまり、カンマは姓名の区切り記号、番地は数字、郵便番号は特定の形式に従うなど)。

これには少し手間がかかりますが、これは実行可能です。おっしゃる通り、私が RegEx の分野に足を踏み入れるつもりはないことはご理解いただけたと思います (C には専用のランタイム ライブラリがあります)。

ググ運!

于 2012-10-18T15:54:04.873 に答える
0

これは私がそれを行う方法です:

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

// It is easyer for the memory allocator to have all in the struct
// It is a bit more wasteful on memory though if you set those too large
#define MAX_SURNAME_LENGTH 32
#define MAX_POSTCODE_LENGTH 32
#define MAX_FULL_ADDRESS_LENGTH (256 - MAX_SURNAME_LENGTH - MAX_POSTCODE_LENGTH - sizeof(int))

typedef struct mentry {
    char surname[MAX_SURNAME_LENGTH];
    char postcode[MAX_POSTCODE_LENGTH];
    int house_number;
    char full_address[MAX_FULL_ADDRESS_LENGTH];
} MEntry;

MEntry *me_get(FILE *fp) {
    MEntry *mentry = calloc(sizeof(MEntry), 1);

    // get name
    char * name = fgets(mentry->surname, sizeof(mentry->surname), fp);
    if (!name) { //failure
        free(mentry);
        return NULL;
    }

    char * comma = strchr(name, ','); // find the first comma appearance
    if (comma) *comma = '\0'; // If name has a comma in it, terminate the string there

    char * address = fgets(mentry->full_address, sizeof(mentry->full_address), fp);
    if (!address) { //failure
        free(mentry);
        return NULL;
    }

    char * restaddress;
    int housenumber = strtol(address, &restaddress, 10);

    if (restaddress != address) // there was a valid number at the start of address
        mentry->house_number = housenumber;

    char * postcode = fgets(mentry->postcode, sizeof(mentry->postcode), fp);
    if (!postcode) { //failure
        free(mentry);
        return NULL;
    }

    return mentry;
}

int main() {
    FILE *fp = fopen("S.txt","r");

    MEntry *mentry;
    while ((mentry = me_get(fp))) {
        // do something useful with mentry
    }

    fclose(fp);
    return 0;
}
于 2012-10-18T16:40:03.597 に答える