IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 《C++程序设计原理与实践》 第十章 习题答案 -> 正文阅读

[C++知识库]《C++程序设计原理与实践》 第十章 习题答案

10.1

#include"../../std_lib_facilities.h"

int main()
try
{
	string iname{ "10_1-Integers.txt" };
	ifstream ist{ iname };
	if (!ist)
		error("can't open input file", iname);
	int sum{ 0 };
	for (int x = 0; ist >> x;)
		sum += x;
	cout << "The sum of integers is " << sum << endl;
	return 0;
}
catch (runtime_error& e)
{
	cerr << "Runtime error: " << e.what() << endl;
	return 1;
}
catch (...)
{
	cerr << "Exception occured!\n";
	return 2;
}

10.2 和 10.4

#include"../../std_lib_facilities.h"

struct Reading {	//温度数据读取
	int hour;		//在[0:23]区间取值的小时数
	double temperature;	//华氏温度值
};

inline double temp_monitor(double a, double b)
{
	//返回每小时温度值,[a, b]的随机浮点数
	double m = a + double(rand()) / RAND_MAX * (b - a);
	return m;
}

int main()
try
{
	string oname{ "raw_temps.txt" };
	ofstream ost{ oname };
	if(!ost)
		error("can't open output file", oname);

	srand(time(NULL));	//为temp_monitor设置随机数种子
	int day{ 3 };	//输出多少天的温度
	Reading r{ 0,0 };
	double a{ 15 }, b{ 35 };
	char corf{ 'c' };	//摄氏温度c 或or 华氏温度f
	while (day-- > 0)
	{
		r.hour = 0;
		while (r.hour < 24)
		{
			r.temperature = temp_monitor(a, b);
			ost << r.hour << ' ' << r.temperature << corf << endl;
			r.hour++;
		}
	}
	return 0;
}
catch (runtime_error& e)
{
	cerr << "Runtime error: " << e.what() << endl;
	return 1;
}
catch (...)
{
	cerr << "Exception occured!\n";
	return 2;
}

10.3 和 10.4

#include"../../std_lib_facilities.h"

struct Reading {	//温度数据读取
	int hour;		//在[0:23]区间取值的小时数
	double temperature;	//华氏温度值
};

inline double ctof(double c)
{
	//摄氏温度转换为华氏温度
	return 1.8 * c + 32.0;
}

int main()
try
{
	string iname{ "raw_temps.txt" };
	ifstream ist{ iname };
	if (!ist)
		error("can't open input file", iname);

	vector<Reading>vr;
	int hour;
	double temperature, sum{ 0 }, average{ 0 };
	char corf{ 'n' };
	while (ist >> hour >> temperature >> corf)
	{
		if (hour < 0 || hour > 23)
			error("hour out of range");
		if (corf == 'c')	// 如果是摄氏温度
			temperature = ctof(temperature);
		else if (corf != 'f')	//如果既不是摄氏温度又不是华氏温度
			error("It's neither Celsius nor Fahrenheit");
		vr.push_back(Reading{ hour, temperature });
		sum += temperature;
	}
	size_t sz = vr.size();
	average = sum / sz;	//温度平均值

	vector<double>vt(sz);
	for (size_t i = 0; i < sz; i++)
		vt[i] = vr[i].temperature;
	sort(vt);
	double mid{ 0 };
	if (sz % 2)
		mid = vt[sz / 2];
	else
		mid = (vt[sz / 2] + vt[sz / 2 + 1]) / 2;

	cout << "Average of temperature is " << average << endl;
	cout << "Middle of temperature is " << mid << endl;

	return 0;
}
catch (runtime_error& e)
{
	cerr << "Runtime error: " << e.what() << endl;
	return 1;
}
catch (...)
{
	cerr << "Exception occured!\n";
	return 2;
}

10.5

void print_year(ostream& os, Year& y)
{
	os << "{ " << year_marker << y.year << '\n';
	for (Month& m : y.month)
	{
		if (m.month != not_a_month)
		{
			os << '\t';
			print_month(os, m);
			os << '\n';
		}
	}
	os << "}\n";
}

10.6 Roman_int 类

Roman_int.h

// Roman to Arabic numerals
struct R2A {
	char c_letter;	//大写字母
	char l_letter;	//小写字母
	int n;	//对应的阿拉伯数字
};

