注意:
輸出主要由重載的左移操作符(<<)來完成,輸入主要由重載的右移操作符(>>)完成。
>>a表示將資料放入a對象中。
<<a表示將a對象中儲存的資料拿出。
接下來我們繼續看一下C++風格的串流量控制,C++引入了ostringstream、istringstream、stringstream這三個類,要使用他們建立
對象就必須包含sstream.h標頭檔。
istringstream類用於執行C++風格的串流的輸入操作。
stringstream類同時可以支援C++風格的串流的輸入輸出操作。
strstream類同時可以支援C風格的串流的輸入輸出操作。
istringstream類是從istream(輸入資料流類)和stringstreambase(c++字串流基類)派生而來,ostringstream是從ostream(輸出
流類)和stringstreambase(c++字串流基類)派生而來,stringstream則是從iostream(輸入輸出資料流類)和和stringstreambase(
c++字串流基類)派生而來。
istringstream是由一個string物件建構而來,istringstream類從一個string對象讀取字元。
istringstream的建構函式原形如下:
istringstream::istringstream(string str);
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
istringstream istr;
istr.str("1 56.7");
//上述兩個過程可以簡單寫成 istringstream istr("1 56.7");
cout << istr.str()<<endl;
int a;
float b;
istr>>a;
cout<<a<<endl;
istr>>b;
cout<<b<<endl;
system("pause");
}
上例中,構造字串流的時候,空格會成為字串參數的內部分界,例子中對a,b對象的輸入"賦值"操作證明了這一點,字串的空
格成為了整型資料與浮點型資料的分解點,利用分界擷取的方法我們事實上完成了字串到整型對象與浮點型對象的拆分轉換過程
。
str()成員函數的使用可以讓istringstream對象返回一個string字串(例如本例中的輸出操作(cout<<istr.str();)。
ostringstream同樣是由一個string物件建構而來,ostringstream類向一個string插入字元。
ostringstream的建構函式原形如下:
ostringstream::ostringstream(string str);
範例程式碼如下:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main()
{
ostringstream ostr;
//ostr.str("abc");//如果構造的時候設定了字串參數,那麼增長操作的時候不會從結尾開始增加,而是修改原有資料,超出的部分
增長
ostr.put('d');
ostr.put('e');
ostr<<"fg";
string gstr = ostr.str();
cout<<gstr;
system("pause");
}
在上例代碼中,我們通過put()或者左移操作符可以不斷向ostr插入單個字元或者是字串,通過str()函數返回增長過後的完整字
符串資料,但值得注意的一點是,當構造的時候對象內已經存在字串資料的時候,那麼增長操作的時候不會從結尾開始增加,而是
修改原有資料,超出的部分增長。
對於stringstream了來說,不用我多說,大家也已經知道它是用於C++風格的字串的輸入輸出的。
stringstream的建構函式原形如下:
stringstream::stringstream(string str);
範例程式碼如下:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main()
{
stringstream ostr("ccc");
ostr.put('d');
ostr.put('e');
ostr<<"fg";
string gstr = ostr.str();
cout<<gstr<<endl;
char a;
ostr>>a;
cout<<a
system("pause");
}
除此而外,stringstream類的對象我們還常用它進行string與各種內建類型資料之間的轉換。
範例程式碼如下:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main()
{
stringstream sstr;
//--------int轉string-----------
int a=100;
string str;
sstr<<a;
sstr>>str;
cout<<str<<endl;
//--------string轉char[]--------
sstr.clear();//如果你想通過使用同一stringstream對象實現多種類型的轉換,請注意在每一次轉換之後都必須調用clear()
成員函數。
string name = "colinguan";
char cname[200];
sstr<<name;
sstr>>cname;
cout<<cname;
system("pause");
}
接下來我們來學習一下輸入/輸出的狀態標誌的相關知識,C++中負責的輸入/輸出的系統包括了關於每一個輸入/輸出操作的結果的
記錄資訊。這些當前的狀態資訊被包含在io_state類型的對象中。io_state是一個枚舉類型(就像open_mode一樣),以下便是它包
含的值。
goodbit 無錯誤
Eofbit 已到達檔案尾
failbit 非致命的輸入/輸出錯誤,可挽回
badbit 致命的輸入/輸出錯誤,無法挽回
有兩種方法可以獲得輸入/輸出的狀態資訊。一種方法是通過調用rdstate()函數,它將返回目前狀態的錯誤標記。例如,假如沒有
任何錯誤,則rdstate()會返回goodbit.
下例樣本,表示出了rdstate()的用法:
#include <iostream>
using namespace std;
int main()
{
int a;
cin>>a;
cout<<cin.rdstate()<<endl;
if(cin.rdstate() == ios::goodbit)
{
cout<<"輸入資料的類型正確,無錯誤!"<<endl;
}
if(cin.rdstate() == ios_base::failbit)
{
cout<<"輸入資料類型錯誤,非致命錯誤,可清除輸入緩衝區挽回!"<<endl;
}
system("pause");
}
另一種方法則是使用下面任何一個函數來檢測相應的輸入/輸出狀態:
bool bad();
bool eof();
bool fail();
bool good();
下例樣本,表示出了上面各成員函數的用法:
#include <iostream>
using namespace std;
int main()
{
int a;
cin>>a;
cout<<cin.rdstate()<<endl;
if(cin.good())
{
cout<<"輸入資料的類型正確,無錯誤!"<<endl;
}
if(cin.fail())
{
cout<<"輸入資料類型錯誤,非致命錯誤,可清除輸入緩衝區挽回!"<<endl;
}
system("pause");
}
如果錯誤發生,那麼流狀態既被標記為錯誤,你必須清除這些錯誤狀態,以使你的程式能正確適當地繼續運行。要清除錯誤狀
態,需使用clear()函數。此函數帶一個參數,它是你將要設為目前狀態的標誌值。,只要將ios::goodbit作為實參。
範例程式碼如下:
#include <iostream>
using namespace std;
int main()
{
int a;
cin>>a;
cout<<cin.rdstate()<<endl;
cin.clear(ios::goodbit);
cout<<cin.rdstate()<<endl;
system("pause");
}
通常當我們發現輸入有錯又需要改正的時候,使用clear()變更標記為正確後,同時也需要使用get()成員函數清除輸入緩衝區,以
達到重複輸入的目的。
範例程式碼如下:
#include <iostream>
using namespace std;
int main()
{
int a;
while(1) //也可以寫成for(;1;)
{
cin>>a;
if(!cin)//條件可改寫為cin.fail()
{
cout<<"輸入有錯!請重新輸入"<<endl;
cin.clear();
cin.get();
}
else
{
cout<<a;
break;
}
}
system("pause");
}
最後再給出一個對檔案流錯誤標記處理的例子,鞏固學習,代碼如下:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream myfile("c://1.txt",ios_base::in,0);
if(myfile.fail())
{
cout<<"檔案讀取失敗或指定檔案不存在!"<<endl;
}
else
{
char ch;
while(myfile.get(ch))
{
cout<<ch;
}
if(myfile.eof())
{
cout<<"檔案內容已經全部讀完"<<endl;
}
while(myfile.get(ch))
{
cout<<ch;
}
}
system("pause");
}