C++ string 使用詳解(含C++20新特性)

目錄

元素訪問

迭代器

容量

操作

查找

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 */);

搜索只考慮區間 [possize()) 。若區間中不存在字符,則將返回 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.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章