字符串

  • std::string_view 比 std::string 具备更好的性能。

  • std::string 无法被 constexpr 修饰。

字符串的构造函数如下:

构造函数作用

string(const char*s)

复制 s 的内容以初始化 string IMPORTANT: s 不得为空指针

string(Iter begin, Iter end)

复制 [begin, end) 中的内容以初始化

string(size_t n , char c)

使用 n 个 c 初始化

string(const string& b, size_t start, size_t n)

使用 b[start, start
n) 初始化

string(const char*s, size_t len)

如果 len 大于 s 长度,多余的长度是随机内容

另外有一个用于表示字符串末尾的常量 std::npos,它的值通常为 uint 的最大值。

另外是一些查找函数,这些函数查找失败时返回 std::npos:

函数签名作用

find(const string&str, size_t pos)

从字符串的 pos 开始查找 str 第一次出现时的索引

find(const char*, size_t pos)

find(const char* s, size_t pos, size_t n)

从字符串的 pos 开始,查找 s 的前 n 个字符串

rfind

与上面相似,只是是从后面开始查的

find_first_of(const char* s)

查找 s 中 任一 字符在字符串中第一次出现的位置

find_last_of

与上面相似,只是是从后面开始查的

find_first_not_of

adjacent_find

在指定范围内查找第一个连续相等的元素

如果 find 失败,则返回值为 end() 或者 rend()

=== find_first_of 不是字符串查找函数,而是字符查找函数。但是它也可以接受字符串参数。。。

常用的字符串处理函数有:

std::string::find字符串查找

std::string::replace(startPos, OldStr, NewStr)

字符串替换

std::stoi

字符串转数字

std::to_string()

数字转字符串

boost::trim(字符串)

去除空白字符

boost::join(容器, ";")

容器转字符串

boost::replace_all(操作字符串, 被替换字符串, 新字符串)

字符串替换

boost::split(容器, 待分割的字符串, boost::is_any_of(由分界符构成的字符串))

字符串分割

boost::erase_all(修改串,需要删除的子串)

字符串删除

fmt::format

字符串格式化

  • std::string::find 查找失败的返回值是 std::string::npos

  • 对于 boost 中的函数而言,使用 _copy 版本的函数代表着产生一个副本,否则则是在原字符串上修改

  • std 中的 replace 需要配合 find 使用:

    s.find("world");
    s = s.replace(startPos, OldStr, NewStr)
  • 对于字符串格式化而言,更加推荐使用 fmt

此外,还有一些辅助函数:

boost::to_upper()

转为大写

boost::to_lower()

转为小写

boost::starts_with()

判断开头

boost::ends_with()

判断结尾

boost::contains()

判断包含

以及一些谓词:

boost::is_space()

空格

boost::is_digit()

数字

参见字符串处理方式

本来是不想写的,因为一般情况下我直接就用 boost 了,但是昨天做题的时候系统输入的内容不是标准的,得自己解析,而且还只能用标准库。当时考试时比较紧张,一直没写出来,后来换 Python 了,今天做个笔记吧。

第一种是截取指定字符串,通常是配合 substrfind_first_of 使用的:

// data = "1,2,3,4,5"
while(data.length()) {
   auto tracatePos = data.find_first_of(',');
   if(tracatePos == string::npos) tracatePos = data.length();
   auto tmp = data.substr(0, tracatePos);
   arr1.push_back(stoi(tmp));
   data.erase(0, tracatePos + 1);
}

string 的 substr 和 erase 实在指定 pos 之前截取的,所以后面使用 erase 的时候需要将 pos + 1

另外一种比较坑的情况是 erase 接受 int 参数,但是行为比较奇怪,往往没法得到正确的结果,正确的方式是使用迭代器

stringstream

使用 istringstream 可以方便地将字符串中的数据储存到变量中:

std::string input = "41 3.14 false hello world";
std::istringstream stream(input);
int n;
double f;
bool b;

stream >> n >> f >> std::boolalpha >> b;
// 用 streambuf 重载释出剩余内容
stream >> std::cout.rdbuf();
std::cout << '\n';

正则表达式

目前而言,C++ 可选的正则表达式引擎有:

引擎解释

Hyperscan

主要为 Intel 优化的引擎。不支持 ARM。完整版需要采购。

re2

由 Google 开发的正则表达式引擎。

pcre2

perl 兼容的引擎。支持 jit 模式

ctre

编译期正则表达式

Boost::regex

性能不太好

std::regex

性能不咋滴。

正则表达式的性能测试可以在 regex-performance 查看。

re2

普通匹配:

assert(RE2::FullMatch("hello", "h.*o"))
assert(!RE2::FullMatch("hello", "e"))

assert(RE2::PartialMatch("hello", "h.*o"))
assert(RE2::PartialMatch("hello", "e"))

子表达式:

// Successful parsing.
int i;
string s;
assert(RE2::FullMatch("ruby:1234", "(\\w+):(\\d+)", &s, &i));
assert(s == "ruby");
assert(i == 1234);

// Fails: "ruby" cannot be parsed as an integer.
assert(!RE2::FullMatch("ruby", "(.+)", &i));

// Success; does not extract the number.
assert(RE2::FullMatch("ruby:1234", "(\\w+):(\\d+)", &s));

// Success; skips NULL argument.
assert(RE2::FullMatch("ruby:1234", "(\\w+):(\\d+)", (void*)NULL, &i));

// Fails: integer overflow keeps value from being stored in i.
assert(!RE2::FullMatch("ruby:123456789123", "(\\w+):(\\d+)", &s, &i));

预编译正则表达式:

RE2 re("(\\w+):(\\d+)");
assert(re.ok());  // compiled; if not, see re.error();

assert(RE2::FullMatch("ruby:1234", re, &s, &i));
assert(RE2::FullMatch("ruby:1234", re, &s));
assert(RE2::FullMatch("ruby:1234", re, (void*)NULL, &i));
assert(!RE2::FullMatch("ruby:123456789123", re, &s, &i));

禁止打印错误消息:

RE2 re("(ab", RE2::Quiet);  // don't write to stderr for parser failure
assert(!re.ok());  // can check re.error() for details
Last moify: 2023-12-15 04:28:35
Build time:2025-07-18 09:41:42
Powered By asphinx