《C++ Primer》第6章 6.1节习题答案

《C++ Primer》第6章 函数

6.1节 函数基础

练习6.1:实参和形参的区别是什么?
【出题思路】
函数名、返回值、参数三者组成了函数,其中参数分为实参和形参。
【解答】
形参出现在函数定义的地方,形参列表可以包含0个、1个或多个形参,多个形参之间以逗号分隔。形参规定了一个函数所接受数据的类型和数量。实参出现在函数调用的地方,实参的数量与形参一样多。实参的主要作用是初始化形参,并且这种初始化过程是一一对应的,即第一个实参初始化第一个形参、第二个实参初始化第二个形参,以此类推。实参的类型必须与对应的形参类型匹配。

练习6.2:请指出下列函数哪个有错误,为什么?应该如何修改这些错误呢?
(a)    int f() {
        string s;
        // ...
        return s;
    }
(b)    f2(int i) { /* ... */}
(c)    int calc(int v1, int v1) /* ... *. }
(d)    double square(double x) return x * x;    
【出题思路】
本题旨在考查函数的一般语法规则。首先,函数的三要素(函数名、返回值、参数)必不可少;其次,函数的主体内容必须放在一对花括号内;最后,函数体内返回的结果必须与函数的返回值类型相同。
【解答】
(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:编写你自己的fact函数,上机检查是否正确。
【出题思路】
通过练习编写自己的阶乘函数,熟悉函数的语法规则和定义函数的方法。
【解答】
原书中的fact函数使用while循环执行递减连乘运算,我们改写该程序,使用普通for循环得到满足题意的函数,如下所示:

#include <iostream>

using namespace std;

int fact(int a, int b)
{
    cout << "call fact======================" << endl;
    int sum = a + b;
    return sum;
}

int main(int argc, const char * argv[]) {
    
    cout << "sum = " << fact(10, 20) << endl;
    return 0;
}

运行结果:

练习6.4:编写一个与用户交互的函数,要求用户输入一个数字,计算生成该数字的阶乘。在main函数中调用该函数。
【出题思路】
理解函数的调用过程,尤其是注意区别形参和实参。
【解答】
满足题意的程序如下所示:

#include <iostream>

using namespace std;

int fact(int val)
{
    if(val < 0)
        return -1;
    int ret = 1;
    //从1连乘到val
    for(int i = 1; i != val + 1; ++i)
        ret *= i;
    
    return ret;
}

int main()
{
    int num;
    cout << "请输入一个整数:" << endl;
    cin >> num;
    cout << num << "的阶乘是:" << fact(num) << endl;
    
    return 0;
}

运行结果:

 练习6.5:编写一个函数,输出其实参的绝对值。
【出题思路】
练习定义函数并在main中调用该函数。
【解答】
根据参数类型的不同,我们可以分别求整数的绝对值和浮点数的绝对值。因为本题主要考查的知识点是编写和使用函数,因此参数的类型不是关键。从通用性的角度出发,我们不妨设定参数类型是双精度浮点数double。满足题意的程序如下所示:

#include <iostream>
#include <cmath>

using namespace std;
//第一个函数通过if-else语句计算绝对值
double myABS(double val)
{
    if(val < 0)
        return val * -1;
    else
        return val;
}

//第二个函数调用cmath头文件的abs函数计算绝对值
double myABS2(double val)
{
    return abs(val);
}

//第三个函数直接在前面加-号
double myABS3(double val)
{
    if(val < 0)
        return -val;
    else
        return val;
}

int main()
{
    double num;
    cout << "请输入一个数:" << endl;
    cin >> num;
    cout << num << "的绝对值是:" << myABS(num) << endl;
    cout << num << "的绝对值是:" << myABS2(num) << endl;
    cout << num << "的绝对值是:" << myABS3(num) << endl;
    return 0;
}

运行结果:

 练习6.6:说明形参、局部变量以及局部静态变量的区别。编写一个函数,同时用到这三种形式。
【出题思路】
理解局部变量的含义,理解自动对象的创建和销毁机制,弄清楚我们为什么需要局部静态变量,应该如何使用局部静态变量。
【解答】
形参和定义在函数体内部的变量统称为局部变量,它们对函数而言是局部的,仅在函数的作用域内可见。函数体内的局部变量又分为普通局部变量和静态局部变量,对于形参和普通局部变量来说,当函数的控制路径经过变量定义语句时创建该对象,当到达定义所在的块末尾时销毁它。我们把只存在于块执行期间的对象称为自动对象。这几个概念的区别是:
●形参是一种自动对象,函数开始时为形参申请内存空间,我们用调用函数时提供的实参初始化形参对应的自动对象。
●普通变量对应的自动对象也容易理解,我们在定义该变量的语句处创建自动对象,如果定义语句提供了初始值,则用该值初始化;否则,执行默认初始化。当该变量所在的块结束后,变量失效。
●局部静态变量比较特殊,它的生命周期贯穿函数调用及之后的时间。局部静态变量对应的对象称为局部静态对象,它的生命周期从定义语句处开始,直到程序结束才终止。下面的程序同时使用了形参、普通局部变量和静态局部变量:

#include <iostream>

using namespace std;

//该函数同时使用了形参,普通局部变量和静态局部变量
double myADD(double val1, double val2)  //val1 和 val2是形参
{
    double result = val1 + val2;  //result是普通局部变量
    static unsigned iCnt = 0;     //iCnt是静态局部变量
    ++iCnt;
    cout << "该函数已经累计执行了" << iCnt << "次" << endl;
    return result;
}

int main()
{
    double num1, num2;
    cout << "请输入两个数:" << endl;
    while(cin >> num1 >> num2)
    {
        cout << num1 << "与" << num2 << "的求和结果是:" << myADD(num1, num2) << endl;
    }
    
    return 0;
}

运行结果:

 练习6.7:编写一个函数,当它第一次被调用时返回0,以后每次被调用返回值加1。
【出题思路】
本题旨在考查局部静态变量的使用方法。
【解答】
我们定义一个非常简单的函数,该函数除了统计执行次数外什么也不做。该函数的定义和调用形式如下所示:

#include <iostream>

using namespace std;

//该函数公用于统计执行的次数
unsigned myCnt()  //完成函数的任务不需要任何参数
{
    static unsigned iCnt = -1;  //iCnt 是静态局部变量
    ++iCnt;
    return iCnt;
}


int main()
{
    cout << "请输入任意字符后按回车键继续" << endl;
    char ch;
    while(cin >> ch)
    {
        cout << "函数myCnt的执行次数是:" << myCnt() << endl;
    }
    
    return 0;
}

运行结果:

练习6.8:编写一个名为Chapter6.h的头文件,令其包含6.1节练习(第184页)中的函数声明。
【出题思路】
函数声明与函数定义的形式非常类似,唯一的区别是函数声明无须函数体,用一个分号替代即可。函数应该在头文件中声明而在源文件中定义。
【解答】
根据题目要求,Chapter6.h头文件的内容如下:
#ifndef CHAPTER6_H_INCLUDED
#define CHAPTER6_H_INCLUDED

int fact(int);
double myABS(double);
double myABS2(double);

#endif //CHAPTER6_H_INCLUDED

练习6.9:编写你自己的fact.cc和factMain.cc,这两个文件都应该导入上一小节的练习中编写的Chapter6.h头文件。通过这些文件,理解你的编译器是如何支持分离式编译的。
【出题思路】
理解分离式编译的机制。
【解答】
fact.cc文件的内容是:

#include "program06_08.h"
#include <iostream>
#include <cmath>

using namespace std;

int fact(int val)
{
    if(val < 0)
        return -1;
    int ret = 1;
    for(int i = 1; i != val + 1; ++i)
        ret *= i;
    
    return ret;
}

void myABS(int &a)
{
    if(a < 0)
        a = -a;
}

int myABS2(int b)
{
    if(b < 0)
        return -b;
    else
        return b;
}

int main()
{
    int num;
    cout << "请输入第一个整数:" << endl;
    cin >> num;
    myABS(num);
    cout << num << "的阶数是:" << fact(num) << endl;
    cout << "请输入第2个整数:" << endl;
    cin >> num;
    num = myABS2(num);
    cout << num << "的阶数是:" << fact(num) << endl;
    return 0;
}

 运行结果:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值