如何将 std::string_view 转换为 double?
How to convert std::string_view to double?
我正在为应用程序的自定义选项文件编写 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
的确切部分,其中包含我要提取的值,但我无法弄清楚读取 [=15= 的方法] 来自 std::string_view
.
我知道 std::stod
不适用于 std::string_view
。它允许我写
double value = std::stod(std::string(value_str));
然而,这很丑陋,因为它转换为实际上不需要的字符串,即使在我的情况下它可能不会产生明显的差异,但如果必须读取大量数据,它可能会太慢文本文件中的数字。
另一方面,atof
将不起作用,因为我不能保证空终止符。我可以通过在构造它时将 [=25=]
添加到 useful_statement
来破解它,但这会使代码与 reader 混淆并且如果代码是 [=39= 则它太容易破解了].
那么,什么是干净、直观且合理有效的方法呢?
既然你用 C++1z 标记了你的问题,那么(理论上)意味着你可以访问 from_chars
。它可以处理你的字符串到数字的转换,只需要一对 const char*
s:
double dbl;
auto result = from_chars(value_str.data(), value_str.data() + value_str.size(), dbl);
当然,这需要您的标准库提供 from_chars
.
的实现
Headers:
#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
p.s。可以使用 vcpkg 轻松安装 Boost(默认为 32 位,第二个命令用于 64 位):
vcpkg install boost-convert
vcpkg install boost-convert:x64-windows
更新:显然,许多 Boost 函数在内部使用字符串流,它锁定了全局 OS 语言环境。所以他们的 multi-threaded 表现很糟糕**。
我现在建议使用 substr 来代替 stoi()
。参见:Safely convert std::string_view to int (like stoi or atoi)
** Boost 的这个奇怪的怪癖使大多数 Boost 字符串处理在 multi-threaded 环境中完全无用,这确实是一个奇怪的悖论。这是来之不易的经验之谈的声音-如果您有任何疑问,请自行测量。与 2 核机器相比,48 核机器在调用许多 Boost 时运行速度并不快。所以现在我避免使用 Boost 的某些部分,就像众所周知的瘟疫一样,因为任何东西都可能依赖于那个该死的全局 OS 区域设置锁。
我正在为应用程序的自定义选项文件编写 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
的确切部分,其中包含我要提取的值,但我无法弄清楚读取 [=15= 的方法] 来自 std::string_view
.
我知道 std::stod
不适用于 std::string_view
。它允许我写
double value = std::stod(std::string(value_str));
然而,这很丑陋,因为它转换为实际上不需要的字符串,即使在我的情况下它可能不会产生明显的差异,但如果必须读取大量数据,它可能会太慢文本文件中的数字。
另一方面,atof
将不起作用,因为我不能保证空终止符。我可以通过在构造它时将 [=25=]
添加到 useful_statement
来破解它,但这会使代码与 reader 混淆并且如果代码是 [=39= 则它太容易破解了].
那么,什么是干净、直观且合理有效的方法呢?
既然你用 C++1z 标记了你的问题,那么(理论上)意味着你可以访问 from_chars
。它可以处理你的字符串到数字的转换,只需要一对 const char*
s:
double dbl;
auto result = from_chars(value_str.data(), value_str.data() + value_str.size(), dbl);
当然,这需要您的标准库提供 from_chars
.
Headers:
#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
p.s。可以使用 vcpkg 轻松安装 Boost(默认为 32 位,第二个命令用于 64 位):
vcpkg install boost-convert
vcpkg install boost-convert:x64-windows
更新:显然,许多 Boost 函数在内部使用字符串流,它锁定了全局 OS 语言环境。所以他们的 multi-threaded 表现很糟糕**。
我现在建议使用 substr 来代替 stoi()
。参见:Safely convert std::string_view to int (like stoi or atoi)
** Boost 的这个奇怪的怪癖使大多数 Boost 字符串处理在 multi-threaded 环境中完全无用,这确实是一个奇怪的悖论。这是来之不易的经验之谈的声音-如果您有任何疑问,请自行测量。与 2 核机器相比,48 核机器在调用许多 Boost 时运行速度并不快。所以现在我避免使用 Boost 的某些部分,就像众所周知的瘟疫一样,因为任何东西都可能依赖于那个该死的全局 OS 区域设置锁。