class Roman_int {
public:
	Roman_int() :n{ 0 } { }
	Roman_int(int num) :n{ num } { }
	int as_int() const;
private:
	int n;
	//string r;
};

Roman_int operator-(const Roman_int& r);
Roman_int operator+(const Roman_int& r1, const Roman_int& r2);
Roman_int operator-(const Roman_int& r1, const Roman_int& r2);
Roman_int operator*(const Roman_int& r1, const Roman_int& r2);
Roman_int operator/(const Roman_int& r1, const Roman_int& r2);
Roman_int operator%(const Roman_int& r1, const Roman_int& r2);
istream& operator>>(istream& is, Roman_int& r);
ostream& operator<<(ostream& os, const Roman_int& r);
int Roman_to_int(char ch);

Roman_int.cpp

#include"../../std_lib_facilities.h"
#include"Roman_int.h"

const vector<R2A>vr2a{
	R2A{'I','i',1}, R2A{'V','v',5}, 
	R2A{'X','x',10}, R2A{'L','l',50}, 
	R2A{'C','c',100}, R2A{'D','d',500},
	R2A{'M','m',1000}
};

int Roman_int::as_int() const
{
	return n;
}

const int not_a_roman{ -1 };

int Roman_to_int(char ch)
{
	for (const R2A& r2a : vr2a)
	{
		if (ch == r2a.c_letter || ch == r2a.l_letter)
			return r2a.n;
	}
	return not_a_roman;
}

//一元运算符- 取相反数操作
Roman_int operator-(const Roman_int& r)
{
	return Roman_int{ -r.as_int() };
}

Roman_int operator+(const Roman_int& r1, const Roman_int& r2)
{
	return Roman_int{ r1.as_int() + r2.as_int() };
}

Roman_int operator-(const Roman_int& r1, const Roman_int& r2)
{
	return Roman_int{ r1.as_int() - r2.as_int() };
}

Roman_int operator*(const Roman_int& r1, const Roman_int& r2)
{
	return Roman_int{ r1.as_int() * r2.as_int() };
}

Roman_int operator/(const Roman_int& r1, const Roman_int& r2)
{
	return Roman_int{ r1.as_int() / r2.as_int() };
}

Roman_int operator%(const Roman_int& r1, const Roman_int& r2)
{
	return Roman_int{ r1.as_int() % r2.as_int() };
}

istream& operator>>(istream& is, Roman_int& r)
/*
	读入罗马数字字符,转换为int存入
*/
{
	char ch{ 0 };
	int prev{ 0 };
	int now{ 0 };
	int all{ 0 };
	bool neg{ false };

	while (is.get(ch))
	{
		if (ch == '-')
		{
			neg = true;
			continue;
		}
		now = Roman_to_int(ch);
		if (now == not_a_roman)
		{
			is.unget();
			break;
		}
		if (now > prev)
			all -= 2 * prev;
		all += now;
		prev = now;
	}
	if (all != 0)
	{
		if (neg)
			all = -all;
		r = Roman_int(all);
	}

	return is;
}

ostream& operator<<(ostream& os, const Roman_int& r)
//	输出罗马数字字符,不能表示四千及以上的数字
{
	int n = r.as_int();
	bool neg = (n < 0);
	if (neg)
		n = -n;
	if (n >= 4000)
	{
		error("can't output number bigger than 4000");
	}
	int rem{ 0 };
	const int mask{ 10 };
	int div{ 10 };
	int level{ 0 };
	int mid_level{ 1 };
	const int max{ 3 };
	string roman;
	string temp_r;

	while (n > 0)
	{
		rem = n % div;
		if (mid_level >= vr2a.size())
			mid_level--;
		if (rem == vr2a[mid_level].n && mid_level > level)
		{
			temp_r += vr2a[mid_level].c_letter;
			rem -= vr2a[mid_level].n;
		}
		else if (rem > vr2a[mid_level].n && mid_level > level)
		{
			if(rem + vr2a[level].n == vr2a[mid_level + 1].n)
				mid_level++;
			else
			{
				temp_r += vr2a[mid_level].c_letter;
				rem -= vr2a[mid_level].n;
			}
		}
		if (rem + vr2a[level].n == vr2a[mid_level].n)
			temp_r = (temp_r + vr2a[level].c_letter) + vr2a[mid_level].c_letter;
		else
			while (rem > 0)
			{
				temp_r += vr2a[level].c_letter;
				rem -= vr2a[level].n;
			}
		
		roman = temp_r + roman;
		temp_r = "";
		level += 2;
		mid_level = level + 1;
		n -= n % div;
		div *= mask;
	}
	if (neg)
		os << '-';
	os << roman;
	return os;
}

