第六单元
练习 6.1
编写你自己的fact函数,上机检查是否正确。注:阶乘。
#include <iostream>
int fact(int i)
{
if(i<0)
{
std::runtime_error err("Input cannot be a negative number");
std::cout << err.what() << std::endl;
}
return i > 1 ? i * fact( i - 1 ) : 1;
}
int main()
{
std::cout << std::boolalpha << (120 == fact(5)) << std::endl;
return 0;
}
启用std::boolalpha,可以输出 "true"或者 “false”。
练习 6.2
编写一个与用户交互的函数,要求用户输入一个数字,计算生成该数字的阶乘。在main函数中调用该函数。
#include <iostream>
#include <string>
int fact(int i)
{
return i > 1 ? i * fact(i - 1) : 1;
}
void interactive_fact()
{
std::string const prompt = "Enter a number within [1, 13) :\n";
std::string const out_of_range = "Out of range, please try again.\n";
for (int i; std::cout << prompt, std::cin >> i; )
{
if (i < 1 || i > 12)
{
std::cout << out_of_range;
continue;
}
std::cout << fact(i) << std::endl;
}
}
int main()
{
interactive_fact();
return 0;
}
练习 6.3
编写一个函数输出其实参的绝对值。
#include <iostream>
int abs(int i)
{
return i > 0 ? i : -i;
}
int main()
{
std::cout << abs(-5) << std::endl;
return 0;
}
练习 6.4
说明形参、局部变量以及局部静态变量的区别。编写一个函数,同时达到这三种形式。
解:
形参定义在函数形参列表里面;局部变量定义在代码块里面; 局部静态变量在程序的执行路径第一次经过对象定义语句时初始化,并且直到程序终止时才被销毁。
// 例子
int count_add(int n) // n是形参
{
static int ctr = 0; // ctr 是局部静态变量
ctr += n;
return ctr;
}
int main()
{
for (int i = 0; i != 10; ++i) // i 是局部变量
cout << count_add(i) << endl;
return 0;
}
练习 6.5
编写一个函数,当它第一次被调用时返回0,以后每次被调用返回值加1。
#include <iostream>
int generate()
{
static int ctr = 0;
return ctr++;
}
int main()
{
for (int i=0; i<10; i++) {
std::cout<< generate()<<std::endl;
}
return 0;
}
练习 6.6
编写一个名为Chapter6.h 的头文件,令其包含6.1节练习中的函数声明。
int fact(int val);
int func();
template <typename T>
T abs(T i)
{
return i >= 0 ? i : -i;
}
练习 6.7
编写你自己的fact.cc 和factMain.cc ,这两个文件都应该包含上一小节的练习中编写的 Chapter6.h 头文件。通过这些文件,理解你的编译器是如何支持分离式编译的。
#include "Chapter6.h"
#include <iostream>
int fact(int val)
{
if (val == 0 || val == 1) return 1;
else return val * fact(val-1);
}
int func()
{
int n, ret = 1;
std::cout << "input a number: ";
std::cin >> n;
while (n > 1) ret *= n--;
return ret;
}
#include "Chapter6.h"
#include <iostream>
int main()
{
std::cout << "5! is " << fact(5) << std::endl;
std::cout << func() << std::endl;
std::cout << abs(-9.78) << std::endl;
}
练习 6.8
编写一个函数,使用指针形参交换两个整数的值。 在代码中调用该函数并输出交换后的结果,以此验证函数的正确性。
#include <iostream>
#include <string>
void swap(int* lhs, int* rhs)
{
int tmp;
tmp = *lhs;
*lhs = *rhs;
*rhs = tmp;
}
int main()
{
for (int lft, rht; std::cout << "Please Enter:\n", std::cin >> lft >> rht;)
{
swap(&lft, &rht);
std::cout << lft << " " << rht << std::endl;
}
return 0;
}
练习 6.9
编写并验证你自己的reset函数,使其作用于引用类型的参数。注:reset即置0。
#include <iostream>
void reset(int &i)
{
i = 0;
}
int main()
{
int i = 42;
reset(i);
std::cout << i << std::endl;
return 0;
}
练习 6.10
改写程序,使其引用而非指针交换两个整数的值。
#include <iostream>
#include <string>
void swap(int& lhs, int& rhs)
{
int temp = lhs;
lhs = rhs;
rhs = temp;
}
int main()
{
for (int left, right; std::cout << "Please Enter:\n", std::cin >> left >> right; )
{
swap(left, right);
std::cout << left << " " << right << std::endl;
}
return 0;
}
练习 6.11
编写一个函数,令其接受两个参数:一个是int型的数,另一个是int指针。 函数比较int的值和指针所指的值,返回较大的那个。
#include <iostream>
using std::cout;
int larger_one(const int i, const int *p)
{
return (i > *p) ? i : *p;
}
int main()
{
int i = 6;
cout << larger_one(7, &i);
return 0;
}
练习 6.12
编写一个函数,令其交换两个int指针。
#include <iostream>
#include <string>
void swap(int*& lft, int*& rht)
{
auto tmp = lft;
lft = rht;
rht = tmp;
}
int main()
{
int i = 42, j = 99;
auto lft = &i;
auto rht = &j;
swap(lft, rht);
std::cout << *lft << " " << *rht << std::endl;
return 0;
}
练习 6.13
#include <iostream>
using std::cout; using std::endl; using std::begin; using std::end;
void print(const int *pi)
{
if(pi)
cout << *pi << endl;
}
void print(const char *p)
{
if (p)
while (*p) cout << *p++;
cout << endl;
}
void print(const int *beg, const int *end)
{
while (beg != end)
cout << *beg++ << endl;
}
void print(const int ia[], size_t size)
{
for (size_t i = 0; i != size; ++i) {
cout << ia[i] << endl;
}
}
void print(int (&arr)[2])
{
for (auto i : arr)
cout << i << endl;
}
int main()
{
int i = 0, j[2] = { 0, 1 };
char ch[5] = "pezy";
print(ch);
print(begin(j), end(j));
print(&i);
print(j, end(j)-begin(j));
print(j);
return 0;
}
练习 6.14
编写一个函数,它的参数是initializer_list类型的对象,函数的功能是计算列表中所有元素的和。
#include <iostream>
#include <initializer_list>
int sum(std::initializer_list<int> const& il)
{
int sum = 0;
for (auto i : il) sum += i;
return sum;
}
int main(void)
{
auto il = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::cout << sum(il) << std::endl;
return 0;
}
练习 6.15
编写一个递归函数,输出vector对象的内容。
#include <iostream>
#include <vector>
using std::vector; using std::cout;
using Iter = vector<int>::const_iterator;
void print(Iter first, Iter last)
{
if (first != last)
{
cout << *first << " ";
print(++first, last);
}
}
int main()
{
vector<int> vec{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
print(vec.cbegin(), vec.cend());
return 0;
}
练习 6.16
给make_plural函数的第二个形参赋予默认实参’s’, 利用新版本的函数输出单词success和failure的单数和复数形式。
#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::endl;
string make_plural(size_t ctr, const string& word, const string& ending = "s")
{
return (ctr > 1) ? word + ending : word;
}
int main()
{
cout << "single: " << make_plural(1, "success", "es") << " "
<< make_plural(1, "failure") << endl;
cout << "plural : " << make_plural(2, "success", "es") << " "
<< make_plural(2, "failure") << endl;
return 0;
}
练习 6.17
改写6.3.2节练习中使用递归输出vector内容的程序,使其有条件地输出与执行过程有关的信息。 例如,每次调用时输出vector对象的大小。 分别在打开和关闭调试器的情况下编译并执行这个程序。
#include <iostream>
#include <vector>
using std::vector; using std::cout; using std::endl;
void printVec(vector<int> &vec)
{
#ifndef NDEBUG
cout << "vector size: " << vec.size() << endl;
#endif
if (!vec.empty())
{
auto tmp = vec.back();
vec.pop_back();
printVec(vec);
cout << tmp << " ";
}
}
int main()
{
vector<int> vec{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
printVec(vec);
cout << endl;
return 0;
}
练习 6.18
编写函数f的4版本,令其各输出一条可以区分的消息。 验证上一个练习的答案,如果你的回答错了,反复研究本节内容直到你弄清自己错在何处。
#include <iostream>
using std::cout; using std::endl;
void f()
{
cout << "f()" << endl;
}
void f(int)
{
cout << "f(int)" << endl;
}
void f(int, int)
{
cout << "f(int, int)" << endl;
}
void f(double, double)
{
cout << "f(double, double)" << endl;
}
int main()
{
f(42);
f(42, 0);
f(2.56, 3.14);
return 0;
}