Essential C++--Exercise of Chpt.2
前言
本文用于记录阅读书籍《Essential C++》Chpt.2后完成课后习题。
正文(Code)
2.1 Continuous Input
先前的main()
只让用户输入一个位置值,然后便结束程序。如果用户想取得两个甚至更多元素值,他必须执行这个程序两次或多次。请改写main()
,使它允许用户不断输入位置值,直到用户希望停止为止。
#include <iostream>
using namespace std;
#if 0
// instance A from template class
template <Class T1, Class T2> Class A
{
public:
int a;
int func_a(T1 a, T2 b);
}
// function func_a definition of class A from template class
template <Class T1, Class T2> int A<T1, T2>::func_a(T1 a ,T2 b)
{
return (a + b);
}
#endif
void pr_sequence(int idx, int elem)
{
cout << elem << (!(idx % 10) ? '\n' : ' ');
}
bool fibon_elem(int pos, int & elem)
{
if (pos <= 0 || pos > 1024)
{
cout << "invalid pos[" << pos << "]" << endl;
return false;
}
switch(pos)
{
case 2:
{
cout << "1 ";
}
case 1:
{
cout << "1 ";
break;
}
default:
{
cout << "1 1 ";
break;
}
}
int n_1 = 1, n_2 = 1;
for(int i = 3; i <= pos; i++)
{
elem = n_1 + n_2;
n_1 = n_2;
n_2 = elem;
pr_sequence(i, elem);
}
cout << endl;
return true;
}
bool usr_try_query(void)
{
bool b_usr_try = false;
char c_usr_ipt = false;
cout << "try it? (Y/y: yes, N/n: no): ";
cin >> c_usr_ipt;
if ('Y' == c_usr_ipt || 'y' == c_usr_ipt)
{
b_usr_try = true;
}
else
{
b_usr_try = false;
if ('N' != c_usr_ipt && 'n' != c_usr_ipt)
{
cout << "invalid input character[" << c_usr_ipt << "]" << endl;
}
}
return b_usr_try;
}
int get_usr_pos(void)
{
int i_usr_pos = 0;
cout << "pls input a pos(1~1024): ";
cin >> i_usr_pos;
cout << endl;
return i_usr_pos;
}
int main()
{
int i_pos;
int i_elem;
while(usr_try_query())
{
i_pos = get_usr_pos();
if (false == fibon_elem(i_pos, i_elem))
{
cout << "cal fibon elem failed!" << endl;
continue;
}
cout << "get fibon elem[" << i_elem << "]" << endl;
}
cout << "usr exit" << endl;
return 0;
}
2.2 List Pentagonal
Pentagonal数列的求值公式是:
P
(
n
)
=
n
(
3
n
−
1
)
/
2
P(n) = n(3n-1)/2
P(n)=n(3n−1)/2
借此产生1, 5, 12, 22, 35
等元素值。试定义一个函数,利用上述公式,将产生的元素放到用户传入的vector
之中,元素个数由用户指定。请检查元素个数的有效性(太大则可能引发overflow
问题)。接下来编写第二个函数,能够将给定的vector
的所有元素一一打印出来。此函数的第二参数接受一个字符串,表示存放在vector
内的数列的类型。最后再写一个main()
,测试上述两个函数。
#include <iostream>
#include <vector>
#include <string>
using namespace std;
bool is_num_valid(int num)
{
return !(num <= 0 || num > 1024);
}
int get_penta_val(int num, vector<int> &v_store)
{
if (true != is_num_valid(num))
{
cout << "invalid num: " << num << endl;
return -1;
}
if (num <= v_store.size())
{
cout << "already ok!" << endl;
return 0;
}
for(int i = v_store.size()+1; i <= num; i++)
{
v_store.push_back(i * (3 * i - 1) / 2);
}
return 0;
}
void pr_usr_vector(vector<int> &vec, string &type)
{
cout << "vector type: " << type << endl;
for(int i = 0; i < vec.size(); i++)
{
cout << vec.at(i) << ((9 == i % 10) ? '\n' : ' ');
}
cout << endl;
return;
}
bool get_another_try(void)
{
bool bTry = false;
char cUsrIpt = 0;
cout << "Try it? (Y/y: yes N/n: no): ";
cin >> cUsrIpt;
if ('Y' == cUsrIpt || 'y' == cUsrIpt)
{
bTry = true;
}
else
{
bTry = false;
if ('N' != cUsrIpt && 'n' != cUsrIpt)
{
cout << "invalid input[" << cUsrIpt << "]" << endl;
}
}
return bTry;
}
int get_usr_input_num(int &num)
{
cout << "pls input num(1~1024): ";
cin >> num;
if (num <= 0 || num > 1024)
{
cout << "invalid input num: " << num << endl;
return -1;
}
cout << "get input num: " << num << endl;
return 0;
}
int main()
{
static vector<int> v_usr;
int i_usr_input = 0;
string str_type("string");
while(get_another_try())
{
if (0 != get_usr_input_num(i_usr_input))
{
continue;
}
if (0 != get_penta_val(i_usr_input, v_usr))
{
cout << "update user vector failed!" << endl;
return -1;
}
pr_usr_vector(v_usr, str_type);
}
cout << "usr exit" << endl;
return 0;
}
2.3 Split Pentagonal List
将练习2.2的Pentagonal
数列求值函数拆分为两个函数,其中之一为inline
,用来检验元素个数是否合理。如果的确合理,而且尚未被计算,便执行第二个函数,执行实际的求值工作。
#include <iostream>
#include <vector>
#include <string>
#include "2.3.h" // header file
using namespace std;
bool is_num_valid(int num)
{
return !(num <= 0 || num > 1024);
}
int get_penta_val(int num, vector<int> &v_store)
{
if (true != is_num_valid(num))
{
cout << "invalid num: " << num << endl;
return -1;
}
if (num <= v_store.size())
{
cout << "already ok!" << endl;
return 0;
}
for(int i = v_store.size()+1; i <= num; i++)
{
v_store.push_back(i * (3 * i - 1) / 2);
}
return 0;
}
void pr_usr_vector(vector<int> &vec, string &type)
{
cout << "vector type: " << type << endl;
for(int i = 0; i < vec.size(); i++)
{
cout << vec.at(i) << ((9 == i % 10) ? '\n' : ' ');
}
cout << endl;
return;
}
bool get_another_try(void)
{
bool bTry = false;
char cUsrIpt = 0;
cout << "Try it? (Y/y: yes N/n: no): ";
cin >> cUsrIpt;
if ('Y' == cUsrIpt || 'y' == cUsrIpt)
{
bTry = true;
}
else
{
bTry = false;
if ('N' != cUsrIpt && 'n' != cUsrIpt)
{
cout << "invalid input[" << cUsrIpt << "]" << endl;
}
}
return bTry;
}
int main()
{
static vector<int> v_usr;
int i_usr_input = 0;
string str_type("string");
while(get_another_try())
{
if (0 != get_usr_input_num(i_usr_input))
{
continue;
}
if (0 != get_penta_val(i_usr_input, v_usr))
{
cout << "update user vector failed!" << endl;
return -1;
}
pr_usr_vector(v_usr, str_type);
}
cout << "usr exit" << endl;
return 0;
}
头文件如下:
#ifndef _2_3_H_
#define _2_3_H_
#include <iostream>
using namespace std;
inline int get_usr_input_num(int &num)
{
cout << "pls input num(1~1024): ";
cin >> num;
if (num <= 0 || num > 1024)
{
cout << "invalid input num: " << num << endl;
return -1;
}
cout << "get input num: " << num << endl;
return 0;
}
#endif
2.4 Split Pentagonal List_V2
写一个函数,以局部静态(local static)
的vector
储存Pentagonal
数列元素。此函数返回一个const
指针,指向该vector
。如果vector
的大小小于指定的元素个数,就扩充vector
的大小。接下来再实现第二个函数,接受一个位置值,返回该位置上的元素。最后,编写main()
测试这些函数。
注:包含的头文件参考2.3小节。
#include <iostream>
#include <vector>
#include <string>
#include "2.3.h" // header file
using namespace std;
bool is_num_valid(int num)
{
return !(num <= 0 || num > 1024);
}
const vector<int> *get_vec(int num)
{
static vector<int> vec;
if (num <= vec.size())
{
cout << "already ok!" << endl;
return &vec;
}
for(int i = vec.size()+1; i <= num; i++)
{
vec.push_back(i * (3 * i - 1) / 2);
}
return &vec;
}
void pr_usr_vector(const vector<int> &vec, string &type)
{
cout << "vector type: " << type << endl;
for(int i = 0; i < vec.size(); i++)
{
cout << vec.at(i) << ((9 == i % 10) ? '\n' : ' ');
}
cout << endl;
return;
}
bool get_another_try(void)
{
bool bTry = false;
char cUsrIpt = 0;
cout << "Try it? (Y/y: yes N/n: no): ";
cin >> cUsrIpt;
if ('Y' == cUsrIpt || 'y' == cUsrIpt)
{
bTry = true;
}
else
{
bTry = false;
if ('N' != cUsrIpt && 'n' != cUsrIpt)
{
cout << "invalid input[" << cUsrIpt << "]" << endl;
}
}
return bTry;
}
int main()
{
const vector<int> *pv_usr = 0;
int i_usr_input = 0;
string str_type("string");
while(get_another_try())
{
if (0 != get_usr_input_num(i_usr_input))
{
continue;
}
if (true != is_num_valid(i_usr_input))
{
cout << "invalid num: " << i_usr_input << endl;
continue;
}
pv_usr = 0;
if (!(pv_usr = get_vec(i_usr_input)))
{
cout << "update user vector failed!" << endl;
return -1;
}
pr_usr_vector(*pv_usr, str_type);
}
cout << "usr exit" << endl;
return 0;
}
2.5 First Meeting with Overload
实现一个重载的max()
函数,让它接受以下参数:(a)两个整数,(b)两个浮点数,(c)两个字符串,(d)一个整数vector
,(f)一个字符串vector
,(g)一个整数数组,以及一个表示数组大小的整数值,(h)一个浮点数数组,以及一个表示数组大小的整数值,(i)一个字符串数组,以及一个表示数组大小的整数值。最后编写main()
测试这些函数。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int max(int a, int b)
{
cout << "func: int + int" << endl;
cout << "get max: " << (a < b ? b : a) << endl;
return 0;
}
int max(float a, float b)
{
cout << "func: float + float" << endl;
cout << "get max: " << (a < b ? b : a) << endl;
return 0;
}
int max(string a, string b)
{
cout << "func: string + string" << endl;
cout << "get max: " << (a < b ? b : a) << endl;
return 0;
}
int max(vector<int> &vec)
{
cout << "func: vector<int>" << endl;
if (vec.empty())
{
cout << "vector empty!" << endl;
return 0;
}
int i_max = vec.at(0);
for(int i = 1; i < vec.size(); i++)
{
i_max = i_max < vec.at(i) ? vec.at(i) : i_max;
}
cout << "get max: " << i_max << endl;
return 0;
}
int max(vector<float> &vec)
{
cout << "func: vector<float>" << endl;
if (vec.empty())
{
cout << "vector empty!" << endl;
return 0;
}
float f_max = vec.at(0);
for(int i = 1; i < vec.size(); i++)
{
f_max = f_max < vec.at(i) ? vec.at(i) : f_max;
}
cout << "get max: " << f_max << endl;
return 0;
}
int max(vector<string> &vec)
{
cout << "func: vector<string>" << endl;
if (vec.empty())
{
cout << "vector empty!" << endl;
return 0;
}
string str_max = vec.at(0);
for(int i = 1; i < vec.size(); i++)
{
str_max = str_max < vec.at(i) ? vec.at(i) : str_max;
}
cout << "get max: " << str_max << endl;
return 0;
}
int max(int (&arr)[2], int num)
{
cout << "func: int array + int" << endl;
if (0 == num)
{
cout << "array empty!" << endl;
return 0;
}
int i_max = arr[0];
for(int i = 1; i < num; i++)
{
i_max = i_max < arr[i] ? arr[i] : i_max;
}
cout << "get max: " << i_max << endl;
return 0;
}
int max(float (&arr)[2], int num)
{
cout << "func: float array + int" << endl;
if (0 == num)
{
cout << "array empty!" << endl;
return 0;
}
float f_max = arr[0];
for(int i = 1; i < num; i++)
{
f_max = f_max < arr[i] ? arr[i] : f_max;
}
cout << "get max: " << f_max << endl;
return 0;
}
int max(string (&arr)[2], int num)
{
cout << "func: string array + int" << endl;
if (0 == num)
{
cout << "array empty!" << endl;
return 0;
}
string str_max = arr[0];
for(int i = 1; i < num; i++)
{
str_max = str_max < arr[i] ? arr[i] : str_max;
}
cout << "get max: " << str_max << endl;
return 0;
}
enum func_idx
{
int_int,
float_float,
string_string,
vec_int,
vec_float,
vec_string,
arr_int,
arr_float,
arr_string,
};
int get_func_idx(int &idx)
{
cout << "pls input your choice: ";
cin >> idx;
if (idx < int_int || idx > arr_string)
{
cout << "invalid input[" << idx << "]" << endl;
return -1;
}
return 0;
}
bool try_another_one(void)
{
char c_ipt = 0;
bool b_try = 0;
cout << "try it? (Y/y: yes N/n: no): ";
cin >> c_ipt;
if ('Y' == c_ipt || 'y' == c_ipt)
{
b_try = true;
}
else
{
b_try = false;
if ('N' != c_ipt && 'n' != c_ipt)
{
cout << "invalid input: " << c_ipt;
}
}
return b_try;
}
int main()
{
int idx = 0;
while(try_another_one())
{
if (0 != get_func_idx(idx))
{
continue;
}
switch(idx)
{
case int_int:
{
max((int)2,(int)3);
break;
}
case float_float:
{
max((float)2.1,(float)3.2);
break;
}
case string_string:
{
string str1("test!");
string str2("yeah!");
max(str1,str2);
break;
}
case vec_int:
{
vector<int> vec_1;
vec_1.push_back(2);
vec_1.push_back(3);
max(vec_1);
break;
}
case vec_float:
{
vector<float> vec_2;
vec_2.push_back(2.1);
vec_2.push_back(3.2);
max(vec_2);
break;
}
case vec_string:
{
vector<string> vec_3;
vec_3.push_back("test!");
vec_3.push_back("yeah!");
max(vec_3);
break;
}
case arr_int:
{
int arr_1[2] = {2, 3};
max(arr_1, 2);
break;
}
case arr_float:
{
float arr_2[2] = {2.1, 3.2};
max(arr_2, 2);
break;
}
case arr_string:
{
string arr_3[2] = {"test!", "yeah!"};
max(arr_3, 2);
break;
}
}
}
cout << "user exit!" << endl;
return 0;
}
2.6 Retry with Template Function
以template
重新完成练习2.5,并对main()
函数做适度的修改。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
template <typename T>
int max(T &a, T &b)
{
cout << "get max: " << (a < b ? b : a) << endl;
return 0;
}
template <typename T>
int max(vector<T> &vec)
{
cout << "func: vector<string>" << endl;
if (vec.empty())
{
cout << "vector empty!" << endl;
return 0;
}
T t_max = vec.at(0);
for(int i = 1; i < vec.size(); i++)
{
t_max = t_max < vec.at(i) ? vec.at(i) : t_max;
}
cout << "get max: " << t_max << endl;
return 0;
}
template <typename T>
int max(T (&arr)[2], int num)
{
cout << "func: string array + int" << endl;
if (0 == num)
{
cout << "array empty!" << endl;
return 0;
}
T t_max = arr[0];
for(int i = 1; i < num; i++)
{
t_max = t_max < arr[i] ? arr[i] : t_max;
}
cout << "get max: " << t_max << endl;
return 0;
}
enum func_idx
{
int_int,
float_float,
string_string,
vec_int,
vec_float,
vec_string,
arr_int,
arr_float,
arr_string,
};
int get_func_idx(int &idx)
{
cout << "pls input your choice: ";
cin >> idx;
if (idx < int_int || idx > arr_string)
{
cout << "invalid input[" << idx << "]" << endl;
return -1;
}
return 0;
}
bool try_another_one(void)
{
char c_ipt = 0;
bool b_try = 0;
cout << "try it? (Y/y: yes N/n: no): ";
cin >> c_ipt;
if ('Y' == c_ipt || 'y' == c_ipt)
{
b_try = true;
}
else
{
b_try = false;
if ('N' != c_ipt && 'n' != c_ipt)
{
cout << "invalid input: " << c_ipt;
}
}
return b_try;
}
int main()
{
int idx = 0;
while(try_another_one())
{
if (0 != get_func_idx(idx))
{
continue;
}
switch(idx)
{
case int_int:
{
int a = 2;
int b = 3;
max(a,b);
break;
}
case float_float:
{
float a_1 = 2.1;
float b_1 = 3.2;
max(a_1, b_1);
break;
}
case string_string:
{
string str1("test!");
string str2("yeah!");
max(str1,str2);
break;
}
case vec_int:
{
vector<int> vec_1;
vec_1.push_back(2);
vec_1.push_back(3);
max(vec_1);
break;
}
case vec_float:
{
vector<float> vec_2;
vec_2.push_back(2.1);
vec_2.push_back(3.2);
max(vec_2);
break;
}
case vec_string:
{
vector<string> vec_3;
vec_3.push_back("test!");
vec_3.push_back("yeah!");
max(vec_3);
break;
}
case arr_int:
{
int arr_1[2] = {2, 3};
max(arr_1, 2);
break;
}
case arr_float:
{
float arr_2[2] = {2.1, 3.2};
max(arr_2, 2);
break;
}
case arr_string:
{
string arr_3[2] = {"test!", "yeah!"};
max(arr_3, 2);
break;
}
}
}
cout << "user exit!" << endl;
return 0;
}
结语
个人阅读书籍《Essential C++》之余创建此专栏,用于记录完成每一章节后附录的exercise。如有问题,请各位不吝指正。