簡體   English   中英

'fread()','fwrite()'和'fseek()'的異常行為

[英]Unexpected behavior of 'fread()', 'fwrite()' and 'fseek()'

我編寫了一個簡單的C程序,該程序使用.txt文件並將所有空格替換為連字符。 但是,程序進入無限循環,結果是連字符的數組無窮。

這是輸入文件:

a b c d e f

進程崩潰后的文件是:

a----------------------------------------------------------------------------
----------------------------------------... (continues thousands of times)... 

我猜想fread()fwrite()fseek()意外行為的原因,或者是我對這些函數的誤解。 這是我的代碼:

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

#define MAXBUF 1024

int main(void) {

    char buf[MAXBUF];
    FILE *fp;
    char c;
    char hyph = '-';

    printf("Enter file name:\n");
    fgets(buf, MAXBUF, stdin);
    sscanf(buf, "%s\n", buf);   /* trick to replace '\n' with '\0' */

    if ((fp = fopen(buf, "r+")) == NULL) {
        perror("Error");
        return EXIT_FAILURE;
    }

    fread(&c, 1, 1, fp);

    while (c != EOF) {
        if (c == ' ') {
            fseek(fp, -1, SEEK_CUR); /* rewind file position indicator to the position of the ' ' */
            fwrite(&hyph, 1, 1, fp); /* write '-' instead */
        }
        fread(&c, 1, 1, fp); /* read next character */
    }

    fclose(fp);

    return EXIT_SUCCESS;
}

這里有什么問題?

您有兩個問題:

1)您應該檢查fread是否返回了您請求的項目數,例如您得到了1。

2)然后,您應該檢查feof(fp),而不是將讀取的字符與EOF進行比較。 這將告訴您您的閱讀是否由於EOF或其他原因退回的物品少/少。

你有一些問題...

檢查標准C庫函數返回的類型以及該返回值的含義。 std C庫將EOF定義為整數 -1。 由於完整字符集為256個字符,並且char類型可以容納0到255(256個diff值),因此必須使EOF為整數。

拋開所有這些怒氣...您還正在錯誤地檢查EOF

問題闡明:

您應該檢查fread的返回值

if( fread(&c, 1, 1, fp) != 1 )
{
    // Handle the error
}

// `EOF` is the integer -1.  It will not fit in a char.  So, your while loop becomes endless unless you get a -1 in the data stream

// The "correct" way to do what you want to do is using the stdlib function feof(fp)
while( !feof( fp ) )
{
    if (c == ' ')
    {
        // You should check the value returned by fseek for errors
        fseek(fp, -1, SEEK_CUR); /* rewind file position indicator to the position of the ' ' */
        // You should check the value returned by fwrite for errors
        fwrite(&hyph, 1, 1, fp); /* write '-' instead */
    }

    if( fread(&c, 1, 1, fp) != 1 )
    {
        // Handle the error
    }
}

所有這些都說明了...在現代系統上一次讀取一個字符效率很低。 修改您的代碼以一次讀取一個完整的緩沖區,然后一次寫出整個修改后的緩沖區。

原因:

對於允許進行輸入和輸出操作的要更新的打開文件(帶有“ +”號的文件),應在進行后續的讀取操作之前對流進行刷新(fflush)或重新定位(fseek,fsetpos,rewind)。寫作操作。 在讀取操作之后的寫入操作之前(無論該操作未到達文件末尾),都應在重定位流之前(fseek,fsetpos,rewind)。

解決方案:

您應該添加“ fflush(fp);” 在fwrite行之后。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM