C++:流類庫與輸入輸出


7.2.1 C++的輸入輸出流
ios:流基類(抽象類)
istream:通用輸入流類和其他輸入流的基類
ostream:通用輸出流類和其他輸出類的基類
iostream:通用輸入輸出流類和其他輸入輸出流類的基類(以下的派生類對象有cin、cout、cerr、clog)
ifstream:輸入文件流類
ofstream:輸出文件流類
fstream:輸入輸出文件流
istrstream:輸入字符串流類
ostrstream:輸出字符串流類
strstream:輸入輸出字符串類
iostream_withassign: 通用輸入輸出流類和其他輸入輸出流類iostream的的派生類

7.2.2 預定義的流對象
C++中包含幾個預定義的流對象,它們是標准輸入流對象cin、標准輸出流對象cout
、非緩沖型的標准出錯流對象ceer、緩沖型的標准出錯流對象clog

cin是istream的派生類istream_withassign的對象,它與標准輸入設備(通常是鍵盤)相聯系。
cout是ostream的派生類ostream_withassign的對象,它與標准輸出設備(通常是顯示器)相聯系。
ceer是ostream的派生類ostream_withassign的對象,它與標准錯誤輸入設備(通常是顯示器)相聯系。
clog是ostream的派生類ostream_withassign的對象,它與標准錯誤輸入設備(通常是顯示器)相聯系。


由於istream和ostream類都在頭文件iostream中聲明的,因此只要在程序中包含頭文件iostream.h,C++程序開始時這四個標准流對象的構造函數都被自動調用。


7.2.3 輸入輸出流的成員函數
(1)put函數
put函數用於輸出一個字符格式:cout.put(char ch)
例如:cout.put('A')===cout.put(65)===cout.put(25+40)

(2)get函數
get函數的功能與提取運算符>>類似,主要不同之處是get函數在讀入數據時可以包括空白字符,而后者不可以。
get函數的用於讀入一個字符,調用形式:cin.get()

(3)getline函數
getline函數用於從輸入流讀取n-1個字符,賦給指定的字符數組(或字符指針指向的數組),然后插入一個字符串結束志"\n"。("\n"可以用其他字符代替)

getline函數格式:
cin.getline(字符數組,字符個數n,終止標志字符)

cin.getline(字符指針,字符個數n,終止標志字符)

(4)ignore函數
ignore函數的功能是跳過輸入流的n個字符(默認的個數為1),或在遇到指定的終止符時 提前結束。
調用格式:cin.ignore(n,終止字符)或cin.ignore()===cin.ignore(1,EOF)
*/

//例子1:put和get函數

#include<iostream>
using namespace std;
int main()
{
 char ch;
 cout<<"Input:";
 while(cin.get(ch))   //讀取輸入的字符,直到結束為止 
  {
   cout.put(ch);      //輸出字符 
  } 
  return 0;
}
/*
程序運行結果是:
 input:123 abc xyz
 123 abc xyz 
*/

 //例子2:getline函數

#include<iostream>
using namespace std;
int main()
{
 char ch[20];
 cout<<"輸入一行字符:"<<endl;
 cin.getline(ch,21,'t');
 cout<<ch<<endl;;
 return 0;
}
/*
程序運行結果是:
輸入一行字符:
shdfjsfefrsdfjt
shdfjsfefrsdfj 
*/
 

7.3.3 輸入輸出的格式控制

1.用流成員函數進行輸入輸出格式控制。
cppreference.com -> C++ I/O

C++ I/O
<iostream>庫自動定義了一些標准對象:

cout, ostream類的一個對象,可以將數據顯示在標准輸出設備上.
cerr, ostream類的另一個對象,它無緩沖地向標准錯誤輸出設備輸出數據.
clog, 類似cerr,但是它使用緩沖輸出.
cin, istream類的一個對象,它用於從標准輸入設備讀取數據.
<fstream>庫允許編程人員利用ifstream和ofstream類進行文件輸入和輸出.

