??xml version="1.0" encoding="utf-8" standalone="yes"?>国产精品嫩草99av在线,亚洲青色在线,亚洲性感激情http://www.shnenglu.com/dancefire/archive/2011/03/09/fix-bad-superblock-in-linux.htmlDancefireDancefireTue, 08 Mar 2011 19:30:00 GMThttp://www.shnenglu.com/dancefire/archive/2011/03/09/fix-bad-superblock-in-linux.htmlhttp://www.shnenglu.com/dancefire/comments/141389.htmlhttp://www.shnenglu.com/dancefire/archive/2011/03/09/fix-bad-superblock-in-linux.html#Feedback3http://www.shnenglu.com/dancefire/comments/commentRss/141389.htmlhttp://www.shnenglu.com/dancefire/services/trackbacks/141389.html阅读全文

Dancefire 2011-03-09 03:30 发表评论
]]>
也谈表达式分析和计算http://www.shnenglu.com/dancefire/archive/2009/02/04/72964.htmlDancefireDancefireWed, 04 Feb 2009 04:02:00 GMThttp://www.shnenglu.com/dancefire/archive/2009/02/04/72964.htmlhttp://www.shnenglu.com/dancefire/comments/72964.htmlhttp://www.shnenglu.com/dancefire/archive/2009/02/04/72964.html#Feedback5http://www.shnenglu.com/dancefire/comments/commentRss/72964.htmlhttp://www.shnenglu.com/dancefire/services/trackbacks/72964.html王博?/a> Blog中?a href="http://www.shnenglu.com/d3d/archive/2009/02/03/72851.html">五进制?/a>q篇文章。其中关?q制?0q制的{换自然没有什么意思,q篇文章l的代码主要是讨论如何进行表辑ּ分析和计的。作者自制了一个StackQƈ且用其Ş成了两个堆栈分别用于存储数值和q算W。比较典型的表达式处理的Ҏ。从实现上看Q代码有些臃肿,而且必要的优化很,另外是没有充分利用标准提供的便利。比如那个Stack完全没有必要自制QSTL提供的std::stack<T>可以很好的完成Q务?br>
而今天我要做的是Q用boost::spirit来实现同L表达式分析和计算。众所周知Qboost是C++中质量很高的库,被称为准标准库,因ؓ其存在的一个很重要的目的就是ؓ下一代C++库提供预案。目前已l有大量的boost库成ZC++标准库的一部分。我现在要用的是Boost的Spirit?/a>。这个库可以直接在C++代码中撰写EBNF。学q编译原理的朋友应该Ҏ都很熟悉Q这是一U比堆栈更灵zȝ解析表达式甚至程序的方式?br>
如果我们要处理四则运的表达式,那么我们只需要在C++中写入下列EBNF的定义:

    group       = '(' >> expression >> ')';
    factor      
= integer | group;
    term        
= factor >> *(('*' >> factor) | ('/' >> factor));
    expression  
= term >> *(('+' >> term) | ('-' >> term));

我们构成了q个表达式的格式定义Q它可以很轻杄处理下列表达式的q算Q?br>
    12345
    
-12345
    
+12345
    
1 + 2
    
1 * 2
    
1/2 + 3/4
    
1 + 2 + 3 + 4
    
