《C++程序设计语言》6.6_18 计算机的例子

/*------------------------------------------------
键入计算机的例子并使之能够工作. 不要"浪费时间"去使用已有的
正文文件. 你将会从发现并改正各种 "小而蠢的错误" 中学到许多
东西.
------------------------------------------------*/
#include <iostream>
#include <sstream>		// include istringstream
#include <string>
#include <map>
#include <cctype>
using std::cout;
using std::cin;
using std::endl;
using std::cerr;
using std::string;
using std::map;
using std::istream;
using std::istringstream;
double expr(bool get);
double term(bool get);
double prim(bool get);
double error(const string& s);
enum Token_value get_token();

map<string, double> table;
enum Token_value
{
	NAME,			NUMBER,			END,
	PLUS = '+',		MINUS = '-',	MUL = '*',	DIV = '/',
	PRINT = ';',	ASSIGN = '=',	LP = '(',	RP = ')'
};
Token_value curr_tok = PRINT;

// 函数expr()处理加和减
double expr(bool get)
{
	double left = term(get);
	for (; ;)
		switch (curr_tok)
		{
			case PLUS:
				left += term(true);
				break;
			case MINUS:
				left -= term(true);
				break;
			default:
				return left;
		}
}

// 函数term()处理乘和除
double term(bool get)
{
	double left = prim(get);
	for (; ;)
		switch (curr_tok)
		{
		case MUL:
			left *= prim(true);
			break;
		case DIV:
			if (double d = prim(true))
			{
				left /= d;
				break;
			}
			return error("divide by 0");
		default:
			return left;
		}
}

// 函数prim()处理初等式
double number_value;
string string_value;
double prim(bool get)
{
	if (get)
		get_token();
	switch(curr_tok)
	{
	case NUMBER:{
		double v = number_value;
		get_token();
		return v;
		}
	case NAME:{
		double &v = table[string_value];
		if (get_token() == ASSIGN)
			v = expr(true);
		return v;
		}
	case MINUS:
		return -prim(true);
	case LP:{
		double e = expr(true);
		if (curr_tok != RP)
			return error(") expected");
		get_token();
		return e;
		}
	default:
		return error("primary expected");
	}
}

// 函数get_token()为输入函数
Token_value get_token()
{
	char ch = 0;
	cin >> ch;
	switch (ch)
	{
	case 0:
		return curr_tok = END;
	case ';':
	case '*':
	case '/':
	case '+':
	case '-':
	case '(':
	case ')':
	case '=':
		return curr_tok = Token_value(ch);
	case '0': case '1': case '2': case '3':
	case '4': case '5': case '6': case '7':
	case '8': case '9': case '.':
		cin.putback(ch);
		cin >> number_value;
		return curr_tok = NUMBER;
	default:
		if (isalpha(ch))
		{
			cin.putback(ch);
			cin >> string_value;
			return curr_tok = NAME;
		}
		error("bad token");
		return curr_tok = PRINT;
	}
}

// 错误处理
int no_of_errors;
double error(const string& s)
{
	no_of_errors++;
	cerr << "error: " << s << '\n';
	return 1;
}

// 驱动程序
istream *input;
int main(int argc, char* argv[])
{
	switch (argc)
	{
	case 1:
		input = &cin;
		break;
	case 2:
		input = new istringstream(argv[1]);
		break;
	default:
		error ("too many arguments");
		return 1;
	}

	table["pi"] = 3.1415926535897932385;	// 插入预定义的名字
	table["e"] = 2.7182818284590452354;

	while (*input)
	{
		get_token();
		if (curr_tok == END) break;
		if (curr_tok == PRINT) continue;
		cout << expr(false) << '\n';
	}

	if (input != &cin)
		delete input;
	return no_of_errors;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值