【问题标题】:How to parse a double from an array of characters using boost::spirit::qi::parse如何使用 boost::spirit::qi::parse 从字符数组中解析双精度
【发布时间】:2017-10-05 21:25:47
【问题描述】:

我可以从存储在 std::string、std::vector 或 std::array 中的字符中解析数字。 但是当字符在 std::unique_ptr 中保存的缓冲区中时,我无法这样做。 我可以将缓冲区复制到一个字符串中以增强精神,但我想避免这种复制

这是我的尝试:

#include<memory>
#include<array>
#include<iostream>
#include "boost/spirit/include/qi.hpp"


int main()
{
    const int max_size = 40;
    std::array<wchar_t, max_size> numeric1;
    std::wstring src = L"5178120.3663";
    std::wcsncpy(numeric1.data(), src.data(), max_size);

    double num = 0.0;
    boost::spirit::qi::parse(numeric1.begin(), numeric1.end(), num);
    std::cout.precision(15);
    std::cout << num << std::endl; // OK

    std::unique_ptr<wchar_t[]> numeric2(new wchar_t[max_size]);
    std::wcsncpy(numeric2.get(), src.data(), max_size);
    std::wcout << L"ok = " << std::wstring(numeric2.get()) << std::endl; // OK

    boost::spirit::qi::parse(numeric2.data(), max_size, num); // fails to compile 
    std::cout.precision(15);
    std::cout << num << std::endl;

    //  'boost::spirit::qi::parse': no matching overloaded function found

    return 0;
}

修复:

boost::spirit::qi::parse(numeric2.get(), numeric2.get() + wcslen(numeric2.get()), num);

查看 Zalman 的回答

【问题讨论】:

    标签: c++ c++11 boost-spirit


    【解决方案1】:

    boost::spirit::qi::parse 采用开始和结束迭代器。你可能想要这样的东西:

    boost::spirit::qi::parse(numeric2.get(), numeric2.get() + wcsnlen(numeric2.get(), max_size), num);
    

    即普通指针用作迭代器,您可以通过添加到开始指针来形成结束指针。

    【讨论】:

    • 这是正确答案。请进行如下修改,我会接受; boost::spirit::qi::parse(numeric2.get(), numeric2.get() + wcslen(numeric2.get()), num) 因为它不能按原样编译
    • 修复使用 wcsnlen,它应该匹配宽字符类型并且仍然保证不会跑出缓冲区的末尾。在示例代码中,最好还是硬编码输入字符串的长度。
    【解决方案2】:

    这个问题太多了:

    • unique_ptr 没有data() 成员函数
    • qi::parse 不将大小作为第二个参数
    • 您将不确定的值随意复制到数组/unique_ptr&lt;wchar_t[]&gt;
    • 更糟糕的是,您甚至尝试解析它。 Spirit 不会将 NUL 字符视为特殊字符,因此您“似乎”可以正确解析,只是因为您忽略了未解析的尾随垃圾
    • 您正在混合 wcoutcout,这是未指定的

    这是对大多数事情的修复:

    Live On Coliru

    #include <boost/spirit/include/qi.hpp>
    #include <array>
    #include <iostream>
    #include <memory>
    
    int main() {
        const int max_size = 40;
        std::wstring src = L"5178120.3663";
        const int actual_len = src.length() + 1; // include NUL character
    
        {
            std::array<wchar_t, max_size> numeric1;
            std::wcsncpy(numeric1.data(), src.data(), actual_len);
    
            double num = 0.0;
            boost::spirit::qi::parse(numeric1.begin(), numeric1.end(), num);
            std::wcout.precision(15);
            std::wcout << num << std::endl; // OK
        }
    
        {
            std::unique_ptr<wchar_t[]> numeric2(new wchar_t[max_size]);
            std::wcsncpy(numeric2.get(), src.data(), actual_len);
    
            double num = 0.0;
            boost::spirit::qi::parse(numeric2.get(), numeric2.get() + actual_len, num);
            std::wcout.precision(15);
            std::wcout << num << std::endl;
        }
    }
    

    【讨论】:

    • 添加了演示Live On Coliru
    • 只是好奇为什么在 wcsncpy 会处理的情况下为空字符添加空格。
    • 老实说,我从来没有看过wcsncpy 的文档(我的问题是“如果你已经知道长度,为什么还要使用wcsncpywcslen”)。
    猜你喜欢
    • 1970-01-01
    • 2017-08-10
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多