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

8.1

/*
	本程序实现了一个简单的表达式计算器,支持变量操作
	输入流是一个显式参数,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"

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;
	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();
	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 = 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 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':
	{
		input.putback(ch);	// put digit back into the input stream
		//cin.unget();	// same as putback(char), except no parameter
		double val;
		input >> val;		// read a floating-point number
		return 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:
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 (input >> 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{ cin };
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;
}

8.2 和 8.3

//exerciese 8-2 and 8-3
#include"../../std_lib_facilities.h"

void print(const string& str, const vector<int>& v);
void fibonacci(int x, int y, vector<int>& v, int n);

int main()
{
	const string str{ "Fibonacci:" };
	vector<int>v;
	fibonacci(1, 2, v, 12);
	print(str, v);
	return 0;
}

void print(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';
	}
}

void fibonacci(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;
	}
}

8.5 和 8.6

//exercise 8-5 and 8-6

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

vector<int> reverse_v1(const vector<int>& v);
void reverse_v2(vector<int>& v);
void print(const string& str, const vector<int>& v);

int main()
{
	vector<int>v{ 1,3,5,7,9,11 };
	vector<int>temp_v;
	
	print("Original vector:", v);
	temp_v = reverse_v1(v);
	print("Reversed temporary vector:", temp_v);
	reverse_v2(v);
	print("Reversed vector:", v);
	return 0;
}

vector<int> reverse_v1(const vector<int>& v1)
{
	vector<int>v2(v1.size());

	for (int i = v1.size() - 1, j = 0; i >= 0; i--, j++)
		v2[j] = v1[i];
	return v2;
}

void reverse_v2(vector<int>& v)
{
	for (int i = 0, j = v.size() - 1; i < j; i++, j--)
		swap(v[i], v[j]);
}

void print(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';
	}
	cout << '\n';
}

8.7

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

void clear_line();

int main()
try
{
	constexpr int len{ 5 };
	vector<string>name(len);
	vector<double>age(len);
	string n;	//name
	double a;	//age

	cout << "Please input " << len << " names\n";
	for (size_t i = 0; i < len; i++)
	{
		cin >> n;
		name[i] = n;
	}
	clear_line();

	cout << "Please input " << len << " ages\n";
	for (size_t i = 0; i < len; i++)
	{
		cout << name[i] << ": ";
		cin >> a;
		age[i] = a;
	}
	clear_line();

	cout << "You input " << len << " (name, age) pairs:\n";
	for (size_t i = 0; i < len; i++)
		cout << '(' << name[i] << ", " << age[i] << ")\n";

	//接下来拷贝一份name的副本,并对副本排序
	vector<string>name_copy = name;
	sort(name_copy.begin(), name_copy.end());
	//接下来按照name副本的顺序生成对应的age副本
	vector<double>age_copy;
	for(string s:name_copy)
		for (size_t i = 0; i < name.size(); i++)
			if (s == name[i])
			{
				age_copy.push_back(age[i]);
				break;
			}
	
	cout << "The sorted (name, age) pairs:\n";
	for (size_t i = 0; i < len; i++)
		cout << '(' << name_copy[i] << ", " << age_copy[i] << ")\n";
	return 0;
}
catch (runtime_error& e)
{
	cout << e.what() << '\n';
}
catch (...)
{
	cout << "exiting\n";
}

void clear_line()
{
	char c;
	while (cin.get(c) && c != '\n')
		continue;
}

8.10

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

struct Data_analysis {
	double min;
	double max;
	double mean;
	double median;
};

Data_analysis analysis(const vector<double>& v);

int main()
try
{
	vector<double>v;
	double x;
	Data_analysis data;

	cout << "Enter some numbers ending by a non-digit character.\n";
	while (cin >> x)
		v.push_back(x);

	data = analysis(v);

	cout << "max: " << data.max << "\tmin: " << data.min << endl;
	cout << "mean: " << data.mean << "\tmedian: " << data.median << endl;

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

Data_analysis analysis(const vector<double>& v)
{
	Data_analysis data;
	vector<double>v2 = v;
	unsigned size = v2.size();
	
	sort(v2);
	data.min = v2[0];
	data.max = v2[size - 1];

	double sum = 0;
	for (double x : v2)
		sum += x;
	data.mean = sum / size;
	
	data.median = (v2[(size - 1) / 2] + v2[size / 2]) / 2;
	
	return data;
}

8.12

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

void read_string(vector<string>& vs);
void output_string_length(const vector<string>& vs, const vector<int>& vi);
vector<int> string_analysis(vector<string> vs);
void dictionary_order_string(vector<string>& vs);

int main()
try
{
	vector<string>vs;
	vector<int>vi;

	read_string(vs);
	vi = string_analysis(vs);
	output_string_length(vs, vi);

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

void read_string(vector<string>& vs)
{
	cout << "Enter some string, ending by character '!'\n";
	string s;
	while (cin >> s && s != "!")
		vs.push_back(s);
}

void output_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;
		}
		else if (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;
}


void dictionary_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"

void f(const int n);

int main()
{
	int i = 5;
	constexpr int j = 6;

	f(i);
	f(j);
	f(7);

	return 0;
}

void f(const int n)
{
	cout << "const in n = " << n << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值