C++ 字符串处理与视图类详解
1. 字符串元素擦除函数
在 C++ 中,提供了一个用于擦除字符串中满足特定条件元素的函数模板:
template <class charT, class traits, class Allocator, class Predicate>
void erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred);
其效果等同于:
c.erase(remove_if(c.begin(), c.end(), pred), c.end());
2. 数值转换函数
2.1 字符串转整数
以下是一系列将字符串转换为整数的函数:
int stoi(const string& str, size_t* idx = nullptr, int base = 10);
long stol(const string& str, size_t* idx = nullptr, int base = 10);
unsigned long stoul(const string& str, size_t* idx = nullptr, int base = 10);
long long stoll(const string& str, size_t* idx = nullptr, int base = 10);
unsigned long long stoull(const string& str, size_t* idx = nullptr, int base = 10);
-
效果
:前两个函数调用
strtol(str.c_str(), ptr, base),后三个函数分别调用strtoul(str.c_str(), ptr, base)、strtoll(str.c_str(), ptr, base)和strtoull(str.c_str(), ptr, base)。若函数不抛出异常且idx != 0,则会将str中第一个未转换元素的索引存储在*idx中。 - 返回值 :转换后的结果。
-
异常抛出
:若
strtol、strtoul、strtoll或strtoull报告无法进行转换,则抛出invalid_argument异常;若转换值超出返回类型的可表示范围,或strtol、strtoul、strtoll或strtoull将errno设置为ERANGE,则抛出out_of_range异常。
2.2 字符串转浮点数
float stof(const string& str, size_t* idx = nullptr);
double stod(const string& str, size_t* idx = nullptr);
long double stold(const string& str, size_t* idx = nullptr);
-
效果
:这些函数分别调用
strtof(str.c_str(), ptr)、strtod(str.c_str(), ptr)和strtold(str.c_str(), ptr)。若函数不抛出异常且idx != 0,则会将str中第一个未转换元素的索引存储在*idx中。 - 返回值 :转换后的结果。
-
异常抛出
:若
strtof、strtod或strtold报告无法进行转换,则抛出invalid_argument异常;若转换值超出返回类型的可表示范围,或strtof、strtod或strtold将errno设置为ERANGE,则抛出out_of_range异常。
2.3 整数/浮点数转字符串
string to_string(int val);
string to_string(unsigned val);
string to_string(long val);
string to_string(unsigned long val);
string to_string(long long val);
string to_string(unsigned long long val);
string to_string(float val);
string to_string(double val);
string to_string(long double val);
每个函数返回一个
string
对象,该对象包含其参数值的字符表示,其生成方式等同于调用
sprintf(buf, fmt, val)
,格式说明符分别为
"%d"
、
"%u"
、
"%ld"
、
"%lu"
、
"%lld"
、
"%llu"
、
"%f"
、
"%f"
或
"%Lf"
,其中
buf
是一个足够大的内部字符缓冲区。
3. 宽字符串数值转换函数
宽字符串也有类似的数值转换函数,例如:
int stoi(const wstring& str, size_t* idx = nullptr, int base = 10);
long stol(const wstring& str, size_t* idx = nullptr, int base = 10);
unsigned long stoul(const wstring& str, size_t* idx = nullptr, int base = 10);
long long stoll(const wstring& str, size_t* idx = nullptr, int base = 10);
unsigned long long stoull(const wstring& str, size_t* idx = nullptr, int base = 10);
其效果、返回值和异常抛出情况与普通字符串的转换函数类似,只是调用的是宽字符版本的函数,如
wcstol
、
wcstoul
等。
4. 哈希支持
对于多种字符串类型,提供了哈希支持:
template<> struct hash<string>;
template<> struct hash<u8string>;
template<> struct hash<u16string>;
template<> struct hash<u32string>;
template<> struct hash<wstring>;
template<> struct hash<pmr::string>;
template<> struct hash<pmr::u8string>;
template<> struct hash<pmr::u16string>;
template<> struct hash<pmr::u32string>;
template<> struct hash<pmr::wstring>;
若
S
是这些字符串类型之一,
SV
是对应的字符串视图类型,
s
是
S
类型的对象,则有
hash<S>()(s) == hash<SV>()(SV(s))
。
5. 字符串字面量后缀
为字符串字面量提供了后缀
s
:
string operator""s(const char* str, size_t len);
u8string operator""s(const char8_t* str, size_t len);
u16string operator""s(const char16_t* str, size_t len);
u32string operator""s(const char32_t* str, size_t len);
wstring operator""s(const wchar_t* str, size_t len);
这些运算符返回相应类型的字符串对象,包含指定的字符序列。
6. 字符串视图类
6.1 概述
basic_string_view
类模板描述了一个可以引用常量连续字符序列的对象,序列的第一个元素位于位置零。该库提供了从
const charT*
和
std::basic_string<charT, ...>
到
std::basic_string_view<charT, ...>
的隐式转换,方便用户代码在需要字符序列的地方接受
std::basic_string_view<charT>
作为非模板参数。
6.2 头文件概述
<string_view>
头文件包含以下内容:
namespace std {
// 类模板 basic_string_view
template<class charT, class traits = char_traits<charT>>
class basic_string_view;
// 非成员比较函数
template<class charT, class traits>
constexpr bool operator==(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) noexcept;
// 其他比较运算符...
// 插入器和提取器
template<class charT, class traits>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& os,
basic_string_view<charT, traits> str);
// 类型别名
using string_view = basic_string_view<char>;
using u8string_view = basic_string_view<char8_t>;
using u16string_view = basic_string_view<char16_t>;
using u32string_view = basic_string_view<char32_t>;
using wstring_view = basic_string_view<wchar_t>;
// 哈希支持
template<class T> struct hash;
template<> struct hash<string_view>;
// 其他哈希特化...
// 字符串视图字面量后缀
inline namespace literals {
inline namespace string_view_literals {
constexpr string_view operator""sv(const char* str, size_t len) noexcept;
// 其他后缀运算符...
}
}
}
6.3 类模板
basic_string_view
template<class charT, class traits = char_traits<charT>>
class basic_string_view {
public:
// 类型定义
using traits_type = traits;
using value_type = charT;
// 其他类型定义...
static constexpr size_type npos = size_type(-1);
// 构造和赋值
constexpr basic_string_view() noexcept;
constexpr basic_string_view(const basic_string_view&) noexcept = default;
constexpr basic_string_view(const charT* str);
constexpr basic_string_view(const charT* str, size_type len);
// 迭代器支持
constexpr const_iterator begin() const noexcept;
// 其他迭代器函数...
// 容量
constexpr size_type size() const noexcept;
constexpr size_type length() const noexcept;
// 元素访问
constexpr const_reference operator[](size_type pos) const;
constexpr const_reference at(size_type pos) const;
// 修改器
constexpr void remove_prefix(size_type n);
constexpr void remove_suffix(size_type n);
constexpr void swap(basic_string_view& s) noexcept;
// 字符串操作
constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const;
constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;
// 搜索
constexpr size_type find(basic_string_view s, size_type pos = 0) const noexcept;
// 其他搜索函数...
private:
const_pointer data_;
size_type size_;
};
以下是
basic_string_view
构造函数的流程图:
graph TD;
A[开始] --> B{选择构造函数};
B -->|basic_string_view()| C[构造空的 basic_string_view];
C --> D[size_ = 0, data_ = nullptr];
B -->|basic_string_view(const charT* str)| E{[str, str + traits::length(str)) 是否有效};
E -->|是| F[初始化 data_ 为 str, size_ 为 traits::length(str)];
E -->|否| G[错误,范围无效];
B -->|basic_string_view(const charT* str, size_type len)| H{[str, str + len) 是否有效};
H -->|是| I[初始化 data_ 为 str, size_ 为 len];
H -->|否| J[错误,范围无效];
D --> K[结束];
F --> K;
I --> K;
G --> K;
J --> K;
以下是
basic_string_view
部分操作的总结表格:
| 操作类型 | 函数 | 功能 | 复杂度 |
| ---- | ---- | ---- | ---- |
| 构造 |
basic_string_view()
| 构造空的视图 | O(1) |
| 构造 |
basic_string_view(const charT* str)
| 从字符串构造视图 | O(traits::length(str)) |
| 构造 |
basic_string_view(const charT* str, size_type len)
| 从指定长度的字符串构造视图 | O(1) |
| 容量 |
size()
| 返回视图的大小 | O(1) |
| 元素访问 |
operator[](size_type pos)
| 访问指定位置的元素 | O(1) |
| 修改器 |
remove_prefix(size_type n)
| 移除前缀 | O(1) |
| 修改器 |
remove_suffix(size_type n)
| 移除后缀 | O(1) |
| 搜索 |
find(basic_string_view s, size_type pos = 0)
| 查找子视图 | 未指定 |
C++ 字符串处理与视图类详解
7.
basic_string_view
详细解析
7.1 类型要求
在每个
basic_string_view<charT, traits>
特化中,
traits
类型必须满足字符特征要求。需要注意的是,如果
traits::char_type
与
charT
不是同一类型,程序将是格式错误的。同时,
iterator
类型要满足常量表达式迭代器要求,并且
basic_string_view
成员函数的复杂度通常为 O(1),除非另有说明。
7.2 构造与赋值
basic_string_view
提供了多种构造函数:
-
constexpr basic_string_view() noexcept;
:此构造函数用于构造一个空的
basic_string_view
,构造后能确保
size_ == 0
且
data_ == nullptr
。
-
constexpr basic_string_view(const charT* str);
:该构造函数期望
[str, str + traits::length(str))
是一个有效范围,它会用
str
初始化
data_
,用
traits::length(str)
初始化
size_
,其复杂度为 O(traits::length(str))。
-
constexpr basic_string_view(const charT* str, size_type len);
:这个构造函数要求
[str, str + len)
是有效范围,它会用
str
初始化
data_
,用
len
初始化
size_
。
以下是构造函数的使用示例表格:
| 构造函数 | 使用示例 | 说明 |
| ---- | ---- | ---- |
|
basic_string_view()
|
basic_string_view<char> sv1;
| 构造空视图 |
|
basic_string_view(const charT* str)
|
const char* s = "hello"; basic_string_view<char> sv2(s);
| 从字符串构造视图 |
|
basic_string_view(const charT* str, size_type len)
|
basic_string_view<char> sv3(s, 3);
| 从指定长度字符串构造视图 |
7.3 迭代器支持
basic_string_view
提供了丰富的迭代器支持:
constexpr const_iterator begin() const noexcept;
constexpr const_iterator cbegin() const noexcept;
constexpr const_iterator end() const noexcept;
constexpr const_iterator cend() const noexcept;
constexpr const_reverse_iterator rbegin() const noexcept;
constexpr const_reverse_iterator rend() const noexcept;
constexpr const_reverse_iterator crbegin() const noexcept;
constexpr const_reverse_iterator crend() const noexcept;
const_iterator
是一个满足常量 Cpp17 随机访问迭代器要求并模拟连续迭代器的类型,其
value_type
为模板参数
charT
。对于
basic_string_view str
,任何使
[str.data(), str.data() + str.size())
范围内指针无效的操作,都会使
str
成员函数返回的指针、迭代器和引用无效。
以下是迭代器使用的流程图:
graph TD;
A[开始] --> B[创建 basic_string_view 对象];
B --> C[获取 begin() 迭代器];
C --> D{是否到达 end()};
D -->|否| E[访问当前元素];
E --> F[迭代器递增];
F --> D;
D -->|是| G[结束];
7.4 容量操作
basic_string_view
提供了几个用于查询容量的函数:
constexpr size_type size() const noexcept;
constexpr size_type length() const noexcept;
constexpr size_type max_size() const noexcept;
[[nodiscard]] constexpr bool empty() const noexcept;
size()
和
length()
都返回
size_
,
max_size()
返回
basic_string_view
能引用的最大字符对象数,
empty()
用于判断视图是否为空。
以下是容量操作的总结表格:
| 函数 | 功能 | 返回值 | 复杂度 |
| ---- | ---- | ---- | ---- |
|
size()
| 返回视图大小 |
size_
| O(1) |
|
length()
| 返回视图长度 |
size_
| O(1) |
|
max_size()
| 返回最大可引用字符数 | 最大字符数 | O(1) |
|
empty()
| 判断视图是否为空 |
true
或
false
| O(1) |
7.5 元素访问
basic_string_view
提供了多种元素访问方式:
constexpr const_reference operator[](size_type pos) const;
constexpr const_reference at(size_type pos) const;
constexpr const_reference front() const;
constexpr const_reference back() const;
constexpr const_pointer data() const noexcept;
operator[](size_type pos)
要求
pos < size()
,返回
data_[pos]
,且不会抛出异常;
at(size_type pos)
若
pos >= size()
会抛出
out_of_range
异常;
front()
要求视图不为空,返回
data_[0]
;
back()
也要求视图不为空,返回
data_[size() - 1]
;
data()
返回
data_
,需注意该指针指向的缓冲区可能未以空字符结尾。
以下是元素访问的使用示例列表:
1. 使用
operator[]
:
basic_string_view<char> sv("hello");
char c = sv[1]; // c 为 'e'
-
使用
at:
try {
char c = sv.at(2); // c 为 'l'
char d = sv.at(5); // 抛出 out_of_range 异常
} catch (const std::out_of_range& e) {
std::cerr << e.what() << std::endl;
}
-
使用
front和back:
char f = sv.front(); // f 为 'h'
char b = sv.back(); // b 为 'o'
-
使用
data:
const char* ptr = sv.data();
7.6 修改器
basic_string_view
提供了两个修改器函数:
constexpr void remove_prefix(size_type n);
constexpr void remove_suffix(size_type n);
remove_prefix(size_type n)
要求
n <= size()
,其效果等同于
data_ += n; size_ -= n;
;
remove_suffix(size_type n)
同样要求
n <= size()
,效果等同于
size_ -= n;
。
以下是修改器使用的流程图:
graph TD;
A[开始] --> B[创建 basic_string_view 对象];
B --> C{选择修改器};
C -->|remove_prefix(size_type n)| D{ n <= size()? };
D -->|是| E[data_ += n, size_ -= n];
D -->|否| F[错误,n 超出范围];
C -->|remove_suffix(size_type n)| G{ n <= size()? };
G -->|是| H[size_ -= n];
G -->|否| I[错误,n 超出范围];
E --> J[结束];
F --> J;
H --> J;
I --> J;
通过对
basic_string_view
的详细解析,我们可以看到它在处理字符串时提供了高效、灵活且安全的方式,能帮助开发者更好地处理和操作字符串数据。同时,C++ 中丰富的字符串处理函数和哈希支持等特性,也为字符串的各种操作提供了全面的解决方案。
超级会员免费看

179

被折叠的 条评论
为什么被折叠?



