字串是程式當中相當重要的議題,我們從 hello, world
就接觸到它,但我們始終用一種敷衍的態度點到為止。在變數型別中,提到字串其實就是字元陣列。如今我們學過陣列,終於可以好好的討論一下字串惹。
與陣列相似,C++ 的字喘也有傳統 C 風格與現代 C++ STL 兩種。雖然競賽實務上往往用 C++ STL 方便許多,但傳統 C-style string 的設計有許多巧思,值得了解。
C-style string#
既然字串是字元陣列,那就直接宣告來用看看吧:
#include <iostream>
using namespace std;
int main()
{
char str[] = "hello, world";
cout << str << '\n'
<< sizeof(str) << '\n';
return 0;
}
'\0'
這個特殊字元。這樣有何好處??我們在遍歷字串時就可以這麼寫:#include <iostream>
using namespace std;
int main()
{
char str[] = "hello, world";
for (int i = 0; str[i]; i++)
cout << str[i];
cout << '\n';
return 0;
}
這在字串長度為之時尤其方便,我們很快就會遇到惹。現在考慮我們接受字串的輸入,那麼問題就出現喇:字元陣列要宣告多長??如果是在解題,題目通常會說明最大長度,我們就宣告這麼長再加一(想一想為什麼),如果是在實務場合,可能就需要一些動態配置記憶體的技巧。
ptt 的 ID 長度上限為 \(12\), 我們可以寫出以下程式接受輸入:
#include <iostream>
using namespace std;
int main()
{
char id[12 + 1];
cin >> id;
for (int i = 0; i < sizeof(id); i++)
cout << id[i];
cout << '\n';
return 0;
}
我們使用最常見的陣列遍歷方法遍歷字串。但這個程式有點問題,試著輸入 ID 越短越好,會發現輸出可能怪怪的,原因是 C/C++ 宣告基本型別變數及陣列時不會初始化,電腦給我們的記憶體可能還留有上個程式的資料。正確的寫法應該是這樣:
#include <iostream>
using namespace std;
int main()
{
char id[12 + 1];
cin >> id;
for (int i = 0; i < sizeof(id) && id[i]; i++)
cout << id[i];
cout << '\n';
return 0;
}
現在你知道為什麼字串的結尾必須是 '\0'
惹。
'\0'
. 往後我們遇到 STL 容器的迭代器, .end()
扮演的角色就有異曲同工之妙。字串的操作#
由於字串就是字元陣列,而我們知道陣列不能直接複製、比較 …, 因此有函式庫 <cstring>
幫我們寫好這些功能,比如 strcpy()
用以複製、strcmp()
用以比較、strcat()
用以串接等等,這些函式都離不開指標,有興趣請自行研究,這裡就姑且略過不提惹。
std::string#
看完上面半篇暈惹嗎??還好 C++ STL 有提供 string 這玩意兒。基本上你可以把 std::string
之於 C-style string 對應到 std::vector<>
之於 C-style array. 也許有人好奇 std::string
為何少惹 <>
?? 原因是 std::string
其實是 std::basic_string<char>
. 實際用起來就是這麼簡單:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
s = "QQ";
cout << s << '\n';
cin >> s;
cout << s << '\n';
return 0;
}
別管什麼最大長度或動態配置記憶體惹,C++ 幫我們處理得好好的。std::string
亦可使用 []
取得某個字元,而我們可以用 .lrngth()
取得字串長度:
#include <iostream>
using namespace std;
int main()
{
string s;
cin >> s;
cout << s.length() << '\n';
for (int i = 0; i < s.length(); i++)
cout << s[i];
cout << '\n';
return 0;
}
字串的操作#
與 vector<>
類似,我們可以直接用 =
來複製字串、用 ==
來判斷兩字串是否相等,我們甚至可以用 +
來串接兩字串:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string a = "AAA", b = "BBB";
char c = 'c';
cout << a + b << '\n'
<< a + b + c << '\n'
<< a + "XXX" << '\n'
<< 'Y' + b << '\n';
return 0;
}
注意在 C++ 中 "..."
仍是 C-style string, 因此 "AAA" + "BBB"
是錯誤的。
注意到平常 cin
以空白分割輸入,如果輸入的字串可能包含空白,必須使用 getline(cin, s);
. 呼叫前須留意如果先前有使用過 cin
, 必須 cin.ignore();
.
Comments