说我有:
3.14 + 3 * (7.7/9.8^32.9 )
我需要对此输入字符串进行标记:
3.14
+
3
*
(
7.7
/
9.8
^
32.9
)
是否有一种方便的方法可以使用字符串流或STL中的其他内容来执行此操作,或者我应该一次查看输入1字符并自己执行此操作?
答案 0 :(得分:3)
通常,您会使用Flex/Bison
生成简单的lexer和parser。或者,如果您仅使用C++
编译器解决方案 - Boost.Spirit
(example)。我相信,没有纯粹的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;
}
}