撒花慶祝下,終於看完了(C++Primer)第一部分,即將進入第二部分!
IO部分,最基本的是iostream(istream、ostream),子類有fstream(ifstream、ofstream)和sstream(istringstream、ostringstream)。
iostream是控制窗口輸入輸出。
fstream是文件輸入輸出。
sstream是字符串輸入輸出(內存中)。
如果兩種類型存在繼承關系,則可以說一個類“繼承”了其父類的行為——接口。
C++ 中所提及的父類稱為基類(base class) ,而繼承而來的類 則稱為派生類(derived class)
IO 類型在三個獨立的頭文件中定義:
iostream 定義讀寫控制窗口的類型,
fstream 定義讀寫已命名文件的類型,而 sstream 所定義的類型則用於讀寫存
儲在內存中的 string 對象。
在 fstream 和 sstream 里定義的每種類型都是從
iostream 頭文件中定義的相關類型派生而來。
wchar_t、wiostream。。。
IO流不允許賦值或者復制
所以,
①函數形參和返回值不能是IO流對象,必須是引用,而且形參不能是const--因為讀寫都會改變狀態。
②只有支持復制的元
素類型可以存儲在 vector 或其他容器類型里。由於流對象不能復制,因此不能
存儲在 vector (或其他)容器中 (即不存在存儲流對象的 vector 或其他容器)。
所有的流對象,都包含一個條件狀態成員,該成員由setstate 和clear 操作管理。該成員類型為iostate 。另外有三個常量,代表三種狀態,可進行位操作。badbit、failbit、eofbit。
流的狀態檢查操作則有:bad、fail、eof、good。如果bad、fail、eof中任一個返回true,則流處於錯誤狀態。否則good操作返回true。
clear和setstate操作用於改變條件成員的狀態。clear會重設為有效狀態。setstate用於打開某個條件,用於表示某個問題的發生。setstate會保留其他狀態。
IO緩沖區:
每個io流對象都管理一個緩沖區!用於存儲程序讀寫的數據。
除了自動刷新緩沖區之外,還可以手動刷新緩沖區:endl、flush、ends。
另外,如果想讓io流刷新輸出每次讀寫的數據,可以使用
unitbuf 。
cout<<
unitbuf<<"first"<<" second"<<
nounitbuf ; //相當於cout<<"first"<<
flush<<"second"<<
flush ;
警告:如果程序崩潰了,則
不會刷新緩沖區!! 這個特性可以用來查找錯誤,只能是在最后輸出語句的后面。
----------------------------------
當輸入流和輸出流
綁到一起時,任何讀輸入流的嘗試,都將
刷新其輸出流關聯的緩沖區。
標准庫將cout和cin綁定到一起,所以,任何cin語句,都會導致cout緩沖區的刷新。
注意:
只是刷新!沒有傳遞數據!!!且一個對象只能綁定一個對象。
交互式系統通常應確保它們的輸入和輸出流是綁在一起的。這樣可以保證任何輸出都是在試圖讀之前進行。
cin.tie(0); //斷開默認的tie(默認cin.tie(&cout)) cin.tie(&cerr); //重新綁定
----------------------------------
文件操作:
fstream 類型除了繼承下來的行為外,還定義了兩個自己的新操作—— open 和 close,以及形參為要打開的文件名的構造函數。
需要讀寫文件時,則必須定義自己的對象,並將它們綁定在需要的文件上。
假設 ifile 和 ofile 是存儲希望讀寫的文件名的 strings 對象,可如下編寫代碼:
// construct an ifstream and bind it to the file named ifile ifstream infile(ifile.c_str()); // ofstream output file object to write file named ofile ofstream outfile(ofile.c_str());
也可以如下編寫代碼:
ifstream infile;
ofstream outfile;
infile.open(ifile.c_str());
outfile.open(ofile.c_str());
為了實現讀寫,需要將指定的文件
打開並
定位,
open 函數完成系統指定的所有需要的操作。
打開文件后,檢查是否正確打開是個好習慣:
if(!infile)...//如果沒打開。
注意:歷史原因,只能使用C風格字符串作為文件名。
#include <iostream> #include <string> using namespace std; int main(){ cout<<"endl!"<<endl; cout<<"flush!"<<flush;// cout<<"null-terminated ends!"<<ends; cout<<"\r\n"; //一次性刷新所有輸出 cout<<unitbuf<<"first"<<" second"<<nounitbuf; //cout<<"first"<<flush<<"second"<<flush; cout<<"\r\n"; ///=---------------------- ostream *old_tie = cin.tie(); cout<<"old_tie:"<<old_tie<<endl; cin.tie(0); cin.tie(&cerr); //why &? cerr.tie(0); cerr.tie(&cout); string str; cin>>str; cerr<<"hehe";//如何不刷新? cerr<<"hehe";//如何不刷新? cin>>str;//再來一次 cerr<<str; cout<<str; return 0; }
#include <iostream> #include <fstream> #include <string> using namespace std; int main(){ string infile="abc"; string outfile="abc"; ifstream in(infile.c_str()); ofstream out(outfile.c_str()); if(!in){ cerr<<"Error: unable to open file:"<<infile<<endl; return -1; } if(!out){ cerr<<"Error: unable to open file:"<<outfile<<endl; return -1; } return 0; }
//這個代碼有問題,忽略吧 #include <iostream> #include <string> #include <stdexcept> using namespace std; void run1(); void run2(); istream &getistream(istream &in); int main(){ run1(); // run2(); // // getistream(cin);//注意,io流不可復制或賦值。 // if(cin){ // cout<<"OK!"<<endl; // }else{ // cout<<"sth is wrong"<<endl; // if(cin.eof()){ // cout<<"eof was not cleared!"<<endl; // } // if(cin.bad()){ // cout<<"bad was not cleared!"<<endl; // } // if(cin.fail()){ // cout<<"fail was not cleared!"<<endl; // } // return -1; // } return 0; } void run1(){ int val; while(cin>>val, !cin.eof()){//有輸入,不是結尾,就繼續 。逗號運算符,返回右邊的結果 if(cin.bad()){ cout<<"input stream damaged!"<<endl; throw runtime_error("IO stream corrupted"); } if(cin.fail()){ cerr<<"bad input!"<<endl; // cin.clear(istream::failbit);// // cin.clear(); // cin.clear(istream::goodbit); cin.clear(istream::failbit); cin.clear(istream::badbit); cin.clear(istream::eofbit); // cin.clear();//why this does not work? // cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); cout<<"try again.."<<endl; continue; } cout<<val<<endl; } } void run2(){ string str; cout<<"type sth .."<<endl; cin>>str; iostream::iostate old_state= cin.rdstate();// cout<<old_state<<endl; cin.clear();//what? //... cin.clear(old_state);//清除舊狀態,而非設置舊狀態!設置應該是setstate。這里書上弄錯了吧。 } istream &getistream(istream &in){ // iostream::iostate old_state = in.rdstate(); cout<<"type sth.."<<endl; string str; while(in>>str, !in.eof()){ // if( in.fail() || in.bad()){ cerr<<"fail or bad"; in.clear(); continue; } cout<<"you typed: "<<str<<endl; } // in.setstate(old_state); // in.clear(old_state);//for what? in.clear();//恢復正常 return in; }
#include <iostream> #include <fstream> #include <string> #include <vector> using namespace std; ifstream &openfile(ifstream &in, string &filename); ofstream &savefile(ofstream &out, string filename); //復制文件練習 int main(){ string filename="e:/DbUtil.java"; string filename2="e:/DbUtil1.java"; ifstream in; ofstream out; openfile(in, filename); savefile(out,filename2); string line; while(getline(in, line)){ out<<line<<endl; } in.close(); out.close(); return 0; } ifstream &openfile(ifstream &in, string &filename){ in.close(); in.clear(); in.open(filename.c_str()); return in; } ofstream &savefile(ofstream &out, string filename){ out.close(); out.clear(); out.open(filename.c_str(),ofstream::app); return out; }
----------------------------------
打開文件需要指定打開的mode,這是文件自身的屬性!
mode:in、out、app、ate、trunc、binary。
單純以out打開,會丟失所有內容。類似out|trunc。
fstream對象默認以in|out模式打開,不清空!!!
fstream inOut("xxx", fstream::in | fstream::out);
ate是個什么鬼?app會在每次寫操作之前都把寫指針置於文件末尾,而ate模式則只在打開時才將寫指針置於文件末尾。ate模式在文件操作過程中,可以通過seekp等操作移動指針位置。
------------------------------------------------
sstream,用於從內存中的字符串讀取數據,或,向內存中的字符串寫入數據!
也可以用於
格式轉換!!!其實就是通過特定類型的
變量來接收!
#include <iostream> #include <fstream> #include <sstream> #include <string> #include <vector> using namespace std; ifstream &openfile(ifstream &in, string &filename); int main(){ string filename="e:/DbUtil.java"; ifstream in; openfile(in, filename); string line, word; while(getline(in, line)){ istringstream strin(line); ostringstream strout(line); while(strin>>word){ strout<<word<<endl;//輸出到string了,看不到 cout<<word<<endl;//輸出string到控制台 } } in.close(); in.clear(); return 0; } ifstream &openfile(ifstream &in, string &filename){ in.close(); in.clear(); in.open(filename.c_str()); return in; }
#include <iostream> #include <fstream> #include <sstream> #include <string> #include <vector> using namespace std; //字符串格式轉換 int main(){ int val1=100,val2=500; string line, word; ostringstream out; out<<"val1: "<<val1<<"\n" <<"val2: "<<val2<<"\n"; cout<<out.str()<<endl; string dump; istringstream in(out.str()); in>>dump>>val1>>dump >>dump>>val2>>dump; cout<<val1<<"--"<<val2<<endl; return 0; }
注意:
i或o是相對內存來說的。將內容讀入內存,是in;將內存中的內容輸出,是out。
參考: