訊息處理

簡易題敘

給你一串由大小寫英文字母、數字以及 # 、 @ 、 % 所組成的字串。在不改變英文字母順序的前提下,去除除了英文字母以外的字元,並讓大寫變小寫,然後分析每個字母分別出現幾次。

範例測資:

  • 輸入
10
Abc#def%%G
  • 輸出
abcdefg
1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

概念講解

首先,先宣告一個字串 s 儲存收到的訊息,一個正整數 n 來儲存字串 s 的長度。

  string s;
  int n;
  cin >> n >> s;

接著再宣告一個一維陣列 a 來儲存出現此字母的次數。

  int a[26] = {};

接著要使用到 for 迴圈來處理收到的訊息,在訊息中,只要處理介在 A 到 Z 和 a 到 z 之間的字元,所以在 for 迴圈中,要加上 if 判斷句判斷使否介在我們要處理的範圍中,若在處理的範圍中,那麼我們需要將此字元換成小寫的,如果收到的訊息是大寫的,那麼我們需要將此字元的編碼加上 32 就可以轉換成小寫的字元了! 那是因為 A 的代碼是 65 ,而 a 的代碼是 97,兩個相差 32
若我們偵測介在 A 到 Z 和 a 到 z 之間的字元,不但要換成小寫的,還需要紀錄出現了幾次,這邊我們就要用上上面宣告的 a 陣列了!
那麼,要怎麼計次呢? 要先觀察規律,我們 a 陣列宣告了 26 個格子,代表26個英文字母出現的次數,我們以大寫的英文字母舉例, A 在程式中的編碼為 65 ,而我們想要將 A 出現的次數存入編號 0 的格子中; B 在在程式中的編碼為 66 ,但我們想要將 B 出現的次數存入編號 1 的格子中,由上面的規律可以看出我們只要將偵測到的大寫英文字母的代碼扣除 65( A ),就可以紀錄正確的次數了!
並且直接輸出轉換完的代碼,字元結束之後記得換行

for(int i = 0;i < n;i++){
    if(s[i] >= 'A' && s[i] <= 'Z'){ // 若介在 A 和 Z 之間
      a[s[i] - 'A']++; // 將大寫的代碼扣除 A 的代碼
      cout << (char)(s[i]+32); // 將大寫的代碼加上 32 輸出
    }else if(s[i] >= 'a' && s[i] <= 'z'){ // 若介在 a 和 z 之間
      a[s[i] - 'a']++; // 將小寫的代碼扣除 a 的代碼
      cout << s[i]; // 將小寫的字元輸出
    }
  }
  cout<<endl;

最後,只要再使用一次 for 迴圈將字母出現的次數輸出即可,注意題目有說明最後行尾不能有空白,所以要加上一個判斷句判斷是否是最後一個

for(int i = 0;i < 26;i++){
    if(i == 25){ // 最後一格的編號為 25 
      cout << a[i] << endl;
    }else{
      cout << a[i] << " ";
    }
  }

範例程式碼

#include<iostream>
using namespace std;
int main(){
  string s;
  int n;
  int a[26] = {};
  cin >> n >> s;
  for(int i = 0;i < n;i++){
    if(s[i] >= 'A' && s[i] <= 'Z'){
      a[s[i] - 'A']++;
      cout << (char)(s[i]+32);
    }else if(s[i] >= 'a' && s[i] <= 'z'){
      a[s[i] - 'a']++;
      cout << s[i];
    }
  }
  cout<<endl;
  for(int i = 0;i < 26;i++){
    if(i == 25){
      cout << a[i] << endl;
    }else{
      cout << a[i] << " ";
    }
  }
}