天天看點

《C++程式設計教程(第3版)》——第3章,第3節cin輸入流

本節書摘來自華章出版社《c++程式設計教程(第3版)》一書中的第3章,第3.3節cin輸入流,作者張志航,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視

3.3 cin輸入流

與cout輸出流對應的是cin輸入流,使用cin輸入流可以友善地從鍵盤輸入資料至記憶體中正在運作的程式。

在程式執行期間,使用cin來給變量輸入資料,其一般格式為:

cin >> <變量名1> [ >> <變量名2> >> … >> <變量名n> ]

其中,運算符“>>”用來從作業系統的輸入緩沖區中提取字元,然後送到程式的記憶體變量中。在c++中這種輸入操作稱為“提取”(extracting)或“得到”(getting),是以運算符“>>”通常稱為提取運算符,表示将暫停程式的執行,等待使用者從鍵盤上輸入相應的資料。

輸入流的使用方法記憶起來非常簡單,可以将cin想象成鍵盤,提取運算符“>>”想象成指向箭頭。由于“箭頭”是從cin“指向”記憶體變量的,是以代表了從鍵盤獲得資料,傳入到記憶體變量中。

與插入運算符“<<”類似,在c++中,運算符“>>”具有多種功能,它除了可以做輸入流的提取運算符之外,還可以作為位運算的右移運算符來使用。但是,當它和cin辨別符連用時,它隻能作為提取運算符來使用。這同樣是利用了面向對象程式設計技術中的運算符重載技術,具體的細節将在後面的有關運算符重載部分加以詳細說明。

根據上面的格式說明,在每個提取運算符後面隻能跟一個變量名,但“>> <變量名>”的組合可以重複多次。即在cin後面使用一次“>> <變量名>”可以給一個變量輸入資料,在cin後邊重複使用多次“>> <變量名>”可以一次給多個變量輸入資料。例如,假設有變量聲明:

`int a, b;

float c, d;

char e, f;`

在程式執行期間,要求把從鍵盤上輸入的資料送給以上6個變量時,可以用cin按照如下方式來實作:

`cin >> a >> b; // a

cin >> c >> d; // b

cin >> e >> f; // c`

當執行到a行語句時,因為有資料流提取運算符“>>”存在,程式停止運作,等待使用者從鍵盤上輸入資料。假設這時使用者輸入:

100 200

則輸入流操作符會根據順序和變量的類型将100賦給整型變量a,将200賦給整型變量b。其中,表示Enter鍵。在使用cin接收數值資料時(包括整型資料和實型資料),為了區分排列在一起的若幹個資料,需要在相鄰的資料之間加入分隔符。這裡的“分隔符”在c++中具有特定的含義,主要包含3種:(空格鍵)、(tab鍵)和< enter>(Enter鍵)。一般在輸入的數值資料之間用一個或多個分隔符隔開,系統在進行處理時,會将相鄰的多個分隔符視為一個來進行處理。

由于3種分隔符在作用上是等價的,是以使用者可以任選一種分隔符來輸入數值資料。輸入的方式也就跟着變化了,上面使用者的輸入方式也可以改為如下方式:

100

200

或者

目前面的程式執行到b行時,又開始了一個新的輸入流操作,又重新開始等待使用者從鍵盤上輸入資料。隻不過這時提取操作符後面的變量類型變成了實型資料類型。假設使用者輸入:

3.141593 77

則将3.141 593賦給了實型變量c,将77.0賦給了實型變量d(資料類型以變量的類型為準)。提取資料的方法和原理與a行完全相同。

在數值資料被分隔符區分以後,如果要使得計算機接收資料,在每行資料輸入完畢後還要輸入Enter鍵加以确認。在每行末尾輸入Enter鍵的作用是:

1)告訴cin一批資料已經輸入完畢,cin開始提取使用者輸入的資料(忽略分隔符),并依次将所提取的資料指派給cin中所列舉的變量中尚未獲得資料的變量。

2)在螢幕上顯示光标換行,為下一行的輸入或者顯示程式的輸出結果做好準備,起到輸入資料之間以及輸入資料與輸出結果之間的分隔符的作用。

當cin遇到Enter鍵時,如果使用者輸入的資料與輸入語句中等待獲得數值的變量的個數不等,會出現兩種情況的處理:

1)使用者輸入的資料的個數小于變量的個數。則此時在提取完輸入的有效資料後仍有變量沒有獲得數值,目前的輸入語句不會結束,會繼續等待使用者輸入新的一批資料。當使用者繼續輸入資料并且按Enter鍵确認輸入後,cin輸入語句會繼續提取新的輸入行中的數值給尚未獲得數值的變量,直到目前輸入語句中的所有變量都獲得了具體的數值為止。在上面的例子中,直到使用者輸入了兩個數值100和200,a行的a變量和b變量分别獲得數值後,a行才執行結束。否則程式将會一直等待使用者繼續輸入數值。

