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;
double temperature;
};
inline double temp_monitor(double a, double 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));
int day{ 3 };
Reading r{ 0,0 };
double a{ 15 }, b{ 35 };
char corf{ 'c' };
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;
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
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;
};
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)
{
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
#include "../../std_lib_facilities.h"
#include"Roman_int.h"
struct Token {
char kind;
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) { }
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;
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 };
case '\n':
return Token{ print };
case 'I': case 'V': case 'X': case 'L':
case 'C': case 'D': case 'M':
{
cin.putback(ch);
Roman_int r;
cin >> r;
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");
}
}
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;
}
class Variable {
public:
string name;
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)
{
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)
{
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;
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);
}
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 = 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);
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);
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
#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) { }
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;
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 };
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);
double val;
is >> val;
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");
}
}
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;
}
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)
{
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)
{
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;
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);
}
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()))
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);
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;
}
|