C++ Primer(第五版)课后习题记录 —— 第六章

本文详细记录了C++ Primer(第五版)第六章关于函数的全部习题解析,涵盖形参与实参的概念、局部变量的行为、函数参数传递方式的理解,以及函数使用中需要注意的细节问题,包括常量引用、数组参数、递归和重载等主题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第六章 函数

练习6.1

形参是定义函数的时候使用的参数,是用来接收调用这个函数时所传递的参数,这个参数就是实参。

练习6.2

//(a) 函数返回类型有误, string 型不能转化为 int 型
string f() {
  string s;
  //...
  return s;
}
//(b) 没有指定返回类型
void f2(int i) { /*...*/ }
//(c) 形参不能有同名
int calc(int v1, int v2) { /*...*/ }
//(d) 函数的操作必须在一个语句块中
double square (double x) {
  return x * x;
}

练习6.3

//输出一个数的小数部分
double fact (double x) {
      x = x - static_cast<int>(x);
      return x;
}

练习6.4

#include <iostream>
using namespace std;
long long fact (int x) {
      long long an = 1;
      while (x != 0)
        an = an * x--;
      return an;
}
int main(){
    int x;
    cin >> x ;
    long long ans;
    ans = fact(x);
    cout << ans << endl;
    return 0;
}

练习6.5

int abs(int x) {
  return x > 0 ? x : -x;
}

练习6.6

形参和函数体内部定义的变量统称为局部变量。形参属于自动对象,在函数开始时申请空间,并被实参初始化,在函数结束时销毁。其他在函数内定义的普通变量在其定义时申请空间,若定义中不含初始值,则执行默认初始化,并在函数结束时销毁。而局部静态变量在程序第一次经过其定义语句时被创建,若没有被显式地初始化,则执行值初始化,但不受函数终止的影响,直到程序终止时才被销毁。

int ohayo (int x) {
  int xx;
  xx = x + 1;
  static int wen = 1;
  wen += xx;
  return wen;
}

练习6.7

int wat () {
  static int a = 0;
  if (a != 0)
    a = 0;
  return a++;
}

练习6.8

//chapter6.h
int abs (int x);
long long fact (int x);

练习6.9

//fact.cc
#include "chapter6.h"
int abs(int x) {
  return x > 0 ? x : -x;
}

long long fact (int x) {
      long long an = 1;
      while (x != 0)
        an = an * x--;
      return an;
}
//factmain.cc
#include <iostream>
#include "chapter6.h"
using namespace std;

int main(){
    int x;
    long long ans;
    cin >> x;
    x = abs(x);
    ans = fact(x);
    cout << ans << endl;
    return 0;
}

练习6.10

#include <iostream>
using namespace std;
void swapp (int *a, int *b){
    int temp;
    temp = * a;
    * a = * b;
    * b = temp;
}
int main(){
    int c,d;
    cin >> c >> d;
    swapp(&c, &d);
    cout << c << ' ' << d << endl;
    return 0;
}

练习6.11

void reset (int &i){
    i -= i;
}

练习6.12

#include <iostream>
using namespace std;
void swapp (int &a, int &b){
    int temp;
    temp = a;
    a = b;
    b = temp;
}
int main(){
    int c,d;
    cin >> c >> d;
    swapp(c, d);
    cout << c << ' ' << d << endl;
    return 0;
}

练习6.13

void f(T) 仅把实参的值传递给形参,函数中形参的任何改变都不会影响到实参。
void f(&T) 实参被引用传递给形参,实参与函数中的形参同变化。

练习6.14

%¥&……%&¥#¥#¥%@¥#@%¥#……

练习6.15

由于 s 是 string 类型, string 对象有可能比较长,应该避免拷贝,所以是引用类型,同时 s 在函数中不发生变化,所以是常量引用。同时,由于 s 是常量引用的类型,可以在函数调用时,用字面值初始化 s。
c 只是用来标记,所以只需要普通引用。
因为希望借助 occurs 来额外返回出现的次数,所以使用引用类型。

练习6.16

函数调用时,不能直接用常量字面值来初始化形参。
bool is_empty(const string &s) { return s.empty(); }

练习6.17

//判断是否含有大写字母
bool upperornot (const string &s) {
  for (auto c : s) {
    if (c >= 'A' && c <= 'Z')
    return true;
  }
  return false;
}
//全改成小写形式
void todowner (string& s) {
  for (auto &c : s) {
    if (c >= 'A' && c <= 'Z')
      c -= ('A' - 'a');
  }
}

不一样,前者只需判断,不要求改变字符串,所以使用常量引用。

练习6.18

//(a)比较两个矩阵是否相等
bool compare (matrix &a, matrix &b);
//(b)迭代改变那某容器的元素
vector<int>::iterator change_val (int a, vector<int>::iterator b);

练习6.19

只有(a)不合法,calc函数声明时只有一个形参。

练习6.20

当某个形参可以使用 const 的时候,就尽量定义成常量引用 。这样可以避免形参错误地被改变。

练习6.21

int bigger (const int a, const int *b) {
  return a > * b ? a : * b;
}

练习6.22

void swapp (const int * &p1, const int * &p2) {
  int * temp;
  temp = p1;
  p1 = p2;
  p2 = temp;
}

