[C++编程笔记] 02 C++字符串总结

[C++编程笔记] 02 C++字符串总结

联系作者:359152155@qq.com


0. 概要

C++标准库提供了诸多字符串类型,它们都是通过模板 std::basic_string 特例化而来的。如下:

类型定义
std::stringstd::basic_string<char>
std::wstringstd::basic_string<wchar_t>
std::u8string (C++20)std::basic_string<char8_t>
std::u16string (C++11)std::basic_string<char16_t>
std::u32string (C++11)std::basic_string<char32_t>
std::pmr::string (C++17)std::pmr::basic_string<char>
std::pmr::wstring (C++17)std::pmr::basic_string<wchar_t>
std::pmr::u8string (C++20)std::pmr::basic_string<char8_t>
std::pmr::u16string (C++17)std::pmr::basic_string<char16_t>
std::pmr::u32string (C++17)std::pmr::basic_string<char32_t>

由于这些类都有相同的接口形式,因此下面只以std::string为例进行介绍,其他类型大同小异。


1. 字符串字面量的字符编码

const char *a = "hello world, 你好世界";        // 单字节字符, 具体编码取决于平台 
const char *b = u8"hello world, 你好世界";      // utf-8编码
const char16_t *c = u"hello world, 你好世界";   // unicode16编码
const char32_t *d = U"hello world, 你好世界";   // unicode32编码 
const wchar_t *e = L"hello world, 你好世界";    // 宽字符, 具体编码取决于平台 

2. string初始化

string s1;默认初始化,初始化为空串
string s2{};
string s2{‘a’, ‘b’, ‘c’, …};
使用初始化列表初始化s2
string s3(n, ‘c’);s3初始化为连续n个字符’c’组成的串
string s4(str);
string s4 = str;
s4初始化为str的副本
string s5(c_str);
string s5 = c_str;
s5初始化为c风格字符串c_str的副本(除去字面量最后的空字符)
string s6(str, pos);
string s6(str, pos, cnt);
使用str的子串初始化s6,pos和cnt用来指定范围,cnt缺省时表示到str结尾
string s7(c_str, cnt);使用c风格字符串c_str的前cnt个字符初始化s7
string s8(first_iter, last_iter);使用迭代器范围[first_iter, last_iter)来初始化s8

3. string基本操作

判断string是否空串

s.empty() // 如果是空串返回true

返回string中字符个数

auto n = s.size(); // 返回值为string::size_t类型,C++标准未指明它的具体类型,在不同平台会有不同定义,因此我们无法确定它具体是什么类型,但可以确定的是它一定是unsigned的。

随机访问string中的元素

  • 方法1. 使用[]访问:
    auto &c = s[pos];
    
    此时如果pos超出范围会发生未定义的行为,因此必须先检查下标值是否正确。
  • 方法2. 使用at成员函数访问:
    auto &c = s.at(pos);
    
    此时如果pos超出范围会抛出std::out_of_range异常,因此可以事后捕获。

访问string首/尾位置的元素

auto &c1 = s.front();
auto &c2 = s.back();

遍历string中的元素

// 1. 普通for循环遍历 
for (auto i = 0; i < str.size(); ++i) { // 正向
    str[i];
}
for (auto i = str.size(); i !=0; --i) { // 反向
    str[i-1];
}

// 2. 范围for遍历
for (auto &itm : str) {
    itm;
}

// 3. 迭代器遍历
for (auto iter = str.begin(); iter != str.end(); iter++) { // 正向
    *iter;
}
for (auto iter = s5.rbegin(); iter != s5.rend(); iter++) { //反向
    *iter;
}

字符串比较

// 注意:string的比较是大小写敏感的

s1 == s2 // 判断是否相等
s1 != s2 // 判断是否不相等

// 以下是按字符的字典序进行大小比较
s1 > s2
s1 >= s2
s1 < s2
s1 <= s2

s1.compare(s2)
s1.compare(pos, count, s2)  // compare函数还有很多重载,编程时可查看文档选择最适合的

截取string的子串

str2 = str1.substr(pos); // 返回str1中从pos位置开始的子串
str2 = str1.substr(pos, count); // 返回str1中从pos开始的count个字符组成的子串

字符串连接

str1 + str2; // 返回新的字符串,其内容是str1和str2的连接
str + c_str; // string可以和c风格字符串c_str连接

c_str1 + c_str2 + str; // 编译错误:c_str1和c_str2不能直接相加,因为他们是char *型
str + c_str1 + c_str2; // 正确:str先加c_str1,其结果再加上c_str2。

