C++ Primier Plus(第六版) 第九章 内存模型和名称空间 编程练习答案

1. 下面是一个头文件:

// golf.h -- for ex1.cpp

const int Len = 40;
struct golf
{
    char fullname[Len];
    int handicap;
};

// non-interactive version
// function sets golf structure to provided name, handicap
// using values passed as arguments to function
void setgolf(golf & g, const char * name, int hc);

// interactive version
// function solicits name and handicap from user
// and sets the members of g to the values entered
// return 1 if name is entered,0 if name is empty string
int setgolf(golf & g);
// function resets handicap to new value
void handicap(golf & g, int hc);

// funciton displays contents of golf structure
void showgolf(const golf & g);

注意到setgolf()被重载,可以这样使用其第一个版本:
golf ann;
setgolf(ann, "Ann Birdfree", 24);
上述函数调用提供了存储在ann结构中的信息。可以这样使用第二个版本:
golf andy;
setgolf(andy);
上述函数将提示用户输入姓名和等级,并将它们存储在andy结构中。这个函数可以(但不是不一定必须)在内部使用第一个版本。根据这个头文件,创建一个多文件程序。其中一个文件名为golf.cpp,它提供了与头文件中的原型匹配的函数定义;另一个文件包含main(),并演示原型化函数的所有特性。例如,包含一个让用户输入的循环,并使用输入的数据来填充一个由golf结构组成的数组,数组被填满或用户将高尔夫选手的姓名设置为空字符串时,循环将结束。main()函数只是用头文件中原型化的函数来访问golf结构。

本题首先按照题目的要求编写golf.cpp文件,这几个函数没有什么难度,在int setgolf(golf & g);函数中,忘了将临时定义的值name与handicap赋给g,需要注意的是字符串数组赋值需要用到函数strcpy();判断字符串为空需要用到strcmp()函数。主函数文件实现了输入用户的功能,显示用户的功能,修改用户等级的功能。代码如下:

// golf.cpp -- defination of dealing with golf function 
#include<iostream>
#include<cstring>
#include"golf.h"

void setgolf(golf & g, const char * name, int hc)
{
    strcpy(g.fullname, name);
    g.handicap = hc;
}

int setgolf(golf & g)
{
    using std::cout;
    using std::cin;
    using std::endl;
    char name[Len];
    int hc;
    cout << "Enter the users'name: ";
    cin.getline(name, Len);
    if(!strcmp(name,""))
        return 0;
    strcpy(g.fullname,name);
    cout << "Enter the users'level: ";
    while(!(cin>>hc))
    {
        cin.clear();
        while(cin.get()!='\n')
            continue;
        cout << "Bad input, please enter a integer: ";
    }
    g.handicap = hc;
    cin.get();
    return 1;
}

void handicap(golf & g, int hc)
{
    g.handicap = hc;
}

void showgolf(const golf & g)
{
    using std::cout;
    cout << "Name: " << g.fullname << ", level: " << g.handicap << "\n" ;
}
// main_ex1.cpp -- using golf.cpp's function 
#include<iostream>
#include"golf.h"

const int Arsize = 5;
int main()
{
    using std::cout;
    using std::cin;
    using std::endl;
    char name[Len];
    int hd, number;
    int count = 0;
    golf gar[Arsize];
    cout << "Enter the Users' name and level(enter empty string to name to quit):\n";
    for(int i = 0; i < Arsize; i++)
    {
        cout << "User #" << i + 1 << ":\n";
        int end_flag = setgolf(gar[i]);
        if (end_flag == 0)
            break;
        count++;
    }
    for(int i = 0; i < count; i++)
    {
        cout << "User #" << i + 1 << ":\t";
        showgolf(gar[i]);
    }
    // using handicap
    
    cout << "Enter the number of user you need to change level(q to quit): ";
    while(cin >> number)
    {
        cout << "The new Level: ";
        cin >> hd;
        handicap(gar[number - 1], hd);
        cout << "Enter next number(q to quit): "; 
    }
    cout << "The new golf users list:\n";
    for(int i = 0; i < count; i++)
    {
        cout << "User #" << i + 1 << ":\t";
        showgolf(gar[i]);
    }
    cout << "Bye\n";
    return 0;
}

