目錄
std::erase, std::erase_if (std::basic_string)
元素訪問
at 返回到位於指定位置 pos 的字符的引用
constexpr reference at( size_type pos );
constexpr const_reference at( size_type pos ) const;
進行邊界檢查,非法訪問時拋出 std::out_of_range 類型的異常。
#include <stdexcept>
#include <iostream>
#include <string>
int main()
{
std::string s("message"); // 爲容量
s = "abc";
s.at(2) = 'x'; // ok
std::cout << s << '\n';
std::cout << "string size = " << s.size() << '\n';
std::cout << "string capacity = " << s.capacity() << '\n';
try {
// 拋出,即使容量允許訪問元素
s.at(3) = 'x';
}
catch (std::out_of_range const& exc) {
std::cout << exc.what() << '\n';
}
}
abx
string size = 3
string capacity = 7
basic_string::at
operator[] 返回到位於指定位置 pos 的字符的引用
constexpr reference operator[]( size_type pos );
constexpr const_reference operator[]( size_type pos ) const;
不進行邊界檢查。若 pos > size() ,則行爲未定義。
#include <iostream>
#include <string>
int main()
{
std::string const e("Exemplar");
for (unsigned i = e.length() - 1; i != 0; i /= 2)
std::cout << e[i];
std::cout << '\n';
const char* c = &e[0];
std::cout << c << '\n'; // 作爲 C 字符串打印
// 更改 s 的最後字符爲 'y'
std::string s("Exemplar ");
s[s.size()-1] = 'y';
std::cout << s << '\n';
}
rmx
Exemplar
Exemplary
front 返回到 string 中首字符的引用
constexpr CharT& front();
constexpr const CharT& front() const;
若 empty() == true 則行爲未定義。
#include <iostream>
#include <string>
int main()
{
{
std::string s("Exemplary");
char& f = s.front();
f = 'e';
std::cout << s << '\n'; // "exemplary"
}
{
std::string const c("Exemplary");
char const& f = c.front();
std::cout << &f << '\n'; // "Exemplary"
}
}
exemplary
Exemplary
back 返回字符串中的末尾的字符
constexpr CharT& back();
constexpr const CharT& back() const;
若 empty() == true 則行爲未定義。
#include <iostream>
#include <string>
int main()
{
{
std::string s("Exemplary");
char& back = s.back();
back = 's';
std::cout << s << '\n'; // "Exemplars"
}
{
std::string const c("Exemplary");
char const& back = c.back();
std::cout << back << '\n'; // 'y'
}
}
Exemplars
y
data 返回指向作爲字符存儲工作的底層數組的指針
constexpr const CharT* data() const noexcept;
constexpr const CharT* data() const noexcept;
此指針滿足範圍 [data(), data() + size()) 爲合法,且其中的值對應存儲於字符串的值。
#include <algorithm>
#include <cassert>
#include <cstring>
#include <string>
int main()
{
std::string const s("Emplary");
assert(s.size() == std::strlen(s.data()));
assert(std::equal(s.begin(), s.end(), s.data()));
assert(std::equal(s.data(), s.data() + s.size(), s.begin()));
assert(0 == *(s.data() + s.size()));
}
c_str 返回指向擁有數據等價於存儲於字符串中的空終止字符數組的指針
constexpr const CharT* c_str() const noexcept;
該指針有範圍 [c_str(), c_str() + size()] 爲合法,且其中的值對應存儲於字符串的值,且在最後位置有個附加的空終止字符。
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int main()
{
const char *p1;
const string s1 = "Asd123";
p1 = s1.c_str();
printf("[2]:%s\n", p1);
return 0;
}
注意:使用c_str()帶來的小問題
const char* c;
std::string s = "1234";
c = s.c_str();
std::cout << c << std::endl; //輸出:1234
s = "abcd";
std::cout << c << std::endl; //輸出:abcd
解決的辦法
char* c = new char;
std::string s = "1234";
//char *strcpy(char* dest, const char *src);
strcpy(c, s.c_str());
std::cout << c << std::endl; //輸出:1234
s = "abcd";
std::cout << c << std::endl; //輸出:1234
operator basic_string_view 返回表示整個字符串內容的字符串視圖
constexpr operator std::basic_string_view<CharT, Traits>() const noexcept;
#include <iostream>
#include <string>
#include <string_view>
void show_wstring_size(std::wstring_view wcstr_v)
{
std::cout << wcstr_v.size() << " code points\n";
}
int main()
{
std::string cppstr = "窄字符串"; // 窄字符串
std::wstring wcstr = L"寬字符串"; // 寬字符串
// 從 string 隱式轉換到 string_view
// 經由 std::string::operator string_view :
std::string_view cppstr_v = cppstr;
std::cout << cppstr_v << '\n'
<< cppstr_v.size() << " code units\n";
// 從 wstring 隱式轉換到 wstring_view
// 經由 std::wstring::operator wstring_view :
show_wstring_size(wcstr);
}
迭代器
begin & cbegin 返回指向字符串首字符的迭代器
constexpr iterator begin() noexcept;
constexpr const_iterator begin() const noexcept;
constexpr const_iterator cbegin() const noexcept;
begin() 返回可變的或常迭代器,取決於 *this 的常性。cbegin() 始終返回常迭代器。
#include <string>
#include <iostream>
int main()
{
std::string s("Exemplar");
*s.begin() = 'e';
std::cout << s <<'\n';
auto i = s.cbegin();
std::cout << *i << '\n';
// *i = 'E'; // 錯誤: i 是常迭代器
}
exemplar
e
end & cend 返回指向後隨字符串末字符的字符的迭代器
constexpr iterator end() noexcept;
constexpr const_iterator end() const noexcept;
constexpr const_iterator cend() const noexcept;
此字符表現爲佔位符,試圖訪問它導致未定義行爲。
#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
int main()
{
std::string s("Exemparl");
std::next_permutation(s.begin(), s.end());
std::string c;
std::copy(s.cbegin(), s.cend(), std::back_inserter(c));
std::cout << c <<'\n'; // "Exemplar"
}
Exemplar
rbegin & crbegin 返回指向逆轉字符串首字符的逆向迭代器
constexpr reverse_iterator rbegin() noexcept;
constexpr const_reverse_iterator rbegin() const noexcept;
constexpr const_reverse_iterator crbegin() const noexcept;
它對應非逆向字符串的末字符。
#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
int main()
{
std::string s("Exemplar!");
*s.rbegin() = 'y';
std::cout << s << '\n'; // "Exemplary"
std::string c;
std::copy(s.crbegin(), s.crend(), std::back_inserter(c));
std::cout << c << '\n'; // "yralpmexE"
}
Exemplary
yralpmexE
rend & crend 返回指向後隨逆向字符串末字符的字符的逆向迭代器
constexpr reverse_iterator rend() noexcept;
constexpr reverse_iterator rend() noexcept;
constexpr const_reverse_iterator crend() const noexcept;
它對應前驅非逆向字符串首字符的字符。此字符表現爲佔位符,試圖訪問它會導致未定義行爲。
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
int main()
{
std::string s("A man, a plan, a canal: Panama");
{
std::string c;
std::copy(s.rbegin(), s.rend(), std::back_inserter(c));
std::cout << c <<'\n'; // "amanaP :lanac a ,nalp a ,nam A"
}
{
std::string c;
std::copy(s.crbegin(), s.crend(), std::back_inserter(c));
std::cout << c <<'\n'; // "amanaP :lanac a ,nalp a ,nam A"
}
}
amanaP :lanac a ,nalp a ,nam A
amanaP :lanac a ,nalp a ,nam A
容量
empty 檢查 string 是否爲空
[[nodiscard]] constexpr bool empty() const noexcept;
#include <iostream>
#include <string>
int main()
{
std::string s;
std::boolalpha(std::cout);
std::cout << "s.empty():" << s.empty() << "\t s:'" << s << "'\n";
s = "Exemplar";
std::cout << "s.empty():" << s.empty() << "\t s:'" << s << "'\n";
s = "";
std::cout << "s.empty():" << s.empty() << "\t s:'" << s << "'\n";
}
s.empty():true s:''
s.empty():false s:'Exemplar'
s.empty():true s:''
max_size 返回 string 由於保有系統或庫實現限制所能保有的最大元素數
constexpr size_type max_size() const noexcept;
#include <iostream>
#include <string>
int main()
{
std::string s;
std::cout << "Maximum size of a string is " << s.max_size() << "\n";
}
Maximum size of a string is 4294967294
reserve 使得 string 能準確地管理存儲分配
constexpr void reserve( size_type new_cap );
若 new_cap 大於當前 capacity(),則分配新存儲,並令 capacity() 大於或等於 new_cap 。若 new_cap 小於或等於當前 capacity() ,則無效果。
#include <cassert>
#include <string>
int main()
{
std::string s;
std::string::size_type new_capacity{ 100u };
assert(new_capacity > s.capacity());
s.reserve(new_capacity);
assert(new_capacity <= s.capacity());
}
capacity 返回當前已爲字符串分配空間的字符數
constexpr size_type capacity() const noexcept;
#include <iostream>
#include <string>
void show_capacity(std::string const& s)
{
std::cout << "'" << s << "' has capacity " << s.capacity() << ".\n";
}
int main()
{
std::string s{"Exemplar"};
show_capacity(s);
s += " is an example string.";
show_capacity(s);
}
'Exemplar' has capacity 15.
'Exemplar is an example string.' has capacity 31.
shrink_to_fit 請求移除未使用的容量
constexpr void shrink_to_fit();
這是減少 capacity() 到 size() 的非強制請求。是否滿足請求取依賴於實現。若(且唯若)發生重分配,則非法化所有指針、引用和迭代器。
include <iostream>
#include <string>
int main()
{
std::string s;
std::cout << "Default-constructed capacity is " << s.capacity()
<< " and size is " << s.size() << '\n';
for (int i=0; i<42; i++)
s.append(" 42 ");
std::cout << "Capacity after a couple of appends is " << s.capacity()
<< " and size is " << s.size() << '\n';
s.clear();
std::cout << "Capacity after clear() is " << s.capacity()
<< " and size is " << s.size() << '\n';
s.shrink_to_fit();
std::cout << "Capacity after shrink_to_fit() is " << s.capacity()
<< " and size is " << s.size() << '\n';
}
Default-constructed capacity is 15 and size 0
Capacity after a couple of appends is 240 and size 168
Capacity after clear() is 240 and size 0
Capacity after shrink_to_fit() is 15 and size 0
操作
clear 如同通過執行 erase(begin(), end()) 從 string 移除所有字符
constexpr void clear() noexcept;
#include <cassert>
#include <string>
int main()
{
std::string s{ "Exemplar" };
std::string::size_type const capacity = s.capacity();
s.clear();
assert(s.capacity() == capacity);
assert(s.empty());
assert(s.size() == 0);
}
insert 插入字符到 string 中
(1)constexpr basic_string& insert( size_type index, size_type count, CharT ch );
(2)constexpr basic_string& insert( size_type index, const CharT* s );
(3)constexpr basic_string& insert( size_type index, const CharT* s, size_type count );
(4)constexpr basic_string& insert( size_type index, const basic_string& str );
(5)constexpr basic_string& insert( size_type index, const basic_string& str );
(6)constexpr iterator insert( const_iterator pos, CharT ch );
(7)constexpr iterator insert( const_iterator pos, size_type count, CharT ch );
(8)template< class InputIt >
constexpr iterator insert( const_iterator pos, InputIt first, InputIt last );
(9)constexpr iterator insert( const_iterator pos, std::initializer_list<CharT> ilist );
(10)template < class T >
constexpr basic_string& insert( size_type pos, const T& t );
(11)template < class T >
constexpr basic_string& insert( size_type index, const T& t,
size_type index_str, size_type count = npos);
(1) 在位置 index 插入 count 個字符 ch 的副本。
(2) 在位置 index 插入 s 所指向的空終止字符串。字符串的長度由首個空字符,用 Traits::length(s) 確定。
(3) 在位置 index 插入範圍 [s, s+count) 中的字符。範圍能含有空字符。
(4) 在位置 index 插入 string str 。
(5) 在位置 index 插入由 str.substr(index_str, count) 獲得的 string 。
(6) 在 pos 所指向的字符前插入字符 ch 。
(7) 在 pos 所指向的元素(若存在)前插入 count 個字符 ch 的副本。
(8) 在 pos 所指向的元素(若存在)前插入來自範圍 [first, last) 的元素。
(9) 在 pos 所指向的元素(若存在)前插入來自 initializer_list ilist 的字符。
(10) 如同用 std::basic_string_view<CharT, Traits> sv = t; 隱式轉換 t 爲 string_view sv ,然後如同用 insert(pos, sv.data(), sv.size()) ,在 pos 所指向的元素(若存在)前插入來自 sv 的元素。
(11) 如同用 std::basic_string_view<CharT, Traits> sv = t; 隱式轉換 t 爲 string_view sv ,然後在 pos 所指向的元素(若存在)前插入來自 sv 的子視圖 [index_str, index_str+count) 的元素。若請求的子視圖越過 sv 的末尾,或若 count == npos ,則作爲結果的子視圖是 [index_str, sv.size()) 。若 index_str > sv.size() 或若 index > size() ,則拋出 std::out_of_range。
#include <cassert>
#include <iterator>
#include <string>
using namespace std::string_literals;
int main()
{
std::string s = "xmplr";
// insert(size_type index, size_type count, char ch)
s.insert(0, 1, 'E');
assert("Exmplr" == s);
// insert(size_type index, const char* s)
s.insert(2, "e");
assert("Exemplr" == s);
// insert(size_type index, string const& str)
s.insert(6, "a"s);
assert("Exemplar" == s);
// insert(size_type index, string const& str,
// size_type index_str, size_type count)
s.insert(8, " is an example string."s, 0, 14);
assert("Exemplar is an example" == s);
// insert(const_iterator pos, char ch)
s.insert(s.cbegin() + s.find_first_of('n') + 1, ':');
assert("Exemplar is an: example" == s);
// insert(const_iterator pos, size_type count, char ch)
s.insert(s.cbegin() + s.find_first_of(':') + 1, 2, '=');
assert("Exemplar is an:== example" == s);
// insert(const_iterator pos, InputIt first, InputIt last)
{
std::string seq = " string";
s.insert(s.begin() + s.find_last_of('e') + 1,
std::begin(seq), std::end(seq));
assert("Exemplar is an:== example string" == s);
}
// insert(const_iterator pos, std::initializer_list<char>)
s.insert(s.cbegin() + s.find_first_of('g') + 1, { '.' });
assert("Exemplar is an:== example string." == s);
}
erase 從 string 移除指定的字符
constexpr basic_string& erase( size_type index = 0, size_type count = npos );
constexpr iterator erase( const_iterator position );
constexpr iterator erase( const_iterator first, const_iterator last );
(1) 移除始於 index 的 min(count, size() - index) 個字符。
(2) 移除位於 position 的字符。
(3) 移除範圍 [first, last) 中的字符。
#include <iostream>
#include <algorithm>
#include <string>
int main()
{
std::string s = "This is an example";
std::cout << s << '\n';
s.erase(0, 5); // 擦除 "This "
std::cout << s << '\n';
s.erase(std::find(s.begin(), s.end(), ' ')); // 擦除 ' '
std::cout << s << '\n';
s.erase(s.find(' ')); // 從 ' ' 到字符串尾裁剪
std::cout << s << '\n';
}
This is an example
is an example
isan example
isan
push_back & pop_back 後附加 / 移除給定字符 ch 到字符串尾
constexpr void push_back( CharT ch );
constexpr void pop_back();
從字符串移除末字符。等價於 erase(end() - 1, 1) 。若字符串爲空則行爲未定義。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string a = "asd";
a.push_back('f');
cout << a <<endl;
a.pop_back();
cout << a <<endl;
return 0;
}
append 後附加額外字符到字符串
(1)constexpr basic_string& append( size_type count, CharT ch );
(2)constexpr basic_string& append( const basic_string& str );
(3)constexpr basic_string& append( const basic_string& str, size_type pos, size_type count = npos );
(4)constexpr basic_string& append( const CharT* s, size_type count );
(5)constexpr basic_string& append( const CharT* s );
(6)template< class InputIt >
constexpr basic_string& append( InputIt first, InputIt last );
(7)constexpr basic_string& append( std::initializer_list<CharT> ilist );
(8)template < class T >
constexpr basic_string& append( const T& t );
(9)template < class T >
constexpr basic_string& append( const T& t, size_type pos, size_type count = npos );
(1) 後附 count 個 ch 的副本
(2) 後附 string str
(3) 後附 str 的子串 [pos, pos+count) 。若請求的子串越過 string 結尾,或若 count == npos ,則後附的子串爲 [pos, size()) 。若 pos > str.size() ,則拋出 std::out_of_range 。
(4) 後附範圍 [s, s + count) 中的字符。此範圍能含有空字符。
(5) 後附 s 所指向的空終止字符串。由首個空字符用 Traits::length(s) 確定字符串的長度。
(6) 後附範圍 [first, last) 中的字符。
(7) 後附來自 initializer_list ilist 的字符。
(8) 如同用 std::basic_string_view<CharT, Traits> sv = t; 隱式轉換 t 爲 string_view sv ,然後如同用 append(sv.data(), sv.size()) 後附所有來自 sv 的字符。
(9) 如同用 std::basic_string_view<CharT, Traits> sv = t; 隱式轉換 t 爲 string_view sv ,然後後附來自 sv 子視圖 [pos, pos+count) 的字符。若請求的子視圖越過 sv 的結尾,或若 count == npos ,則後附的子視圖爲 [pos, sv.size()) 。
#include <string>
#include <iostream>
int main() {
std::basic_string<char> str = "string";
const char* cptr = "C-string";
const char carr[] = "Two and one";
std::string output;
// 1) 後附 char 3 次。
// 注意,這是僅有的接受 char 的重載。
output.append(3, '*');
std::cout << "1) " << output << "\n";
// 2) 後附整個 string
output.append(str);
std::cout << "2) " << output << "\n";
// 3) 後附字符串的一部分(此情況爲最後 3 個字母)case)
output.append(str, 3, 3);
std::cout << "3) " << output << "\n";
// 4) 後附 C 字符串的一部分
// 注意,因爲 `append` 返回 *this ,我們能一同鏈式調用
output.append(1, ' ').append(carr, 4);
std::cout << "4) " << output << "\n";
// 5) 後附整個 C 字符串
output.append(cptr);
std::cout << "5) " << output << "\n";
// 6) 後附範圍
output.append(std::begin(carr) + 3, std::end(carr));
std::cout << "6) " << output << "\n";
// 7) 後附 initializer_list
output.append({ ' ', 'l', 'i', 's', 't' });
std::cout << "7) " << output << "\n";
}
1) ***
2) ***string
3) ***stringing
4) ***stringing Two
5) ***stringing Two C-string
6) ***stringing Two C-string and one
7) ***stringing Two C-string and one list
operator+= 後附加額外字符到字符串
(1)constexpr basic_string& operator+=( const basic_string& str );
(2)constexpr basic_string& operator+=( CharT ch );
(3)constexpr basic_string& operator+=( const CharT* s );
(4)constexpr basic_string& operator+=( std::initializer_list<CharT> ilist );
(5)template < class T >
constexpr basic_string& operator+=( const T& t );
(1) 後附 string str 。
(2) 後附字符 ch 。
(3) 後附 s 所指向的空終止字符串。
(4) 後附 initializer_list ilist 中的字符。
(5) 如同用 std::basic_string_view<CharT, Traits> sv = t; 隱式轉換 t 爲 string_view sv ,然後後附字符串視圖 sv 中的字符,如同用 append(sv) 。
#include <iostream>
#include <iomanip>
#include <string>
int main()
{
std::string str;
str.reserve(50); // 預留足夠的存儲空間以避免內存分配
std::cout << std::quoted(str) << '\n'; // 空字符串
str += "This";
std::cout << std::quoted(str) << '\n';
str += std::string(" is ");
std::cout << std::quoted(str) << '\n';
str += 'a';
std::cout << std::quoted(str) << '\n';
str += {' ','s','t','r','i','n','g','.'};
std::cout << std::quoted(str) << '\n';
str += 76.85; // 等價於 str += static_cast<char>(76.85) ,可能不合意圖
std::cout << std::quoted(str) << '\n';
}
""
"This"
"This is "
"This is a"
"This is a string."
"This is a string.L"
compare 比較兩個字符序列
(1)constexpr int compare( const basic_string& str ) const noexcept;
(2)constexpr int compare( size_type pos1, size_type count1, const basic_string& str ) const;
(3)constexpr int compare( size_type pos1, size_type count1,
const basic_string& str,
size_type pos2, size_type count2 = npos ) const;
(4)constexpr int compare( const CharT* s ) const;
(5)constexpr int compare( size_type pos1, size_type count1, const CharT* s ) const;
(6)constexpr int compare( size_type pos1, size_type count1, const CharT* s, size_type count2 ) const;
(7)template < class T >
constexpr int compare( const T& t ) const noexcept(/* see below */);
(8)template < class T >
constexpr int compare( size_type pos1, size_type count1, const T& t ) const;
(9)template < class T >
constexpr int compare( size_type pos1, size_type count1,
const T& t, size_type pos2, size_type count2 = npos) const;
(1) 比較此 string 與 str 。
(2) 比較此 string 的 [pos1, pos1+count1) 子串與 str 。若 count1 > size() - pos1 則子串爲 [pos1, size()) 。
(3) 比較此 string 的 [pos1, pos1+count1) 子串與 str 的子串 [pos2, pos2+count2) 。若 count1 > size() - pos1則第一子串爲 [pos1, size()) 。類似地若 count2 > str.size() - pos2 則第二子串爲 [pos2, str.size()) 。
(4) 比較此 string 與始於 s 所指向字符的長度爲 Traits::length(s) 的空終止字符序列。
(5) 比較此 string 的 [pos1, pos1+count1) 子串與始於 s 所指向字符的長度爲 Traits::length(s) 的空終止字符序列。若 count1 > size() - pos1 則子串爲 [pos1, size()) 。
(6) 比較此 string 的 [pos1, pos1+count1) 子串與範圍 [s, s + count2) 中的字符。(注意:範圍 [s, s + count2) 中的字符可包含空字符。)
(7) 如同用 std::basic_string_view<CharT, Traits> sv = t; 隱式轉換 t 爲 string_view sv ,然後比較此 string 與 sv 。
(8) 如同用 std::basic_string_view<CharT, Traits> sv = t; 隱式轉換 t 爲 string_view sv ,然後比較此 string 的 [pos1, pos1+count1) 子串與 sv ,如同用 std::basic_string_view<CharT, Traits>(data(), size()).substr(pos1, count1).compare(sv) 。
(9) 如同用 std::basic_string_view<CharT, Traits> sv = t; 隱式轉換 t 爲 string_view sv ,然後比較此 string 的 [pos1, pos1+count1) 子串與 sv 的 [pos2, pos2+count2) 子串,如同用 std::basic_string_view<CharT, Traits>(data(), size()).substr(pos1, count1).compare(sv.substr(pos2, count2));。
按下列方式比較始於 data1 的 count1 個字符組成的字符序列與始於 data2 的 count2 個字符組成的字符序列。首先,如同用 size_type rlen = std::min(count1, count2) 計算要比較的字符數。然後調用 Traits::compare(data1, data2, rlen) 比較序列。對於標準字符特性,此函數進行逐字符字典序比較。若結果爲零(到此爲止的字符序列相等),則按下列方式比較其大小:
#include <cassert>
#include <string>
#include <iostream>
int main()
{
// 1) 與另一 string 比較
{
int compare_value{
std::string{"Batman"}.compare(std::string{"Superman"})
};
std::cout << (
compare_value < 0 ? "Batman comes before Superman\n" :
compare_value > 0 ? "Superman comes before Batman\n" :
"Superman and Batman are the same.\n"
);
}
// 2) 與另一 string 比較子串
{
int compare_value{
std::string{"Batman"}.compare(3, 3, std::string{"Superman"})
};
std::cout << (
compare_value < 0 ? "man comes before Superman\n" :
compare_value > 0 ? "Superman comes before man\n" :
"man and Superman are the same.\n"
);
}
// 3) 與另一子串比較子串
{
std::string a{"Batman"};
std::string b{"Superman"};
int compare_value{a.compare(3, 3, b, 5, 3)};
std::cout << (
compare_value < 0 ? "man comes before man\n" :
compare_value > 0 ? "man comes before man\n" :
"man and man are the same.\n"
);
// 與另一子串比較子串
// 默認到爲另一 string 的末尾
assert(compare_value == a.compare(3, 3, b, 5));
}
// 4) 與另一 char 指針比較
{
int compare_value{std::string{"Batman"}.compare("Superman")};
std::cout << (
compare_value < 0 ? "Batman comes before Superman\n" :
compare_value > 0 ? "Superman comes before Batman\n" :
"Superman and Batman are the same.\n"
);
}
// 5) 與另一 char 指針比較子串
{
int compare_value{std::string{"Batman"}.compare(3, 3, "Superman")};
std::cout << (
compare_value < 0 ? "man comes before Superman\n" :
compare_value > 0 ? "Superman comes before man\n" :
"man and Superman are the same.\n"
);
}
// 6) 與另一 char 指針子串比較子串
{
int compare_value{std::string{"Batman"}.compare(0, 3, "Superman", 5)};
std::cout << (
compare_value < 0 ? "Bat comes before Super\n" :
compare_value > 0 ? "Super comes before Bat\n" :
"Super and Bat are the same.\n"
);
}
}
Batman comes before Superman
Superman comes before man
man and man are the same.
Batman comes before Superman
Superman comes before man
Bat comes before Super
starts_with 檢查 string 是否始於某一前綴
(1)constexpr bool starts_with( std::basic_string_view<CharT,Traits> sv ) const noexcept;
(2)constexpr bool starts_with( CharT c ) const noexcept;
(3)constexpr bool starts_with( const CharT* s ) const;
(1) string_view sv (可以是從另一 std::basic_string 隱式轉換的結果)。
(2) 單個字符 c
(3) 空終止字符串 s
所有三個重載等效地返回 std::basic_string_view<CharT, Traits>(data(), size()).starts_with(x) ,其中 x 是參數。
#include <iostream>
#include <string_view>
#include <string>
template <typename PrefixType>
void test_prefix_print(const std::string& str, PrefixType prefix)
{
std::cout << '\'' << str << "' starts with '" << prefix << "': " <<
str.starts_with(prefix) << '\n';
}
int main()
{
std::boolalpha(std::cout);
auto helloWorld = std::string("hello world");
test_prefix_print(helloWorld, std::string_view("hello"));
test_prefix_print(helloWorld, std::string_view("goodbye"));
test_prefix_print(helloWorld, 'h');
test_prefix_print(helloWorld, 'x');
}
'hello world' starts with 'hello': true
'hello world' starts with 'goodby': false
'hello world' starts with 'h': true
'hello world' starts with 'x': false
ends_with 檢查 string 是否終於某一後綴
(1)constexpr bool ends_with( std::basic_string_view<CharT,Traits> sv ) const noexcept;
(2)constexpr bool ends_with( CharT c ) const noexcept;
(3)constexpr bool ends_with( const CharT* s ) const;
(1) string_view sv (可以是從另一 std::basic_string 隱式轉換的結果)。
(2) 單個字符 c
(3) 空終止字符串 s
所有三個重載等效地返回 std::basic_string_view<CharT, Traits>(data(), size()).ends_with(x) ,其中 x 是參數。
#include <iostream>
#include <string_view>
#include <string>
template <typename SuffixType>
void test_suffix_print(const std::string& str, SuffixType suffix)
{
std::cout << '\'' << str << "' ends with '" << suffix << "': " <<
str.ends_with(suffix) << '\n';
}
int main()
{
std::boolalpha(std::cout);
auto helloWorld = std::string("hello world");
test_suffix_print(helloWorld, std::string_view("world"));
test_suffix_print(helloWorld, std::string_view("goodby"));
test_suffix_print(helloWorld, 'd');
test_suffix_print(helloWorld, 'x');
}
'hello world' ends with 'world': true
'hello world' ends with 'goodby': false
'hello world' ends with 'd': true
'hello world' ends with 'x': false
replace 以新字符串替換 [pos, pos + count) 或 [first, last) 所指示的 string 部分
(1)constexpr basic_string& replace( size_type pos, size_type count, const basic_string& str );
constexpr basic_string& replace( const_iterator first, const_iterator last, const basic_string& str );
(2)constexpr basic_string& replace( size_type pos, size_type count,
const basic_string& str,
size_type pos2, size_type count2 = npos );
(3)template< class InputIt >
constexpr basic_string& replace( const_iterator first, const_iterator last,
InputIt first2, InputIt last2 );
(4)constexpr basic_string& replace( size_type pos, size_type count, const CharT* cstr, size_type count2 );
constexpr basic_string& replace( const_iterator first, const_iterator last, const CharT* cstr, size_type count2 );
(5)constexpr basic_string& replace( size_type pos, size_type count, const CharT* cstr );
constexpr basic_string& replace( const_iterator first, const_iterator last, const CharT* cstr );
(6)constexpr basic_string& replace( size_type pos, size_type count, size_type count2, CharT ch );
constexpr basic_string& replace( const_iterator first, const_iterator last, size_type count2, CharT ch );
(7)constexpr basic_string& replace( const_iterator first, const_iterator last, std::initializer_list<CharT> ilist );
(8)template < class T >
constexpr basic_string& replace( size_type pos, size_type count, const T& t );
template < class T >
constexpr basic_string& replace( const_iterator first, const_iterator last, const T& t );
(9)template < class T >
constexpr basic_string& replace( size_type pos, size_type count, const T& t,
size_type pos2, size_type count2 = npos );
(1) string str ;
(2) str 的子串 [pos2, pos2 + count2) ,除了若 count2==npos 或若它可能越過 str.size() ,則使用 [pos2, str.size()) 。
(3) 範圍 [first2, last2) 中的字符。
(4) 範圍 [cstr, cstr + count2) 中的字符;
(5) 範圍 [cstr, cstr + Traits::length(cstr)) 中的字符;
(6) 字符 ch 的 count2 個副本;
(7) initializer_list ilist 中的字符;
(8) 如同用 std::basic_string_view<CharT, Traits> sv = t; 從 t 轉換而來的 string_view sv 的字符。
(9) 如同用 std::basic_string_view<CharT, Traits> sv = t; 從 t 轉換而得的字符串視圖 sv 的子視圖 [pos2, pos2 + count2) ,除了若 count2==npos 或它將越過 sv.size() ,則使用 [pos2, sv.size()) 。
#include <iostream>
#include <string>
int main()
{
std::string str("The quick brown fox jumps over the lazy dog.");
str.replace(10, 5, "red"); // (5)
str.replace(str.begin(), str.begin() + 3, 1, 'A'); // (6)
std::cout << str << '\n';
}
A quick red fox jumps over the lazy dog.
substr 返回子串 [pos, pos+count)
constexpr basic_string substr( size_type pos = 0, size_type count = npos ) const;
若請求的子串越過 string 的結尾,或若 count == npos ,則返回的子串爲 [pos, size()) 。
#include <string>
#include <iostream>
int main()
{
std::string a = "0123456789abcdefghij";
// count 爲 npos ,返回 [pos, size())
std::string sub1 = a.substr(10);
std::cout << sub1 << '\n';
// pos 和 pos+count 都在邊界內,返回 [pos, pos+count)
std::string sub2 = a.substr(5, 3);
std::cout << sub2 << '\n';
// pos 在邊界內, pos+count 不在,返回 [pos, size())
std::string sub4 = a.substr(a.size()-3, 50);
std::cout << sub4 << '\n';
try {
// pos 在邊界外,拋出
std::string sub5 = a.substr(a.size()+3, 50);
std::cout << sub5 << '\n';
} catch(const std::out_of_range& e) {
std::cout << "pos exceeds string size\n";
}
}
abcdefghij
567
hij
pos exceeds string size
copy 複製子串 [pos, pos+count) 到 dest 所指向的字符串
constexpr size_type copy( CharT* dest, size_type count, size_type pos = 0 ) const;
若請求的子串越過 string 結尾,或若 count == npos ,則複製的子串爲 [pos, size()) 。產生的字符串不是空終止的。若 pos > size() ,則拋出 std::out_of_range 。
#include <string>
#include <iostream>
int main()
{
std::string foo("quuuux");
char bar[7]{};
foo.copy(bar, sizeof bar);
std::cout << bar << '\n';
}
quuuux
resize 重設 string 大小以含 count 個字符
constexpr void resize( size_type count );
constexpr void resize( size_type count, CharT ch );
若當前大小小於 count ,則後附額外的字符。若當前大小大於 count ,則縮減 string 到爲其首 count 個元素。第一版本初始化新字符爲 CharT() ,第二版本初始化新字符爲 ch 。
#include <iostream>
#include <stdexcept>
int main()
{
std::cout << "Basic functionality:\n";
const unsigned desired_length(8);
std::string long_string( "Where is the end?" );
std::string short_string( "Ha" );
// 縮短
std::cout << "Before: \"" << long_string << "\"\n";
long_string.resize( desired_length );
std::cout << "After: \"" << long_string << "\"\n";
// 加長
std::cout << "Before: \"" << short_string << "\"\n";
short_string.resize( desired_length, 'a' );
std::cout << "After: \"" << short_string << "\"\n";
std::cout << "\nErrors:\n";
{
std::string s;
try {
// 大小 OK ,無 length_error
// (可能拋 bad_alloc )
s.resize(s.max_size() - 1, 'x');
} catch (const std::bad_alloc&) {
std::cout << "1. bad alloc\n";
}
try {
// 大小 OK ,無 length_error
// (可能拋 bad_alloc )
s.resize(s.max_size(), 'x');
} catch (const std::bad_alloc& exc) {
std::cout << "2. bad alloc\n";
}
try {
// 大小錯誤,拋出 length_error
s.resize(s.max_size() + 1, 'x');
} catch (const std::length_error&) {
std::cout << "3. length error\n";
}
}
}
Basic functionality:
Before: "Where is the end?"
After: "Where is"
Before: "Ha"
After: "Haaaaaaa"
Errors:
1. bad alloc
2. bad alloc
3. length error
swap 交換 string 與 other 的內容
constexpr void swap( basic_string& other ) noexcept(/* see below */);
#include <string>
#include <iostream>
int main()
{
std::string a = "AAA";
std::string b = "BBB";
std::cout << "before swap" << '\n';
std::cout << "a: " << a << '\n';
std::cout << "b: " << b << '\n';
a.swap(b);
std::cout << "after swap" << '\n';
std::cout << "a: " << a << '\n';
std::cout << "b: " << b << '\n';
}
before swap
a: AAA
b: BBB
after swap
a: BBB
b: AAA
查找
find 尋找首個等於給定字符序列的子串
(1)constexpr size_type find( const basic_string& str, size_type pos = 0 ) const noexcept;
(2)constexpr size_type find( const CharT* s, size_type pos, size_type count ) const;
(3)constexpr size_type find( const CharT* s, size_type pos = 0 ) const;
(4)constexpr size_type find( CharT ch, size_type pos = 0 ) const noexcept;
(5)template < class T >
constexpr size_type find( const T& t, size_type pos = 0 ) const noexcept(/* see below */);
搜索始於 pos ,即找到的子串必須不始於 pos 之前的位置。
(1) 尋找等於 str 的首個子串。
(2) 尋找等於範圍 [s, s+count) 的首個子串。此範圍能含空字符。
(3) 尋找等於 s 所指向的字符串的首個子串。由首個空字符,用 Traits::length(s) 確定字符串長度。
(4) 尋找首個字符 ch (由後述規則當作單字節子串)。
(5) 如同用 std::basic_string_view<CharT, Traits> sv = t; 隱式轉換 t 爲 string_view sv ,然後尋找等於字符串視圖 sv 的首個子串。
#include <string>
#include <iostream>
void print(std::string::size_type n, std::string const &s)
{
if (n == std::string::npos) {
std::cout << "not found\n";
} else {
std::cout << "found: " << s.substr(n) << '\n';
}
}
int main()
{
std::string::size_type n;
std::string const s = "This is a string";
// 從 string 開始搜索
n = s.find("is");
print(n, s);
// 從位置 5 開始搜索
n = s.find("is", 5);
print(n, s);
// 尋找單個字符
n = s.find('a');
print(n, s);
// 尋找單個字符
n = s.find('q');
print(n, s);
}
found: is is a string
found: is a string
found: a string
not found
rfind 尋找等於給定字符序列的最後子串
(1)constexpr size_type rfind( const basic_string& str, size_type pos = npos ) const noexcept;
(2)constexpr size_type rfind( const CharT* s, size_type pos, size_type count ) const;
(3)constexpr size_type rfind( const CharT* s, size_type pos = npos ) const;
(4)constexpr size_type rfind( CharT ch, size_type pos = npos ) const noexcept;
(5)template < class T > constexpr size_type
rfind( const T& t, size_type pos = npos ) const noexcept(/* see below */);
搜索始於 pos ,即找到的子串必須不始於 pos 後的位置。若將 npos 或任何不小於 size()-1 的值作爲 pos 傳遞,則在整個字符串中搜索。
(1) 尋找等於 str 的最後子串。
(2) 尋找等於範圍 [s, s+count) 的最後子串。此範圍能包含空字符。
(3) 尋找等於 s 所指向的字符串的最後子串。由首個空字符,用 Traits::length(s) 確定字符串長度。
(4) 尋找等於 ch 的最後字符。
(5) 如同用 std::basic_string_view<CharT, Traits> sv = t; 隱式轉換 t 爲 string_view sv ,然後尋找等於 sv 內容的最後子串。
#include <string>
#include <iostream>
void print(std::string::size_type n, std::string const &s)
{
if (n == std::string::npos) {
std::cout << "not found\n";
} else {
std::cout << "found: \"" << s.substr(n) << "\" at " << n << '\n';
}
}
int main()
{
std::string::size_type n;
std::string const s = "This is a string";
// 從字符串尾反向搜索
n = s.rfind("is");
print(n, s);
// 從位置 4 反向搜索
n = s.rfind("is", 4);
print(n, s);
// 尋找單個字符
n = s.rfind('s');
print(n, s);
// 尋找單個字符
n = s.rfind('q');
print(n, s);
}
found: "is a string" at 5
found: "is is a string" at 2
found: "string" at 10
not found
find_first_of 尋找等於給定字符序列中字符之一的首個字符
(1)constexpr size_type find_first_of( const basic_string& str, size_type pos = 0 ) const noexcept;
(2)constexpr size_type find_first_of( const CharT* s, size_type pos, size_type count ) const;
(3)constexpr size_type find_first_of( const CharT* s, size_type pos = 0 ) const;
(4)constexpr size_type find_first_of( CharT ch, size_type pos = 0 ) const noexcept;
(5)template < class T > constexpr size_type find_first_of( const T& t,
size_type pos = 0 ) const noexcept(/* see below */);
搜索只考慮區間 [pos, size()) 。若區間中不存在字符,則返回 npos。
(1) 尋找等於 str 中字符之一的首個字符。
(2) 尋找等於範圍 [s, s+count) 中字符中字符之一的首個字符。此範圍能包含空字符。
(3) 尋找等於 s 所指向的字符串中字符之一的首個字符。由首個空字符,用 Traits::length(s) 確定字符串長度。
(4) 尋找等於 ch 的首個字符。
(5) 如同用 std::basic_string_view<CharT, Traits> sv = t; 隱式轉換 t 爲 string_view sv ,然後尋找等於 sv 中字符之一的首個字符。
#include <iostream>
#include <string>
int main()
{
// 測試字符串
std::string str = std::string("Hello World!");
// 搜索用的字符串和字符
std::string search_str = std::string("o");
const char* search_cstr = "Good Bye!";
std::cout << str.find_first_of(search_str) << '\n';
std::cout << str.find_first_of(search_str, 5) << '\n';
std::cout << str.find_first_of(search_cstr) << '\n';
std::cout << str.find_first_of(search_cstr, 0, 4) << '\n';
// 'x' 不在 "Hello World' 中,從而它將返回 std::string::npos
std::cout << str.find_first_of('x') << '\n';
}
4
7
1
4
18446744073709551615
find_first_not_of 尋找不等於給定字符序列中任何字符的首個字符
(1)constexpr size_type find_first_not_of( const basic_string& str, size_type pos = 0 ) const noexcept;
(2)constexpr size_type find_first_not_of( const CharT* s, size_type pos, size_type count ) const;
(3)constexpr size_type find_first_not_of( const CharT* s, size_type pos = 0 ) const;
(4)constexpr size_type find_first_not_of( CharT ch, size_type pos = 0 ) const noexcept;
(5)template < class T > constexpr size_type find_first_not_of( const T& t,
size_type pos = 0 ) const noexcept(/* see below */);
搜索只考慮區間 [pos, size()) 。若區間中不存在字符,則將返回 npos 。
(1) 尋找不等於 str 中任何字符的首個字符。
(2) 尋找不等於範圍 [s, s+count) 中任何字符的首個字符。此範圍能包含空字符。
(3) 尋找不等於 s所指向的字符串中任何字符的首個字符。用 Traits::length(s) ,由首個空終止符確定字符串長度。
(4) 尋找不等於 ch 的首個字符。
(5) 如同用 std::basic_string_view<CharT, Traits> sv = t; 隱式轉換 t 爲 string_view sv ,然後尋找不等於 sv中任何字符的首個字符。
#include <string>
#include <iostream>
int main() {
std::string to_search = "Some data with %MACROS to substitute";
std::cout << "Before: " << to_search << '\n';
auto pos = std::string::npos;
while ((pos = to_search.find('%')) != std::string::npos) {
// 宏名中容許大寫字母、小寫字母和數字
const auto after = to_search.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", pos + 1);
// 現在 to_search[pos] == '%' 而 to_search[after] == ' ' (在 'S' 後)
if(after != std::string::npos)
to_search.replace(pos, after - pos, "some very nice macros");
}
std::cout << "After: " << to_search << '\n';
}
Before: Some data with %MACROS to substitute
After: Some data with some very nice macros to substitute
find_last_of 尋找等於給定字符序列中字符之一的最後字符
(1)constexpr size_type find_last_of( const basic_string& str, size_type pos = npos ) const noexcept;
(2)constexpr size_type find_last_of( const CharT* s, size_type pos, size_type count ) const;
(3)constexpr size_type find_last_of( const CharT* s, size_type pos = npos ) const;
(4)constexpr size_type find_last_of( CharT ch, size_type pos = npos ) const noexcept;
(5)template < class T > constexpr size_type find_last_of( const T& t,
size_type pos = npos ) const noexcept(/* see below */);
不指定準確的搜索算法。搜索只考慮區間 [0, pos] 。若區間中不存在這種字符,則返回 npos 。
(1) 尋找等於 str 中字符之一的最後字符。
(2) 尋找等於範圍 [s, s+count) 中字符之一的最後字符。此範圍能包含空字符。
(3) 尋找等於 s 所指向的字符串中字符之一的最後字符。用 Traits::length(s) ,由首個空字符確定字符串長度。
(4) 尋找等於 ch 的最後字符。
(5) 如同用 std::basic_string_view<CharT, Traits> sv = t; 隱式轉換 t 爲 string_view sv ,然後尋找等於 sv 中字符之一的最後字符。
#include<string>
#include<iostream>
int main()
{
const std::string path="/root/config";
auto const pos=path.find_last_of('/');
const auto leaf=path.substr(pos+1);
std::cout << leaf << '\n';
}
config
find_last_not_of 尋找不等於給定字符序列中任何字符的最後字符
(1)constexpr size_type find_last_not_of( const basic_string& str, size_type pos = npos ) const noexcept;
(2)constexpr size_type find_last_not_of( const CharT* s, size_type pos, size_type count ) const;
(3)constexpr size_type find_last_not_of( const CharT* s, size_type pos = npos ) const;
(4)constexpr size_type find_last_not_of( CharT ch, size_type pos = npos ) const noexcept;
(5)template < class T > constexpr size_type find_last_not_of( const T& t,
size_type pos = npos ) const noexcept(/* see below */);
搜索只考慮區間 [0, pos] 。若區間中不存在這種字符,則返回 npos 。
(1) 尋找不等於 str 中任何字符的最後字符。
(2) 尋找不等於範圍 [s, s+count) 中任何字符的最後字符。此範圍能包含空字符。
(3) 尋找不等於 s 所指向的字符串中任何字符的最後字符。用 Traits::length(s) 確定字符串長度。
(4) 尋找不等於 ch 的最後字符。
(5) 如同用 std::basic_string_view<CharT, Traits> sv = t; 隱式轉換 t 爲 string_view sv ,然後尋找不等於 sv中任何字符的最後字符。
#include <iostream>
#include <string>
void show_pos(const std::string& str, std::string::size_type found) {
if (found != std::string::npos) {
std::cout << "[" << found << "] = \'" << str[found] << "\'\n";
} else {
std::cout << "not found" "\n";
}
}
int main()
{
std::string str { "abc_123" };
char const* skip_set { "0123456789" };
std::string::size_type str_last_pos { std::string::npos };
show_pos(str, str.find_last_not_of(skip_set)); // [3] = '_'
str_last_pos = 2;
show_pos(str, str.find_last_not_of(skip_set, str_last_pos)); // [2] = 'c'
str_last_pos = 2;
show_pos(str, str.find_last_not_of('c', str_last_pos)); // [1] = 'b'
const char arr[] { '3', '4', '5' };
show_pos(str, str.find_last_not_of(arr)); // [5] = '2'
str_last_pos = 2;
std::string::size_type skip_set_size{4};
show_pos(str, str.find_last_not_of(skip_set,
str_last_pos,
skip_set_size)); // [2] = 'c'
show_pos(str, str.find_last_not_of("abc")); // [6] = '3'
str_last_pos = 2;
show_pos(str, str.find_last_not_of("abc", str_last_pos)); // 找不到
}
[3] = '_'
[2] = 'c'
[1] = 'b'
[5] = '2'
[2] = 'c'
[6] = '3'
not found
std::erase, std::erase_if (std::basic_string)
(1)template< ..., class U >
constexpr typename std::basic_string<...>::size_type
erase(std::basic_string<...>& c, const U& value);
(2)template< ..., class Pred >
constexpr typename std::basic_string<...>::size_type
erase_if(std::basic_string<...>& c, Pred pred);
(1) 從容器中擦除所有比較等於 value 的元素。等價於
auto it = std::remove(c.begin(), c.end(), value);
auto r = std::distance(it, c.end());
c.erase(it, c.end());
return r;
(2) 從容器中擦除所有滿足 pred 的元素。等價於
auto it = std::remove_if(c.begin(), c.end(), pred);
auto r = std::distance(it, c.end());
c.erase(it, c.end());
return r;
#include <iostream>
#include <numeric>
#include <string>
void print_container(const std::string& c)
{
for (auto x : c) {
std::cout << x << ' ';
}
std::cout << '\n';
}
int main()
{
std::string cnt(10, ' ');
std::iota(cnt.begin(), cnt.end(), '0');
std::cout << "Init:\n";
print_container(cnt);
auto erased = std::erase(cnt, '3');
std::cout << "Erase \'3\':\n";
print_container(cnt);
std::erase_if(cnt, [](char x) { return (x - '0') % 2 == 0; });
std::cout << "Erase all even numbers:\n";
print_container(cnt);
std::cout << "In all " << erased << " even numbers were erased.\n";
}
Init:
0 1 2 3 4 5 6 7 8 9
Erase '3':
0 1 2 4 5 6 7 8 9
Erase all even numbers:
1 3 7 9
In all 5 even numbers were erased.