练习6.23

&#(@)#@#HHUF$V@GF@F!

练习6.24

数组会被转换成指针传递到函数中,所以形参中定义的数组的维度其实是无关的。因此不能直接在函数中的循环次数简单的设为10次,如果传递的数组中元素少于10个,就会输出无关的结果。

练习6.25 & 练习6.26

#include <iostream>
#include <string>
using namespace std;
int main(int argc, char** argv)
{
    string str;
    cout << argc << endl;
    for (int i = 0; i != argc; ++i) {
        str += argv[i];
        str += " ";
    }
    cout << str << endl;
}

练习6.27

int sumup (initializer_list<int> lis) {
    int sum = 0;
    for (auto c : lis)
        sum += c;
    return sum;
}

练习6.28

循环中的 elem 属于对字符串的常量引用。

练习6.29

看情况啊,如果 initializer_list 中的元素易于被拷贝,那么就不需要声明成引用类型。

练习6.30

(Code::Blocks)
..\temp.cpp|10|error: return-statement with no value, in function returning ‘bool’ [-fpermissive]|

练习6.31

返回局部对象的引用无效。
在返回常量引用时,若返回的是一个局部临时量,就无效。

练习6.32

合法。给 ia 数组的十个元素赋予与下标相等的值。

练习6.33

int outputvec (vector<int>::iterator vbeg, vector<int>::iterator vend) {
    if (vbeg != vend) {
        cout << * vbeg << endl;
        outputvec(++vbeg, vend);
    }
    return 1;
}

练习6.34

如果输入的实参为正,则无影响。但如果输入的实参为负,则该函数会无限递归下去。

练习6.35

val– 表达式返回的仍是 val 的原值。

练习6.36

string (&func(string (&arr)[10])[10];

练习6.37

//使用类型别名
typedef string (&arr)[10];
arr func (arr in);
//使用尾置返回类型
auto func (arr in) -> string (&)[10];
//使用 decltype 关键字
string str[10];
decltype(str) &func (decltype(str) &in);

练习6.38

int odd[] = {1, 3, 5, 7, 9};
int even[] = {2, 4, 6, 8, 0};
decltype(odd) &arrptr(int i) {
  return (i % 2) ? return odd : even;
}

练习6.39

(a) 和 (b) 不合法。(c) 合法。

练习6.40

(a)合法。
(b)不合法,wd 和 backgnd 都必须有默认实参。

练习6.41

(a)不合法。ht 没有默认实参,所以在调用时,声明 ht 对应的实参。
(b)合法合理。
(c)合法,但是与程序员初衷不符。 ’ * ’ 被传递给了 wd 。

练习6.42

#include <iostream>
#include <string>
using namespace std;
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.43

都会放在头文件中。

练习6.44

inline bool isShorter(const string &s1, const string &s2) {
  return s1.size() < s2.size();
}

练习6.45

¥%¥%¥#%%!#¥#%!¥#%!¥#%%!

练习6.46

不能。因为函数返回值时调用的 size 函数,该函数不是 constexpr 类型。

练习6.47

#include <iostream>
#include <string>
#include <vector>
//#define NDEBUG
using namespace std;
using iter = vector<int>::iterator;
int outputvec (iter vbeg, iter vend) {
    #ifndef NDEBUG
    cerr << "Size of the vec is " << vend - vbeg << "." << endl;
    #endif // NDEBUG
    if (vbeg != vend) {
        cout << * vbeg << endl;
        outputvec(++vbeg, vend);
    }
    return 1;
}
int main (void) {
    vector<int> vec{1, 2, 3, 4, 5, 6, 7};
    iter vbegin = vec.begin();
    iter vend = vec.end();
    outputvec(vbegin, vend);
    return 0;
}

练习6.48

不合理啊,assert 函数应该在 while 循环里才有用。

练习6.49

候选函数是在函数调用时,被选中的重载函数集中的函数。
可行函数是在候选函数中能被调用中所提供的一组实参调用的函数。

练习6.50

(a) 不合法,二义性。
(b) void f(int);
(c) void f(int, int);
(d) void f(double, double = 3.14);

练习6.51

#include <iostream>
using namespace std;
void f(){
    cout << "____" << endl;
}
void f(int) {
    cout << "int" << endl;
}
void f(int, int) {
    cout << "int, int" << endl;
}
void f(double, double = 3.14) {
    cout << "double, double" << endl;
}
int main (void) {
    //f(2.56, 42);
    f(42);
    f(42, 0);
    f(2.56, 3.14);
}

练习6.52

(a) 通过类型提升实现的匹配。
(b) 通过算数类型转换实现的匹配。

练习6.53

(a) 合法。
(b) 合法。
(c) 不合法,两者的形参都对应 char * 类型的实参。

练习6.54 & 练习6.55 & 练习6.56

#include <iostream>
#include <vector>
using namespace std;
int func(int, int);
int add (int a, int b) {
    return a + b;
}
int substract (int a, int b) {
    return a - b;
}
int multiply (int a, int b){
    return a * b;
}
int divide (int a, int b) {
    return a/b;
}
int main (void) {
    vector<decltype(func) * > vec{add, substract, multiply, divide};
    for (auto f : vec)
        cout << f(4, 3) << endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值