日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

c语言标准io中可读可写,C语言标准IO: [先读再feof] VS [先feof再读]

發布時間:2024/9/30 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c语言标准io中可读可写,C语言标准IO: [先读再feof] VS [先feof再读] 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

剛學習C語言讀取文件的時候,可能都遇到過這個“bug”,讀到末尾時數據有重復。

解決方案也是五花八門,甚至有人把數據先緩存了,再忽略掉最后一組....

不妨看一段代碼,兩種解決方案,猜猜看,究竟哪一個方案是正確的。

/*

*方案一:先判斷,后讀取

*/

while(!feof(fp))?{

fread(buf,?1,?100,?fp);

//do_some_thing

}

/*

*方案二:先讀取,后判斷

*/

while(1)?{

fread(buf,?1,?100,?fp);

if(feof(fp))

break;

//do_some_thing

}

/*

*方案一:先判斷,后讀取

*/

while (!feof(fp)) {

fread(buf, 1, 100, fp);

//do_some_thing

}

/*

*方案二:先讀取,后判斷

*/

while (1) {

fread(buf, 1, 100, fp);

if (feof(fp))

break;

//do_some_thing

}

曾經,我毫不猶豫的選擇一,過了不久又毫不猶豫的選擇二。然而,非常遺憾,沒有

一個是正確的。暫不解釋why,來一段MSDN上的代碼,關于feof的一個example:

#include?

#include?

intmain(void)

{

intcount,?total?=?0;

charbuffer[100];

FILE*stream;

fopen_s(?&stream,"crt_feof.txt","r");

if(?stream?==?NULL?)

exit(?1?);

//?Cycle?until?end?of?file?reached:

while(?!feof(?stream?)?)

{

//?Attempt?to?read?in?100?bytes:

count?=?fread(?buffer,sizeof(char),?100,?stream?);

if(?ferror(?stream?)?)??????{

perror("Read?error");

break;

}

//?Total?up?actual?bytes?read

total?+=?count;

}

printf("Number?of?bytes?read?=?%d/n",?total?);

fclose(?stream?);

}

#include

#include

int main( void )

{

int count, total = 0;

char buffer[100];

FILE *stream;

fopen_s( &stream, "crt_feof.txt", "r" );

if( stream == NULL )

exit( 1 );

// Cycle until end of file reached:

while( !feof( stream ) )

{

// Attempt to read in 100 bytes:

count = fread( buffer, sizeof( char ), 100, stream );

if( ferror( stream ) ) {

perror( "Read error" );

break;

}

// Total up actual bytes read

total += count;

}

printf( "Number of bytes read = %d/n", total );

fclose( stream );

}

不要驚訝,你沒看錯,MSDN是先使用feof,然后再讀取,跟網上的看法有些出入。

到底是為什么呢?我覺得,還是從feof和fread的源碼開始分析比較好,實現可能不同,用法應該是一致的。以GLIBC 2.10的源碼為例。不管是 unlocked 還是 非unlocked,feof最終還是調

用了unlocked的那個_IO_feof_unlocked“函數”,所以分析該“函數”即可。

#define?_IO_feof_unlocked(__fp)?(((__fp)->_flags?&?_IO_EOF_SEEN)?!=?0)

#define _IO_feof_unlocked(__fp) (((__fp)->_flags & _IO_EOF_SEEN) != 0)

現在可以得到一個結論:

feof的返回值,僅僅取決于文件結構是否被打上 _IO_EOF_SEEN 標志。

feof本身并不影響這個標志,因此可以斷定,標志是在讀取的時候被修改的,于是

去追尋fread的源碼。經歷了宏的泥淖,欣賞了純C填虛函數表模擬C++多態的壯

烈,終于找到了fread的背后黑手。fread實際上可能調用不同的函數,mmap文件

和普通文件的處理,是不一樣的,不過知道其中一個便可,因為底層的差異,對程

序員是透明的,只要展示給程序員看的一面是一致的就OK。且看關鍵部分代碼:

count?=?_IO_SYSREAD?(fp,?s,?count);

if(count?<=?0)

{

if(count?==?0)

fp->_flags?|=?_IO_EOF_SEEN;

else

fp->_flags?|=?_IO_ERR_SEEN;

break;

}

count = _IO_SYSREAD (fp, s, count);

if (count <= 0)

{

if (count == 0)

fp->_flags |= _IO_EOF_SEEN;

else

fp->_flags |= _IO_ERR_SEEN;

break;

}

看到_IO_SYSREAD有什么感覺呢? 哦,你可以把它當成表現跟read系統調用一樣

的東西,返回值大于0,就是實際讀取字節數;等于0,就是文件之前已被讀完(或者

是文件根本就是空的),本次沒讀到數據;小于0就是失敗,有錯誤發生。

總結代碼中的流程和細節,整理出來就是:

標準IO是帶有緩存的,每一次請求,未必對應一次系統調用

緩存剩余字節數大于等于請求的,直接使用緩存,不產生系統調用

fread當且僅當,系統調用讀取到的字節數為0時,才會打上結束標志

