如何将标准::string_view转换为双倍?

How to convert std::string_view to double?

本文关键字:转换 view 标准 string      更新时间:2023-10-16

我正在为应用程序的自定义选项文件编写一个 c++ 解析器。我有一个循环,可以从文本文件中读取option=value形式的行,value必须将其转换为double。在伪代码中,它执行以下操作:

while(not EOF)
statement <- read_from_file
useful_statement <- remove whitespaces, comments, etc from statement
equal_position <- find '=' in useful_statement
option_str <- useful_statement[0:equal_position)
value_str <- useful_statement[equal_position:end)
find_option(option_str) <- double(value_str)

为了处理字符串拆分和传递给函数,我使用std::string_view因为它避免了过度复制并清楚地说明了查看预先存在的std::string段的意图。我已经完成了所有工作,以至于std::string_view value_str指向包含我要提取的值的useful_statement的确切部分,但我无法弄清楚从std::string_view读取double的方法。

我知道std::stod不适用于std::string_view.它允许我写

double value = std::stod(std::string(value_str));

然而,这很丑陋,因为它转换为实际上不需要的字符串,即使它在我的情况下可能不会产生明显的差异,但如果必须从文本文件中读取大量数字,它可能太慢了。

另一方面,atof不起作用,因为我无法保证空终止符。我可以通过在构造它时向useful_statement添加来破解它,但这会使读者对代码感到困惑,并且如果代码被更改/重构,它很容易被破坏。

那么,什么是干净、直观和合理有效的方法来做到这一点呢?

既然你用 C++1z 标记了你的问题,那么(理论上(意味着你可以访问from_chars.它可以处理您的字符串到数字的转换,而只需要一对const char*

double dbl;
auto result = from_chars(value_str.data(), value_str.data() + value_str.size(), dbl);

当然,这需要您的标准库提供from_chars的实现。

标头:

#include <boost/convert.hpp>
#include <boost/convert/strtol.hpp>

然后:

std::string x { "aa123.4"};
const std::string_view y(x.c_str()+2, 5); // Window that views the characters "123.4".
auto value = boost::convert<double>(y, boost::cnv::strtol());
if (value.has_value())
{
cout << value.get() << "n"; // Prints: 123.4
}

经过测试的编译器:

  • MSVC 2017

附言可以使用 vcpkg 轻松安装 Boost(默认为 32 位,第二个命令适用于 64 位(:

vcpkg install boost-convert
vcpkg install boost-convert:x64-windows

更新:显然,许多 Boost 函数在内部使用字符串流,这锁定了全局操作系统区域设置。因此,它们的多线程性能很差**。

我现在建议使用 substr 代替stoi()。请参阅:安全地将 std::string_view 转换为 int(如 stoi 或 atoi(

** Boost 的这种奇怪怪癖使得大多数 Boost 字符串处理在多线程环境中完全无用,这确实是一个奇怪的悖论。这是来之不易的经验说话的声音 - 如果您有任何疑问,请自己衡量。与 2 核计算机相比,48 核计算机在多次 Boost 调用下的运行速度并不快。所以现在我避免了 Boost 的某些部分,比如众所周知的瘟疫,因为任何事情都可能依赖于该死的全局操作系统区域设置锁。