一些C++ I/O流(精度,判斷等)的行為可以通過操作不同的標志來修改。

Constructors 構造器
bad() 如果出現錯誤則返回true
clear() 清除狀態標志
close() 關閉一個流
eof() 如果處於文件結尾處則返回true
fail() 如果出現錯誤則返回true
fill(char ch) 控制默認填充字符 //格式:char ios::fill(char ch) 調用格式:流對象.fill(ch)
flags() 操作flags
flush() 清空緩沖區
gcount() 返回讀取的最后一次輸入的字符數
get(char ch) 讀取字符
getline() 讀取一行字符
good() 如果沒有出現過錯誤則返回true
ignore() 讀取字符並忽略指定字符
open() 創建一個輸入流
peek() 檢查下一個輸入的字符
precision(int n) 設置精度 //格式:int ios::percision(int n) 調用格式:流對象.precision(n)
put(char ch) 寫字符
putback() 返回字符給一個流
rdstate() 返回流的狀態
read() 讀取字條符
seekg() 在一個輸入流中進行隨機訪問
seekp() 在一個輸出流中進行隨機訪問
setf() 設置格式標志 //格式:long ios::setf(long flags) 調用格式:流對象.setf(ios::狀態標志)
sync_with_stdio() 同標准I/O同步
tellg() 使用輸入流讀取流指針
tellp() 使用輸出流讀取流指針
unsetf() 清除格式標志 //格式:long ios::unsetf(long flags) 調用格式:流對象.unsetf(ios::狀態標志)
width(int n) 操作域寬度 //格式:int ios::width(int n) 調用格式:流對象.width(n)
write() 寫字符

//流成員函數使用方法舉例

#include<iostream>
using namespace std;
int main()
{
 cout<<"------------1----------\n";
 cout.width(10);                     //設置域寬為10
 cout<<123<<endl;                    //輸出整數123,占10位,默認為右對齊
 cout<<"------------2----------\n"; 
 cout<<123<<endl;                    //輸出整數123,上面的width(10)已經不起作用,此時按系統默認的域寬輸出
                                     //按數據實際長度輸出 
 cout<<"------------3----------\n";
 cout.fill('&');                     //設置填充字符為'&'
 cout.width(10);                     //設置域寬為10
 cout<<123<<endl;                    //輸出整數123,占10位,默認為右對齊,填充字符為'&'
 cout<<"------------4----------\n"; 
 cout.setf(ios::left);               //設置左對齊
 cout<<123<<endl;                    //輸出整數123,上面的width(10)已經不起作用,此時按系統默認的域寬輸出
                                     //按數據實際長度輸出
 cout<<"------------5----------\n"; 
 cout.precision(4);                  //設置實際的精度為4
 cout<<123.45678<<endl;              //以一般10進制形式輸出,有效數字為4
 cout<<"------------6----------\n"; 
 cout.setf(ios::fixed);              //用固定點格式(固定小數位數)顯示浮點數
 cout<<123.45678<<endl;              //以fixed形式輸出,小數位數為4
 cout<<"------------7----------\n"; 
 cout.width(15);                     //設置域寬是15
 cout.unsetf(ios::fixed);            //消除固定點格式(固定小數位數)顯示浮點數
 cout.setf(ios::scientific);         //用科學表示法格式(指數)顯示浮點數
 cout<<123.45678<<endl;              //用科學表示法格式(指數)顯示浮點數,小數點占4位
 cout<<"------------8----------\n";
 int a=21;
 cout.setf(ios::showbase);           //輸出整數時顯示基數符號
 cout.unsetf(ios::dec);              //終止10進制的格式設置
 cout.setf(ios::hex);                //設置以16進制輸出格式
 cout<<a<<endl;                      //以16進制輸出a 
 return 0;                                      
}
/*
程序運行結果是:
------------1----------                 
       123                               (域寬為10,默認為右對齊)
------------2----------
123                                      (按照數據實際長度輸出) 
------------3----------
&&&&&&&123                               (域寬為10,默認為右對齊,空白處用'&'填充) 
------------4----------
123                                      (按照數據實際長度輸出,左對齊) 
------------5----------
123.5                                    (以一般十進制形式輸出時,有效數字為4) 
------------6----------
123.4568                                 (以fixed形式輸出時,小數點占4位) 
------------7----------
1.2346e+02&&&&&                          (用指數格式輸出,域寬位10,小數占4位,用‘&’填充) 
------------8----------
0x15                                     (十六進制形式,以0x開頭) 
*/ 