运行结果如下:
image

2. 修改程序清单9.9:用string对象代替字符数组。这样,该程序将不在需要检查输入的字符串是否过长,同时可以将输入的字符串同字符串""进行比较,以判断是否为空行。

本题首先增加头文件string,接下来修改函数strcount()的函数声明,修改完函数声明之后重点修改函数定义,定义需要修改的是while的判断条件,str为const常量,因此应该用判断str[count]是否为'\0'的方法,接着修改主函数调用,样例代码如下:

// ex2.cpp -- using a static local variable and using string
#include<iostream>
#include<string>
// constants
const int ArSize = 10;
// function prototype
void strcount(const std::string str);

int main()
{
    using namespace std;
    string input;
    char next;

    cout << "Enter a line:\n";
    getline(cin, input);
    while(cin)
    {   if(input == "")
            break;
        strcount(input);
        cout << "Enter next line(empty line to quit):\n";
        getline(cin, input);
    }
    cout << "Bye\n";
}

void strcount(const std::string str)
{
    using namespace std;
    static int total = 0;
    int count = 0;

    cout << "\"" << str << "\" contains ";
    while(str[count])
    {
        count++;
    }
    total += count;
    cout << count << " characters\n";
    cout << total << " characters total\n";
}

运行结果如下:
image

3. 下面是一个结构声明:

struct chaff
{
char dross[20];
int slag;
};
编写一个程序,使用定位new运算符将一个包含两个这种结构的数组放在一个缓冲区中。然后,给结构的成员赋值(对于char数组,使用函数strcpy()),并使用一个循环来显示内容。一种方法是程序清单9.10那样将一个静态数组用作缓冲区;另一种方法是使用常规new运算符来分配缓冲区。
本题考查的是定位new运算符的使用,这里使用new来创建动态缓冲区,需要最后释放掉该缓冲区。使用了两个函数,分别给结构赋值和显示结构,样例代码如下:

// ex3.cpp -- using placement new to store structure array
#include<iostream>
#include<cstring>

const int BUF = 500;
const int CSize = 20;

struct chaff
{
    char dross[CSize];
    int slag;
};
// dynamic ram
char * buffer = new char[BUF];
//enter dross is empty string to stop enter
int setchaff(chaff & c);
void showchaff(const chaff & c);

int main()
{
    using std::cout;
    using std::cin;
    using std::endl;
    int num;
    int count = 0;                          // store the enter num of chaff
    cout << "Enter the number of chaff: ";
    cin >> num;
    cin.get();
    chaff *arr = new(buffer) chaff[num];
    for(int i = 0; i < num; i++)
    {
        cout << "Chaff #" << i + 1 << ":\n";
        if(!setchaff(arr[i]))
            break;
        count++;
    }

    for(int i = 0; i < count; i++)
    {
        cout << "Chaff #" << i + 1 << ":\t";
        showchaff(arr[i]);
    }
    cout << "Bye\n";
    delete []buffer;
    return 0;
    
}

int setchaff(chaff & c)
{
    using std::cout;
    using std::cin;
    char name[CSize];
    cout << "Dross(enter empty string to quit): ";
    cin.getline(name,CSize);
    if(!strcmp(name,""))
        return 0;
    strcpy(c.dross,name);
    cout << "slag: ";
    cin >> c.slag;
    cin.get();
    return 1;
}

void showchaff(const chaff & c)
{
    using std::cout;
    cout << "Dross: " << c.dross << ", slag = " << c.slag << "\n";
}

运行结果如下:
image

4. 请基于下面这个名称空间编写一个由3个文件组成的程序:

	namespace SALES
{
    const int QUARTERS = 4;
    struct Sales
    {
        double sales[QUARTERS];
        double average;
        double max;
        double min;
    };
    // copies the lesser of 4 or n items for the array ar
    // to the sales member of s and computes and stores the
    // average, maximum,and minimum values of the entered items;
    // remaining elements of sales, if any, set to 0
    void setSales(Sales & s, const double ar[], int n);
    // gathers sales for 4 quraters interactively, stores them
    // in the sales member of s and computes and stores the
    // average, maximum, and minimum values
    void setSales(Sales & s);
    // display all information in structure s
    void showSales(const Sales & s);
}