feof只檢查_IO_EOF_SEEN標志位,不做其它影響返回值的判斷

根據這些,不難得出以下結論:

文件全部讀完,即使緩存用盡且SYS_READ讀盡,feof未必返回真值

SYS_READ實際讀取到0字節的事情發生后,feof一定返回真值

fread實際讀取的字節數少于預期時,feof一定返回真值

feof可以只檢查標志就做出判斷,而fread可能多一次系統調用才知道結束

feof返回0的時候,上一次讀取的數據,一定是有效數據

至此,已經不難理解,為什么最上面貼的兩種方案都是錯的。因為它們都沒有對

fread的返回值做出反應,如果對這個返回值加以處理,無論是先讀后判斷還是先

判斷后讀取,都是沒有問題的,都能得到正確的結果。當然,這得有個前提,就是

除了feof外,有別的方法判斷是否結束,倘若如fgetc那般,讀取的字符作為函數返

回值,讀二進制文件時,就無法判斷了,因為二進制文件本身也可能含有EOF字符。

這種情況,只有一種方案,就是先讀取,再用feof判斷是否結束。

做了那么長時間的鋪墊,現在回到本文的核心。是先讀取還是先判斷?我認為:

在決定用哪一種方案前,首先要考慮用于讀取的那個函數的返回值的意義

如果你不想了解細節,也不屑于些許性能,一律先讀取后判斷,肯定不會有錯

如果讀取函數的返回值蘊含是否讀取成功,那么先判斷后讀取,可能更加高效

但是有一點,不管是哪種方式,如果用于讀取的函數,返回值包含讀取是否成功或者實際 讀取字節數等信息,這個信息是一定要考慮的。同樣,寫入操作也好,其它操作也好,只 要函數帶有返回值,且未注明這個返回值沒有意義,都應該認真推敲下這個返回值的意義, 然后決定是否需要處理這個返回值。

總結

以上是生活随笔為你收集整理的c语言标准io中可读可写,C语言标准IO: [先读再feof] VS [先feof再读]的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产亚洲视频在线观看 | 韩国性经典xxxxhd | 美美女高清毛片视频免费观看 | 青青青青青操 | 神马影院一区二区三区 | 国产老妇伦国产熟女老妇视频 | 丁香六月天婷婷 | 中文资源在线播放 | 欧美视频www | 穿越异世荒淫h啪肉np文 | 超碰97在线免费观看 | 夜夜撸影院 | 女女互慰揉小黄文 | 在线视频日本 | 欧美日韩国产不卡 | 色天天综合 | 精品人妻天天爽夜夜爽视频 | 强伦人妻一区二区三区视频18 | 亚洲成人一区二区 | 精品欧美一区二区三区成人 | 麻豆网站在线 | 日本黄色高清视频 | 欧美视频一区二区三区四区在线观看 | 超碰伦理 | 久久久久久久久久久久久久久久久久 | 亚洲图色av| 欧美肥老妇 | 亚洲天堂网一区二区 | 图片一区二区 | 伊人亚洲综合 | 成人理论片 | 韩国av中文字幕 | 天天综合永久入口 | 天天视频污 | 六月激情网 | 在线免费观看黄色av | 久久午夜电影网 | 日韩美女三级 | 在线观看久 | 1000部啪啪未满十八勿入 | 粉嫩av.com | 免费看的毛片 | 天天av综合 | 狠狠人妻久久久久久综合 | 未满十八岁勿进 | 少妇一级淫片免费放 | 亚洲天堂中文字幕在线观看 | 青青久久av | 伊人激情在线 | 天天干网 | 一区在线播放 | 激情五月婷婷丁香 | 欧美 变态 另类 人妖 | 国产一区二区三区在线免费 | 亚洲av无码不卡一区二区三区 | 欧美日韩va| 欧美性猛交xxx乱大交3蜜桃 | 国产精品永久久久久久久久久 | 少妇视频一区 | 超级砰砰砰97免费观看最新一期 | 国产av电影一区二区三区 | 日本h在线观看 | 91超薄肉色丝袜交足高跟凉鞋 | 亚洲人掀裙打屁股网站 | japanese中文字幕 | 精品免费看 | 北条麻妃久久 | 国产精品美女久久久久图片 | 国产12页 | 久久一区av | 亚洲欧美精品aaaaaa片 | 欧美91精品| 国产哺乳奶水91在线播放 | 国产精品自拍在线 | 一区二区在线视频 | 亚洲男人网 | 日韩av综合网 | 岛国av中文字幕 | 免费黄色一区二区 | 久久久精品亚洲 | 成在人线av | 99自拍网 | 国产免费91 | 任你躁av一区二区三区 | 台湾少妇xxxx做受 | 九九少妇 | 泽村玲子av | 视色影院 | 日韩在线观看av | 超碰一区二区三区 | sm在线观看 | 成人av网站在线播放 | 性做久久久久久久免费看 | 亚洲av久久久噜噜噜熟女软件 | www.sesehu| 国产精品xxx在线观看 | 樱桃香蕉视频 | 欧美一区国产一区 | 亚洲欧美综合一区二区 |