原书:Essential C++, Stanley B. Lippman, 电子工业出版社, 2013.
章节:第2章 面向过程的编程风格
环境:CLion + MinGW + GCC 8.1.0
2.1 改写程序,让用户不断输入位置值,直到用户希望停止
#include <iostream>
#include <iomanip>
using namespace std;
bool fibonacci_elem(int, int &);
int main() {
int index, elem;
cout << "Please enter a positive integer, and you can enter -1 to terminate" << endl;
while(cin >> index) {
if(index == -1)
break;
fibonacci_elem(index, elem);
cout << elem << endl;
cout << "Please enter a positive integer, and you can enter -1 to terminate" << endl;
}
return 0;
}
bool fibonacci_elem(int index, int &elem) {
const int max_index = 45; // 限制最大索引值,否则结果可能会溢出
if(index <= 0 || index > max_index){
cerr << "Your should enter a positive integer no more than "
<< max_index << endl;
return false; // 返回值为布尔类型,表示能否计算得到指定索引的Fibonacci序列元素
}
int ans = 1;
int n1 = 1, n2 = 1;
for(int i = 3; i <= index; ++i){
ans = n1 + n2;
n1 = n2;
n2 = ans;
}
elem = ans; // 通过引用返回对应的Fibonacci序列元素值
return true;
}
2.2 Pentagonal数列的求值公式为P(n) = n(3n - 1) / 2,借此产生1,5,12,22,35等元素值。定义一个函数利用上述公式将元素放到用户传入的vector中,元素个数由用户指定,检查元素个数的有效性。定义另一个函数,将给定的vector的所有元素一一打印出来,函数的第二参数接受一个字符串,表示存放在vector内的数列的类型。最后编写main()函数测试以上函数
#include <iostream>
#include <vector>
using namespace std;
bool pent_seq(vector<int> & vec, int size);
void display(const vector<int> & vec, string msg);
int main(){
int size;
cin >> size;
vector<int> vec;
if(pent_seq(vec, size))
display(vec, "int");
return 0;
}
bool pent_seq(vector<int> & vec, int size) {
// 题目要求用户传入vector,使用pass by reference,返回bool值表示size有效性
const int max_size = 1024;
if(size <= 0 || size > max_size) {
cerr << "Invalid size" << endl;
return false;
}
for(int i = 1; i <= size; i++)
vec.push_back(i * (3 * i - 1) / 2);
return true;
}
void display(const vector<int> & vec, string msg){
cout << "The type of the elements in the vector is " << msg << endl;
for(int i = 0; i < vec.size(); i++){
cout << vec[i] << ' ';
if((i + 1) % 10 == 0)
cout << endl;
}
}
2.3 将2.2中的Pentagonal数列求值函数拆分为两个函数,其中之一为inline,用于检验元素个数是否合理,若合理且尚未被计算则执行第二个函数以执行实际的求职工作
(1) 将inline函数check_size()定义在头文件中
// pent.h
#ifndef CHAPTER2_PENT_H
#define CHAPTER2_PENT_H
#include <iostream>
inline bool check_size(int size) { // 将inline函数定义在头文件中
const int max_size = 1024;
if(size <= 0 || size > max_size) {
std::cerr << "Invalid size" << std::endl;
return false;
}
return true;
}
#endif //CHAPTER2_PENT_H
(2) 相对于用户传入vector,在pent_seq中定义静态局部对象,并返回指向该对象的const vector<int>*指针给用户可能是更好的实现方式
// main.cpp
#include <iostream>
#include <vector>
#include "pent.h" // 包含自定义的pent.h头文件,其中包含inline函数check_size的定义
using namespace std;
const vector<int>* pent_seq(int size);
void display(const vector<int> & vec, const string& msg);
int main(){
int size;
cin >> size;
const vector<int>* vec;
if(check_size(size)){
vec = pent_seq(size);
display(*vec, "int");
}
return 0;
}
const vector<int>* pent_seq(int size) {
static vector<int> vec; // 静态局部对象
for(int i = vec.size() + 1; i <= size; i++)
vec.push_back(i * (3 * i - 1) / 2);
return &vec;
}
void display(const vector<int> & vec, const string& msg){
cout << "The type of the elements in the vector is " << msg << endl;
for(int i = 0; i < vec.size(); i++){
cout << vec[i] << ' ';
if((i + 1) % 10 == 0)
cout << endl;
}
}
2.4 编写函数,以局部静态的vector存储Pentagonal数列元素,返回一个const指针指向该vector,若vector的大小小于指定的元素个数,扩充vector。实现第二个函数,接受位置值,返回该位置上的元素,编写main()函数测试
int pent_elem(int pos) {
const vector<int> * vec = pent_seq(pos);
if(vec)
return (*vec)[pos-1];
else
return -1;
}
const vector<int>* pent_seq(int size) {
static vector<int> vec;
if(!check_size(size))
return nullptr;
for(int i = vec.size() + 1; i <= size; i++)
vec.push_back(i * (3 * i - 1) / 2);
return &vec;
}
2.5 实现一个重载的max()函数,接受两个整数,两个浮点数,两个字符串,一个整数vector,一个浮点数vector,一个字符串vector,一个整数数组以及一个表示数组大小的整数,一个浮点数数组以及表示数组大小的整数,一个字符串数组即表示数组大小的整数,编写main()测试这些函数
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int max(int, int);
double max(double, double);
string max(const string&, const string&);
int max(const vector<int>*);
double max(const vector<double>*);
string max(const vector<string>*);
int max(const int*, int);
double max(const double*, int);
string max(const string*, int);
int main() {
int i1 = 1, i2 = 2;
double d1 = 1.0, d2 = 2.0;
string s1 = "abc", s2 = "ABC";
int arr1[] = {i1, i2};
double arr2[] = {d1, d2};
string arr3[] = {s1, s2};
vector<int> vec1(arr1, arr1 + 2);
vector<double> vec2(arr2, arr2 + 2);
vector<string> vec3(arr3, arr3 + 2);
cout << max(i1, i2) << endl;
cout << max(d1, d2) << endl;
cout << max(s1, s2) << endl;
cout << max(&vec1) << endl;
cout << max(&vec2) << endl;
cout << max(&vec3) << endl;
cout << max(arr1, 2) << endl;
cout << max(arr2, 2) << endl;
cout << max(arr3, 2) << endl;
return 0;
}
int max(int val1, int val2) {
return val1 >= val2? val1 : val2;
}
double max(double val1, double val2) {
return val1 >= val2? val1 : val2;
}
string max(const string& val1, const string& val2) {
return val1 >= val2? val1 : val2;
}
int max(const vector<int>* vec) {
return *max_element(begin(*vec), end(*vec));
}
double max(const vector<double>* vec) {
return *max_element(begin(*vec), end(*vec));
}
string max(const vector<string>* vec) {
return *max_element(begin(*vec), end(*vec));
}
int max(const int *arr, int size) {
int max_val = -10e6;
for(int i = 0; i < size; i++) {
if(arr[i] > max_val)
max_val = arr[i];
}
return max_val;
}
double max(const double *arr, int size) {
double max_val = -10e6;
for(int i = 0; i < size; i++) {
if(arr[i] > max_val)
max_val = arr[i];
}
return max_val;
}
string max(const string *arr, int size) {
string max_val;
for(int i = 0; i < size; i++) {
if(arr[i] > max_val)
max_val = arr[i];
}
return max_val;
}
2.6 以template重新完成2.5,编写main()进行测试
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template<typename type> type max_elem(type, type);
template<typename elem_type> elem_type max_elem(const vector<elem_type>*);
template<typename array_type> array_type max_elem(const array_type*, int);
int main() {
int i1 = 1, i2 = 2;
double d1 = 1.0, d2 = 2.0;
string s1 = "abc", s2 = "ABC";
int arr1[] = {i1, i2};
double arr2[] = {d1, d2};
string arr3[] = {s1, s2};
vector<int> vec1(arr1, arr1 + 2);
vector<double> vec2(arr2, arr2 + 2);
vector<string> vec3(arr3, arr3 + 2);
cout << max_elem(i1, i2) << endl;
cout << max_elem(d1, d2) << endl;
cout << max_elem(s1, s2) << endl;
cout << max_elem(&vec1) << endl;
cout << max_elem(&vec2) << endl;
cout << max_elem(&vec3) << endl;
cout << max_elem(arr1, 2) << endl;
cout << max_elem(arr2, 2) << endl;
cout << max_elem(arr3, 2) << endl;
return 0;
}
template<typename type>
type max_elem(type val1, type val2) {
return val1 >= val2? val1 : val2;
}
template<typename elem_type>
elem_type max_elem(const vector<elem_type>* vec) {
return *max_element(begin(*vec), end(*vec));
}
template<typename array_type>
array_type max_elem(const array_type *arr, int size) {
return *max_element(arr, arr + size);
}
在CLion + MinGW + GCC8.1.0环境下,命名为max()函数引发了冲突,错误信息如下
error: call of overloaded 'max(int&, int&)' is ambiguous
cout << max(i1, i2) << endl;
函数名改为max_elem后能正常编译运行