2.使用預定義的操縱符進行輸入輸出格式控制

使用ios類中的成員函數進行輸入輸出格式控制時,每個函數的調用需要寫一條語句,而且
不能將它們直接嵌入到輸入輸出語句中去,顯然使用起來不方便。C++提供了一種進行輸入
輸出格式控制的方法,這一方法使用了一種稱之為操縱符(也稱之為操作和控制符)的特殊函
數。在很多情況下,使用操縱符進行格式化控制比用ios狀態標志和成員函數更方便。

所有不帶形參的操縱符都定義在頭文件iostream.h中,而帶形參的操縱符則定義在頭文件
iomanip.h,因而使用相應的操作符就必須包含相應的頭文件。

表7.4 C++預定義的操作符
//在頭文件iostream中:
dec 設置整數的基數為10 用於輸入/輸出
hex 設置整數的基數為16 用於輸入/輸出
oct 設置整數的基數為8 用於輸入/輸出
ws 跳過開頭的空白部分 用於輸入
endl 輸出一個換行符並刷新輸出流 用於輸出
ends 插入一個空字符null,通常結束字符串 用於輸出
flush 刷新一個輸出流 用於輸出

//在頭文件iomanip中:
setbase(n) 設置整數的基數(0、8、10、16(0默認為十進制)) 用於輸入/輸出
setfill(c) 設置c為填充字節,默認為空格 用於輸出
setprecision(n) 設置精度(一般十進制時,n為有效數字;有fixed時,n為小數位數) 用於輸出
setw(n) 設置域寬為n 用於輸出
setiosflags(f)設置由參數f指定的狀態標志 用於輸入/輸出
resetiosflags(f) 終止由參數f指定的狀態標志 用於輸入/輸出

操縱符setiosflags和resetiosflags要帶上狀態標志才能用。

表7.5 部分帶有狀態標志的操縱符setiosflags和resetiosflags
setiosflags(ios::left) 數據按域寬左對齊輸出
setiosflags(ios::right) 數據按域寬有對齊輸出
setiosflags(ios::fixed) 固定的小數點位數顯示
setiosflags(ios::scientific) 設置浮點數以科學表示法(即指數形式)顯示
setiosflags(ios::showbase) 在整數前加一個"+"號輸出
setiosflags(ios::uppercase) 在以科學表示法格式E和十六進制輸出字母時以大寫字母顯示
resetiosflags(f) 終止已經設置的狀態標志,在括號應指定f的內容。
//例7.5 預定義的操縱符的使用方法舉例

#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
 cout<<setw(10)<<123<<567<<endl;
 cout<<123<<setiosflags(ios::scientific)<<setiosflags(ios::uppercase)<<setw(20)<<123.456789<<endl;
 cout<<123<<setw(10)<<hex<<123<<endl;
 cout<<123<<setw(10)<<oct<<123<<endl;
 cout<<123<<setw(10)<<hex<<123<<endl;
 cout<<resetiosflags(ios::scientific)<<setprecision(4)<<123.456789<<endl;
 cout<<setiosflags(ios::left)<<setfill('#')<<setw(8)<<123<<endl;
 cout<<resetiosflags(ios::left)<<setfill('$')<<setw(8)<<456<<endl;
 return 0;
}
/*
程序運行結果是:
       123567
123        1.234568E+02
123        7B
7B       173
173        7B
123.5
7B######
$$$$$1C8 
*/ 

