手把手教會你C語言檔案操作(2)

2021-10-17 11:45:36 字數 3535 閱讀 8066

linux c 檔案操作

手把手教會你c語言檔案操作(1)

2. 檔案操作位置是否到達了文件末尾?

1.1 偏移操作

說是說指標偏移,將其稱之為「尋找操作位置」也未嘗不可,也更加容易記住這個函式。為什麼這麼說呢,尋找 ----- seek,不難猜出這個函式就是 fseek。

來看看函式原型:

int

fseek

(file *fp,

long offset,

int origin)

; @fp: 要偏移操作位置的檔案指標

@offset: 偏移大小

@origin:

seek_set

0 開頭

seek_cur

1 當前

seek_end

2 末尾

返回值:成功返回0,失敗返回-

1。

關於第二引數 offset ,我們注意一下他的型別是 long 而不是 unsigned long ,這說明這個引數可能是負數,那就很奇怪了呀,可以使正數、負數、0,那怎麼確定是哪個呢?

那如果我告訴你這個正負性是指偏移方向,負數向左,正數向右偏移的話,你能想到什麼呢?

沒錯,這個引數是基於第 3 個引數的,在第 3 個引數的位置的基礎上前後移動 offset 個位元組。

做個試驗

假設我有乙個 a.txt 檔案,裡面儲存著萬年新手** hello world。

那麼下面的語句讀取到的是什麼內容呢?

if(!

fseek

(fp,0,

seek_set))

}if(!

fseek

(fp,-5

,seek_cur))

}if(!

fseek

(fp,-6

,seek_end))

}

buffer = hello

buffer = hello

buffer = world

分析一下

第乙個大 if 的意思是:從頭開始,不加左右偏移,讀取 5 個位元組儲存在 buffer 中。

第二個大 if 執行時,當前檔案操作指標在 hello 的 o 之後,再讀取內容時就是空格開始了。此時的 fseek 語句是指:指標先保持當前位置不動,然後加上向前偏移 5 個位元組開始讀取 5 個位元組內容。

第三個大 if 的意思就跟簡單了,偏移至最後之後,已經讀取不到內容了,已經到了文件末尾(end of file),也就是再標頭檔案中定義的 eof 巨集值。在這個基礎上向前偏移 6 個位元組讀取 5 個位元組。

是不是覺得不夠直觀,想要看到直接一點的資料?這不,他來了。

1.2 獲取當前操作位置與檔案開頭之間的位元組數

函式原型:

long

ftell

(file *fp)

;返回值:成功返回當前操作位置與開頭的位元組數,失敗返回-

1;

嗯,這個函式多簡單是吧,我們把這個函式加入到上面的**中。

就是這樣了,這個小函式還是比較簡單的。

1.3 面試題:給出乙個檔名,返回該檔案的位元組數(檔案大小)。

相信有童鞋已經想到了,將檔案操作指標偏移至檔案末尾,再用 ftell 獲取其與檔案開頭的值即可。

**如下:

long

getfilesize

(const

char

*file_name)

file *fp =

fopen

(file_name,

"r");if

(fp ==

null)if

(!fseek

(fp,0,

seek_end))

else

}

到這裡應該能夠理解 fseek 的使用了吧,那我們再順便提一提上面提到的 eof。

當我們使用 fread 去讀取檔案時,相信大家還記得我們是如何判斷操作是否成功的對吧。不過呢,不知道各位有沒有注意到有個特殊情況 ------- 檔案操作位置位於文件末尾。由於此時的位置之後已經沒有內容可讀了,fread 自然而然返回了 0,而我們卻把它當做錯誤處理掉了,想想好像有點不太合適?

那我們如何判斷呢?鏘鏘,就是這個巨集 ---- eof,全稱為:end of file。

同時,還有兩個小函式一併解決了吧:

int

feof

(file *fp)

;返回值:成功返回真;失敗返回假。

intferror

(file *fp)

;返回值:成功返回真;失敗返回假。

不作過多解釋了,依舊是那個只有 「hello world.」 的 a.txt 檔案,加上這兩個保險的話就是這樣子滴:

int

main()

char buf[5]

=;int ret;

/***********************************/

while(1

)// 讀完為止,或者是出錯停下if(

ferror

(fp)

)// 沒有到文件末尾多半就是出錯啦,不過既然說到這個函式就給個面子吧。

}printf

("read buf = %s\n"

, buf)

;// 看看每次讀取到了什麼?

}// 不管是出錯還是讀取完畢,關閉檔案的操作必不可少,養成好習慣哦。

/****************************************/

return0;

}

執行結果:

read buf = h

read buf = e

read buf = l

read buf = l

read buf = o

read buf =

read buf = w

read buf = o

read buf = r

read buf = l

read buf = d

read buf =

.end of file, nothing to read.

嗯,到這的話其實都差不多說完了,寫入檔案也是一樣的道理,其實只要你像我這兩篇文章的思路,大膽去將介面試一試,提出問題,用執行結果來佐證或是推翻你的猜測,我覺得已經沒有什麼是很難的了。

好吧,本文最後炒一炒冷飯,不使用檔案操作指標偏移,僅使用 fread 、feof 和 ferror 來統計檔案大小又該怎麼寫呢?

手把手教會你C語言檔案操作(1)

在c語言學習過程中,對於資料的儲存是無法避免的問題之一。我們學習了用陣列來儲存某一種型別資料,用結構體來儲存多種不同型別資料,但是這些都是程式中的容器,程式退出後這些資料也就隨之消失了。所以我們嘗試尋找一種方式,能夠將資料儲存與程式分離開來。在 linux 中有這麼一句話 一切皆檔案。所以我們嘗試將...

手把手教會你C語言檔案操作(3)

如題所說,這篇博文就來聊聊檔案的寫入,也就是將資料從程式中儲存至指定檔案當中。手把手教會你c語言檔案操作 1 手把手教會你c語言檔案操作 2 檔案操作相關函式 好吧,我也知道沒啥人看我的寫的部落格,就不自取其辱了,直接進入正題吧。首先要明確一下這個操作許可權指的是什麼。它是指我們用fopen開啟某個...

手把手入門C語言 列舉

列舉中的變數是遞增的 預設是0開始 首元素的值是0 include include 列舉中的變數是遞增的 預設是0開始 首元素的值是0 定義乙個列舉 enum weekday main 測試列舉中的變數是遞增的 修改下面的 monday 0,tuesday,wednesday,thursday,fr...