C++ STL 之 string

string 是 C++ 對數據結構字符動態數組的實現。要使用 string,請在程序頭添加:

#include <string>
using name space std;

string 對象的定義與初始化

string<int> s; 定義一個空 string 對象
string<int> s(3,'a'); s = “aaa”
string<int> s("aaa");
string<int> s1(s); s1 = s
string<int> s1 = s;
string<int> s { "abc" }; s = “abc”
string<int> s = { "abc" };
string<int> s = "abc";

高級 string 對象構造方法

string s(cp, n) 拷貝 cp 指向的數組中的前 n 個字符
string s(s1, pos) s 是 string s1 從下標 pos 開始的拷貝
string s(s1, pos, len) s 是 string s1 從下標 pos 開始的長度爲 len 的拷貝

substr操作
string s = s1.substr(pos, n) s 是 s1 從下標開始,長度爲 n 的拷貝。

向 string 對象添加元素

string 可以看做是一種專門用於存儲字符的 vector,因此與 vector 大部分的操作也類似。

使用 push_back 在 string 尾部插入元素

string s ("abc");
s.push_back('d'); // s = "abcd";

使用 insert 在 string 任意位置插入元素

插入單個元素

string s ("abc");
s.insert(s.begin(), 'd'); // s = "dabc";

插入一段元素

string s ("ab");
string s1 ("cd");
s1.insert(s1.begin(), s.begin(), s.end()); // s1 = "abcd";

在循環中插入元素
插入元素通常會使迭代器失效,這會給在循環中插入元素帶來不小的麻煩。insert 操作在插入元素成功後會返回插入位置的有效迭代器。

string s ("ab");
string s1 ("cd");
auto it = s1.begin();
for (auto c:s)
	auto it = s1.insert(it, c);
// s1 = "bacd";

刪除 string 中的一個元素

使用 pop_back 刪除 string 尾元素

string s ("abc");
s.pop_back(); // s = "ab";

使用 erase 刪除 string 中任意位置的元素

刪除一個元素

string s ("abc");
s.erase(s.begin()); // s = "bc";

刪除一段元素

string s ("abc");
s.erase(s.begin(), s.begin()+2); //  s = "c";

在循環中刪除元素
刪除元素通常會使迭代器失效,這會給在循環中刪除元素帶來不小的麻煩。erase 操作在插入元素成功後會返回插入位置的有效迭代器。

string s ("abcd");
auto it = s.beign();
while (it!=s.end()) {
	//刪除 c 之前的字母
	if (*it < 'c')
		auto it = s.erase(it);
	else
		it++;
	}
// s = "c";

訪問 string 中的元素

使用下標訪問

像數組一樣,string 支持下標隨機訪問

string s ("abcd");
cout << s[1]; // 輸出 b

使用迭代器進行訪問

string s ("abcd");
//將 s 中在 c 前面的字母置爲 c
for (auto it=s.begin(); it!=s.end(); it++) {
    if (*it < c)
    	*it = c;
}
// s = "cccd"

使用 C++ 11 新特性訪問

string s ("abcd");
//輸出 s 中在 c 之前的字母
for (auto e : s) {
    if (e < 'c') 
    	cout << e;
}
// 輸出:ab

注意:這種方式得到的 e 是 s 中元素的拷貝,若想要得到 s 元素的本身,請使用 &
for (auto &e:s)

string 搜索操作

string 類提供了 6 個不同的搜索函數。每個搜索函數都返回一個 string :: size_type 類型的值,表示匹配發生位置的下標。如果搜索失敗,則返回一個名爲 string :: npos 的 static 成員 (string :: size_type npos = -1,由於 string :: size_type 實際上就是 unsigned int 類型,故 npos == UINT_MAX)

s.find(c)s.find(s1)
在 s 搜索指定的字符 c 或者字符串 s1,返回第一個匹配位置的下標。

string s {"hello"};
cout << s.find('l'); // 輸出 2
cout << s.find("he");// 輸出 0
cout << s.find("eo");// 輸出 UINT_MAX

s.rfind(c)s.rfind(s1)
在 s 中搜索指定的字符 c 或者字符串 s1,返回最後一個匹配位置的下標。

s.find_first_of(c)s.find_first_of(s1)
在 s 中搜索指定的字符 c 或者字符串 s1 中的任何一個字符,返回第一個匹配位置的下標。

