这里是第六章的练习题记录。
6.1节练习
练习6.1
实参是形参的初始值。第一个实参初始化第一个形参,第二个实参初始化第二个形参,以此类推。尽管实参与形参存在对应关系,但是并没有规定实参的求值顺序,编译器能以任意可行的顺序对实参求值。
实参的类型必须与对应的形参类型匹配,函数中有几个形参,就必须提供相同数量的实参。因为函数的调用规定实参数量应与形参数量一致,所以形参一定会被初始化。
练习6.2
(a)函数体返回的结果类型和函数的返回值类型不一致,且不能自动转换。 可将 int f() 改为 string f();
(b)函数缺少返回值类型,加上即可,如 int f2();
(c)形参的名称不能重复,可将其中一个形参v1 改为 v2;
(d)函数体必须放置在一对花括号内,应改为 { return x * x ;}。
练习6.3
int fact(int val)
{
int n = 1;
while (val > 1)
n *= val--;
return n;
}
int main()
{
int val = 5, mul = 0;
mul = fact(val);
cout << mul << endl;
}
练习6.4
int fact(int val)
{
int n = 1;
while (val > 1)
n *= val--;
return n;
}
int main()
{
int val = 0, mul = 0;
cout << "请输入一个数字:";
cin >> val;
mul = fact(val);
cout << "该数字的阶乘为: " << mul << endl;
}
练习6.5
int absval(int val)
{
if (val >= 0)
return val;
else
return -val;
}
int main()
{
int val = 0, mul = 0;
cout << "请输入一个数字:";
cin >> val;
mul = absval(val);
cout << "该数字的绝对值为: " << mul << endl;
}
6.1.1节练习
练习6.6
略
int fact(int val)
{
int n = 1;
static size_t m = 0;
while (val > 1)
n *= val--;
m += 1;
cout << "该函数已经执行了 " << m << "次" << endl;
return n;
}
int main()
{
int val = 0, mul = 0;
cout << "请输入一个数字:";
cin >> val;
mul = fact(val);
cout << "该数字的阶乘为: " << mul << endl;
}
练习6.7
int fact()
{
static size_t m = 0;
return m++;
}
int main()
{for(int i = 0; i < 10; ++i)
cout << "该函数被调用的次数为: " << fact() << endl;
}
6.1.2节练习
练习6.8
#ifndef CHAPTER6_H_INCLUDED #define CHAPTER6_H_INCLUDED int fact(int); int absval(int); #endif // CHAPTER6_H_INCLUDED
6.1.3节练习
练习6.9
fact.cc
#include "Chapter6.h"
using namespace std;
int fact(int val)
{
int n = 1;
while (val > 1)
n *= val--;
return n;
}
factMain.cc
#include#include "Chapter6.h" using namespace std; int main() { int val = 0, mul = 0; cout << "请输入一个数字:"; cin >> val; mul = fact(val); cout << "该数字的阶乘为: " << mul << endl; }
6.2.1节练习
练习6.10
void sw(int *p, int *q)
{
int m = *p;
*p = *q;
*q = m;
}
int main()
{
int a = 10, b = 0;
int* p = &a, * q = &b;
sw(p,q);
cout << a << endl;
cout << b << endl;
}
6.2.2节练习
练习6.11
void reset(int &n)
{
n = -n;
}
int main()
{
int n;
cout << "请输入一个整数:";
cin >> n;
reset(n);
cout << "整数n的相反数为: " << n << endl;
}
练习6.12
void sw(int& p, int& q)
{
int m = p;
p = q;
q = m;
}
int main()
{
int a = 10, b = 0;
sw(a, b);
cout << a << endl;
cout << b << endl;
}
我觉得使用引用的方法更容易,不容易出错,不需要额外声明指针变量,简单。
练习6.13
void f(T) 形参采用传值方式,函数对形参所做的所有操作都不会影响实参。
void f(T&) 形参采用传引用方式,引用形参是它对应的实参的别名,通过使用引用形参,允许函数改变一个或多个实参的值。
练习6.14
当函数需要同时返回多个值时,用到引用形参。
形参不能是引用类型的例子我还不知道诶,等我知道了我再来补吧。
练习6.15
字符串s使用引用类型,可避免拷贝长字符串,提高效率。字符串内容不需改变,声明为常量引用。
字符c比较小,且不需改变实参,所以不需使用引用类型。
occurs值需要传递到函数外,且会改变,所以定义为引用类型,而不是常量引用。
把函数不会改变的形参定义成普通的引用是一种比较常见的错误,这么做会带给函数调用者一种误导,即函数可以修改形参的值。此外,使用引用而非常量引用也会极大的限制函数所能接受的实参类型。我们不能把const对象,字面值或者需要类型转换的对象传递给普通的引用形参。因此应尽量使用常量引用形参。
6.2.3节练习
练习6.16
把形参类型 string& 改为 const string&
练习6.17
判断string中是否含有大写字母:
bool isupper(const string& s)
{
int b = 0;
for (auto& c : s)
if (c == toupper(c))
++b;
return b;
}
int main()
{
string s;
cout << "请输入一串字符:";
cin >> s;
cout << isupper(s) << endl;
}
把string对象全都改写为小写形式:
string Tolower(string& s)
{
for (auto& c : s)
c = tolower(c);
return s;
}
int main()
{
string s;
cout << "请输入一串字符:";
cin >> s;
Tolower(s);
cout << "将string对象全部改写为小写形式后的结果为:" << s << endl;
}
在两个函数中使用的形参类型不同,因为第一个要求中不需要改变实参的值,所以使用常量引用;第二个要求需要改变实参的值,使用普通引用。
练习6.18
(a)bool compare(const matrix &,const matrix &);
(b)vector::iterator changeval(int ,vector ::iterator);
练习6.19
(a)非法,参数数量不一致;
(b)合法;
(c)合法;
(d)合法,3.8可自动转换为形参所需的int类型。
练习6.20
函数不会改变的形参应该定义为常量引用。将其设置为普通引用可能会编译不通过。
6.2.4节练习
练习6.21
int comp(int a, const int *p)
{
if (a > *p)
return a;
else
return *p;
}
int main()
{
int a = 5, b = 2;
int* p = &b;
cout << "较大的值为:" << comp(a, p) << endl;
}
指针的类型为指向常量的指针。
练习6.22
void sw(int* p, int* q)
{
int m = *p;
*p = *q;
*q = m;
}
int main()
{
int a = 10, b = 0;
int* p = &a, * q = &b;
sw(p, q);
cout << a << endl;
cout << b << endl;
}
练习6.23
void print(const int* beg,const int* en)
{
while (beg != en)
cout << *beg++ << endl;
}
int main()
{
int i = 0, j[2] = {0,1};
auto beg = begin(j),en = end(j);
print(beg,en );
}
练习6.24
输出数组。
该代码限制了print函数的可用性,可修改为
void print(const int ia[],const int sz)
{
for(size_t i = 0; i != sz; ++i)
cout << ia[i] << endl;
}
6.2.5节练习
练习6.25
int main(int argc,char **argv)
{
string str;
for (int i = 0; i != argc; ++i)
str += argv[i];
cout << str << endl;
return 0;
}
练习6.26
int main(int argc,char **argv)
{
string str;
for (int i = 0; i != argc; ++i)
cout << "argc[" << i << "]: "<< argv[i] << endl;
return 0;
}
6.2.6节练习
练习6.27
int sum(initializer_listli) { int sum = 0; for (auto& c : li) sum += c; return sum; } int main() { int s = 0; s = sum({ 1,2,3,4,5,6 }); cout << "列表中所有元素的和为: "<< s << endl;
练习6.28
const string &
练习6.29
只有当initialize_list对象的元素是类类型或容器类型时,才有必要把范围for循环的循环控制变量设为引用类型吧。
6.3.2节练习
练习6.30
编译器只报告了一处错误,str_subrange函数必须返回值。
练习6.31
返回局部对象的引用是无效的。
当不希望返回的对象被修改时,返回对常量的引用无效。
练习6.32
合法,为 ia[10]的每一项赋值。
练习6.33
void print(vectorarry, int i) { int n = arry.size(); if (!arry.empty() && i < n) { cout << arry[i] << endl; print(arry, i + 1); } } int main() { vector arr = { 1,2,3,4 }; print(arr, 0); }
练习6.34
程序将陷入死循环。
练习6.35
变量的递减操作与读取变量值的操作共存于同一条表达式中,有可能产生未定义的值。
6.3.3节练习
练习6.36
string(&print())[10];
练习6.37
typedef string arr[10]; arr& print(); //使用类型别名 auto print() -> string(&)[10];//尾置返回类型 string str[10]; decltype(str) &print();//decltype 关键字
我觉得尾置返回类型最好,表达清楚,编写简单。
练习6.38
把 *arrPtr 改为 &arrPtr 即可。



