C++ Primer Plus习题及答案-第八章

习题选自:C++ Primer Plus(第六版)
内容仅供参考,如有错误,欢迎指正 !

1.内联函数:与普通函数的区别在于,编译器在处理内联函数的语句的时候,不会将语句编译成函数调用的指令,而是将整个函数的代码插入调用语句处(普通函数在调用的时候需要创建时间、参数传入等操作,会造成时间和空间的额外空间)

优点:不会产生函数调用的开销,提高了效率,减少了一些不必要的开销。

缺点:导致主函数指令增多,可能会增加二进制可执行文件的大小

1. 复习题

1.哪种函数适合定义为内联函数?

只有一行代码的小型、非递归的函数适合作为内联函数。

2假设song()函数的原形如下:

void song(const char * name, int times);

a.如何修改原形,使times的默认值为1?
b.函数定义需要做哪些修改?
c.能否为name提供默认值"O,My Papa"?

a.void song(const char * name, int times = 1);

b.函数定义不需要修改,只有函数原型包含默认信息。

c.可以,void song(char * name ="O,My Papa", int times = 1);

3.编写iquote()的重载版本--显示其用双引号括起的参数,编写3个版本:一个用于int参数,一个用于double参数,另一个用于string参数。
//用于 int 参数
void iquote(int n)
{
    cout << "\"" << n << "\"" << endl;
}
//用于 double 参数
void iquote(couble n)
{
    cout << "\"" << n << "\"" << endl;
}
//用于 string 参数
void iquote(char * str)
{
    cout << "\"" << str << "\"" << endl;
}
4.下面是一个结构模板:
struct box
{
    char maker[40];
    float height;
    float width;
    float length;
    float volume;
}
a.请编写一个函数,他将box结构体的引用作为形参,并显示每个成员的值。
b.请编写一个函数,他将box结构的引用作为行参,并将volume成员设置为其他3边的乘积。

a.

void showBox(const box & b)
{
    cout << "maker : " << b.maker << endl;
    cout << "height : " << b.height <

b.

void setVolume(box & b)
{
    b.volume = b.height * b.width * b.length;
}
5.为让函数fill()和show()使用引用参数,需要对程序清单7.15做哪些修改?

修改后的代码:

#include 
#include 
#include 
const int Seasons = 4;
const std::array Snames =
    {"Spring", "Summer", "Fall", "Winter"};

void fill(std::array &pa);
void show(const std::array &da);
int main()
{
    std::array expenses;
    fill(expenses);
    show(expenses);
    return 0;
}

void fill(std::array &pa)
{
    for (int i = 0; i < Seasons; i++)
    {
        std::cout << "Enter " << Snames[i] << " expenses: ";
        std::cin >> pa[i];
    }
}

void show(const std::array &da)
{
    double total = 0.0;
    std::cout << "\nEXPENSES\n";
    for (int i = 0; i < Seasons; i++)
    {
        std::cout << Snames[i] << ": $" << da[i] << '\n';
        total += da[i];
    }
    std::cout << "Total: $" << total << '\n';
}
6.指出下面每个目标是否可以使用默认参数或函数重载完成,或者这两种方法都无法完成,并提供合适的原型。
a. mass(density,volume)返回密度为density、体积为volume的物体的质量,而mass(density)返回密度为density、体积为1.0立法米的物体的质量。这些值的类型都为double。
b. repeat(10,"I'm OK")将指定的字符串显示10次,而repeat("But you're kind of stupid")将指定的字符串显示5次。
c. average(3,6)返回两个int参数的平均值(int类型),而average(3.0,6.0)返回两个double值的平均值(double类型)。
d. mangle("I'm glad to meet you")根据是将值赋给char变量还是char*变量,分别返回字符1和指向字符串“I'm glad to meet you”的指针。

a.

//既可以使用默认参数,又可以使用函数重载
//1.默认参数
double mass(double density, double volume = 1.0);

//2.函数重载
double mass(double density, double volume);
double mass(double density);

b.

//不能使用默认参数,因为使用默认值必须从右到左提供默认值
//函数重载
void repeat(int times, const char* str);
void repeat(const char* str);

c.

//函数重载
int average(int a, int b);
double average(double a, double b);

d.两种方法都不能完成,需分成两个不同的函数实现。

7.编写返回两个参数中较大值的函数模板。

代码实现:

template
T max(T t1, T t2)
{
    return t1 > t2 ? t1 : t2;
}
8.给定复习题6的模板和复习题4的box结构,提供一个模板具体化,它接受两个box参数,并返回体积较大的一个。

代码实现:

template<>
box max(box b1, box b2)
{
    return b1.volume > b2.volume ? b1 : b2;
}
9.在下述代码(假定这些代码是一个完整程序的一部分)中,v1、v2、v3、v4和v5分别是哪种类型?
int g(int x);

....

float m = 5.5f;

float &rm = m;

decltype(m)v1 = m;

decltype(rm)v2 = m;

decltype((m)) v3 = m;

decltype(g(100))v4;

decltype(2.0*m)v5;
decltype(m)v1 = m;     //类型为float
decltype(rm)v2 = m;    //类型为float &
decltype((m)) v3 = m;  //类型为float &
decltype(g(100))v4;    //类型为int
decltype(2.0*m)v5;     //类型为double

编程练习

1. 编写通常接受一个参数(字符串的地址),并打印该字符串的函数。然而,如果提供了第二个参数(int类型),且该参数不为0,则该函数打印字符串的次数将为该函数被调用的次数(注意,字符串的打印次数不等于第二个参数的值,而等于函数被调用的次数)。是的,这是一个非常可笑的函数,但它让您能够使用本章介绍的一些技术。在一个简单的程序中使用该函数,以演示该函数是如何工作的。

代码实现:

#include

using namespace std;

int myShowStr(char* str, int printTimes);

int main()
{
    char mystr[50] = "Hello,world!";
    myShowStr(mystr, 5);
    return 0;
}

int myShowStr(char* str, int printTimes)
{
    if(printTimes > 1)
    {
        cout << str << endl;
        printTimes--;
        myShowStr(str, printTimes);
    }
    else
    {
        cout << str << endl;
    }
    return printTimes;
}
2. CandyBar结构包含3个成员,第一个成员存储candy bar的品牌名称;第二个成员存储candy bar的重量(可能有小数);第三个成员存储candy bar的热量(整数)。请编写一个程序,它使用一个这样的函数,即将CandyBar的引用、char指针、double和int作为参数,并用最后3个值设置相应的结构成员。最后3个参数的默认值分别为“Millennium Munch”、2.85和350。另外,该程序还包含一个以CandyBar的引用为参数,并显示结构内容的函数。请尽可能使用const。

代码实现:

#include
using namespace std;
#define DEFAULT_BRAND  (char*)"Millennium Munch"
struct CandyBar{
    char* brand;
    double weight;
    int heat;
};
void setCandyBar(CandyBar& candyBar, char* brand = DEFAULT_BRAND, double weight = 2.85, int heat = 350);
void display(const CandyBar& candyBar);

int main()
{
    CandyBar cb,cb1;
    setCandyBar(cb1);
    setCandyBar(cb, (char*)"MJJ", 3.55, 120);
    display(cb);
    display(cb1);
    return 0;
}

void setCandyBar(CandyBar& candyBar, char *brand, double weight, int heat)
{
    candyBar.brand = brand;
    candyBar.weight = weight;
    candyBar.heat = heat;
}

void display(const CandyBar& candyBar)
{
    cout << "BRAND : " << candyBar.brand << endl;
    cout << "WEIGHT : " << candyBar.weight << endl;
    cout << "HEAT : " << candyBar.heat << endl;
}
3. 编写一个函数,它接受一个指向string对象的引用作为参数,并将该string对象的内容转化成大写,为此可以使用表6.4描述的函数toupper()。然后编写一个程序,它通过使用一个循环让您能够用不同的输入来测试这个函数,该程序的运行如下:

Enter a string (q to quit):go away
GO AWAY
Enter a string (q to quit):good grief!
GOOD GRIEF!
Enter a string (q to quit):q
Bye.

代码实现:

#include
#include
using namespace std;
void Conversion(string& str);
int main()
{
    string str;
    cout<<"Enter a string(q to quit): ";
    while(getline(cin,str) && str != "q")
    {
        Conversion(str);
        cout << str << endl;
        cout << "Next string(q to quit): ";
    }
    cout << "Bye." << endl;
    return 0;
}

void Conversion(string& str)
{
    int size = str.size();
    for(int i =0; i < size; i++)
    {
        str[i] = toupper(str[i]);
    }
}
4.下面是一个程序框架:
#include
#include
using namespace std;

struct stringy{
    char * str;
    int ct;
};

int main()
{
    stringy beany;
    char testing[] = "Reality isn't what it used to be.";
    set(beany, testing);
    show(beany);
    show(beany, 2);
    testing[0] = 'D';
    testing[1] = 'u';
    show(testing);
    show(testing, 3);
    show("Done!");

    return 0;
}

请提供其中描述的函数和原型,从而完成该程序。注意,应有两个show()函数,每个都使用默认参数。请尽可能使用const参数。set()使用new分配足够的空间来存储指定的字符串。这里使用的技术与设计和实现类时使用的相似。(可能还必须修改头文件的名称,删除using编译指令,这取决于所用的编译器)。

代码实现:

#include
#include
using namespace std;

struct stringy{
    char * str;
    int ct;
};

void set(stringy& stry, const char* test);
void show(const stringy& stry, int showTimes = 1);
void show(const char* ch, int showTimes = 1);
int main()
{
    stringy beany;
    char testing[] = "Reality isn't what it used to be.";
    set(beany, testing);
    show(beany);
    show(beany, 2);
    testing[0] = 'D';
    testing[1] = 'u';
    show(testing);
    show(testing, 3);
    show("Done!");

    return 0;
}

void set(stringy& stry, const char* test)
{
    stry.ct = strlen(test);
    stry.str = new char[stry.ct];
    strcpy(stry.str, test);
}

void show(const stringy& stry, int showTimes)
{
    for(int i =0; i < showTimes; i++)
    {
        cout << stry.str <
5.编写模板函数max5(),它将一个包含5个T类型元素的数组作为参数,并返回数组中最大的元素(由于长度固定,因此可以在循环中使用硬编码,而不必通过参数来传递)。在一个程序使用该函数,将T替换为一个包含5个int值的数组和一个包含5个double值的数组,以测试该函数。

代码实现:

#include

using namespace std;

template
T max5(T *t);

int main()
{
    int arr1[5] = {5, 3, 5, 9, 6};
    double arr2[5] = {5.2, 3.1, 6.8, 10.8, 7.1};
    cout << "arr1 max num : " << max5(arr1) << endl;
    cout << "arr2 max num : " << max5(arr2) << endl;
    return 0;
}

template
T max5(T* t)
{
    T maxValue = t[0];
    for(int i = 1; i < 5; i++)
    {
        if(maxValue < t[i])
        {
            maxValue = t[i];
        }
    }
    return maxValue;
}
6.编写模板函数maxn(),他将由一个T类型元素组成的数组和一个表示数组元素数目的整数作为参数,并返回数组中最大的元素。在程序对它进行测试,该程序使用一个包含6个int元素的数组和一个包含4个都不了元素的数组来调用该函数。程序还包含一个具体化,他将char指针数组和数组中的指针数量作为参数,并返回最长的字符串的地址。如果有多个这样的字符串,则返回其中第一个字符串的地址。使用由5个字符串指针组成的数组来测试该具体化。

代码实现:

#include
#include

using namespace std;

template
T maxn(T* t, int n);

template<>
char* maxn(char* pch[], int n);

int main()
{
    int arr1[6] = {5, 3, 5, 9, 6, 11};
    double arr2[4] = {5.2, 3.1, 2.8, 4.8};
    char const * arr3[5] = {
        "abcde",
        "abcdef",
        "abc",
        "ab",
        "abcdefg"
    };
    cout << "arr1 max num : " << maxn(arr1, 6) << endl;
    cout << "arr2 max num : " << maxn(arr2, 4) << endl;
    cout << "arr3 max len : " << maxn(arr3, 5) << endl;
    return 0;
}

template
T maxn(T* t, int n)
{
    T maxValue = t[0];
    for(int i = 1; i < n; i++)
    {
        if(maxValue < t[i])
        {
            maxValue = t[i];
        }
    }
    return maxValue;
}

template<>
char* maxn(char* pch[], int n)
{
    auto maxLen = strlen(pch[0]);
    int index = 0;
    for(int i = 1; i < n; i++)
    {
        if(maxLen < strlen(pch[i]))
        {
            maxLen = strlen(pch[i]);
            index = i;
        }
    }
    return pch[index];
}
7.修改程序清单8.14,使其使用两个名为SumArray()的模板函数来返回数组元素的总和,而不是显示数组的内容。程序应显示thing的总和以及所有debt的总和。
/******************程序清单8.14******************/
// tempover.cpp --- template overloading
#include 

template             // template A
void ShowArray(T arr[], int n);

template             // template B
void ShowArray(T * arr[], int n);

struct debts
{
    char name[50];
    double amount;
};

int main()
{
    using namespace std;
    int things[6] = {13, 31, 103, 301, 310, 130};
    struct debts mr_E[3] =
    {
        {"Ima Wolfe", 2400.0},
        {"Ura Foxe", 1300.0},
        {"Iby Stout", 1800.0}
    };
    double * pd[3]; 

// set pointers to the amount members of the structures in mr_E
    for (int i = 0; i < 3; i++)
        pd[i] = &mr_E[i].amount;
    
    cout << "Listing Mr. E's counts of things:\n";
// things is an array of int
    ShowArray(things, 6);  // uses template A
    cout << "Listing Mr. E's debts:\n";
// pd is an array of pointers to double
    ShowArray(pd, 3);      // uses template B (more specialized)
    // cin.get();
    return 0;
}

template 
void ShowArray(T arr[], int n)
{
    using namespace std;
    cout << "template A\n";
    for (int i = 0; i < n; i++)
        cout << arr[i] << ' ';
    cout << endl;
}

template 
void ShowArray(T * arr[], int n)
{
    using namespace std;
    cout << "template B\n";
    for (int i = 0; i < n; i++)
        cout << *arr[i] << ' ';
    cout << endl; 
}

代码实现:

#include 

template   
T SumArray(T arr[], int n);

template    
T SumArray(T * arr[], int n);

struct debts
{
    char name[50];
    double amount;
};

int main()
{
    using namespace std;
    int things[6] = {13, 31, 103, 301, 310, 130};
    struct debts mr_E[3] =
    {
        {"Ima Wolfe", 2400.0},
        {"Ura Foxe", 1300.0},
        {"Iby Stout", 1800.0}
    };
    double * pd[3];

    for (int i = 0; i < 3; i++)
        pd[i] = &mr_E[i].amount;

    cout << "sum of things : " << SumArray(things, 6) << endl;
    cout << "sum of debts :" << SumArray(pd, 3) << endl;;

    return 0;
}

template 
T SumArray(T arr[], int n)
{
    T sum = 0;
    for(int i =0; i < n; i++)
    {
        sum = sum + arr[i];
    }
    return sum;
}

template 
T SumArray(T * arr[], int n)
{
    T sum = 0;
    for(int i =0; i < n; i++)
    {
        sum = sum + *arr[i];
    }
    return sum;
}

你可能感兴趣的:(C++ Primer Plus习题及答案-第八章)