【C++】競程筆記:字串處理
【C++】競程筆記:字串處理
本筆記僅個人學習用途,斟酌參考。
額…我發現我的字串處理實在是太爛了,所以做這篇來挽救一下我的字串題目。
String 宣告方式
有四種:
1 | string s1; // 空字串 "" |
s1 什麼都沒寫,僅宣告的話就是空字串。
s2 賦值 "Hello" 字串,則表示 s2 初始化為 "Hello"。
s3(s2) 括號 s2 寫法就是 s3 複製 s2 的 "Hello"。
s4(5, 'A'),前面是次數,後面是字元,表示重複 5 次 'A'。
輸入方式
輸入字串的方式有一行一行讀跟整行讀。
一行一行讀就是 cin,整行讀就是 getline(cin, line)。
使用 getline(cin, line) 有個陷阱:
「如果前面已經有寫 cin >> s 的話,接下來又用 getline(cin, s),那麼 cin 留下的換行符號會被 getline 讀去,導致看起來像是『跳過了一次輸入』。」
這個解法就是在兩者之間加一行 cin.ignore() 來吃掉那個換行符號。
最後還有一個就是 cin.get(),可以讀所有字元,包含換行字元。
基本操作
取得長度
1 | string s = "Hello"; |
字串串接(+)
1 | string a = "Happy"; |
存取與修改字元
像陣列一樣使用 []。
1 | s[0] = 'h'; // 變成 "hello" (大小寫轉換常用, 只要更改第一個字元即可) |
比較
直接使用 ==, !=, <, > 等運算子(依照字典序比較)。
1 | if (s == "hello") { ... } |
核心功能
尋找 find()
找子字串或字元的位置。如果找不到,會回傳特殊常數 string::npos。
1 | string s = "Hello World"; |
擷取子字串 substr()
語法:s.substr(開始位置, 長度)
需注意:第二個參數是「長度」,不是結束位置。
1 | string s = "2023-12-25"; |
插入、刪除、取代
- 插入:
s.insert(位置, "字串"); - 刪除:
s.erase(開始位置, 長度); - 取代:
s.replace(開始位置, 長度, "新字串");
1 | string s = "I like C++"; |
型態轉換
數字轉字串
用 to_string()。
1 | int num = 123; |
字串轉數字
有四種方法:
- stoi():String to Integer
- stoll():String to Long Long
- stof():String to Float
- stod():String to Double
1 | string a = "123"; |
二進位字串轉整數:stoi(line, nullptr, 2),當中最後面的 2 參數是 line 的進位制。
搭配 <algorithm> 跟 <sstream>
字串反轉與排序
使用這些方法前需要引入 #include <algorithm>,而且要用 iterator:
- reverse():反轉元素。
- sort():排序
1 | string s = "dbca"; |
字串切割(stringstream)
需要引入 #include <sstream>。
當題目輸入是一整行字串,包含未知的空白數量,要把單字一個個切出來時,就可以用 sstream。
1 | string line = " This is a pen "; |
<cctype>
#include <cctype> 引入這個標頭檔。
這邊有幾個好用的函式可以用:
isalnum():判斷是否為英文字母跟數字。isalpha():判斷是否為英文字母。isspace():判斷是否有空白。isdigit():判斷是否為字母。islower():判斷是否為小寫字母。isupper():判斷是否為大寫字母。tolower():將字元轉成小寫字母。toupper():將字元轉成大寫字母。
練習題
ZJ d018. 字串讀取練習
Problem Source:https://zerojudge.tw/ShowProblem?problemid=d018
用 stringstream 讀取,至於有 : 的部分,可以先用 int pos = s.find(':') 找到字元的位置,然後再用 s.substr(pos + 1) 跟 s.substr(pos - 1) 分別擷取「序號」跟「實數」。
1 |
|
Uva 10082 - WERTYU
PDF Source:https://onlinejudge.org/external/100/10082.pdf
Uva Online Judge:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=1023
Zerojudge:https://zerojudge.tw/ShowProblem?problemid=c054
題目的意思是輸入的字元都是在 QWERTY 鍵盤上往右錯了一位的結果,然後需要將它往左移回一位。
解題思路:
- 建立對照表:鍵盤上的所有字元都存進一個字串。
- 尋找、替換:讀取輸入的每一個字元,在對照表中找到該字元的位置,然後輸出它左邊那一個字元。
- 特殊字元處理:空白字元(Space)不需要轉換,直接輸出。
範例程式碼:
1 |
|
LeetCode 125. Valid Palindrome
Problem Source:https://leetcode.com/problems/valid-palindrome/description/
迴文判斷。
解題思路:
觀察題目,會發現要將字元改小寫,再判斷迴文才可以。
建立 a 跟 b 字串,a 作為原字串,b 是反轉後的字串,要比較兩者是否相同。
針對字母字元跟數字字元這兩個加進去 a 裡面,之後可以用 reverse() 來反轉字串。
範例程式碼:
1 | class Solution { |
ZJ a065. 提款卡密碼
Problem Source:https://zerojudge.tw/ShowProblem?problemid=a065
懂 ASCII Code 就知道怎麼做。基本上就是字元 - 字元,會得到之間的差值,記得用 abs(),有可能會有負號。
範例程式碼:
1 |
|
Uva 494 - Kindergarten Counting Game
PDF Source:https://onlinejudge.org/external/4/494.pdf
Uva Online Judge:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=435
Zerojudge:https://zerojudge.tw/ShowProblem?problemid=a011
解題思路:運用 isalpha() 判斷是否為字母,並建立一個 bool inWord = false 判斷目前是不是一個單字,如果碰到非字母字元,則表示已經跳到下個字去了。
範例程式碼:
1 |
|
LeetCode 151. Reverse Words in a String
Problem Source:https://leetcode.com/problems/reverse-words-in-a-string/description/
解題思路:運用 stringstream,將每個單字推到 vector 裡面,之後用 for 從 vector 最右邊開始存取,並用 result 字串變數串接單字。
範例程式碼:
1 | class Solution { |





