-2

たとえば、テキストの「ブロック」を読み取るには、単純なパーサーを開発する必要があります。

/TEST
 {. text .}
/TEST_DATA
 {. infs .}

そして、ラベルの内側の情報を読み取る必要があります....そして...ファイルにはこの情報が含まれています...同じperfilで多くのラベルがあります

例えば:

/TEST
 {. text .}
/TEST_DATA
 {. infs .}

/LBL1
 {. text .}
/LBL1_DATA
 {. infs .}

/LBL2
 {. text .}
/LBL2_DATA
 {. infs .}

/LBL3
 {. text .}
/LBL3_DATA
 {. infs .}

たとえば、特定のラベルのブロックを読み取る必要があります。

parseFile("ファイル名.txt", LBL1)

および関数、return for me、ブロック内のテキスト: LBL1 および LBL1_DATA または、return for me、LBL1 および LBL1_DATA の内容

どうすればいいのかわからない:xxx 助けが必要 ;x

ありがとう。

4

3 に答える 3

4

データが 1 行であると仮定すると、非常に単純なコード例を次に示します。

明らかに、テストし、テストし、テストする必要があります。あなたの行動を見て、考えられるバグと私がするのを忘れていたことを修正し(今はあなたの仕事です)、あなたの新しい実装もそうです。

int main(void)
{
    const char *key = "TEST";
    const char *filename = "file";

    char *val = get(filename, key);
    if(val) {
        printf("%s\n", val); // {. text .}
        free(val); // don't to forget!
    } else {
        printf("'%s' was not found.\n", key);
    }


}


char*
get(const char *filename, const char *key) {

    char *line = NULL, *pline = NULL, *buf = NULL, *pbuf, *tbuf;
    size_t size = -1, ssearch = strlen(key), i = 0, bufsize = 256;
    int open = 0;
    FILE *fp = fopen(filename, "r");

    if(fp == NULL) {
        fprintf(stderr, "Cannot read '%s' file.\n", filename);
        exit(EXIT_FAILURE);
    }

    while(getline(&line, &size, fp) != -1) {

        if(open == 0 && *line == '/' && 
           strncmp(line + 1, key, ssearch) == 0 && isspace(((unsigned char)*(line + ssearch + 1)))) {
            open = 1;
            continue;
        }

        if(open) {
            pline = line;

            while(isspace((unsigned char) *pline)) ++ pline; /* strip white-spaces [\r\n\t\v ] */

            if(*pline == '{') {
                if((buf = malloc(bufsize)) == NULL) {
                    fprintf(stderr, "NO MEMORY!");
                    exit(EXIT_FAILURE);
                }

                ++pline; /* strip '{' */

                pbuf = buf;
                while(1) {

                    if(*pline == '\0') {
                        fprintf(stderr, "EOF but '{' was not closed.");
                        exit(EXIT_FAILURE);
                    }

                    /* etc.. */

                    if(*pline == '}') break; 

                    if((i + size + 1) >= bufsize) {

                        if((tbuf = realloc(buf, bufsize + size + 1)) == NULL) {
                            if(buf) free(buf);
                            fprintf(stderr, "No MEMORY!\n");
                            exit(EXIT_FAILURE);
                        }

                        buf = tbuf;
                    }   

                    *pbuf ++= *pline++, 
                    i ++;
                }   

                *pbuf ++= '\0';

                if(pline != NULL) 
                    free(line);

                fclose(fp);

                return buf;

            } else {
                fprintf(stderr, "expected '{' but '%c' was found.\n", *pline);
                exit(EXIT_FAILURE);
            }
        }

        line = NULL;
        size = -1;
    }

    if(line != NULL)
        free(line);

    fclose(fp);


    return NULL;
}

更新:より単純なコードが書かれました。

#define EXPECTEDSYMBOL(w, f) \
        fprintf(stderr, "expected '%c' but '%c' was found.\n", w, f); \
        exit(EXIT_FAILURE)

char* get2(const char *filename, const char *key) {

    char *line = NULL, *buf = NULL, *pline;
    size_t size = -1, ssearch = strlen(key);
    int open = 0;
    FILE *fp = fopen(filename, "r");

    if(fp == NULL) {
        fprintf(stderr, "Cannot read '%s' file.\n", filename);
        exit(EXIT_FAILURE);
    }

    while(getline(&line, &size, fp) != -1) {

        if(open == 0 && *line == '/' && 
           strncmp(line + 1, key, ssearch) == 0 && isspace(((unsigned char)*(line + ssearch + 1)))) {
            open = 1;
            continue;
        }

        if(open) {

            pline = line;

            while(isspace((unsigned char) *pline)) ++ pline;

            if(*pline != '{') {
                EXPECTEDSYMBOL('{', *pline);
            } 

            if(strchr(pline, '}') == NULL) {
                EXPECTEDSYMBOL('}', *(pline + strlen(pline) - 1));
            }

            buf = pline;

            break;
        }

        line = NULL;
    }

    fclose(fp);


    return buf;

}

これがお役に立てば幸いです。

編集#2:あなたの質問をもう一度読んだところ、以下のキーも必要であることがわかりました。

これを試して:

void
get(const char *filename, const char *key, char buf[][512]) {

    char *line = NULL;
    size_t size = -1, ssearch = strlen(key);
    int open = 0;

    FILE *fp = fopen(filename, "r");

    if(fp == NULL) {
        fprintf(stderr, "Cannot read '%s' file.\n", filename);
        exit(EXIT_FAILURE);
    }

    while(getline(&line, &size, fp) != -1) {

        if(open == 0 && *line == '/' && 
           strncmp(line + 1, key, ssearch) == 0 && isspace(((unsigned char)*(line + ssearch + 1)))) {
            open = 1;
            continue;
        }

        if(open == 1) {
            strcpy(buf[0], line);
            ++ open;
            continue;
        }

        if((open + 1) == 3) {
            getline(&line, &size, fp);
            strcpy(buf[1], line);
            break;
        }
    }

    fclose(fp); 

}

その後:

const char *key = "TEST"; // /TEST
const char *filename = "config";
char buf[2][512] = { { 0 } };

get(filename, key, buf);
printf("%s\n", buf[0]); //  {. text . }
printf("%s\n", buf[1]); //  {. infs .}
于 2012-06-19T00:11:47.853 に答える
1

主に次の 2 つの選択肢があります。

  • すべてを実行時構造体に格納し、トークンを解析文字列にスキップしてデータを解析することにより、ファイルを手動で解析します (stdio を使用して、たとえばfreadfscanfなどfseek) 。
  • パーサージェネレーターの使用 ( flex + bisonが最初の選択肢です): これらがどのように機能するかを少し勉強する必要がありますが、すべてが魅力的に機能し、簡単に保守できます始める
于 2012-06-18T18:06:01.913 に答える
0

私は通常 awk を使用してテキストを処理します。

$ awk '/^\/TEST$/, /}/{print $0}' test.dat | tail -1
 {. text .}

これは awk に一連の行を返すように指示します。返される最初の行は、この正規表現に一致し^\/TEST$ます。返された最後の行は、これと一致し}ます。そしてtail -1、最後の行だけを stdout に渡します。

「テキスト」が実際に何行ものテキストになる可能性がある場合は、おそらくテールではなく awk にパイプします。

$ awk '/^\/TEST$/, /}/{print $0}' test.dat | awk 'NR!=1{print $0}'
 {. text
text
text
.}

必要に応じて、そのワンライナーをシェル スクリプトとして再パッケージ化できます。

于 2012-06-18T18:21:41.640 に答える