/*
本程序实现了一个简单的表达式计算器,支持变量操作
输入流是一个显式参数,Token_stream 接受istream & 参数的构造函数
输入文法如下:
Calculation:
Statement
Print
Quit
Calculation Statement
Print:
';'
Quit:
'q'
"quit"
Statement:
Declaration
Expression
Declaration:
"let" name '=' Expression
"const" name '=' Expression
Expression:
Term
Expression '+' Term
Expression '-' Term
Term:
Primary
Term * Primary
Term / Primary
Term % Primary
Primary:
Number
'(' Expression ')'
- Primary //处理负数
Assignment
Number:
floating-point-literal
Assignment:
name '=' Expression
*/#include"../../std_lib_facilities.h"structToken{char kind;double value;
string name;Token(char ch):kind(ch),value(0){}Token(char ch,double val):kind(ch),value(val){}Token(char ch, string n):kind(ch),name(n){}};classToken_stream{private:bool full;
Token buffer;
istream& input;public:Token_stream(istream& in):full(false),buffer(0),input(in){}// The constructor just sets full to indicate that the buffer is empty:
Token get();voidputback(Token t);voidignore(char);};const string declkey ="let";constchar let ='L';const string quitkey ="quit";constchar quit ='q';const string helpkey ="help";constchar help ='h';constchar print =';';constchar number ='8';constchar name ='a';constchar assign ='=';constchar con ='C';const string constkey ="const";
Token Token_stream::get(){if(full){
full =false;return buffer;}char ch;//cin >> ch; // note that >> skips whitespace (space, newline, tab, etc.)while(isspace((ch = input.get()))&& ch !='\n')continue;switch(ch){case'(':case')':case'+':case'-':case'*':case'/':case'%':case'=':case quit:case print:return Token{ ch };// let each character represent itselfcase'\n':return Token{ print };case'.':case'0':case'1':case'2':case'3':case'4':case'5':case'6':case'7':case'8':case'9':{
input.putback(ch);// put digit back into the input stream//cin.unget(); // same as putback(char), except no parameterdouble val;
input >> val;// read a floating-point numberreturn Token{ number, val };}default:if(isalpha(ch)){
string s;
s += ch;//名字为字母开头的,带字母数字和下划线的字符串while(input.get(ch)&&(isalpha(ch)||isdigit(ch)|| ch =='_'))
s += ch;
input.putback(ch);if(s == declkey)return Token{ let };// 声明变量关键字if(s == constkey)return Token{ con };// 声明常量关键字if(s == helpkey ||(s.size()==1&& s[0]== help))return Token{ help };if(s == quitkey)return Token{ quit };return Token{ name, s };}error("Bad token");}}// The putback() member function puts its argument back into the Token_stream's buffer:voidToken_stream::putback(Token t){if(full)error("putback() into a full buffer.");
buffer = t;
full =true;}voidToken_stream::ignore(char c){if(full && c == buffer.kind){
full =false;return;}
full =false;char ch;while(input >> ch)if(ch == c)return;}//---------------------------------------------------------// set VariableclassVariable{public:
string name;double value;bool is_const;Variable(string n,double v,bool b):name(n),value(v),is_const(b){}};classSymbol_table{public:Symbol_table(){}doubleget(string var);voidset(string var,double d);boolis_declared(string var);doubledefine(string var,double val,bool is_const);private:
vector<Variable> var_table;};doubleSymbol_table::get(string s){for(const Variable& v : var_table)if(v.name == s)return v.value;error("get: undefined name ", s);}voidSymbol_table::set(string s,double d){for(Variable& v : var_table)if(v.name == s){if(v.is_const)error("set: can not assign to a const ", s);
v.value = d;return;}error("set: undefined name ", s);}boolSymbol_table::is_declared(string var){//判断var是否已经在var_table中了for(const Variable& v : var_table)if(v.name == var)returntrue;returnfalse;}doubleSymbol_table::define(string var,double val,bool is_const){//将(var, val)加入var_table中if(is_declared(var))error(var," declared twice");
var_table.push_back(Variable{ var, val, is_const });return val;}
Token_stream ts{ cin };
Symbol_table st;//--------Expression---------------doubleexpression();doubleassignment(string var){// 函数假设已经读入了赋值语句的左值和赋值符号double right =expression();
st.set(var, right);return right;}doubleprimary(){
Token t = ts.get();switch(t.kind){case'(':{double d =expression();
t = ts.get();if(t.kind !=')')error("'(' expected");return d;}case'-':return-primary();case number:return t.value;case name:{
Token t2 = ts.get();if(t2.kind != assign){
ts.putback(t2);return st.get(t.name);// if next char is not a assignment operator, then return variable value}elsereturnassignment(t.name);}default:error("primary expected");}}doubleterm(){double left =primary();while(true){
Token t = ts.get();switch(t.kind){case'*':
left *=primary();break;case'/':{double d =primary();if(d ==0)error("divide by zero");
left /= d;break;}case'%':{double d =primary();if(d ==0)error("divide by zero");
left =fmod(left, d);break;}default:
ts.putback(t);return left;}}}doubleexpression(){double left =term();while(true){
Token t = ts.get();switch(t.kind){case'+':
left +=term();break;case'-':
left -=term();break;default:
ts.putback(t);return left;}}}doubledeclaration(char kind){
Token t = ts.get();if(t.kind != name)error("name expected in declaration");
string var_name = t.name;
Token t2 = ts.get();if(t2.kind !='=')error("= missing in declaration of ", var_name);double d =expression();bool is_const = kind == con;
st.define(var_name, d, is_const);return d;}doublestatement(){
Token t = ts.get();switch(t.kind){case let:case con:returndeclaration(t.kind);default:
ts.putback(t);returnexpression();}}voidclean_up_mess(){
ts.ignore(print);}const string prompt ="> ";const string result ="= ";voidhelp_message(){
cout <<"Please enter expressions using floating-point numbers.\n";
cout <<"You can use \"+ - * / %\" operators, ';' to output result, 'h' to help, and 'q' to quit.\n";
cout <<"You can also define variables and constant by using let and const"<< endl;
cout <<"For example: let a = 1 define a variable a, const b = a * 3 define a constant b"<< endl;}voidcalculate(){while(true)try{
cout << prompt;
Token t = ts.get();while(t.kind == print) t = ts.get();// 丢弃之前的所有打印字符if(t.kind == quit)return;if(t.kind == help){help_message();continue;}
ts.putback(t);
cout << result <<statement()<< endl;}catch(runtime_error& e){
cerr << e.what()<< endl;clean_up_mess();}}intmain()try{
cout <<"Welcome to our simple calculator.\n";
cout <<"Please enter expressions using floating-point numbers.\n";
cout <<"You can use \"+ - * / %\" operators, ';' to output result, 'h' to help, and 'q' to quit.\n";
cout <<"You can also define variables and constant by using let and const"<< endl;
cout <<"For example: let a = 1 define a variable a, const b = a * 3 define a constant b"<< endl;calculate();return0;}catch(exception& e){
cerr <<"exception: "<< e.what()<< endl;char c;while(cin >> c && c !=';');return1;}catch(...){
cerr <<"exception\n";char c;while(cin >> c && c !=';');return2;}
8.2 和 8.3
//exerciese 8-2 and 8-3#include"../../std_lib_facilities.h"voidprint(const string& str,const vector<int>& v);voidfibonacci(int x,int y, vector<int>& v,int n);intmain(){const string str{"Fibonacci:"};
vector<int>v;fibonacci(1,2, v,12);print(str, v);return0;}voidprint(const string& str,const vector<int>& v){
cout << str << endl;for(size_t i =0; i < v.size(); i++){
cout <<" "<< v[i];if(i %10==9)
cout <<'\n';}}voidfibonacci(int x,int y, vector<int>& v,int n){//首先将x和y作为v[0]和v[1]if(--n >=0)
v.push_back(x);if(--n >=0)
v.push_back(y);int z{0};while(n-->0){
z = x + y;
v.push_back(z);
x = y;
y = z;}}
#include"../../std_lib_facilities.h"voidread_string(vector<string>& vs);voidoutput_string_length(const vector<string>& vs,const vector<int>& vi);
vector<int>string_analysis(vector<string> vs);voiddictionary_order_string(vector<string>& vs);intmain()try{
vector<string>vs;
vector<int>vi;read_string(vs);
vi =string_analysis(vs);output_string_length(vs, vi);return0;}catch(runtime_error& e){
cerr << e.what()<< endl;return1;}catch(...){
cerr <<"Exception occured!\n";return2;}voidread_string(vector<string>& vs){
cout <<"Enter some string, ending by character '!'\n";
string s;while(cin >> s && s !="!")
vs.push_back(s);}voidoutput_string_length(const vector<string>& vs,const vector<int>& vi){
cout <<"length\tstring\n";for(size_t i =0; i < vs.size(); i++)
cout << vi[i]<<'\t'<< vs[i]<<'\n';}
vector<int>string_analysis(vector<string> vs){if(vs.size()<=0)error("vector<string> is empty");
vector<int>vi;
size_t str_size{0}, max{ vs[0].size()}, min{ vs[0].size()};//max size, min size
size_t max_i{0}, min_i{0};//max index, min index, begin with vs[0]for(size_t i =0; i < vs.size(); i++){
str_size = vs[i].size();if(str_size > max){
max = str_size;
max_i = i;}elseif(str_size < min){
min = str_size;
min_i = i;}
vi.push_back(int(str_size));}
cout <<"The maximum length string is:\n\t"<< vs[max_i]<< endl;
cout <<"The minimum length string is:\n\t"<< vs[min_i]<< endl;dictionary_order_string(vs);return vi;}voiddictionary_order_string(vector<string>& vs){if(vs.size()<=0)error("vector<string> is empty");//version_1: O(NlogN) /*sort(vs);
cout << "the first string in dictionary order is:\n\t" << vs[0] << endl;
cout << "the last string in dictionary order is:\n\t" << vs[vs.size()-1] << endl;*///version2: O(N)
size_t first_i{0}, last_i{0};// begin with vs[0]
string first_str{ vs[0]}, last_str{ vs[0]};for(size_t i =0; i < vs.size(); i++){if(first_str > vs[i]){
first_str = vs[i];
first_i = i;continue;}if(last_str < vs[i]){
last_str = vs[i];
last_i = i;}}
cout <<"the first string in dictionary order is:\n\t"<< vs[first_i]<< endl;
cout <<"the last string in dictionary order is:\n\t"<< vs[last_i]<< endl;}
8.13
#include"../../std_lib_facilities.h"voidf(constint n);intmain(){int i =5;constexprint j =6;f(i);f(j);f(7);return0;}voidf(constint n){
cout <<"const in n = "<< n << endl;}