第一个文件时一个头文件,其中包含名称空间;第二文件是一个源代码文件,它对这个名称空间进行拓展,以提供这三个函数的定义;第三个文件声明两个Sales对象,并使用setSales()的交互版本为一个结构提供值,然后使用setSales()的非交互式版本为另一个结构提供值。另外它还使用showSales()来显示这个结构提供值。

本题比较难,编程过程中遇到了很多错误;第一个难点是void setSales(Sales & s, const double ar[], int n);函数的实现,要求函数找出数组ar中四个较小的值,我采用了一个方法,首先找出最小值,找次小值的时候给首先赋初始值为最大值,让每一个值先判断大于最小值,大于然后和次小值比较大小,给次小值赋两个中较小的值,由此来得到最小值。
还有就是命名空间的使用我还不够熟悉,刚开始联合编译时,编译出现了错误。原因是没有将函数的定义补充到命名空间中,编译时找不到函数的定义。声明静态函数时应该在补充命名空间的上方声明,这样命名空间里的函数参可以调用这些函数。样例代码如下:

// sale.cpp -- function definiation of sale
#include<iostream>
#include"sale.h"

static double find_min(const double ar[], int n);
static double find_max(const double ar[], int n);
static double average(const double ar[], int n);
static double * find_4less(const double ar[], int n);


namespace SALES
{
    void setSales(Sales & s, const double ar[], int n)
    {
        s.min = find_min(ar, n);
        s.max = find_max(ar, n);
        s.average = average(ar,n);
        if(n <= 4)
        {
            int i;
            for(i = 0; i < n; i++)
                s.sales[i] = ar[i];
            for(;i < 4; i++)
                s.sales[i] = 0;
        }
        else
        {
            for(int i = 0; i < 4; i++)
                s.sales[i] = find_4less(ar, n)[i];
        }
    
    }

    void setSales(Sales & s)
    {
        using std::cout;
        using std::cin;
        cout << "Enter four sales:\n";
        for(int i = 0; i < 4; i++)
        {
            cout << "Sales #" << i + 1 << ": ";
            cin >> s.sales[i];
        }

        s.min = find_min(s.sales, 4);
        s.max = find_max(s.sales, 4);
        s.average = average(s.sales, 4);
    }

    void showSales(const Sales & s)
    {
        using std::cout;
        cout << "Sales list:\n";
        for(int i = 0; i < 4; i++)
        {
            cout << "Sales #" << i + 1 << ": ";
            cout << s.sales[i] << "\t";
        }
        cout << "\n";
        cout << "Average = " << s.average << ", max = " << s.max;
        cout << ", min = " << s.min << "\n";
    }


}


double find_min(const double ar[], int n)
{
    double min = ar[0];
    for(int i = 0; i < n; i++)
        min = min < ar[i] ? min : ar[i];
    return min;
}

double find_max(const double ar[], int n)
{
    double max = ar[0];
    for(int i = 0; i < n; i++)
        max = max < ar[i] ? ar[i] : max;
    return max;
}

double average(const double ar[], int n)
{
    double sum = 0;
    for(int i = 0; i < n; i++)
        sum += ar[i];
    return sum / n;
}
static double * find_4less(const double ar[], int n)
{
    double * lesser4 = new double[4];
    double lesser;
    lesser4[0] = find_min(ar, n);
    for(int i = 1; i < 4; i++)
    {
        lesser = find_max(ar, n);
        for(int j = 0; j < n; j++)
        {
            if(ar[j] > lesser4[i-1])
                lesser = lesser < ar[j] ? lesser : ar[j]; 
        }
        lesser4[i] = lesser;
    }
    return lesser4;
}
// ex4.cpp -- main() of sale.cpp
#include<iostream>
#include"sale.h"



int main()
{
    using namespace SALES;
    using std::cout;
    Sales s1,s2;
    double arr[6] = {1111.1, 666.6, 999.9, 333.3, 2222.2, 1234.5};
    setSales(s1);
    showSales(s1);
    setSales(s2, arr, 6);
    showSales(s2);
    cout << "Bye\n";
    return 0;
}

运行结果如下:
image

posted @ 2021-12-23 13:43  Fight!GO  阅读(176)  评论(0编辑  收藏  举报