向string后追加内容

// 1. 使用push_back
str.push_back(c); // 向str中追加一个字符

// 2. 使用append,append函数返回this索引,可以级联调用
str.append(...).append(...).append(...); // append函数有很多不同的重载,编程时可查看文档选择最适合的

// 3. 使用+=运算符
str += c;   // 追加字符c
str += str2; // 追加一个string
str += c_str; // 追加一个c风格字符串

向string中插入内容

str.insert(...); // insert函数有很多重载,编程时可查看文档选择最合适的

从string中移除内容

str.pop_back(); // 移除尾部一个字符

str.erase(index); // 移除index后的全部字符,注意:是后面的全部字符
str.erase(index, 1); // 移除index位置的字符
str.erase(index, count); // 移除index后的count个字符
str.erase(pos_iter); // 移除迭代器iter后的全部字符,注意:仅移除一个字符
str.erase(first_iter, last_iter); // 移除迭代器范围[first_iter, last_iter)中的字符

str.clear(); // 清空

4. string的容量管理

// capacity函数返回string分配的存储容量
string::size_type cap = str.capacity();

// size和length函数功能一样,返回字符串的长度
string::size_type sz = str.size();
string::size_type len = str.length();

// max_size函数返回string中可存放的字符串的极限长度
string::size_type max_sz = str.max_size();

// reserve函数确保string中分配的容量超过某个值
str.reserver(new_cap);

// resize函数调整字符串的长度。
// 如果n超过原长度将会使用字符c填充,如果没有指定c那么使用0值填充。
// 如果n小于原长度,效果等价于去除尾部一些字符。
str.resize(n);
str.resize(n, c);

// shrink_to_fit函数请求移除未使用的容量。
// 这是减少 capacity() 到 size() 的非强制请求。是否满足请求取依赖于实现。
str.shrink_to_fit();

5. string中查找和替换

查找

// 1. find函数,本函数找到子串都会返回子串位置,找不到则返回string::npos。
// pos是str1中起始搜索的位置
str1.find(c, pos=0); // 在str1中查找字符c
str1.find(str2, pos=0); // 在str1中查找str2
str1.find(c_str1, pos=0); // 在str1中查找c风格字符串c_str1
str1.find(c_str1, pos, cnt); // 在str1中查找c分割字符串的子串[c_str1, c_str1+cnt)

// 2. rfind函数:反向查找,参数的定义与find函数一致
str1.rfind(c, pos=string::npos); // 在str1中反向查找字符c
str1.rfind(str2, pos=string::npos); // 在str1中反向查找str2
str1.rfind(c_str1, pos=string::npos); // 在str1中反向查找c风格字符串c_str1
str1.rfind(c_str1, posstring::npos, cnt); // 在str1中反向查找c分割字符串的子串[c_str1, c_str1+cnt)

// 3. find_first_of函数:
// find_first_of 函数最容易出错的地方是和find函数搞混。它最大的区别就是如果在一个字符串str1中查找另一个字符串str2,如果str1中含有str2中的任何字符,则就会查找成功,而find则不同;
size_type find_first_of ( const string& str, size_type pos = 0 ) const;
size_type find_first_of ( const char* s, size_type pos, size_type n ) const;
size_type find_first_of ( const char* s, size_type pos = 0 ) const;
size_type find_first_of ( char c, size_type pos = 0 ) const;

// 4. find_first_not_of函数:与find_fisrt_of恰好相反,查找的是this中未出现在目标str中的字符。

// 5. find_last_of函数:与find_fist_of相似但是反向查找

// 6. find_last_not_of函数:与find_last_of恰好相反,查找的是this中未出现在目标str中的字符。

替换

// 使用replace函数. 将[pos, pos+cnt)或[first, last)范围内的元素替换为目标字符串.
string& replace(size_type pos, size_type cnt, 
                       const string& str);
string& replace(const_iterator first, const_iterator last, 
                       const string& str);
string& replace(size_type pos, size_type cnt,
                       const string& str, size_type pos2, size_type cnt2=string::npos);
string& replace(const_iterator first, const_iterator last,
                       InputIt first2, InputIt last2);
string& replace(size_type pos, size_type cnt,
                       const char* cstr );
string& replace(size_type pos, size_type cnt,
                       const char* cstr, size_type cnt2);
string& replace( const_iterator first, const_iterator last,
                       const char* cstr );
string& replace(const_iterator first, const_iterator last,
                       const char* cstr, size_type cnt2);
// ... 还有一些重载,编程时可查看文档选择最合适的              


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时空旅客er

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值