#include <list>
using namespace std;
/*
─────────────────────────────
│ 10 │ + │ 20 │ * | 5 |
─────────────────────────────
(run interpret)
===>>>
Token[Digits] : 10
Token[Operator] : +
Token[Digits] : 20
Token[Operator] : *
Token[Digits] : 5
===>>>
10 + 20 * 5
优先级:
x÷ > +-
===>>>
10 + 100
===>>>
110
*/
//
// 配置
//
const char CounterDigits[] = "1234567890";
const char CounterOperators[] = "*/+-";
const char CounterNils[] = " ";
enum TokensTypes
{
Nil,
Operator,
Digits,
Eof,
Err
};
//
// common
//
inline bool isinchars( const char* str, char s ) {
int len = strlen( str );
for( int i = 0; i < len; i++ )
if( s == str[i] )
return true;
return false;
}
inline bool isDigit( char s ) {
return isinchars( CounterDigits, s );
}
inline bool isOperator( char s ) {
return isinchars( CounterOperators, s );
}
inline bool isNil( char s ) {
return isinchars( CounterNils, s );
}
//
// 类实现
//
class Token
{
public:
Token( TokensTypes tts ) {
this->type = tts;
for( char &ch : raw )
ch = 0;
}
Token( TokensTypes tts, char* rawstr, int startpos, int endpos ) {
this->type = tts;
char tmpch = rawstr[endpos];
rawstr[endpos] = 0;
strcpy( this->raw, rawstr + startpos );
rawstr[endpos] = tmpch;
}
TokensTypes type;
char raw[11];
};
class CounterInterpreter
{
public:
CounterInterpreter( char* linestr ) : rawstring( linestr ), pos( 0 ) {}
~CounterInterpreter() { tokens.clear(); }
//每个Token分析
Token readtoken() {
int startpos = this->pos;
while( 1 )
{
//空格时startpos和pos同时递增
if( isNil( rawstring[this->pos] ) ) {
startpos = ++this->pos;
continue;
}
//只有startpos处就是Operator时才判断为操作符
else if( isOperator( rawstring[startpos] ) ) {
return Token( TokensTypes::Operator, rawstring, startpos, ++this->pos );
}
//前方不是数字的数字处为Digits的结束处
else if( isDigit( rawstring[this->pos] ) ) {
if( !isDigit( rawstring[this->pos + 1] ) )
return Token( TokensTypes::Digits, rawstring, startpos, ++this->pos );
}
//EOF
else if( rawstring[this->pos] == 0 ) {
return Token( TokensTypes::Eof );
}
//ERROR
else {
this->pos++;
return Token( TokensTypes::Err );
}
this->pos++;
}
}
//Token分解
bool analysis() {
while( 1 ) {
Token t = readtoken();
tokens.push_back( t );
if( t.type == Eof )
break;
if( t.type == Err )
return false;
}
return true;
}
//正确性验证
bool verify() {
TokensTypes nextstatus = TokensTypes::Digits;
for( auto t : tokens ) {
//d+o+d
if( t.type != nextstatus && t.type != TokensTypes::Eof )
return false;
//数字可以放在最前最后 但操作符不行
if( t.type == TokensTypes::Eof && nextstatus == TokensTypes::Digits )
return false;
if( nextstatus == TokensTypes::Digits )
nextstatus = TokensTypes::Operator;
else if( nextstatus == TokensTypes::Operator )
nextstatus = TokensTypes::Digits;
}
return true;
}
//最终计算
int execute() {
//优先计算*/
//遇到*/时,将自己+身边的2个Token进行重新计算后,
//删除右边的2个,并将结果写入最左边Token
for( auto t = tokens.begin(); t != tokens.end(); t++ ) {
if( (*t).type == TokensTypes::Operator ) {
if( (*t).raw[0] == '*' ) {
t--;
int tmp = strtol( (*t).raw, 0, 10 );
t++; t++;
tmp *= strtol( (*t).raw, 0, 10 );
t--; t--;
sprintf( (*t).raw, "%d", tmp );
t++;
tokens.erase( t++ );
tokens.erase( t++ );
t--;
}
else if( (*t).raw[0] == '/' ) {
t--;
int tmp = strtol( (*t).raw, 0, 10 );
t++; t++;
tmp /= strtol( (*t).raw, 0, 10 );
t--; t--;
sprintf( (*t).raw, "%d", tmp );
t++;
tokens.erase( t++ );
tokens.erase( t++ );
t--;
}
}
}
//最后得出总数:计算+-
int total = 0;
for( auto t = tokens.begin(); t != tokens.end(); t++ ) {
if( (*t).type == TokensTypes::Digits ) {
total = strtol( (*t).raw, 0, 10 );
}
else if( (*t).type == TokensTypes::Operator ) {
switch( (*t).raw[0] ) {
case '+':
t++;
total += strtol( (*t).raw, 0, 10 );
break;
case '-':
t++;
total -= strtol( (*t).raw, 0, 10 );
break;
}
}
}
return total;
}
//将token按顺序装起来
list tokens;
char* rawstring;
int pos;
};
简单测试一下:
void main() {
string str;
while( 1 ) {
//cin >> str; //bug: cin会处理空格为结束符
getline( cin, str );
CounterInterpreter ci( (char*)(str.data()) );
cout << "analysis : " << ci.analysis() << endl;
cout << "verify : " << ci.verify() << endl;
cout << "result : " << ci.execute() << endl;
}
}