2)使用者輸入的資料個數大于變量的個數。則輸入語句隻依次提取輸入行中的部分數值給變量。而多餘的數值會被下一條cin輸入語句中的變量所提取,或者在沒有後續的輸入語句的情況下被程式舍棄。

假設在執行a行時,使用者輸入:

100 200 3.141593 77

a行的cin會将輸入行中的100和200分别賦給變量a和b,這時a行中的兩個整型變量都獲得了有效的資料,a行執行完畢;接着執行b行,因為使用者輸入行中的資料沒有被a行提取完,于是b行接着提取,把使用者輸入行的後兩個資料3.141 593和77.0分别賦給實型變量c和d。根據上面的例子可以總結出:在輸入數值資料時,隻要按照分隔符和行末回車符的規則來輸入,可以将4個輸入資料在一行内輸入、在兩行内輸入,或者分多行輸入。

如果使用者輸入的一行僅僅是一個Enter鍵,則cin把該鍵作為分隔符來處理(将其忽略),而不是行末回車符。這時沒有資料輸送給變量,隻是在螢幕上顯示光标換行。程式會繼續等待使用者輸入資料,直到使用者輸入有效資料為止。

在cin輸入流的使用過程中,程式員不需要指定輸入的資料類型,輸入資料的類型由cin根據變量的類型來自動判定。是以,從鍵盤上輸入資料的個數、類型及順序必須與cin中列舉的變量一一對應。若輸入的類型不對,則輸入的資料不正确。例如:

`int a, b;

cin >> a >> b;`

執行cin時,若輸入字元資料:

d f

則由于使用者輸入的資料是字元類型,而對應的接收變量是整數類型,兩者類型不比對,變量a得不到有效值,其值為0。而由于前面已經出現錯誤,cin語句停止執行,則後續的變量b無法繼續獲得數值,其值為一個随機數。同時,錯誤會繼續向後延伸,造成後續的cin語句也不能正确提取資料。

再如:

`int a;

float b;

cin >> b >> a;

執行cin時,若輸入:

300 1.234 `

則根據第2章學習的内容,實型b變量進行資料類型轉換,将整數300轉換為實數300.0,最終獲得300.0的數值,影響不大。而整型變量a也同樣進行資料類型轉換,将小數1.234轉換為整數1,小數部分被丢棄。這樣可能會造成後續的、有變量a參與計算的計算結果産生極大偏差。

上面我們以數值資料的輸入為例,介紹了cin輸入流的基本使用方法。在輸入整型資料時,除了标準的輸入方法以外,還有一些其他格式的輸入方法,并且字元資料輸入的寫法也與數值資料輸入的寫法不同,下面我們就這些不同點分别加以具體的說明。

3.3.1 輸入十六進制或者八進制資料

與前面提到的cout中的處理類似,對于整型變量,從鍵盤上輸入的資料預設為十進制。除此以外,還可以按照八進制或者十六進制來輸入資料。如前面例子中所示,在預設的情況下,系統規定輸入的整數都是十進制資料。當要求按照八進制或者十六進制輸入資料時,必須在cin中指明相應的資料類型:hex表示十六進制,oct表示八進制,dec表示十進制。具體應用如例3.6所示。

例3.6 示範不同進制的輸入輸出流使用方法。

`include

using namespace std;

int main()

{

}`

當執行到語句cin時,若輸入的資料為:

20 21 22 23

則根據程式的進制設定,将第一個數20作為十六進制數指派給變量a,将第二個數21和第三個數22作為八進制數分别指派給變量b和c,将第四個數23作為十進制數指派給變量d。無論将整數按照什麼進制輸入變量,在變量中都是按照二進制數的方式存放的。在輸出的時候如果不加特别說明,系統會預設按照十進制的方式進行輸出。在例3.6中針對上述輸入的輸出結果為:

32, 17, 18, 23

其中,十進制的32對應的是十六進制的20;十進制的17和18對應的是八進制的21和22;最後一個變量原來就是按照十進制形式輸入的,是以輸出依然是23,沒有變化。

在c++中,整數常量和變量都可以表現為十六進制和八進制的形式。無論按照哪種進制表現的整數其本質都是以二進制補碼形式存儲的,都可以混合運算。在某些特殊的運算中(如位運算等),直接使用十六進制或八進制資料進行運算可以得到更加清晰的結果。要做到直接使用十六進制或八進制資料進行輸入,必須在cin中指明輸入資料時所用的數制。

使用非十進制輸入資料時,要注意以下幾點。

