1

目的:無限ループを停止するためにEOFを正常に実装する方法は?

関数が呼び出される部分:

do {
    pId = readInputField(fptr, DELIMITER_SPACE);
    pName = readInputField(fptr, DELIMITER_SEMICOLON);
    pDob = readInputField(fptr, DELIMITER_SPACE);
    pHobbyList = readInputField(fptr, DELIMITER_NEWLINE);
} while (NULL != pId
         && NULL != pName
         && NULL != pDob
         && NULL != pHobbyList);

関数の定義:

char* readInputField(FILE* fPtr, const char delimiter) {
    int numCharRead;
    char bufferString[MAX_LENGTH_INPUT];
    char *pBufferString;

    numCharRead = 0;

    // flush: if spaces are found
    ' ' == (bufferString[numCharRead] = fgetc(fPtr)) ? 0 : numCharRead++;

    // get chracter array before delimiter
    while (delimiter != bufferString[numCharRead - 1]
            && numCharRead < MAX_LENGTH_INPUT) {
        bufferString[numCharRead++] = fgetc(fPtr);
    }

    // exclude delimiter from the string
    bufferString[numCharRead - 1] = '\0';

    printf("numCharRead=  \"%d\"\n", numCharRead);

    printf("delimiter:    \"%c\"\n", delimiter);
    printf("bufferString: \"%s\"\n", bufferString);

    pBufferString = malloc(sizeof(char*) * strlen(bufferString));

    /* deleted:
    pBufferString = bufferString;
    return EOF == bufferString[numCharRead - 1] ? NULL : pBufferString;
    */
}

サンプル入力:

VIC Lee, Victoria; 02/25/90 Knitting;Photography;Dance;

サンプル出力:

numCharRead=  "4"
delimiter:    " "
bufferString: "VIC"
numCharRead=  "14"
delimiter:    ";"
bufferString: "Lee, Victoria"
numCharRead=  "9"
delimiter:    " "
bufferString: "02/25/90"
numCharRead=  "28"
delimiter:    "
"
bufferString: "Knitting;Photography;Dance;"

// after this, infinite loop begins with garbage data

私の呼びかけは、上記のreturnステートメントを確認することです。何らかの理由で、EOFであるかどうかを検出しません。

どんな助けでも大歓迎です!ありがとう!


更新: @JoachimPileborgに感謝します!以下のコードを更新しました:

  // check for EOF
    if(bufferString[numCharRead-1] == EOF) {
        return NULL;
    } else {
        pBufferString = malloc(sizeof(char*));
        strcpy(pBufferString, bufferString);
        return pBufferString;
    }
4

2 に答える 2

2

EOF次のように、ファイルから読み取った場所を確認します

// flush: if spaces are found
' ' == (bufferString[numCharRead] = fgetc(fPtr)) ? 0 : numCharRead++;
if(bufferString[numCharRead-1] == EOF)
    return NULL;

while (delimiter != bufferString[numCharRead - 1]
            && numCharRead < MAX_LENGTH_INPUT) {
    bufferString[numCharRead++] = fgetc(fPtr);
    /* check for EOF */
    if(bufferString[numCharRead-1] == EOF)
        return NULL;
}

@JoachimPileborgのコメントで言及されている問題もあります

  • fgetc戻りintませんchar
  • bufferStringあなたは機能するローカルなものを返しています。
于 2013-02-12T08:23:34.030 に答える
1

コメントにコードを書くことができないので、これを回答として投稿します。

あなたは質問にこのコードを持っています(または少なくとも持っていました):

pBufferString = malloc(sizeof(char*) * strlen(bufferString));
pBufferString = bufferString;
return EOF == bufferString[numCharRead - 1] ? NULL : pBufferString;

上記の最初の行で、メモリを割り当てpBufferString、そのメモリをポイントします。

2行目pBufferStringでは、ローカル配列bufferStringを指すようになっているため、割り当てたメモリへのポインタがなくなりmalloc、メモリリークが発生します(後でそのポインタを使用しようとするとクラッシュする可能性がありfreeます)。

次にpBufferString、を返します。これはローカル配列を指しており、関数が戻った後、ローカル配列によって占有されているスタックメモリが無効になるため、未定義の動作につながります。

上記の問題に加えて、必要なメモリのほぼ4倍または8倍を割り当てます。ポインタのサイズは4バイトまたは8バイトです(32ビットまたは64ビットのプラットフォームを使用しているかどうかによって異なります)が、acharは1バイトのみです。strlen(bufferString) + 1割り当てるサイズとして使用するだけで十分です。

pBufferString = malloc(strlen(bufferString) + 1);

+ 1文字列のターミネータ文字が文字列の長さに含まれていないため、が必要です。

于 2013-02-12T09:13:03.287 に答える