C++ string 使用详解(含C++20新特性)
目錄
元素訪問
迭代器
容量
操作
查找
std::erase,?std::erase_if?(std::basic_string)
std::basic_string?簡介
basic_string 是類模版,并且是容器類模版,basic_string 類模版的對象管理的序列是標準的 C++ 字符串,string 是模版形參為 char 的basci_string 模版類的類型定義,basic_string?還包括 wstring 、u16string 和 u32string?等。basic_string 的聲明如下:?
template<?class?CharT,?class?Traits?=?std::char_traits<CharT>,?class?Allocator?=?std::allocator<CharT> >?class?basic_string;CharT - 字符類型 Traits - 指定字符類型上操作的特性類 Allocator - 用于分配內部存儲的分配器?(Allocator)?類型?
?
元素訪問
?
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'; // okstd::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) 后附整個 stringoutput.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_listoutput.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_errors.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_typerfind(?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::nposstd::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_typeerase(std::basic_string<...>&?c,?const?U&?value);(2)template<?...,?class?Pred?>constexpr?typename?std::basic_string<...>::size_typeerase_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.?
總結
以上是生活随笔為你收集整理的C++ string 使用详解(含C++20新特性)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 快用一用 lambda 表达式吧,让你的
- 下一篇: Socket编程:必须要了解的网络字节序