10.7


/*
	calculator07.cpp
	It may be called "finished" 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"
#include"Roman_int.h"

struct Token {
	char kind;
	//int value;
	Roman_int roman;
	string name;
	Token(char ch) :kind(ch), roman(0) { }
	Token(char ch, Roman_int r) :kind(ch), roman(r) { }
	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':*/
	case 'I': case 'V': case 'X': case 'L':
	case 'C': case 'D': case 'M':				//暂不支持小写字母,因为会与let和const冲突
	{
		cin.putback(ch);	// put digit back into the input stream
		//cin.unget();	// same as putback(char), except no parameter
		Roman_int r;
		cin >> r;		// read a floating-point number
		return Token{ number, r };
	}
	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;
	Roman_int roman;
	bool is_const;
	Variable(string n, Roman_int r, bool b) :name(n), roman(r), is_const(b) { }
};
class Symbol_table {
public:
	Symbol_table() {}
	Roman_int get(string var);
	void set(string var, Roman_int r);
	bool is_declared(string var);
	Roman_int define(string var, Roman_int r, bool is_const);
private:
	vector<Variable> var_table;
};

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

void Symbol_table::set(string s, Roman_int r)
{
	for (Variable& v : var_table)
		if (v.name == s)
		{
			if (v.is_const)
				error("set: can not assign to a const ", s);
			v.roman = r;
			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;
}

Roman_int Symbol_table::define(string var, Roman_int r, bool is_const)
{
	//将(var, val)加入var_table中
	if (is_declared(var))
		error(var, " declared twice");
	var_table.push_back(Variable{ var, r, is_const });
	return r;
}

Token_stream ts;
Symbol_table st;

//--------Expression---------------
Roman_int expression();

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

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

Roman_int primary()
{
	Token t = ts.get();
	switch (t.kind) {
	case '(':
	{
		Roman_int d = expression();
		t = ts.get();
		if (t.kind != ')')
			error("'(' expected");
		return d;
	}
	case '-':
		return -primary();
	case number:
		return t.roman;
	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");
	}
}

Roman_int term()
{
	Roman_int left = primary();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case '*':
			left = left * primary();
			break;
		case '/':
		{
			Roman_int d = primary();
			if (d.as_int() == 0) error("divide by zero");
			left = left / d;
			break;
		}
		case '%':
		{
			Roman_int d = primary();
			if (d.as_int() == 0) error("divide by zero");
			//left = fmod(left, d);
			left = left % d;
			break;
		}
		default:
			ts.putback(t);
			return left;
		}
	}
}

Roman_int expression()
{
	Roman_int left = term();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case '+':
			left = left + term();
			break;
		case '-':
			left = left - term();
			break;
		default:
			ts.putback(t);
			return left;
		}
	}
}

Roman_int 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);

	Roman_int d = expression();
	bool is_const = (kind == con);
	st.define(var_name, d, is_const);

	return d;
}


Roman_int 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.9 Merge two sorted file

#include"../../std_lib_facilities.h"

void merge_sort(istream& is1, istream& is2, ostream& os)
{
	string s1, s2;

	is1 >> s1;
	is2 >> s2;
	if (s1 < s2)
	{
		os << s1;
		is1 >> s1;
	}
	else if (s1 > s2)
	{
		os << s2;
		is2 >> s2;
	}
	else
	{
		os << s1 << ' ' << s2;
		is1 >> s1;
		is2 >> s2;
	}

	while (is1 && is2)
	{
		if (s1 < s2)
		{
			os << ' ' << s1;
			is1 >> s1;
		}
		else if (s1 > s2)
		{
			os << ' ' << s2;
			is2 >> s2;
		}
		else
		{
			os << ' ' << s1 << ' ' << s2;
			is1 >> s1;
			is2 >> s2;
		}
	}
	for (; is1; is1 >> s1)
		os << ' ' << s1;
	for (; is2; is2 >> s2)
		os << ' ' << s2;
}

