2016-03-07 63 views
0

在我的FreeBSD系統上運行得很好的程序在Windows上構建時失敗(Visual Studio 15)。它進入這裏無限循環:爲什麼fgetc向後移動文件位置指示器?

//... 
while (1) { 
    if ('@' == fgetc(f)) { 
     // we do some stuff here. irrelevant for stackoverflow question 
     break; 
    }   
    fseek(f, -1, SEEK_CUR);   
    if (0 != fseek(f, -1, SEEK_CUR)) { 
     // Beginning of file. 
     break; 
    } 
} 
//... 

在細看(通過加入一些fgetpos的() - 電話)我發現龜etc移動文件位置指示器向後。所以它會錯過文件的開始和一些'@',如果它們從最後不在3的倍數位置。

我注意到,文件F打開時與

fopen(filename, "a+"); 
//text mode read/append 

這只是一切發生的時候當我將其更改爲

fopen(filename, "ab+"); 
//binary mode read/append 

則一切正常。 我認爲我的代碼是安全的,只是一直使用二進制模式。 但仍有兩個問題:

  • 是否有原因對抗二進制模式?
  • 在文本模式下,錯誤的方向有什麼欺騙?
+2

請問您可以發佈[MCVE](http://stackoverflow.com/help/mcve)嗎? –

+1

以文本模式打開文件時,可能會發生一些字符翻譯,尤其是Windows中的換行符是「\ r \ n」',並且在讀取它時翻譯爲普通的''\ n''。在像BSD這樣的Unix系統上,換行符只是一個''\ n「',所以在這些系統上不需要翻譯。我不知道這是否解釋了你的問題。 –

+0

「是否存在違反二進制模式的原因?」 - 實際上,對*文本*模式有很多要說的... – DevSolar

回答

2

報價C11 7.21.9.2fseek功能:

對於文本流,無論是偏應是零,或者應的值由先前的成功調用返回的偏移在與同一個文件關聯的流上實現函數,並且這個函數應該是SEEK_SET。

SEEK_CUR上在文本模式下打開流的何處參數調用fseek不被C標準覆蓋。以二進制模式打開文件似乎是一個更好的選擇。

fgetpos()返回的值作爲文件中的偏移量可能沒有意義,它只是作爲參數傳遞給fsetpos()

作爲一般性評論,你應該嘗試改變你的算法,以避免依賴流中的向後尋求,尤其是依靠fseek()錯誤似乎不可靠。請將fgetc()前的位置保存爲ftell()fgetpos(),並在需要時使用fseek(pos, SEEK_SET, fp)fsetpos()將其恢復。

相關問題