1)八進制或十六進制數的輸入隻能适用于整型變量,不适用于字元型變量、實型變量。

2)當在cin中指明使用的輸入數制後,則所指明的數制一直有效,直到在下一個cin語句中指明采用不同的輸入數制時為止。例如在例3.6中,輸入變量c的值時,雖然沒有再次指定按照八進制輸入,但程式仍然會按照八進制進行輸入。

3)使用者從鍵盤輸入資料的格式、個數和類型必須與cin中所列舉的變量類型一一對應。一旦輸入出錯,不僅使目前的輸入資料不正确,而且使得後面的提取資料也不正确。具體的例子請參考上面對輸入流基本操作的介紹。

使用輸入流輸入資料時,如果出現輸入錯誤,可以通過相關函數來檢測錯誤,并且可以根據具體的錯誤進行相應的處理,具體操作将在第14章進行詳細的介紹。

3.3.2 輸入字元資料

當要為字元變量輸入資料時,輸入的資料必須是字元型資料。此時cin的格式及用法與輸入十進制整數和實數時是相同的。設有如下程式片段:

`char c1, c2, c3, c4;

cin >> c1 >> c2 >> c3;`

當執行cin語句時,cin等待使用者從鍵盤上輸入資料。如果輸入:

a b c

則cin分别将字元a、b、c指派給字元型變量c1、c2、c3,如果輸入:

abc

cin也同樣分别将字元a、b、c指派給字元型變量c1、c2、c3,即字元之間是否有分隔符都一樣。在預設的情況下,cin會自動過濾輸入的空格等分隔符(參考輸入流基本功能介紹中的分隔符概念),輸入流cin不會将輸入的空格和Enter鍵等分隔符賦給字元型變量。

在使用輸入流輸入字元資料時,最容易出現的錯誤是将數字與字元資料混淆,如例3.7所示。

例3.7 示範輸入輸出流的字元輸入方法。

假設使用者輸入如下資料:

12 34 5678

則由于變量a和變量b是整數類型,輸入流cin會根據分隔符的辨別,将12指派給變量a,将34指派給變量b。接下來就是給字元類型變量c和變量d指派了。根據第2章學習的知識,我們知道一個字元占用一位元組的空間,一個字元變量存放一個字元。是以,雖然5678是連寫在一起的數字,但是輸入流不會将它們當成一個整體指派給字元變量,而是将它們看成4個連續的字元。'5'字元将被指派給變量c,'6'字元将被指派給變量d,而剩餘的'7'字元和'8'字元由于沒有對應的變量接收,将被舍棄。

在進行字元輸入時,不但可以按照順序輸入字元,還可以對輸入的内容有選擇地接收,這時就要用到函數cin.ignore()了。cin.ignore()的作用是在字元讀取過程中忽略若幹個字元,而讀取後面的字元。其格式為:

cin.ignore( <忽略的字元個數> );

例如将例3.7中程式的輸入修改如下:

`cin >> a >> b;

cin.ignore(3);

cin >> c >> d;`

同樣輸入如下資料:

但這時的輸出結果卻變化如下:

12, 34, 7, 8

可以看出,cin.ignore(3)語句讓程式忽略了整數34後面的3個字元(包括空格符),而直接從第四個字元讀起。将'7'字元指派給了變量c,将'8'字元指派給了變量d。

前面提到,輸入流cin不會将輸入的空格和Enter鍵等分隔符賦給字元型變量。由于分隔符也是有效字元,那麼當使用者想要将3種分隔符作為字元輸入計算機時,如何實作呢?借助函數cin.get()可以實作上述的要求。函數cin.get()的作用是把從鍵盤上輸入的每一個字元,包括空格符和回車符等分隔符都作為一個輸入字元賦給字元型變量。其格式為:

cin.get( <字元型變量> );

函數cin.get()從輸入行中取出一個字元,并将它指派給對應的字元型變量。該語句一次隻能從輸入行中提取一個字元。例如:

`char c5, c6, c7, c8;

cin.get(c5);

cin.get(c6);

cin.get(c7);

cin.get(c8);`

當程式執行第一行輸入語句時,如果使用者輸入:

a b

在輸入字元a前沒有空格,在字元a與b之間有一個空格,則根據前面的介紹,程式會将字元a、空格、字元b分别指派給變量c5、c6、c7;第四行語句中的c8變量也将獲得字元值,即回車字元。也就是對于cin.get()來說,使用者一共輸入了4個字元。若第四行使用語句:

cin >> c8;

代替cin.get(c8),則cin将回車作為确認符和分隔符處理,在螢幕上顯示光标換行,但并不會将回車符存入變量c8。這時由于變量c8尚未獲得有效值,程式會一直等待使用者繼續輸入一個有效字元。

繼續閱讀