int main()
try
{
	//打开第一个已排序的输入文件
	cout << "Please enter input file1 name\n";
	string iname1;
	cin >> iname1;
	ifstream ifs1{ iname1 };
	if (!ifs1)
		error("can't open input file", iname1);

	ifs1.exceptions(ifs1.exceptions() | ios_base::badbit);	//抛出bad()状态的异常

	//打开第二个已排序的输入文件
	cout << "Please enter input file2 name\n";
	string iname2;
	cin >> iname2;
	ifstream ifs2{ iname2 };
	if (!ifs2)
		error("can't open input file", iname2);

	ifs2.exceptions(ifs2.exceptions() | ios_base::badbit);	//抛出bad()状态的异常

	//打开一个输出文件
	cout << "Please enter output file name\n";
	string oname;
	cin >> oname;
	ofstream ofs{ oname };
	if (!ofs)
		error("can't open output file", oname);

	merge_sort(ifs1, ifs2, ofs);

	return 0;
}
catch (runtime_error& e)
{
	cerr << "Runtime error: " << e.what() << endl;
	return 1;
}
catch (...)
{
	cerr << "Exception occured!\n";
	return 2;
}

10.10


/*
	calculator07.cpp
	It may be called "finished" calculator.

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

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

//全局变量输入输出
istream* pis = &cin;
ostream* pos = &cout;
#define is (*pis)
#define os (*pos)


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 string constkey = "const";
const char con = 'C';
const string fromkey = "from";
const char from = 'F';
const string tokey = "to";
const char to = 'T';

Token Token_stream::get()
{
	if (full)
	{
		full = false;
		return buffer;
	}
	char ch;
	//is >> ch;	// note that >> skips whitespace (space, newline, tab, etc.)
	while (isspace((ch = is.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':
	{
		is.putback(ch);	// put digit back into the input stream
		//is.unget();	// same as putback(char), except no parameter
		double val;
		is >> val;		// read a floating-point number
		return Token{ number, val };
	}
	default:
		if (isalpha(ch)) {
			string s;
			s += ch;
			//名字为字母开头的,带字母数字和下划线的字符串
			while (is.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_'))
				s += ch;
			is.putback(ch);
			if (s == declkey) return Token{ let };	// 声明变量关键字
			if (s == constkey) return Token{ con };	// 声明常量关键字
			if (s == fromkey)
			{
				string fname;
				is >> fname;
				return Token{ from, fname };	// 声明从文件获得输入关键字
			}
			if (s == tokey) 
			{
				string fname;
				is >> fname;
				return Token{ to , fname};		// 声明向文件输出关键字
			}
			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 (is >> 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;
		}
		if (t.kind == from)
		{
			if (t.kind != from)
				error("Invalid file name");
			static ifstream ifs{ t.name };
			if (!ifs)
				error("can't open file", t.name);
			pis = &ifs;
			continue;
		}
		else if (t.kind == to)
		{
			if (t.kind != to)
				error("Invalid file name");
			static ofstream ofs{ t.name };
			if (!ofs)
				error("can't open file", t.name);
			pos = &ofs;
			continue;
		}
		ts.putback(t);
		os << result << statement() << endl;
	}
	catch (runtime_error& e) {
		os << 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 (is >> c && c != ';');
	return 1;
}
catch (...) {
	cerr << "exception\n";
	char c;
	while (is >> c && c != ';');
	return 2;
}

10.11

#include"../../std_lib_facilities.h"

int sum_int(istream& is)
{
	int sum{ 0 };
	int x{ 0 };
	char ch{ 0 };
	string s;
	
	while (is >> ch)
	{
		is.unget();
		if (isdigit(ch))
		{
			if (is >> x)
			{
				if(isspace(ch = is.get()))		//说明这就是个整数,而不是12F 12.0这样的字符串
					sum += x;
				else
				{
					is.putback(ch);
					is >> s;
				}
			}
			else
				error("can't read integer");
		}
		else
			is >> s;
	}
	return sum;
}

int main()
try
{
	//打开一个输入文件
	cout << "Please enter input file name\n";
	string iname;
	cin >> iname;
	ifstream ifs{ iname };
	if (!ifs)
		error("can't open input file", iname);

	ifs.exceptions(ifs.exceptions() | ios_base::badbit);	//抛出bad()状态的异常

	cout << "sum: " << sum_int(ifs) << endl;

	return 0;
}
catch (runtime_error& e)
{
	cerr << "Runtime error: " << e.what() << endl;
	return 1;
}
catch (...)
{
	cerr << "Exception occured!\n";
	return 2;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-22 14:29:00  更:2021-09-22 14:29:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 22:24:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码