2010-06-26 17 views
5

की वृद्धि भावना क्यूई न्यूमेरिक पार्सिंग मैं निम्नलिखित परिणाम को समझने की कोशिश कर रहा हूं। परीक्षण का मामला कोडपूर्णांक और फ्लोटिंग पॉइंट्स

#include <boost/config/warning_disable.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix_core.hpp> 
#include <boost/spirit/include/phoenix_operator.hpp> 
#include <boost/spirit/include/phoenix_fusion.hpp> 
#include <boost/spirit/include/phoenix_stl.hpp> 
#include <boost/fusion/include/adapt_struct.hpp> 
#include <boost/variant/recursive_variant.hpp> 
#include <boost/spirit/home/support/context.hpp> 
#include <boost/spirit/home/phoenix.hpp> 
#include <boost/foreach.hpp> 

#include <iostream> 
#include <fstream> 
#include <string> 
#include <cstdlib> 
#include <vector> 

namespace sp = boost::spirit; 
namespace qi = boost::spirit::qi; 
using namespace boost::spirit::ascii; 

namespace fusion = boost::fusion; 
namespace phoenix = boost::phoenix; 

using phoenix::at_c; 
using phoenix::push_back; 
using phoenix::bind; 

template <typename P> 
void test_parser(
    char const* input, P const& p, bool full_match = true) 
{ 
    using boost::spirit::qi::parse; 

    char const* f(input); 
    char const* l(f + strlen(f)); 
    if (parse(f, l, p) && (!full_match || (f == l))) 
     std::cout << "ok" << std::endl; 
    else 
     std::cout << "fail" << std::endl; 
} 


int main() { 

test_parser("+12345", qi::int_); //Ok 
test_parser("+12345", qi::double_ - qi::int_); //failed, as expected 
test_parser("+12345.34", qi::int_); // failed, as expected 
test_parser("+12345.34", qi::double_ - qi::int_); //failed but it should be Ok! 
}; 

है प्रेरणा यहाँ है कि मैं नंबर '12345' पूर्णांक के रूप में और कभी नहीं के रूप में चल अंक मिलान करना चाहते हैं। '12345.34' डबल_ से मेल खाता है और कभी भी int_ नहीं होगा लेकिन पारस्परिक मामला सत्य नहीं है; '12345' दोनों पूर्णांक (int_) और फ़्लोटिंग पॉइंट (double_) से मेल खाता है। मैंने double_ - int_ की कोशिश की और यह '12345' से मेल खाने में सफलतापूर्वक विफल रहा। हालांकि मेरी आशा थी कि अंतिम टेस्ट केस '12345.34' सकारात्मक रूप से डबल_ - int_ से मेल खाता है, लेकिन परिणाम जो मुझे मिलता है वह मेल नहीं हो पाता है।

क्यों यह इतना है, और मैं कैसे एक पार्सर कि केवल पूर्णांकों से मेल खाता है और दूसरा वह केवल अस्थायी अंक से मेल खाता है मिलता है डबल के साथ (जैसे ग में, 5.0 चल बिन्दु रूप में दर्शाया जाएगा)

उत्तर

14

आपके विशिष्ट उदाहरण के लिए, मुझे लगता है कि यह वास्तव में Boost Spirit documentation में RealPolicies विशेषज्ञता के तहत वर्णित है। आप के लिए चीजों को थोड़ा आसान बनाने के लिए, मैं एक त्वरित "असली" पार्सर बाहर मार पड़ी है, कि केवल वास्तविक संख्या और नहीं पूर्णांकों को पार्स करता है (या कम से कम यह अपने सरल उदाहरण के साथ काम किया):

template <typename T> 
struct strict_real_policies : qi::real_policies<T> 
{ 
    static bool const expect_dot = true; 
}; 

qi::real_parser< double, strict_real_policies<double> > real; 

और आप उपयोग कर सकते हैं यह किसी अन्य पार्सर की तरह है (जैसे int_ और double_)। आप जोड़ने के लिए हो सकता है:

#include <boost/spirit/include/qi_numeric.hpp> 

यह संकलित करने के लिए प्राप्त करने के लिए।

+0

+1 यह एक बेहतर समाधान है। – academicRobot

+0

धन्यवाद, यह सही काम करता है – lurscher

4
समस्या

नहीं-int qi::double_ - qi::int_ यह है कि एक व्यक्तिगत पार्सर को एक सफल मैच होने के लिए पूरे इनपुट से मेल नहीं करना पड़ेगा। "12,345.34" के लिए, क्यूई :: double_ पूरी बात और क्यूई :: पूर्णांक पर एक सफल मैच, "12,345" पर एक सफल मैच देता है, ताकि qi::double_ - qi::int_ एक गैर मुकाबला नहीं है बनाता है। अंतर ऑपरेटर के लिए, प्रत्येक पार्सर को अलग से लागू करने के बारे में सोचें और क्या इनपुट के पहले भाग के लिए प्रत्येक के लिए एक वैध मिलान है या नहीं।

आप क्यूई :: int_ के बाद सीमा के कुछ प्रकार की आवश्यकता द्वारा व्यवहार आप चाहते हैं मिल सकता है। क्या होता है जब एक qi :: int_ फ़्लोट के पहले भाग से मेल खाता है, एक वैध फ्लोट (उदाहरण के लिए "+12345.34" मैचों "+12345" पर qi :: int_ स्ट्रीम के आगे ".34" छोड़कर)। इसलिए, आप एक नाव के लिए आगे एक नकारात्मक देखो कर सकते हैं:

int_rule %= qi::int_ >> !qi::double_; 

double_rule %= qi::double_ - int_rule; 

या

double_rule %= qi::double_ - (qi::int_ >> !qi::double_); 

!qi::double भी खाली स्थान के और ईओआई के लिए सच है, तो मुझे लगता है इस मानक प्रारूप के लिए बहुत सामान्य होना चाहिए। हालांकि यह वैज्ञानिक नोटेशन के लिए काम नहीं करेगा।

+0

आह मैं एबी ऑपरेटर अभिनय किया सोचा: दिए गए एक स्ट्रिंग एन से मेल खाता है कि एक, अगर B यह तो मेल खाता एबी से मेल नहीं खाएगी (लेकिन यहाँ बात का उल्लेख है, यह बी के साथ इसके बारे में _part_ मिलान कर सकते हैं, पूरी बात नहीं) तो बहुत सहज नहीं है, लेकिन अब मैं समझता हूं, धन्यवाद! – lurscher

संबंधित मुद्दे