C++のIOライブラリ(一)


時間:2014.03.16
場所:基地2階
---------------------------------------------------------------------------
一、よくあるIO施設の概要
まず、よく使われるIO施設を簡単にまとめてみましょう
1.istream入力フロータイプ、入力操作を提供する
2.ostream出力ストリームタイプ、出力操作を提供する
3.cin 1つのistreamオブジェクト、標準入力からデータを読み込む
4.cout ostreamオブジェクト、標準出力への書き込みデータ
5.cerrプログラムエラー情報を出力し、標準エラーに書き込むostreamオブジェクト
6.>>演算子、istremオブジェクトから入力データを読み込む
7.<<演算子、出力データを1つのostreamオブジェクトに書き込む
8.getling関数は、所与のistreamから1行のデータを読み出し、所与のstringオブジェクトに格納する
getling関数の詳細は、次のとおりです.
一般的にcin>>というフォーマットで入力を取得するのに慣れていますが、なぜgetlineなのでしょうか.なぜなら、最終的に得られた文字列に入力時の空白文字を残したいからです.これはcin>>は需要を満たすことができません.getlineを使います.getline関数のパラメータは、入力ストリームとstringオブジェクトです.関数は、所定の入力ストリームから改行文字に出会うまで内容を読み込み、改行文字も読み込まれます.次にstringオブジェクトに読み込んだ内容を格納しますが、改行は保存されず、実際には破棄されます.getlineが改行文字に遭遇すると、読み取り操作を終了して結果を返します.最初から改行してもそうです.たとえば最初から改行文字であれば、getlineは改行文字を読み込んで改行文字であることを検出し、読み取り操作を終了して内容を返すが、このときは何もないので空のstringである.
入力演算子と同様にgetlineもストリームパラメータを返し,入力演算子が判別条件として利用できることを知っているので,getlineの結果も同様である.たとえばgetlineの結果を条件として、プログラムに1行ずつ出力させることができます.
int main(){
  string line;
  while(getline(cin,line){
      cout<<line<<endl;
  return 0;
}

また、ヘッダファイルiostreamでは、読み書きストリームの基本タイプである通常ストリームを定義し、ヘッダファイルfstreamは読み書きネーミングファイルのタイプであるファイルストリームを定義し、ヘッダファイルsstreamは読み書きメモリstringオブジェクトのタイプであるstringストリームを定義します.
一般的には、派生クラスオブジェクトをベースクラスオブジェクトとして使用できます.タイプifstreamおよびistringstreamオブジェクトはistreamから継承され、ofstreamおよびostringstreamはostreamから継承されます.これにより、istreamオブジェクトを使用するように使用できます.たとえば、ifstreamオブジェクトまたはistringstreamオブジェクトに対してgetlineを呼び出すか、>>ifstreamオブジェクトまたはistringstreamオブジェクトからデータを読み込むことができます.
---------------------------------------------------------------------------
二、IOオブジェクトのコピーなし無付与
IOオブジェクトのコピーと割り当ては意味がないので、次のような操作はできません.
ofstring out1,out2;
out1=out2;   // ,        
ofstream print(ofstream);  //  ,     ofstream  
out2=print(out2);  //       

IOオブジェクトをコピーすることはできないため、設計オブジェクトのコピーを返すため、一般的にIO操作を設計する関数は、フロータイプを参照してフロータイプに設定することはできません.また、IOオブジェクトを読み書きするとストリームの状態が変化するため、渡された参照と返される参照はconstではありません.
---------------------------------------------------------------------------
三、条件状態
IOオペレーションではエラーが発生することがよくあります.この問題に対応するために、IOクラスはいくつかの関数とフラグを定義し、これらのストリームの条件状態に基づいてプログラマがエラーを処理するのに役立ちます.よく使われるIOライブラリ条件状態の関数とフラグをまとめてみました
strm::iostate iostateは機械関連のタイプで、条件状態を表現する完全な機能を提供します.
strm::badbitは、ストリームがクラッシュしたことを示すために使用されます.
strm::failbitはIO操作の失敗を指摘するために使用されます
strm::eofbitはファイルの終了までストリームが流れたことを示します
strm::goodbitは、ストリームがエラー状態にないことを示します.この値はゼロに保証されます.
s.eof()sのeofbitセットがtrueに戻る場合
s.fail()sのfailbitまたはbadbitがセットされている場合はtrueを返します.
s.bad()sのbadbitがセットされている場合はtrueを返します
s.good()sが有効な場合はtrueを返します
s.clear()sのすべての状態をリセットし、ストリームの状態を有効に設定し、voidを返します.
s.clera(flags)は、所与のflagsフラグビットに基づいて、ストリームsにおける対応条件状態をリセットし、flagsのタイプはstrm::iostate、voidを返す
s.setstate(flags)は、所与のflagフラグビットに基づいてストリームsにおける対応条件状態をセットし、falgsは同上である
s.rdstate()はストリームsの現在の条件状態を返し、戻り値タイプはstrm::iostateエラー操作の例:
int val;
cin>>ival;

HuNanを入力すると、intタイプを読み込むことを期待していたが、文字Hが得られ、cinストリームがエラー状態になるため、読み取り操作に失敗します.1つのストリームにエラーが発生すると、後続のIO操作は失敗します.ストリームがエラー状態にある可能性があるため、コードはストリームを使用する前に、ストリームが良好な状態にあるかどうかを確認する必要があります.最も簡単な方法は、それを条件として使用することです.
while(cin>>word)
  //.....

これによりwhileは>>式が返すストリーム状態をループチェックします.入力操作に成功すると、ストリームは有効な状態を保存し、条件は真で、次のループを続行します.
---------------------------------------------------------------------------
四、クエリーフローの状態
ストリームの具体的なステータスがストリームのようになぜ失敗したのかを知りたい場合があります.その原因については、異なる処理方法に関連する可能性があります.そこで、ストリームのステータスをクエリーします.IOライブラリは、マシンに関係のないiostateタイプを定義し、ストリーム状態を表現する完全な機能を提供します.このタイプは、ビットセットとして使用する必要があります.
badbitテーブルシステムレベルのエラー、読み書きエラーを復元できない場合、badbitがセットされるとストリームは使用できません.
failbit IO操作に失敗し、被セット、所望の読み取り値で1文字まで読み出すなどのエラーが発生した場合、この問題は通常修正でき、ストリームは引き続き使用でき、ファイルが終了するとeofbitとfailbitはいずれもセットされます.
goobit値は0で、ストリームにエラーが発生していないことを示します.
badbit failbit eofbitのいずれかがセットされている場合、ストリーム状態を検出する条件は失敗します.
標準ライブラリには、これらのフラグビットのステータスをクエリーする関数のセットも定義されています.上記のようにまとめる.goodを操作すると、すべてのエラービットがセットされていない場合にtrueが戻る、bad failとeofは対応するエラービットがセットされている場合にtrueが戻る.また、badbitがセットされている場合、failもtrueを返します.すなわちgoodとfailを用いることは,ストリームの全体的な状態を決定する正しい方法である.ストリームを条件として使用すると等価です!fail() .eofおよびbad操作は、特定のエラーのみを表すことができます.
---------------------------------------------------------------------------
五、管理条件状態
ストリームオブジェクトのrdstateメンバー関数は、ストリームの現在のステータスに対するistate値を返します.setstate操作では、所定の条件位置ビットを、対応エラーが発生したことを示すことができます.clearは、パラメータを受け入れない2つのバージョンのリロードメンバー関数で、すべてのエラーフラグビット、すなわちリセットが消去されます.clear()を実行するとgood()を呼び出すとtrue.が返されます.簡単な例は次のとおりです.
#include<istream>
#include<ostream>
#include<iostream>
using namespace std;
int main(){
	auto old_state = cin.rdstate();    //       
	cout << "old_state  " << old_state << endl;
	int a;     
	cin >> a;                              //           int    ,         
	auto current_state = cin.rdstate();    //       ,          
	cout << "current_state  " << current_state << endl;
	cin.clear();                           //          ,      ,     ,              ,     
	cin.setstate(old_state);               //      ,            
	auto nex_state = cin.rdstate();
	cout << "new_state  "<<nex_state << endl;
}

ここで説明すると、ストリームにエラーが発生した後、clear()対流をリセットしないと、後の対流の動作は成功しないことに注意してください.
パラメータ付きclear()は、ストリームの新しい状態を表すiostate値を受け入れるように使用することができ、rdstateで読み出されたiostate値、すなわち現在の条件状態をハスで読み取ることができる.その後、ビット操作で必要なリセットを行い、新しい状態を生成する.ここでは、数式を使用します.
(b)& (~b)=0
failbitとbadbitをリセットしたい場合は、0に設定しますが、eofbitは変更されません.
cin.clear(cin.rdstate()&~cin.failbit&~cin.badbit);

上のビットと操作が状態を表すfailbitとbadbitは0となり、新しい状態が得られ、clear()が伝達されて目的を達成する.