[英]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.