使用getline和get方法讀取字符串


使用cin對象對C風格字符串執行輸入操作時存在一個缺陷,如下:

#include <iostream>
using namespace std;

int main()
{
    const int stringSize = 64;

    char string1[stringSize];
    char string2[stringSize];
    
// enter 1st string cout
<< "Enter first string: "; cin >> string1;
// enter 2nd string cout
<< "Enter second string: "; cin >> string2;
  // show the result of input cout
<< "The first string is " << "\"" << string1 << "\"" << ", the second string is " << "\"" << string2 << "\"" << endl;
  // pause
  system("pause");
return 0; }

一般情況下該程序應該可以正常完成工作:接收用戶輸入的兩段字符串(有長度限制),並一起進行輸出。

然而當用戶的輸入中包含空格等空白元素時,則會出現下述意料之外的狀況

Enter first string: test string1
Enter second string: The first string is "test", the second string is "string1"

 

解釋上面的運行情況之前,不妨先考慮一個問題,cin對象是如何確定已完成字符串輸入?由於C風格字符串使用空字符‘0’作為結尾,而這種空字符是無法通過鍵盤之間輸入的,因此cin需要借助別的方法來確定字符串的結尾位置。cin使用空白(空格,制表符,換行符)來確定字符串的結尾位置,這意味着cin在獲取字符數組輸入時只讀取一個單詞(或者說不內含空白的一段字符串)。讀取該單詞后,cin將該字符串放到數組中,並自動在結尾添加空字符。這樣一來也就能很好的解釋上面的情況了。


面向行的輸入

  每次讀取一個單詞通常不是最好的選擇,要將整條短語而不是一個單詞作為字符串輸入,需要采用另一種字符串讀取方法。具體的說,需要采用面向行而不是面向單詞的方法。幸運的是,istream中的類提供了一些面向行的類成員函數:getline()和get()。這兩個函數都讀取一行輸入,直到到達換行符。然而,隨后getline()將丟棄換行符,而get()將換行符保留在輸入序列中,下面詳細介紹它們,首先介紹getline()。

  • cin.getline()

  getline()函數讀取整行,它使用通過回車鍵輸入的換行符來確定輸入結尾。要調用這種方法,可以使用cin.getline()。該函數有兩個參數。第一個參數是用來存儲輸入行的數組的名稱,第二個參數是要讀取的字符數。如果這個參數為20,則函數最多讀取19個字符,余下的空間用於存儲自動在結尾處添加的空字符。getline()成員函數在讀取指定數目的字符或遇到換行符時停止讀取。

#include <iostream>
using namespace std;

int main()
{
    const int stringSize = 64;

    char string1[stringSize];
    char string2[stringSize];
    
    // enter 1st string
    cout << "Enter first string: ";
    //cin >> string1;
    cin.getline(string1, stringSize);

    // enter 2nd string
    cout << "Enter second string: ";
    //cin >> string2;
    cin.getline(string2, stringSize);

    // show the result of input
    cout << "The first string is " << "\"" << string1 << "\""
        << ", the second string is " << "\"" << string2 << "\"" << endl;

    // pause
    system("pause");
    return 0;
}

  運行結果:

  Enter first string: test string1
  Enter second string: test string2
  The first string is "test string1", the second string is "test string2"

  • cin.get()

  我們來試試另一種方法。istream類有另一個名為get()的成員函數,該函數有幾種變體。其中一種變體的工作方法與getline()類似,它們接受的參數相同,解釋參數的方式也相同,並且都讀取到行尾,但get()並不再讀取並丟棄換行符,而是將其留在輸入隊列中。假設我們連續兩次調用get():

  cin.get(string1, stringSize);

  cin.get(string2, stringSize);  // 將會出現問題

  由於第一次調用后,換行符將留在輸入隊列中,因此第二次調用時看到的第一個字符便是換行符,因此get()認為已經到達行尾,而沒有發現任何可讀取的內容。如果不借助幫助,get()將不能跨過該換行符。

  幸運的是,get()有另一種變體。使用不帶任何參數的cin.get()調用可讀取下一個字符(即使是換行符),因此可以用它來處理換行符,為讀取下一行輸入做好准備。也就是說,可以采用下面的調用序列:

  cin.get(string1, stringSize);  // 讀取第一行

  cin.get();               // 讀取換行符

  cin.get(string2, stringSize);  // 讀取第二行

  另一種使用get()的方式是將兩個類成員函數拼接起來(合並),如下所示:

  cin.get(string1, stringSize).get();

  之所以可以這樣做,是由於cin.get(string1, stringSize)返回一個cin對象,該對象隨后將被用來調用cin.get()函數。同樣,下面的語句將把輸入中連續的兩行分別讀入到數組string1和string2中,其效果與兩次調用cin.getline()相同:

  cin.getline(string1, stringSize).getline(string2, stringSize);

#include <iostream>
using namespace std;

int main()
{
    const int stringSize = 64;

    char string1[stringSize];
    char string2[stringSize];
    
    // enter 1st string
    cout << "Enter first string: ";
    //cin >> string1;
    cin.get(string1, stringSize).get();

    // enter 2nd string
    cout << "Enter second string: ";
    //cin >> string2;
    cin.get(string2, stringSize).get();

    // show the result of input
    cout << "The first string is " << "\"" << string1 << "\""
        << ", the second string is " << "\"" << string2 << "\"" << endl;

    // pause
    system("pause");
    return 0;
}

  運行結果:

  Enter first string: test string1
  Enter second string: test string2
  The first string is "test string1", the second string is "test string2"

 

  為什么要使用get(),而不是getline()呢?首先,老式實現中並沒有getline()。其次,get()使輸入更仔細。例如,假設用get()將一行讀入數組中。如何知道停止讀取的原因是由於已經讀取了整行,而不是由於數組已經被填滿?查看下一個輸入字符,如果是換行符,說明已讀取了整行;否則,說明該行中還有其他輸入。總之,getline()使用起來簡單一些,但get()使得檢查錯誤更簡單些。可以用其中的任何一個來讀取一行輸入;只是應該知道,它們的行為稍有不同。

 


免責聲明!

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



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