2017-10-05 3 views
2

Je peux analyser des nombres à partir de caractères stockés dans std :: string, std :: vector ou std :: array. Mais je ne suis pas capable de le faire quand les caractères sont dans un tampon contenu dans std :: unique_ptr. je pouvais copier le tampon dans une chaîne puis pour stimuler l'esprit, mais je veux éviter cette copieComment analyser un double d'un tableau de caractères en utilisant boost :: spirit :: qi :: parse

Voici ma tentative:

#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; 
} 

Le correctif:

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

Voir Zalman de anwer

Répondre

1

boost::spirit::qi::parse prend un itérateur de début et de fin. Vous voulez probablement quelque chose comme:

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

I.e. Les pointeurs simples fonctionnent comme des itérateurs et vous pouvez former le pointeur de fin en ajoutant au début.

+0

C'est le bonne réponse. S'il vous plaît modifier comme suit et je vais accepter; boost :: esprit :: qi :: parse (numeric2.get(), numeric2.get() + wcslen (numeric2.get()), num) car il ne compile pas tel quel –

+0

Fixé pour utiliser wcsnlen, qui devrait correspondre le type de char large et garantit toujours de ne pas couler la fin de la mémoire tampon. Dans l'exemple de code, il est peut-être préférable de tout simplement coder en dur la longueur de la chaîne d'entrée. –

0

Trop de choses sont hors avec ceci:

  • unique_ptr ne dispose pas d'une fonction membre data()
  • qi::parse ne prend pas une taille comme second paramètre
  • vous copier des valeurs indéterminées généreusement le tableau/unique_ptr<wchar_t[]>
  • pire, vous essayez même de l'analyser. Esprit ne traite pas les caractères NUL comme spécial, vous avait « semble » pour analyser correctement, uniquement parce que vous ne tenez pas compte des déchets de fuite unparsed
  • vous mixez wcout et cout qui est non spécifiée

est ici un correction de la plupart des choses:

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; 
    } 
} 
+0

Démonstration ajoutée [Live On Coliru] (http://coliru.stacked-crooked.com/a/f35879c92c25580a). – sehe

+0

Juste curieux de savoir pourquoi ajouter de l'espace pour le caractère nul quand wcsncpy prendra soin de cela. –

+0

Pour être honnête, je n'ai jamais regardé les documents pour 'wcsncpy' (ma question serait" pourquoi utiliser 'wcsncpy' ou' wcslen' si vous connaissez déjà la longueur "). – sehe