对算术表达式进行标记?

时间:2014-02-07 22:15:05

标签: c++ stl

说我有:

3.14 + 3 * (7.7/9.8^32.9  )

我需要对此输入字符串进行标记:

3.14
+
3
*
(
7.7
/
9.8
^
32.9
)

是否有一种方便的方法可以使用字符串流或STL中的其他内容来执行此操作,或者我应该一次查看输入1字符并自己执行此操作?

2 个答案:

答案 0 :(得分:3)

通常,您会使用Flex/Bison生成简单的lexerparser。或者,如果您仅使用C++编译器解决方案 - Boost.Spiritexample)。我相信,没有纯粹的STL解决方案,你想要它。

我赞成Flex / Bison方法,所以用Flex编写的tokenizer将是:

%{

#include <iostream>
#include <memory>

%}


%option prefix="Calc"
%option noyywrap
%option c++

ws      [ \t]+

dig     [0-9]
num1    [-+]?{dig}+\.?([eE][-+]?{dig}+)?
num2    [-+]?{dig}*\.{dig}+([eE][-+]?{dig}+)?
number  {num1}|{num2}

%%

{ws} /* skip */
{number} std::cout << "=> number " << YYText() << '\n';

"+"|"-"|"*"|"/"|"^" std::cout << "=> operator " << YYText() << '\n';

"("|")" std::cout << "=> parenthesis " << YYText() << '\n';

. std::cout << "=> unknown " << YYText() << '\n';

%%

int main( int argc, char **argv )
{
    std::unique_ptr<FlexLexer> lexer(new CalcFlexLexer);
    while(lexer->yylex());
    return 0;
}

编译命令行:

$ flex calc.l
$ g++-4.7 -std=c++11 -o calc lex.Calc.cc
$ calc
1 + (2e4^3)
=> number 1
=> operator +
=> parenthesis (
=> number 2e4
=> operator ^
=> number 3
=> parenthesis )

答案 1 :(得分:3)

这取决于你所说的'方便'。您可以使用stringstream 轻松进行操作,但我不知道您是否正在寻找:

#include <iostream>
#include <vector>
#include <sstream>

using namespace std;

struct token{
      char c;
      float f;
      bool number;

      token():number(false),c(0){};
};

vector<token> split(string input)
{
   stringstream parser(input);
   vector<token> output;
   while(parser)
   {
      token t;
      if(isalnum(parser.peek()))
         parser >> t.f;
      else
         parser >> t.c;
      t.number = (t.c==0); 
      output.push_back(t);
   }
   output.pop_back();
   return output;
}

int main()
{
    string input = "3.14 + 3 * (7.7/9.8^32.9  )";
    vector<token> tokens = split(input);
    for(unsigned int i=0;i<tokens.size();i++)
    {
       if(tokens[i].number) cout << "number: " << tokens[i].f << endl;
       else cout << "sign: " << tokens[i].c << endl;
    }
}