C++程序设计原理与实践 习题答案 第七章 第7章习题答案

第七章 习题答案

前言

这一章的习题是有连贯性的,我就不放分开来的代码了,直接上最终版本

Calculator


/*
	本程序实现了一个简单的表达式计算器,支持变量操作
	从cin读入,输出到cout。

	输入文法如下:
		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"

struct Token {
	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) { }
};

class Token_stream {
private:
	bool full;
	Token buffer;
public:
	Token_stream() :full(false), buffer(0) { }	// The constructor just sets full to indicate that the buffer is empty:

	Token get();
	void putback(Token t);
	void ignore(char);
};

const string declkey = "let";
const char let = 'L';
const string quitkey = "quit";
const char quit = 'q';
const string helpkey = "help";
const char help = 'h';
const char print = ';';
const char number = '8';
const char name = 'a';
const char assign = '=';
const char 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 = cin.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 itself
	case '\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':
	{
		cin.putback(ch);	// put digit back into the input stream
		//cin.unget();	// same as putback(char), except no parameter
		double val;
		cin >> val;		// read a floating-point number
		return Token{ number, val };
	}
	default:
		if (isalpha(ch)) {
			string s;
			s += ch;
			//名字为字母开头的,带字母数字和下划线的字符串
			while (cin.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_'))
				s += ch;
			cin.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:
void Token_stream::putback(Token t)
{
	if (full)
		error("putback() into a full buffer.");
	buffer = t;
	full = true;
}

void Token_stream::ignore(char c)
{
	if (full && c == buffer.kind) {
		full = false;
		return;
	}
	full = false;

	char ch;
	while (cin >> ch)
		if (ch == c) return;
}


//---------------------------------------------------------
// set Variable
class Variable {
public:
	string name;
	double value;
	bool is_const;
	Variable(string n, double v, bool b) :name(n), value(v), is_const(b) { }
};
class Symbol_table {
public:
	Symbol_table() {}
	double get(string var);
	void set(string var, double d);
	bool is_declared(string var);
	double define(string var, double val, bool is_const);
private:
	vector<Variable> var_table;
};

double Symbol_table::get(string s)
{
	for (const Variable& v : var_table)
		if (v.name == s)
			return v.value;
	error("get: undefined name ", s);
}

void Symbol_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);
}

bool Symbol_table::is_declared(string var)
{
	//判断var是否已经在var_table中了
	for (const Variable& v : var_table)
		if (v.name == var)
			return true;
	return false;
}

double Symbol_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;
Symbol_table st;

//--------Expression---------------
double expression();

double assignment(string var)
{
	// 函数假设已经读入了赋值语句的左值和赋值符号

	double right = expression();
	st.set(var, right);
	return right;
}

double primary()
{
	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
		}
		else
			return assignment(t.name);
	}
	default:
		error("primary expected");
	}
}

double term()
{
	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;
		}
	}
}

double expression()
{
	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;
		}
	}
}

double declaration(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;
}


double statement()
{
	Token t = ts.get();
	switch (t.kind) {
	case let:
	case con:
		return declaration(t.kind);
	default:
		ts.putback(t);
		return expression();
	}
}

void clean_up_mess()
{
	ts.ignore(print);
}

const string prompt = "> ";
const string result = "= ";

void help_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;
}

void calculate()
{
	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();
	}
}

int main()
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();
	return 0;
}
catch (exception& e) {
	cerr << "exception: " << e.what() << endl;
	char c;
	while (cin >> c && c != ';');
	return 1;
}
catch (...) {
	cerr << "exception\n";
	char c;
	while (cin >> c && c != ';');
	return 2;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值