1 * 2 * 3 * 4
    (
1 + 2* (3 + 4)
    (
-1 + 2* (3 + -4)
    
1 + ((6 * 200- 20/ 6
    (
1 + (2 + (3 + (4 + 5))))

很简单吧Q?br>
使用qyacc或?lex的朋友对q类定义肯定很熟悉。但是所不同的是Q他们都是让用户写一个模板,然后用yacc或?lex处理模板生成相应语言的程序。程序臃肿且很难阅读。而且׃不是自己写的E序Q调整v来总要l过一步手l,比较J琐?br>
而用C++的朋友则不用有这U烦|Boost的Spirit充分利用了C++强大的语法功能。我们可以直接在E序中写入上q的表达式定义,然后我们的程序就支持q些表达式的处理了。不需要Q何额外的E序处理。所需要的仅仅是include一些头文g而已。是的,仅仅是include一些头文g。不要担心需要安装什么额外的东西Q或者需要链接什么库Q因为Spirit的实现完全是头文件组成的Q我们不需要链接Q何库。把boost的头文g路径攑ֈ~译期中Q直接编译就ok了。很dy?br>
下面是我用Boost Spirit实现的四则运表辑ּ的代码,׃我的重点是表辑ּ的解析和计算Q因此我没有特别处理五进制到十进制的转换问题。但是添加v来显然不ȝ。我只给Z一个五q制整数部分的输出。如果表辑ּ出错Q可以直接用头指出哪里有错。很方便调试Q) 而且代码量是原文章的五分之一。编译后也仅仅是35KBQ也不是很臃肿的?br>
大家多了解标准库Q多了解BoostQC++的编码也是很有趣味的?br>
#include <boost/config/warning_disable.hpp>
#include 
<boost/spirit/include/qi.hpp>
#include 
<boost/spirit/include/phoenix_operator.hpp>

#include 
<iostream>
#include 
<string>
#include 
<cmath>
#include 
<limits>

using namespace boost::spirit;
using namespace boost::spirit::qi;
using namespace boost::spirit::ascii;
using namespace boost::spirit::arg_names;

template 
<typename Iterator>
struct calculator : grammar<Iterator, double(), space_type>
{
    calculator() : calculator::base_type(expression)
    {
        expression 
= term[_val = _1]
        
>> *( ('+' >> term[_val += _1]) | ('-' >> term[_val -= _1]) );

        term 
= factor[_val = _1]
        
>> *( ('*' >> factor[_val *= _1]) | ('/' >> factor[_val /= _1]) );

        factor 
= double_[_val = _1]    | '(' >> expression[_val = _1] >> ')'
            
|   ('-' >> factor[_val = -_1]) | ('+' >> factor[_val = _1]);
    }

    rule
<Iterator, double(), space_type> expression, term, factor, number;
};

//    http://www.jb.man.ac.uk/~slowe/cpp/itoa.html
std::string itoa(int value, int base) {
    
const int MAX_DIGITS = 35;
    
const char* DIGITS = "0123456789abcdefghijklmnopqrstuvwxyz";
    std::
string buf;
    buf.reserve( MAX_DIGITS ); 
// Pre-allocate enough space.
    if (base < 2 || base > 36return buf;
    
int quotient = value;
    
do {
        buf.push_back(DIGITS[ std::abs(quotient 
% base) ]);
        quotient 
/= base;
    } 
while ( quotient );
    
if ( value < 0) buf.push_back('-');
    std::reverse( buf.begin(), buf.end() );
    
return buf;
}

int main(int argc, char* argv[])
{
    std::cout 
<< "误入一个表辑ּQ如Q?+2.5*(6-25/4)-8.32" << std::endl << std::endl;
    std::cout 
<< "或输入q退出?/span>" << std::endl << std::endl;
    std::cout 
<< "";
    calculator
<std::string::const_iterator> calc;

    std::
string str;
    
double result;
    
while (std::getline(std::cin, str))
    {
        
if (str.empty() || str[0== 'q' || str[0== 'Q')
            
break;

        std::
string::const_iterator iter = str.begin();
        std::
string::const_iterator end = str.end();
        
bool r = phrase_parse(iter, end, calc, result, space);

        
if (r && iter == end)
        {
            std::cout 
<< "输入语法正确Q表辑ּ的gؓQ?/span>";

            
if (result == std::numeric_limits<double>::infinity())
                std::cout 
<< "";
            
else if (result == std::numeric_limits<double>::quiet_NaN())
                std::cout 
<< "l果非数?/span>";
            
else
            {
                std::cout 
<< result << std::endl;
                std::cout 
<< "整数部分转换?q制为:" << itoa(static_cast<int>(result), 5);
            }
            std::cout 
<< std::endl;

        }
        
else
        {
            std::cout 
<< "[输入的表辑ּ错误]" << std::endl;
            std::cout 
<< str << std::endl;
            std::cout 
<< std::string(iter - str.begin(), '-'<< "^" << std::endl;
        }
        std::cout 
<< std::endl << "";
    }
    
return 0;
}




q行l果如下Q?br>
误入一个表辑ּQ如Q?/span>3+2.5*(6-25/4)-8.32

或输入q退出?br>
> 3+2.5*(6-25/4)-8.32
输入语法正确Q表辑ּ的gؓQ?/span>-5.945
整数部分转换?q制为:
-10

> -6
输入语法正确Q表辑ּ的gؓQ?/span>-6
整数部分转换?q制为:
-11

> 6
输入语法正确Q表辑ּ的gؓQ?/span>6
整数部分转换?q制为:
11

> 1/0
输入语法正确Q表辑ּ的gؓQ?#8734;

> 23 + 4 ((5)-3* 6+ (-1)
[输入的表辑ּ错误]
23 + 4 ((5)-3* 6+ (-1)
-------^

> 23 + 4 ( ( 5-3*6+1)
[输入的表辑ּ错误]
23 + 4 ( ( 5-3*6+1)
-------^

> 23 + 4 + ( -5 *3)
输入语法正确Q表辑ּ的gؓQ?/span>12
整数部分转换?q制为:
22

>




Dancefire 2009-02-04 12:02 发表评论
]]>
ŷþۺ| Ʒ޾þþþþ888| 97rþþƷ99| þ޸ۿ| þþþþŹƷ| 99þѹƷ| þþþþҹƷ| þþžžƷ99Ʒ| 91Ʒ91þþþþ| ˾Ʒþ޸岻| ĻƷѾþ| ޾þþһ| ˺ݺۺϾþ88| ޹þþۺ| ӰԺ˾þ| þٸ۲AV| ھƷþþþþþɬ| ľþþþר| þþùƷ| ޹Ʒ˾þ| ŷ޳ҹƷþ| þþƷƵ91| ɫ꼤þۺ| Ʒþþþav| ˾Ʒþ| þ̳| þþþþaŷa| þۺ97ɫֱ| 99þҹɫƷվ| 99þþƷ⿴һ| һһþۺϺݺ| ߾þþƷĹ| ھƷþþþþþɬ| 99Ʒþ| 99þþƷӰԺѼ| ˾þþƷһ| þþAVҰ| ɫþþۺ| ˾þô߽ۺվ| Ұ¾þһ| Ļþи|