string s {"hello"};
cout << s.find_first_of('l'); // 輸出 2
cout << s.find_first_of("eo");// 輸出 1

s.find_last_of(c)s.find_last_of(s1)
在 s 中搜索指定的字符 c 或者字符串 s1 中的任何一個字符,返回最後一個匹配位置的下標。

s.find_first_not_of(c)s.find_first_not_of(s1)
在 s 中搜索不是字符 c 或者不在字符串 s1 中的字符,返回第一個匹配位置的下標。

string s {"hello"};
cout << s.find_first_not_of('h'); // 輸出 1
cout << s.find_first_not_of("heo");// 輸出 2

s.find_last_not_of(c)s.find_last_not_of(s1)
在 s 中搜索不是字符 c 或者不在字符串 s1 中的字符,返回最後一個匹配位置的下標。

指定開始搜索的位置

上述 string 的 6 個搜索函數都有一個帶有指定開始加搜索位置的參數的重載版本。如:
s.find(c, string::size_type pos)

數值轉換

將其他類型的值轉換爲 string 對象
to_string(val)

將 string 對象轉換爲其他類型的值
stoi(s, p, b)
stol(s, p, b)
stoul(s, p, b)
stoll(s, p, b)
stoull(s, p, b)
stof(s, p)
stod(s, p)
stold(s, p)

string 流

sstream 頭文件定義了三個類型來支持內存 IO。
istringstream 從 string 讀取數據,ostringstream 向 string 寫入數據,而 stringstream 既可以從 string 讀取數據,也可以向 string 寫入數據。要使用這些類型,需要包涵頭文件
include<sstream>
using namespace std;

string 流的創建與綁定

istringstream is; 創建一個輸入流
ostringstream os;
stringstream ss;
istringstream is(s); 創建一個輸入流並綁定 string s
ostringstream os(s);
stringstream ss(s);
is.str(); 返回 is 綁定的 string
os.str();
ss.str();
is.str(s); 將 string s 拷貝(綁定)到 is 中
os.str(s);
ss.str(s);

使用 istringstream

在進行處理文本時,如果文本中的元素類型混雜(例如既有數字也有單詞),亦或元素的數目不定。使用 istringstream 將帶來很大的方便。

例如,輸入算式的值,需要我們計算這個算式的值。一個必要的預處理便是將輸入字符串中的數字和運算符號解析出來。使用 istreamstring 可以很輕鬆的完成這一工作

string str;
cin >> str;
str.push_back('$'); // 爲方便處理,添加一個結束標記符 $
istringstream is(str);
vector<int> nums;
vector<char> syms;
int n;
char c;
while (is >> n) {
	nums.push_back(n);
	is >> c;
	syms.push_back(c);
}
// 輸入:2*3 - 5/4 + 6
// nums = { 2, 3, 5, 4, 6 }; syms = { '*', '-', '/', '+', '$' };

使用 ostringstream

有時,我們輸出的內容中包含多種多樣的元素類型,此時可先將一些輸出寫入輸出流,帶輸出流填充完畢後,再一次性地輸出。

例如,假設我們要讀取一行以空格分開的數字,並將分隔符由空格變爲等號輸出。

string str;
getline(cin, str); // 輸入:1 2 3 4 5
istringstream is(str);
ostringstream os;
int n;
is >> n; // 爲了不在最末尾添加‘,’,進行了一下調整
os << n;
while (is >> n) {
	os << ',';
	os << n;
}
cout << os.str(); // 輸出:1,2,3,4,5

常見字符串預處理

轉換大小寫

#include<algorithm>

string str = "Hello, World!";
// 轉換爲小寫
for_each(str.begin(), str.end(), [](char &ch){ ch = tolower(ch); });
// 轉換爲大寫
for_each(str.begin(), str.end(), [](char &ch){ ch = toupper(ch); });

分割

當分割符只有空格時,參看上文 istringstream 使用簡例

當有多個分隔符時

vector<string> split(const string &str, const string &separators) {
	vector<string> words;
	int i = 0;
	while (i < str.size()) {
		while (i < str.size() && separators.find(str[i]) < separators.size())
			++i;
		if (i >= str.size())
			break;
		int j = min(str.find_first_of(separators, i), str.size());
		words.push_back(str.substr(i, j - i));
		i = j + 1;
	}
	return words;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章