本節書摘來自華章出版社《c++程式設計教程(第3版)》一書中的第3章,第3.2節cout輸出流,作者張志航,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視
3.2 cout輸出流
計算機的輸入輸出分為兩大類:标準輸入輸出和檔案輸入輸出。鍵盤是計算機的預設标準輸入裝置,顯示器是計算機的預設标準輸出裝置,是以在鍵盤和顯示器上的輸入輸出稱為标準輸入輸出。資料在磁盤上是以檔案為機關存放的,是以磁盤資料的輸入輸出稱為檔案輸入輸出。由于在一個系統中,鍵盤和顯示器一般都隻有一個,從鍵盤擷取資料,将結果顯示到顯示器上,是以操作起來比較簡單。而在磁盤通路中,往往需要同時對多個檔案進行操作,是以操作起來比較複雜。本章是c++學習的基礎,是以隻讨論簡單的标準輸入輸出的操作方法。
c++中沒有專門的輸入輸出語句,所有的輸入輸出操作都是通過輸入輸出流來實作的。在輸入輸出流中,輸入操作是通過流對象cin來實作的,而輸出操作是通過流對象cout來實作的。cin是由c和in兩個單詞組成的,代表c++的輸入流;cout是由c和out兩個單詞組成的,代表c++的輸出流。
由于cin和cout都是在頭檔案iostream中定義的,前面我們提到過,c++中任何系統提供的操作或者函數的使用都需要加入對應的頭檔案說明。是以,要使用c++提供的輸入輸出流技術時,必須在程式的開頭增加兩行說明,如下:
`include
using namespace std;`
即在程式中首先包含輸入輸出流的頭檔案iostream,同時說明c++标準程式庫被定義于一個名為std的namespace中。關于包含檔案的作用,在第6章将進行詳細介紹。下面舉例說明如何使用輸入輸出流技術來實作與例3.1完全相同的功能。
例3.2 示範基本的c++輸入輸出流的使用方法。
using namespace std;
int main()
{
}`
從上面的例子可以看出,使用輸入輸出流時不再需要對輸入和輸出的變量類型加以說明,系統會自動識别,這一點是利用面向對象的重載技術實作的,是對傳統的輸入輸出函數的重大改進。下面我們來具體介紹輸出流的基本使用方法。
使用cout輸出流可以友善地将記憶體中的資料顯示給使用者檢視。根據本章開始的介紹,在程式中輸出功能的重要性還要大于輸入功能,任何一個有實際用途的程式至少要有一個輸出來顯示計算結果。是以,在本節中将花較多的篇幅來介紹把字元、整數、實數及字元串等不同類型資料輸出到顯示器的基本方法。同樣,有關輸出流對象cout所能實作的詳細功能,将在第14章中進行介紹。
在程式執行期間,我們使用cout将變量中的資料或者字元串輸出到螢幕上或者檔案中,以便使用者檢視。其一般格式為:
cout << <表達式1> [ << <表達式2> << … << <表達式n> ]
其中,運算符“<<”用來将記憶體中的資料插入cout資料流中,然後輸出到标準輸出裝置顯示器上。在c++中這種輸出操作稱為“插入”(inserting),是以運算符“<<”也稱為插入運算符,它将緊跟其後的表達式的值插入cout資料流中,輸出到顯示器目前光标的位置。程式執行中如果遇到插入運算符,則将記憶體變量的值輸出,然後程式繼續向下運作。
輸出流的使用方法記憶起來也非常簡單,可以将cout想象成顯示器,插入運算符“<<”想象成指向箭頭。由于“箭頭”是從記憶體變量“指向”cout的,是以代表了将記憶體變量中的資料插入輸出裝置中。
在c++中,運算符“<<”具有多種功能,它除了可以做輸出流的插入運算符之外,還可以作為位運算的左移運算符來使用。但是,當它和cout關鍵字連用的時候,它隻能作為插入運算符來使用。這種同一個符号具有不同的使用含義的特性是c++對傳統的c語言的一種重要擴充,利用了面向對象程式設計技術中的運算符重載技術,具體的細節将在本書後面的有關運算符重載部分加以詳細說明。
根據上面的格式說明,在每個插入運算符後面可以跟一個表達式。在顯示資料時可以将變量值和字元串融合在一起,構造出直覺的答案。這樣,cout輸出流在使用中的變化就要比cin輸入流來得複雜,能夠實作的功能也要強大一些。同樣,“<< <表達式>”的組合可以重複多次,即在cout後面使用一次“<< <表達式>”可以輸出一個表達式的值,在cout後邊重複使用多次“<< <表達式>”可以一次輸出多個表達式的值,并且可以将多個變量的值與多個字元串組合在一起,構成複雜的輸出結果,如例3.3所示。
例3.3 示範使用輸出流技術的問答式程式。
在執行第一條cout語句時,在顯示器上顯示:
請輸入變量i的值:
即cout将雙引号中的字元串常量按其原樣輸出。接着執行cin語句,螢幕上的光标停留在冒号的後面,等待使用者輸入變量i的值。通常在程式設計中,在每一個cin語句之前,都會用一個cout語句給出提示資訊,指明使用者給什麼變量輸入資料,并且以什麼樣的數制輸入。這樣使用者面對的不再是孤零零的黑色螢幕,而是針對每一個提示輸入相關的資料,能夠降低出錯的機率。這種程式的編制方法稱為問答式程式界面。
下面再舉例說明輸出流cout對多變量的處理方法,如例3.4所示。
例3.4 示範使用輸出流技術的多變量輸出。
輸出結果為:
1020
3060
5.23100
以上每一個cout語句輸出一行,其中endl表示要輸出一個換行符,它是短語“end of line”的縮寫,它等同于轉義字元'n'。當用cout輸出多個資料時,預設情況下,是按每一個資料的實際長度輸出的,即在每一個輸出的資料之間不會自動加入分隔符。顯然,如果直接輸出資料,所有的資料将連接配接在一起,無法厘清哪一個變量的輸出值是多少。如第一行輸出1020,實際上是先輸出a的值10,再輸出b的值20。為了區分輸出的資料項,在每一個輸出資料之間要輸出分隔符。分隔符可以是空格、标點符号或者換行符等。如上面的輸出語句可改寫為:
`cout << a << ',' << b<< endl;
cout << c << ',' << n-d << endl;
cout << m << ',' << n << endl;`
則輸出結果為:
`10, 20
30, 60
5.23, 100`
還可以改寫成:
`cout <<"a=" << a << 't' <<"b=" << b << endl;
cout <<"c=" << c << 't' << n << "-" << d <<"=" << n-d << endl;
cout <<"m=" << m << 't' <<"n="<< n << endl;`
則執行這3個輸出語句後,輸出:
a=10 b=20
c=30 100-40=60
m=5.23 n=100
從上面的例子可以看出,在cout中輸出資料的格式并不是根據變量的類型确定的。例如,變量y是雙精度浮點數類型,按道理應該輸出一個小數格式的資料,但是輸出的資料卻是一個整數100。在輸出流cout中是根據變量的數值而不是根據變量的資料類型來決定輸出資料的格式的。同時,我們還要看到,一個清晰的輸出結果往往是由字元串、控制字元和變量值共同組成的。是以在使用輸出流cout時,一定要綜合使用多種控制技術,以便使用者能夠從輸出結果中輕松地獲得需要的資訊。
使輸出的資料項之間隔開的另一種辦法是使用setw()函數來指定輸出資料項的寬度。例如上面的3個輸出語句可以改寫為:
`cout << setw(10) << a << setw(10) << b << endl;
cout << setw(10) << c << setw(10) << n-d << endl;
cout << setw(10) << m << setw(10) << n << endl;`
其中,setw(10)指明其後的輸出項占用的字元寬度為10,即括号中的值指出緊跟其後的輸出項占用的字元位置個數,并且給定寬度大于實際資料位數時預設向右對齊,左側填充空格,填滿給定的寬度。setw是“set width”的縮寫。執行以上3個語句後的輸出為:
10 20
30 60
5.23 100
使用setw()函數應該注意以下4點。
1)setw()函數是定義在iomanip頭檔案中的系統函數,是以要使用它就必須在程式的開始位置包含頭檔案iomanip,即在程式的開頭增加:
include
2)括号中必須給出一個正整數或者數學表達式(值為正整數),它指明緊跟其後輸出的資料項的寬度。
3)該設定僅對其後的一個輸出項有效。一旦按指定的寬度輸出其後的輸出項後,程式又自動回到原來的按實際寬度輸出的預設輸出方式。
4)當設定了資料的輸出寬度後,如果資料的實際位數小于指定的寬度,則添加填充符(預設填充符為空格,且右對齊、左邊補空格)。如果資料的實際位數大于指定的寬度,則資料按照實際的寬度輸出,不會按照指定的寬度來截斷資料。
上面介紹了輸出流對象cout對于資料的通用處理方法。在cout中除了基本操作方法以外,還針對不同的資料設計了一些特殊的處理方法。下面分别按照數值型資料和字元型資料來對這些處理方法進行分類介紹。
3.2.1 輸出八進制數、十六進制數和用科學記數法表示的數
在cout中對于整型資料可以指定以十六進制或八進制輸出。對于實型資料可以指定以小數形式或者科學記數法形式輸出,如例3.5所示。
例3.5 示範使用輸出流技術按照特定的格式輸出數值資料。
執行該程式後,輸出:
`a=12 b=24
c=1e n-d=6.000000e+001
m=5.230000e+000
m=5.23 n=100`
在程式中,hex和oct這兩個辨別符用在輸出流cout中,分别代表了程式應該按照十六進制和八進制格式輸出資料。一旦在cout語句中指定了輸出的進制格式後,這種格式将一直有效,直到指定另外一種進制格式為止。
在程式中調用了兩個系統函數:cout.setf()和cout.unsetf()。其中,cout.setf()函數用來設定标志位ios::scientific,指定對實數按照科學記數法格式輸出,而cout.unsetf()用來取消标志位設定,終止對實數按照科學記數法格式輸出。與整數的特定進制格式輸出相同,一旦指定了按照科學記數法輸出實數,其後所有的實數都将按照科學記數法的格式輸出,直到取消科學記數法的輸出格式為止。關于cout.setf()函數和cout.unsetf()函數的使用原理,我們将在第14章中進行介紹。
在例3.5輸出的結果中,由于指定了按照八進制格式輸出變量a和b的值,是以将十進制數10輸出成八進制數12,将十進制數20輸出成八進制數24。随後指定将實數按照科學記數法格式輸出,由于變量c是整數,是以将十進制數30按照十六進制格式輸出成1e。由于變量n是實數,是以計算結果也是實數,按照科學記數法格式輸出成6.000 000 e+001。随後,按照科學記數法格式輸出變量m的值為5.230 000 e+000。取消了科學記數法格式,恢複了小數格式以後,輸出變量m和n的值分别為5.23和100。
3.2.2 輸出字元或字元串
輸出流對象cout除了能夠輸出正常可視的标準字元外,還可以輸出一些不可見的控制字元,這些字元就是第2章中所說的轉義字元。如下面的程式片段所示:
`char c='a',c1='b';
cout << "c=" << c << 't' << "c1=" << c1 << 'n';`
執行cout語句時,先輸出“c=”可視的标準字元串;接着輸出變量c的值;再輸出不可視的“橫向制表符”控制字元,跳到下一個tab位置;再輸出“c1=”可視的标準字元串;接着輸出變量c1的值;最後輸出一個不可視的“換行符”控制字元,表示以後的輸出從下一行開始。是以該行的輸出結果為:
c=a c1=b
在計算機字元界面中,一屏顯示界面可以顯示80×25個字元,即一屏顯示25行字元,每行最多80個字元。将螢幕位置按照8列為一個機關進行劃分,整個螢幕可以劃分為10個機關,每個機關就是我們所說的一個tab位置。當使用者按下鍵盤上的tab鍵時,光标會從目前的8列區間移動到下一個8列區間的第1列的位置。例如,目前光标處于螢幕的第3列屬于第一個區間,按下tab鍵,光标會移動到第9列,即第二個區間的第1列。如果光标處于第7列,因為同樣屬于第一個區間,按下tab鍵,光标還是會移動到第9列。同樣的道理,如果光标處于第12列,則按下tab鍵,會移動到第17列。以此類推,可以很容易地計算出輸出内容之間的間隔。例如,在上面的例子中兩個輸出變量之間的間隔為5個字元。
根據上例所示,使用第2章介紹的轉義字元的書寫方法,用cout可以輸出任何ascii碼的字元。