How to convert std::string_view to double?

佐手、 提交于 2020-12-04 15:58:13

问题


I'm writing a c++ parser for a custom option file for an application. I have a loop that reads lines in the form of option=value from a text file where value must be converted to double. In pseudocode it does the following:

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)

To handle the string splitting and passing around to functions, I use std::string_view because it avoids excessive copying and clearly states the intent of viewing segments of a pre-existing std::string. I've done everything to the point where std::string_view value_str points to the exact part of useful_statement that contains the value I want to extract, but I can't figure out the way to read a double from an std::string_view.

I know of std::stod which doesn't work with std::string_view. It allows me to write

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

However, this is ugly because it converts to a string which is not actually needed, and even though it will presumably not make a noticeable difference in my case, it could be too slow if one had to read a huge amount of numbers from a text file.

On the other hand, atof won't work because I can't guarantee a null terminator. I could hack it by adding \0 to useful_statement when constructing it, but that will make the code confusing to a reader and make it too easy to break if the code is altered/refactored.

So, what would be a clean, intuitive and reasonably efficient way to do this?


回答1:


Since you marked your question with C++1z, then that (theoretically) means you have access to from_chars. It can handle your string-to-number conversion without needing anything more than a pair of const char*s:

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

Of course, this requires that your standard library provide an implementation of from_chars.




回答2:


Headers:

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

Then:

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
}

Tested Compilers:

  • MSVC 2017

p.s. Can easily install Boost using vcpkg (defaults to 32-bit, second command is for 64-bit):

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

Update: Apparently, many Boost functions use string streams internally, which has a lock on the global OS locale. So they have terrible multi-threaded performance**.

I would now recommend something like stoi() with substr instead. See: Safely convert std::string_view to int (like stoi or atoi)

** This strange quirk of Boost renders most of Boost string processing absolutely useless in a multi-threaded environment, which is strange paradox indeed. This is the voice of hard won experience talking - measure it for yourself if you have any doubts. A 48-core machine runs no faster with many Boost calls compared to a 2-core machine. So now I avoid certain parts of Boost like the proverbial plague, as anything can have a dependency on that damn global OS locale lock.



来源:https://stackoverflow.com/questions/45637697/how-to-convert-stdstring-view-to-double

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!