C/C++ 中帶空格字符串輸入的一些小trick

今天在重溫 C++ 的時候發現自己存在的一些問題,特此記錄下來。

我們可以看一下下面這段代碼:

#include <iostream>
#include <cstdio>
#include <string>
#include <cctype>
using namespace std;
int main(int argc, char const *argv[])
{
    string s;
  cin >> s;
    int cnt[26]={0};//字母統計次數
    for(int i = 0; i < s.length(); i++){
        char c = s[i];
        if(isalpha(c)){
            cnt[toupper(c) - 'A'] ++;
        }
    }
    for(int i = 0; i < 26; i++){
        if(cnt[i] != 0){
            cout << char(i + 'A') << ": " << cnt[i] <<endl;
        }
    }
    return 0;
}

當我們輸入字符串 Hello World! 時,結果會是多少呢?

apple@localhost  ~/Desktop/cpp_code  g++ run.cpp -o run.out -std=c++11 -O2
apple@localhost  ~/Desktop/cpp_code  ./run.out
Hello World!
E: 1
H: 1
L: 2
O: 1

上面這段代碼並不能很好的統計字符串中每個英文字母在其中的出現頻率,我苦思冥想了許久,才發現了一個曾經忽略過的一個問題,cin 標準輸入字符串在遇到空格時候將會被截斷,而我們需要對輸入一個帶空格的字符串進行特殊處理,而使用 getline 可以完美的解決該問題。getline(std::cin, std::string) 在輸入回車符號時纔會被截斷,把上述代碼的輸入做一些調整就可以完美的解決問題。

ps: 這種方法是針對 string 類

#include <iostream>
#include <cstdio>
#include <string>
#include <cctype>
using namespace std;
int main(int argc, char const *argv[])
{
    string s;
    getline(cin, s);
    int cnt[26]={0};//字母統計次數
    for(int i = 0; i < s.length(); i++){
        char c = s[i];
        if(isalpha(c)){
            cnt[toupper(c) - 'A'] ++;
        }
    }
    for(int i = 0; i < 26; i++){
        if(cnt[i] != 0){
            cout << char(i + 'A') << ": " << cnt[i] <<endl;
        }
    }
    return 0;
}

當我們再次輸入字符串 Hello World! 時,結果又會是多少呢?

apple@localhost  ~/Desktop/cpp_code  g++ run.cpp -o run.out -std=c++11 -O2
apple@localhost  ~/Desktop/cpp_code  ./run.out
Hello World!
D: 1
E: 1
H: 1
L: 3
O: 2
R: 1
W: 1

這就很OK了!

除此之外,還有沒有其他方法可以輸入帶空格的字符串呢?

答案是有的,以下我將所有可能出現的情況一一列舉出來。

情景一:已知輸入的字符串序列

針對這種情況,我們可以直接在定義的時候輸入字符串序列即可,例如我們已知我們要輸入的字符串序列爲 Hello World! ,我們可以寫出如下定義:

str = "Hello World!";

情景二:輸入字符串序列未知,但是知道字符串序列的最大長度範圍

方法一:

按照上述所給的 getline 函數,我們可以通過如下調用方法:

cin.getline(str, len);

第一個參數 str 用來存儲輸入行的數組名稱,第二個參數是要讀取的字符數。

方法二:

我們可以使用字符數組的方式去解決這個問題,這個時候我們自然會想到 get 方法,調用方式如下:

cin.get(str, len);

和方法一一樣,兩者都是讀取一行輸入,直至換行符,而兩者的不同在於 getline 將換行符丟棄,而 get() 將換行符保留在輸入序列裏,於是我們會考慮如下改寫方式:

while((c=cin.get())!='\n')

而若是採用 C 語言函數庫中的辦法,我們又應該如何去表示呢?

方法三:

C語言中輸入一個字符串,我們首先想到的就是使用 scanf 函數,但 scanf 默認回車和空格是輸入不同組之間的間隔和結束符號,所以輸入帶空格,tab或者回車的字符串是不可以的,我們可以利用格式符 “%[]” 。它的作用爲掃描字符集合,調用方式如下:

scanf("%[^c]", str);

其中 “c” 是一個具體的字符常量(包括控制字符)。當輸入字符串時,字符 “c” 將被當作當前輸入的結束符。利用此格式符就可以由編程者自己指定一個輸入結束符。

方法四:

C語言中還有一種輸入字符串的方式,即使用 gets 函數。gets函數是以回車作爲結束符,調用方式如下:

char str[length]; 
gets(str);

其中 length 是字符串序列最大的長度範圍,是一個具體的數值。

情景三:輸入字符串序列未知,且字符串序列的最大長度範圍也未知

針對這種 string 類問題,這個時候我們只有採用 getline 函數去解決了,調用方式如下:

getline(cin, s);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章