【问题标题】:::tolower using std::transform::tolower 使用 std::transform
【发布时间】:2022-11-22 23:29:40
【问题描述】:

为什么 std::transform 不能这样工作:

std::string tmp = "WELCOME";
std::string out = "";
std::transform(tmp.begin(), tmp.end(), out.begin(), ::tolower);

出来是空的!

但这有效:

std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);

我不希望转换就地发生。

【问题讨论】:

  • C++ 算法分配给范围。有成为那里分配的范围。空字符串是一个空范围。但是请注意,您的代码 sn-p 中有一点未定义的行为。
  • 你需要通过back_inserter

标签: c++ transform std tolower


【解决方案1】:

您正在越界内存中写入,因为 out 的范围小于 tmp 的范围。您可以通过应用std::back_inserter将结果存储在out中。

正如 user17732522 指出的那样,由于 it's not legal to take the adress of a standard libary function,最好在需要时传递在 char 上调用 std::tolower 的 lamda 对象。

std::transform(tmp.begin(), tmp.end(), std::back_inserter(out), [](char c) {
    return std::tolower(c);
});

【讨论】:

  • std::tolower 更糟糕:“如果参数的值既不能表示为 unsigned char 也不等于 EOF,则 std::tolower 的行为未定义”,需要从 int 转换为 unsigned char/。
【解决方案2】:

一种方法是调整字符串的大小,为 std::transform 分配足够的内存来填充它。

out.resize(tmp.size()); // <---
std::transform(tmp.begin(), tmp.end(), out.begin(), ::tolower);

或者,正如其他人提到的,您可以使用std::back_inserter,它会为您处理插入。我们也可以调用out.reserve 来节省分配时间(尤其是当您的字符串很大时)。

out.reserve(tmp.size()); // (optional) Smol optimisation.
std::transform(tmp.begin(), tmp.end(), std::back_inserter(out), ::tolower);

【讨论】:

  • 这通常会起作用,但如果直接传递像 ::tolower 这样的标准库函数,该行为在技术上仍未指定。应该传递调用该​​函数的 lambda。
猜你喜欢
  • 1970-01-01
  • 2015-10-13
  • 2016-04-22
  • 2020-04-24
  • 1970-01-01
  • 2011-07-29
  • 2018-04-07
  • 1970-01-01
  • 2011-09-14
相关资源
最近更新 更多