C++Primer第五版习题答案详解(六) 发表于 2022-07-16 | 更新于 2024-11-18
| 字数总计: 2.8k | 阅读时长: 12分钟 | 阅读量:
答案目录
第6章 函数
练习6.1
形参:函数定义的时的参数—也就是无赋值的变量(作用是说明参数的类型)
实参:调用函数时使用的参数—也就是有赋值的变量(函数实际操作的对象)
练习6.2
1 2 3 4 5 6 int f () { string s; return s; }
1 int calc (int v1, int v1) { }
1 double square (double x) return x * x ;
练习6.4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int jiecheng (int num) { int result = 1 ; if (num == 1 || num == 0 ) { return 1 ; } else { return num * jiecheng (num - 1 ); } } int main () { int k = 5 , result; result = jiecheng (k); cout << result << endl; }
练习6.5
1 2 3 4 int abs (int num) { return num > 0 ? num : -num; }
练习6.6
形参,指的是函数声明时的函数列表中定义的局部变量,在整个函数中起作用。
局部变量,指的是定义在块中的变量,只在块中起作用。
局部静态变量:在函数体内定义的静态变量,但是当函数结束时不会被销毁,直到整个程序结束之后才会销毁。
练习6.7
1 2 3 4 5 6 7 8 9 10 11 12 int leijia (int val) { static int cnt = 0 ; int result = 1 ; cout << "The function is call " << ++cnt << "times." ; if (val == 1 || val == 0 ) { return 1 ; } else { return val *leijia (val - 1 ); } }
练习6.10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void swap_pointer (int * a, int * b) { int tmp; tmp = *a; *a = *b; *b = tmp; } int main () { int x = 5 , y = 10 ; swap_pointer (&x, &y); cout << "x = " << x << ", y = " << y << endl; }
练习6.13
前者以传值方式传入参数,不能修改实参。后者以传址的方式传入参数,可以修改实参。
练习6.14
形参是否是引用类型应该根据是否需要修改对应实参的值来看,如果需要修改,则应是引用类型
练习6.15
原因:因为s字符串是不能被函数所修改的,所以是常量引用。
c可能是一个临时变量,所以不需要使用引用类型,也无需函数加以修改其本身。
如果令occurs为常量引用,则输出occurs为0(不能加以修改),而s可能会在程序中被修改。
练习6.16
1 2 3 bool is_empty (string& s) { return s.empty (); }bool is_empty (const string& s) { return s.empty (); }
练习6.17
判断是否有大写字母应该使用const 引用类型,因为不会改变该参数的值。而转换为大写字母不能使用const类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 bool is_have_upper (const string& s) { for (int i = 0 ; i < s.size (); i++) { if (isupper (s[i])) { return true ; } } return false ; } void to_upper (string& s) { for (int i = 0 ; i < s.size (); i++) { s[i] = toupper (s[i]); } }
练习6.18
1 bool compare (const matrix& a, const matrix& b) ;
1 vector<int >::iterator change_val (int val, vector<int >::iterator iter) ;
练习6.19
1 2 3 4 5 6 7 8 9 double calc (double ) ;int count (const string&, char ) ;int sum (vector<int >::iterator, vector<int >::iterator, int ) ;vector<int > vec (10 ) ;(a) calc (23.4 , 55.1 ); (b) count ("abcda" , 'a' ); (c) calc (66 ); (d) sum (vec.begin (), vec.end (), 3.8 );
练习6.20
无需在函数中改变的参数应该为常量引用,普通情况下,可能不会出错,但是有些不小心改变了不应该改变的参数就会引发不必要的错误
练习6.21
1 2 3 4 int compare (int x, const int *y) { return (x > *y) ? x : *y; }
练习6.22
1 2 3 4 5 6 void swap_pointer (int * &x, int * &y) { int *temp = x; x = y; y = temp; }
练习6.23
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 void print (const int *p) { if (p != nullptr ) { cout << *p << 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 ++ << " " ; } cout << endl; } void print (const int a[], size_t size) { for (size_t i = 0 ; i < size; i++) { cout << a[i] << " " ; } cout << endl; }
练习6.24
此题明显以传值的方式传递数组,是错误的
数组做参数时,会退化为指针,因此函数中的const int a[10]等同于const int *a,并且长度是不确定的,传a[3]或a[255]是没有区别的
因此如果我们要确定传递一个长度为10的数组,应该这样定义:
1 void print (const int (&a)[10 ]) ;
练习6.25,6.26
1 2 3 4 5 6 7 8 9 10 11 12 13 14 int main (int argc, char **argv) { if (argc != 3 ) { cout << "Usage: should have two arguments." << endl; } string str; for (int i = 1 ; i < argc; i++) { str += string (argv[i]) + " " ; } cout << str << endl; return 0 ; }
练习6.27
1 2 3 4 5 6 7 8 9 10 11 12 13 14 int sum (initializer_list<int > const il) { int sum = 0 ; for (auto i : il) { sum += i; } return sum; } int main () { auto il = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 }; cout << sum (il) << endl; }
练习6.28
该函数中的elem应该是const string& 类型
练习6.29
当循环控制变量是基本类型是,可以不声明为引用,否则还应该声明成引用,因为initializer_list对象可能是各种类型,有可能是自定义类型或者string类型。此时使用引用可以避免拷贝。
练习6.30
运行该函数,现在使用的MinGW编译器报错误1,不报错误2,
错误 C2561 “str_subrange”: 函数必须返回值 C++ Prime D:\Visio Studio project\C++ Prime\源.cpp 21
练习6.31
返回局部引用时无效,返回局部定义的常量引用无效。要确保返回的引用有效,就要确定引用所返回的是在函数之前已经存在的某个对象。
练习6.32
1 2 3 4 5 6 7 8 int & get (int *array, int index) { return array[index]; }int main () { int ia[10 ]; for (int i = 0 ; i != 10 ; ++i) get (ia, i) = i; }
练习6.33
1 2 3 4 5 6 7 void print_vector (vector<int >::const_iterator beg, vector<int >::const_iterator end) { if (beg != end) { cout << *beg << " " ; print_vector (++ beg, end); } }
练习6.34
如果传入的参数为负数,那么将永远不会停止
练习6.35
–在后是先用后减,达不到我们减一的目的。结果就是一直使用val循环
练习6.36
1 string (&func (string (&str)[10 ]))[10 ]
练习6.37
1 2 3 4 5 6 7 8 9 10 using arrStr = string[10 ];arrStr& func ( arrStr& arr_str ) ;auto func (string (&str)[10 ] ) -> string (&) [10] ;string str[10 ]; decltype (str) &func ( decltype (str)& );
练习6.38
1 2 3 4 decltype (odd) &arrPtr (int i){ return (i % 2 ) ? odd : even; }
练习6.39
1 2 3 4 5 6 7 8 9 10 11 12 -- a int calc (int , int ) ;int calc (const int , const int ) ; -- b int get () ;double get () ;-- c int *reset (int *) ;double *reset (double *) ;
练习6.40
1 2 3 4 -- a int ff ( int a, int b = 0 , int c = 0 ) ; -- b char *init (int ht = 24 , int wd, char bckgrnd) ;
练习6.41
1 2 3 4 char *init (int ht, int wd = 80 , char bckgrnd = ' ' ) ;(a) init (); (b) init (24 , 10 ); (c) init (14 , '*' );
练习6.43
1 2 (a) inline bool eq (const BigInt&, const BigInt& ) { ... } (b) void putValues (int *arr, int size) ;
练习6.44
1 2 3 4 inline bool isShorter (const string& str1, const string& str2) { return str1.size () < str2.size (); }
练习6.45
练习题中的函数短小的,应该被定义成内联函数。改写为内联函数只需要在函数声明前加inline关键字就可以
练习6.46
不能,因为isShorter函数中传入的参数不是字面值类型,str1.size() < str2.size()返回的也不是字面值类型
练习6.47
1 2 3 4 5 6 7 8 9 10 11 12 13 14 void print_vec (vector<int >& ivec) {#ifndef NDEBUG cout << "vector's size is " << ivec.size () << endl; #endif if (!ivec.empty ()) { auto tmp = ivec.back (); ivec.pop_back (); print_vec (ivec); cout << tmp << " " ; } cout << endl; }
练习6.48
不合理,函数的意义是让用户进行输入,直到输入的字符串是sought是停止。因此assert (cin) 一直为真,这条语句也就没有意义。可以改为:assert ( s == sought)
练习6.49
重载函数集合中的函数称为候选函数,候选函数具备两个特征:(1)与被调用的函数同名;(2)其声明在调用点可见。
从候选函数中选出能被这组实参调用的函数成为可行函数,可行函数也有两个特征:(1)其形参数量与本次调用提供的实参数量相等;(2)每个实参的类型与对应的形参类型相同,或是能转换成形参的类型
练习6.50
1 2 3 4 (a) f (2.56 , 42 ) (b) f (42 ) (c) f (42 , 0 ) (d) f (2.56 , 3.14 )
练习6.52
1 2 (a) manip ('a' , 'z' ); (b) manip (55.4 , dobj);
练习6.53
1 2 3 4 5 6 (a) int calc (int &, int &) ; int calc (const int &, const int &) ; (b) int calc (char *, char *) ; int calc (const char *, const char *) ; (c) int calc (char *, char *) ; int calc (char * const , char * const ) ;
练习6.54
1 2 3 4 5 6 7 8 9 using func1 = int (int , int );vector<func1*> fvec; int func (int a, int b) ;typedef decltype (func) * func2 ;vector<func2> fvec; using func3 = int (*) (int , int );vector<func3> fvec;
练习6.55,6.56
1 2 3 4 5 6 7 8 9 10 11 12 int add (int a, int b) { return a+b; }int sub (int a, int b) { return (a-b); }int multiply (int a, int b) { return a*b; }int divide (int a, int b) { return b != 0 ? a/b : 0 ; }int main () { typedef int (*p) (int , int ) ; vector<p> vec{add, sub,multiply, divide}; for (auto f : vec) { cout << f (2 , 4 ) << endl; } }