3. 使用用戶自定義的操縱符進行輸入輸出格式控制

若為輸出流定義操縱符函數,則定義格式如下:
ostream &操縱符名(ostream &stream)
{
      自定義代碼
      return stream;
}

若為輸入流定義操縱符函數,則定義格式如下:
istream &操縱符名(istream &stream)
{
      自定義代碼
      return stream;
}
stream可以用其它的標識符。

//例7.6 用戶自定義操縱符的使用辦法1

#include<iostream>
#include<iomanip>
using namespace std;
ostream &output(ostream &stream)
{
  stream.setf(ios::left);
  stream<<setw(10)<<hex<<setfill('&');
  return stream;
}
int main()
{
 cout<<123<<endl;
 cout<<output<<123<<endl;
 return 0;
}
/*
程序運行結果是:
123
7b&&&&&&&& 
*/

//例7.7 用戶自定義操縱符的使用辦法2 

#include<iostream>
#include<iomanip>
using namespace std;
istream &input(istream &in)
{
 in>>hex;
 cout<<"Enter number using hex formar:";
 return in;
}
int main()
{
 int i;
 cin>>input>>i;
 cout<<"hex:"<<hex<<i<<"------dec:"<<dec<<i<<endl;
 return 0;
}
/*
程序運行結果是:
Enter number using hex formar:23ae
hex:23ae------dec:9134
*/

7.3.1 插入運算符和提取運算符

cin>>變量; //輸入
cout<<常量或變量; //輸出

其實,在頭文件iostream中有兩組運算符函數分別對運算符">>"、"<<" 進行函數的重載。

也即: istream& operator>>(istream &類型名);
       ostream& operator>>(ostream &類型名);
       
       例如:
            當系統執行 cout<<"this a oby" 的操作時,就調用了插入運算符重載函數
             ostream& operator<<(ostream char*)
             cout.operator<<("this a oby") 

7.3.2 用戶自定義類的輸入輸出
1、重載(輸出運算符)插入運算符 <<

格式: ostream& operator<<(ostream &out, user_name &obj)
             {
              out<<obj.item1;  
              out<<obj.item2;
              out<<obj.item3;
              ......
              out<<obj.itemn; 
              return out;
             }
             
             user_name:用戶自定義的類名;
             out:ostream類對象的引用,即out是輸出流對象,out可以改變 
             item:用戶自定義類型中的數據成員。

2、重載(輸出運算符)插入運算符 >> 

 格式: istream& operator<<(istream &cin, user_name &obj)
             {
              cin<<obj.item1;
              cin<<obj.item2;
              cin<<obj.item3;
              ......
              cin<<obj.itemn; 
              return cin;
             }
             
             user_name:用戶自定義的類名;
             cin:ostream類對象的引用,即cin是輸出流對象,cin可以改變 
             item:用戶自定義類型中的數據成員。

//舉例

#include<iostream>
using namespace std;
class Coord{
  public:
    Coord(int i=0,int j=0)
    {
     x = i;
     y = j;
    }
    friend istream& operator>>(istream &input,Coord &ob);   //聲明提取運算符">>"的友元重載函數 
    friend ostream& operator<<(ostream &ouput,Coord &ob);   //聲明插入運算符"<<"的友元重載函數 
  private:
    int x,y;    
}; 
istream& operator>>(istream &input,Coord &ob)
{
  cout<<"輸入x、y的值:";
  input>>ob.x;
  input>>ob.y;
  return input;
}
ostream& operator<<(ostream &ouput,Coord &ob)
{
  cout<<"輸出x、y的值:";
  ouput<<ob.x<<","<<ob.y<<endl;
  return ouput;
}
int main()
{
 Coord a(55,66);
 cout<<a<<endl; //operator<<(cout,a) 
 
 cin>>a;        //operator>>(cin,a)
 cout<<a<<endl; 
 
 return 0; 
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM