将std::string_view转换为float

3

我正在尝试使用C++20编译器将std::string_view直接转换为浮点数,而不需要先将其转换为std::string(这会导致额外的堆分配)。

#include <iostream>
#include <charconv>

int main() {
    std::string_view s = "123.4";
    float x;
    std::from_chars(s.data(), s.data() + s.size(), x);
        
    std::cout << x << std::endl;
}

但我无法编译这段代码:

error: no matching function for call to 'from_chars(std::basic_string_view<char>::const_pointer, std::basic_string_view<char>::const_pointer, float&)'

我做错了什么?

3
你确定你的编译器支持浮点数的 from_chars 吗?许多编译器目前还无法实现它。 - ALX23z
既然您有一个视图而不是std::string,那么也许可以使用std::strtof - Some programmer dude
另外,除非您有非常特定的要求需要使用“float”,否则请改用“double”。它是C++的“本地”浮点类型。 - Some programmer dude
这看起来还不错: https://godbolt.org/z/rT87ajnTj (没有可见的转换),我刚意识到 end 的初始化甚至是不必要的。 - Pepijn Kramer
1
它在GCC(Trunk)上运行 https://godbolt.org/z/KMevc1Yfx。也许你的编译器还不支持它。 - foragerDev
显示剩余2条评论
4个回答

4

GCC的C++标准库实现在GCC 11.1中首次支持std::from_chars用于float,而10.x不支持。

如果您不检查成功,并且知道您的字符串以空字符结尾,那么可以使用同样不安全的atof()。如果想要正确检查解析错误,请使用strtof,它将给出与from_chars类似的信息,表示输入是否匹配:

#include <iostream>
#include <cstdlib>

int main() {
    std::string_view s = "123.4";
    char * end;
    float x = std::strtof(s.data(), &end);
    if (end != s.data() + s.size())
    {
        std::cout << "Parse error";
    }
    else
    {
        std::cout << x << std::endl;
    }
}

0

只有当您知道您的字符串视图以空字符结尾时,才可以使用此方法。

float x = static_cast<float>(atof(s.data()));

0

查看charconv头文件。例如,GCC在其中有下一个保护程序

#if defined __cpp_lib_to_chars || _GLIBCXX_HAVE_USELOCALE

这可能是因为它没有被实现,或者您的编译器未配置为使用至少C++17标准。例如,对于GCC和Clang没有-std=c++20,对于Microsoft VC++命令行选项没有/std:c++latest传递给编译器,或者您的实现即端口未实现此功能并且未完全实现标准。

您始终可以使用strtof c函数替换from_chars。

例如:

#include <iostream>
#include <string_view>
#include <system_error>
#include <cmath>
#include <charconv>
#include <cstdlib>

int main(int argc, const char** argv)
{
    std::string_view sv("12.345678");

#ifdef __cpp_lib_to_chars
    float result = NAN;
    auto conv_ret = std::from_chars(sv.data(), (sv.data() + sv.size()), result);
    std::error_code ec = std::make_error_code(conv_ret.ec);
#else
    char *endp = nullptr;
    float result = std::strtof(sv.data(), &endp);
    std::error_code ec;
    if (errno == ERANGE) {
        ec = std::make_error_code(std::errc::result_out_of_range);
    }
#endif
    if(ec) {
        std::cerr << ec.message() << std::endl;
        return ec.value();
    }
    std::cout << "Float: " << result  << std::endl;
    return 0;
}

-1
error: no matching function for call to 'from_chars(std::basic_string_view<char>::const_pointer, std::basic_string_view<char>::const_pointer, float&)'

尝试了基于上述错误的以下代码:
#if defined(CYGWIN_NT) || defined(AIX71) || defined(SUNOS)
    #include <iostream>
    using namespace std;
#elif defined(LINUX) || defined(HPUX11)
    #include <iostream.h>
#else
    #error handle iostream/iostream.h error.
#endif
#include <charconv>
int main()
{
    string_view s = "123.4";
    // Always better to initialize.
    float x = 0.0f;
    from_chars(s.data(), s.data() + s.size(), x);
    cout << x << endl;
    return 0;
}
// Sample compilation:
// echo g++ -Wall 73333331.cpp -D$(uname -s | sed "s/-[0-9].*.[0-9].*-[0-9].*//;") -std=c++20 -o ./a.out
// g++ -Wall 73333331.cpp -DCYGWIN_NT -std=c++20 -o ./a.out
// ./a.out
// 123.4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接