C++ 如何使用boost::spirit::qi::parse从字符数组中解析double

C++ 如何使用boost::spirit::qi::parse从字符数组中解析double,c++,c++11,boost-spirit,C++,C++11,Boost Spirit,我可以从存储在std::string、std::vector或std::array中的字符解析数字。 但是,当字符位于std::unique\u ptr中保存的缓冲区中时,我无法这样做。 我可以将缓冲区复制到一个字符串中,以增强精神,但我希望避免这种复制 以下是我的尝试: #include<memory> #include<array> #include<iostream> #include "boost/spirit/include/qi.hpp" in

我可以从存储在std::string、std::vector或std::array中的字符解析数字。 但是,当字符位于std::unique\u 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;
}

请参阅Zalman的anwer

boost::spirit::qi::parse
使用开始和结束迭代器。您可能需要以下内容:

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

也就是说,普通指针作为迭代器工作,您可以通过添加到开始指针来形成结束指针。

这样做会导致太多问题:

  • unique\u ptr没有
    data()
    成员函数
  • qi::parse
    不将大小作为第二个参数
  • 可以将不确定值自由复制到数组/
    unique\u ptr
  • 更糟糕的是,你甚至试图解析它。Spirit不会将NUL字符视为特殊字符,所以您“似乎”能够正确解析,只是因为您忽略了未解析的尾随垃圾
  • 您正在混合
    wcout
    cout
    ,这是未指定的
以下是大多数问题的解决方案:

#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;
    }
}
#包括
#包括
#包括
#包括
int main(){
const int max_size=40;
标准::wstring src=L“5178120.3663”;
const int actual_len=src.length()+1;//包含NUL字符
{
std::数组numeric1;
std::wcsncpy(numeric1.data(),src.data(),实际长度);
双数值=0.0;
boost::spirit::qi::parse(numeric1.begin(),numeric1.end(),num);
标准:输出精度(15);

std::wcout这是正确的答案。请修改如下,我将接受;boost::spirit::qi::parse(numeric2.get(),numeric2.get()+wcslen(numeric2.get()),num)因为它不会编译为固定使用wcsnlen,它应该匹配宽字符类型,并且仍然保证不会耗尽缓冲区的末尾。在示例代码中,可能最好只是硬编码输入字符串的长度。添加了演示。只是好奇为什么要为空字符添加空间,而wcsncpy会解决这个问题。说实话我从未看过
wcsncpy
的文档(我的问题是“如果你已经知道长度,为什么要使用
wcsncpy
wcslen
)。
#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;
    }
}