Scanner 类图。
Scanner 作用是,一个字符一个字符的扫描表达式。登记表达式当前的状态。
完毕,错误,数字,加法,减法,惩罚,除法,左括号,右括号,变量。
Scanner :字符串,数字,当前位置,状态。
字符串转成double 的实现
为什么是指针的指针?
指针传递本质上也是值传递。希望改变指针本身的地址,而不是指针指向的内容。就需要用到指针的指针。看成值传递。
strtod 测试
#include <iostream>
#include <string>
#include "Scanner.h"
#include "Parser.h"
using namespace std;
int main(void)
{
char *string, *stopstring;
double x;
string = "3.1415926This stopped it";
x = strtod( string, &stopstring );
cout<<x<<endl;
cout<<string<<endl;
cout<<stopstring<<endl;
return 0;
}
Scanner.h
#ifndef _SCANNER_H_
#define _SCANNER_H_
#include <string>
using namespace std;
enum EToken{
TOKEN_END,
TOKEN_ERROR,
TOKEN_NUMBER,
TOKEN_PLUS,
TOKEN_MINUS,
TOKEN_MULTIPLY,
TOKEN_DIVIDE,
TOKEN_LPARENTHESIS,
TOKEN_RPARENTHESIS,
TOKEN_IDENTIIER,
TOKEN_ASSIGN
};
class Scanner
{
public:
Scanner(const string& buf);
void Accept();//扫描方法
double Number() const;//不会修改
EToken Token() const;
private:
void SkipWhite();
const string buf_;
EToken token_;
double number_;//把数字返回,以便parser 类能够解析 parser 创建树节点
unsigned int curPos_;//当前扫描的位置。
};
#endif
Scanner.cpp
#include "Scanner.h"
#include <cctype>
Scanner::Scanner(const string& buf):buf_(buf),curPos_(0)
{
Accept();//调用构造方法就开始扫描了。
}
double Scanner::Number() const
{
return number_;
}
EToken Scanner::Token() const
{
return token_;
}
//忽略空白字符
void Scanner ::SkipWhite()
{
while(isspace(buf_[curPos_]))
{
++curPos_;
}
}
void Scanner::Accept()
{
SkipWhite();//首先忽略空白字符
switch (buf_[curPos_])
{
case '+':
token_=TOKEN_PLUS;
++curPos_;
break;
case '-':
token_=TOKEN_MINUS;
++curPos_;
break;
case '*':
token_=TOKEN_MULTIPLY;
++curPos_;
break;
case '/':
token_=TOKEN_DIVIDE;
++curPos_;
break;
case '(':
token_=TOKEN_LPARENTHESIS;
++curPos_;
break;
case ')':
token_=TOKEN_RPARENTHESIS;
++curPos_;
break;
case '0':case '1':case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9':case '.':
token_=TOKEN_NUMBER;
char* p;
number_=strtod(&buf_[curPos_],&p);//&p 是指针的指针 指针指向了第一个不是数字的位置
//然后根据&p 得到cur_pos 的位置 指针的位置减去首地址
//curPos_ 是一个整数 要将地址转换成数字
curPos_=p-&buf_[0];
break;
case '\\0':case '\n':case '\r':case EOF:
token_=TOKEN_END;//表达式结束
break;
default:
token_=TOKEN_ERROR;
break;
}
}