1. 程式人生 > >ifstream 檔案流讀取格式資料出現的問題

ifstream 檔案流讀取格式資料出現的問題

在檔案中均為數字的時候,需要將這些數字按整型讀取,可以直接利用檔案流進行讀取,但是一旦檔案中存在非數字字元的時候,比如出現字串就會出現異常。因此我們需要處理這種情況。下面這段程式可以處理這個問題。其實問題的關鍵就是在in.ignore()函式。該函式的原型為:

istream& ignore (streamsize n = 1, int delim = EOF);

第一個引數表示的是要忽略的字元數,第二個引數表示遇到該字元就停止,該字元前面的資料全部忽略(包括該字元)。

程式中的numeric_limits<std::streamsize>::max()表示的是streamsize型別的最大值。

當檔案中的資料都是用空格分隔時,使用in.ignore(std::numeric_limits<std::streamsize>::max(),' ');沒有任何問題,方便簡潔。

但是如果檔案中既有空格,又有換行的時候,就會出現問題:如檔案格式為:

123 456 gchch

34   12   500

當讀取到gchch的時候,是異常的,但是gchch後直接是換行,不會截止,所以會一直將34也忽略掉。這樣就會丟失一個數據。

這個時候就應該使用預設的ignore函式,每次忽略一個字元

正確的做法是將

#include<iostream>

#include <fstream>
#include <stdexcept>
#include <cstdlib>
#include <limits>
using namespace std;
int main()
{
ifstream in("a.txt");
int x;
//string x;
while(in>>x,!in.eof())
{
if(in.bad())
throw runtime_error("ifstream corrupted");
if(in.fail())
{
cout<<"bad data,try again"<<endl;
//in.clear(ifstream::failbit);
in.clear();
//in.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
//in.ignore(std::numeric_limits<std::streamsize>::max(),' ');
//in.ignore(1,' ');
in.ignore();
continue;
}
if(x%2 == 0)
{
cout<<x/2<<endl;

//cout<<x.c_str()<<endl;
}
return 0;

}

下面是一些關於判斷檔案狀態的資料:

你已經學會了open() 和close() 方法, 不過這裡還有其它你可能用到的方法。

  方法good() 返回一個布林值,表示檔案開啟是否正確。

  類似的,bad() 返回一個布林值表示檔案開啟是否錯誤。 如果出錯,就不要繼續進一步的操作了。

  最後一個檢查的方法是fail(), 和bad()有點相似, 但沒那麼嚴重。

  讀檔案

  方法get() 每次返回一個字元。

  方法ignore(int,char) 跳過一定數量的某個字元, 但你必須傳給它兩個引數。第一個是需要跳過的字元數。第二個是一個字元, 當遇到的時候就會停止。 例子,

fin.ignore(100, ‘/n’);



  會跳過100個字元,或者不足100的時候,跳過所有之前的字元,包括 ‘/n’。

  方法peek() 返回檔案中的下一個字元, 但並不實際讀取它。所以如果你用peek() 檢視下一個字元, 用get() 在peek()之後讀取,會得到同一個字元, 然後移動檔案計數器。

  方法putback(char) 輸入字元, 一次一個, 到流中。我沒有見到過它的使用,但這個函式確實存在。

  寫檔案

  只有一個你可能會關注的方法.?那就是 put(char), 它每次向輸出流中寫入一個字元。

  開啟檔案

  當我們用這樣的語法開啟二進位制檔案:

ofstream fout("file.dat", ios::binary);

  "ios::binary"是你提供的開啟選項的額外標誌. 預設的, 檔案以ASCII方式開啟, 不存在則建立, 存在就覆蓋. 這裡有些額外的標誌用來改變選項。

  ios::app 新增到檔案尾
  ios::ate 把檔案標誌放在末尾而非起始。
  ios::trunc 預設. 截斷並覆寫檔案。
  ios::nocreate 檔案不存在也不建立。
  ios::noreplace 檔案存在則失敗。

  檔案狀態

  我用過的唯一一個狀態函式是eof(), 它返回是否標誌已經到了檔案末尾。 我主要用在迴圈中。 例如, 這個程式碼斷統計小寫‘e’ 在檔案中出現的次數。

ifstream fin("file.txt");
char ch; int counter;
while (!fin.eof()) {
ch = fin.get();
if (ch == ‘e’) counter++;
}
fin.close();

  我從未用過這裡沒有提到的其他方法。還有很多方法,但是他們很少被使用。參考C++書籍或者檔案流的幫助文件來了解其他的方法。

  結論

  你應該已經掌握瞭如何使用ASCII檔案和二進位制檔案。有很多方法可以幫你實現輸入輸出,儘管很少有人使用他們。我知道很多人不熟悉檔案I/O操作,我希望這篇文章對你有所幫助。每個人都應該知道. 檔案I/O還有很多顯而易見的方法,?例如包含檔案 <stdio.h>. 我更喜歡用流是因為他們更簡單。祝所有讀了這篇文章的人好運, 也許以後我還會為你們寫些東西。