PAT甲級 字符串處理題_C++題解

字符串處理題

目錄

  • 《算法筆記》 重點摘要
  • 1001 A+B Format (20)
  • 1005 Spell It Right (20)
  • 1108 Finding Average (20)
  • 1132 Cut Integer (20)
  • 1140 Look-and-say Sequence

《算法筆記》 3.6 字符串處理 重點摘要

  1. 注意分析輸入輸出格式
  2. 注意細節和邊界狀況

1001 A+B Format (20)

#include<iostream>
using namespace std;
int main()
{
    int a, b, sum;
    cin >> a >> b;
    sum = a + b > 0 ? a + b : -(a + b); 
    if (a + b < 0) cout << "-";
    string s = to_string(sum);
    if (s.length() > 3){
        for (int i = s.length()-3; i > 0; i = i - 3) s.insert(i, ",");
        cout << s << endl;
    }
    else cout << sum << endl;
    return 0;
}
  • string.insert (pos, str); 在 pos 位置插入 str

1005 Spell It Right (20)

#include<iostream>
using namespace std;
int main()
{
    string words[10] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
    string N;
    cin >> N;
    int sum = 0;
    for (int i = 0; i < N.length(); i++) sum += stoi(N.substr(i,1));
    string s = to_string(sum);
    cout << words[stoi(s.substr(0,1))];
    for (int i = 1; i < s.length(); i++) cout << " " << words[stoi(s.substr(i,1))];
    return 0;
}
  • string 轉 int: stoi()
    • s[i] 是char,不符合參數要求,用 s.substr(i,1) 返回子串便可
  • int 轉 string: to_string()

1108 Finding Average (20)

題目思路

  • 將輸入先接收到字符串中
  • 依序檢查是否有非數字,注意負號和小數點合法,其餘非數字出現即不合法
  • 均爲數字後,檢查是否有小數點
    • 無小數點則爲整數
    • 有小數點要分別檢查是否有多個小數點(s.find_first_of('.') != s.find_last_of('.'))和小數位數是否超過2(s.length()-s.find('.') > 3)
  • 以上去掉格式不合法數字後,轉化爲double型,看是否在[-1000,1000]範圍內,不在亦不合法
  • 輸出時注意區分 0、1(number單數) 及其餘
#include<iostream>
using namespace std;
int main()
{
    int n, num = 0;
    cin >> n;
    string s;
    double data, sum = 0;
    for (int i = 0; i < n; i++){
        bool islegal = true;
        cin >> s;
        for (int j = 0; j < s.length(); j++){
            if ((s[j]>'9' || s[j]<'0') && s[j]!='-' && s[j]!='.'){
                cout << "ERROR: " << s << " is not a legal number\n";
                islegal = false;
                break;
            }
        }
        if (islegal){
            if (s.find('.') != string::npos){
                if(s.find_first_of('.') != s.find_last_of('.') || s.length()-s.find('.') > 3){
                    cout << "ERROR: " << s << " is not a legal number\n";
                    continue;
                }
            }
            data = stod(s);
            if (data >= -1000 && data <= 1000){
                sum += data;
                num++;
            }
            else cout << "ERROR: " << s << " is not a legal number\n";
        }
    }
    if (!num) cout << "The average of 0 numbers is Undefined";
    else if (num == 1) printf("The average of 1 number is %.2f", num, sum);
    else printf("The average of %d numbers is %.2f", num, sum/num);
    return 0;
}

二刷(參考柳婼小姐姐的代碼

#include<iostream>
#include<cstring>
using namespace std;
int main(){
    int n, k = 0;
    scanf("%d", &n);
    char s[50], t[50];
    double num, sum = 0.0;
    for (int i = 0; i < n; i++){
        scanf("%s", s);
        sscanf(s, "%lf", &num);
        sprintf(t, "%.2f", num);
        bool islegal = true;
        for (int j = 0; j < strlen(s); j++)
            if (s[j] != t[j]) islegal = false;
        if (islegal && num >= -1000 && num <= 1000){
            k++;
            sum += num;
        }
        else printf("ERROR: %s is not a legal number\n", s);
    }
    if (!k) printf("The average of 0 numbers is Undefined\n");
    else if (k == 1) printf("The average of 1 number is %.2f\n", sum);
    else printf("The average of %d numbers is %.2f\n", k, sum / k);
    return 0;
}
  • sscanf() – 從一個字符串中讀進與指定格式相符的數據
  • sprintf() – 字符串格式化命令,主要功能是把格式化的數據寫入某個字符串中

1132 Cut Integer (20)

#include<iostream>
using namespace std;
int main()
{
    int n, z;
    scanf("%d", &n);
    for (int i = 0; i < n; i++){
        scanf("%d", &z);
        string s = to_string(z);
        int len = s.length();
        int a = stoi(s.substr(0,len/2));
        int b = stoi(s.substr(len/2));
        printf("%s", !b || z % (a * b) ? "No\n" : "Yes\n");
    }
    return 0;
}
  • 注意 b 可能爲 0 致使 a*b 爲 0 發生取餘 0 狀況致使浮點錯誤
  • string.substr(pos) 可表示pos到end的子串ios

    string substr (size_t pos = 0, size_t len = npos) const;算法

浮點錯誤

  • 是否可能出現了一個數除以0的狀況
  • 是否可能出現了一個數取餘0的狀況
  • 是否發生了數據溢出而致使的除以0或者取餘0的狀況

1140 Look-and-say Sequence

題目思路

  • 依序遍歷當前字符串,若s[j] == s[j+1],將記錄s[j]數量的sum++;若不等,則說明s[j]爲一串相同數字的末尾,此時將s[j]的內容和其個數sum壓入新串next
  • 注意遍歷到串尾時,繼續檢查j+1會越界,因爲每一個s[j]的內容其實在上一次循環已經被檢查過,且上一次循環記錄的sum是這次循環對應值,可直接將串尾內容及sum壓入next串
#include<iostream>
using namespace std;
int main()
{
    int D, N;
    cin >> D >> N;
    string s = to_string(D);
    for (int i = 1; i < N; i++){
        string next;
        int sum = 1;
        for (int j = 0; j < s.length(); j++){
            if (j == s.length()-1){
                next.append(s.substr(j,1));
                next.append(to_string(sum));
                break;
            }
            if (s[j] == s[j+1]) sum++;
            else{
                next.append(s.substr(j,1));
                next.append(to_string(sum));
                sum = 1;
            }
        }
        s = next;
    }
    cout << s << endl;
    return 0;
}

二刷(參考柳婼小姐姐的代碼

  • 遍歷 s ,令 j 從當前位置 i 開始檢查 s[j] 是否等於 s[i]
  • 當 j 檢查到與 s[i] 不一樣或到串尾時會停在第一個不與 s[i] 相同的點 或是 串尾+1,那麼 j-i 即爲與 s[i] 相同的個數。
  • 將 s[i] 和個數 j-i 壓入新串
  • 令 i=j,即從與上一個 s[i] 不一樣點處繼續檢查。
#include<iostream>
using namespace std;
int main()
{
    string s;
        int n, j;
    cin >> s >> n;
    for (int k = 1; k < n; k++){
        string t;
        for (int i = 0; i < s.length(); i = j){
            for (j = i; j < s.length() && s[j] == s[i]; j++);
            t += s[i] + to_string(j - i);
        }
        s = t;
    }
    cout << s;
    return 0;
}
相關文章
相關標籤/搜索