C++ primer plus习题集及解析第九章(内存模型和名字空间)

发布于:2024-05-16 ⋅ 阅读:(48) ⋅ 点赞:(0)

题目:9.1

下面是一个头文件:

const int Len = 40;
struct golf {
    char fullname[Len];
    int handicap;
};
void handicap(golf & g, int hc);
void showgolf(const golf & g);
int setgolf(golf & g);

 注意到 setgolf() 被重载,可以这样使用其第一个版本:(有参构造)

golf ann;
setgolf(ann, "Ann Birdfree", 24);

上述函数调用提供了存储在ann结构中的信息。可以这样使用其第二个版本:(拷贝构造)

golf andy;
setgolf(andy);

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

代码: 

//golf.h
#include<iostream>
#include<string>
const int Len = 40;
struct golf {
    char fullname[Len];
    int handicap;
};
//设置等级
void handicap(golf& g, int hc);

//展示信息
void showgolf(const golf& g);

//设置信息,方式1,拷贝构造
int setgolf(golf& g);

//设置信息 方式2,有参构造
void setgolf(golf &object,const char* name, int hc);
//golf.cpp
#include "golf.h"

//设置等级
void handicap(golf& g, int hc)
{
	g.handicap = hc;
}

//展示信息
void showgolf(const golf& g)
{
	std::cout <<"名字:"<< g.fullname << std::endl;
	std::cout << "等级:" << g.handicap << std::endl;
}

//设置信息,方式1,拷贝构造
int setgolf(golf& g)
{
	//手动输入
	std::string name;
	
	std::cout << "请输入选手的姓名:";
	std::cin >> name;
	std::cout << std::endl;
	int hc;
	std::cout << "请输入选手的等级:";
	std::cin >> hc;
	int len = name.length();
	strcpy_s(g.fullname, len + 1, name.c_str());
	g.handicap = hc;

	return 1;
}

//设置信息 方式2,有参构造
void setgolf(golf& object, const char* name, int hc)
{
	int len = sizeof(name) / sizeof(name[0]);
	strcpy_s(object.fullname, len + 1, name);
	object.handicap = hc;
}

 问题1:void showgolf(const golf& g)为什么使用const golf&g

 使用const golf&g是为了确保在showgolf函数中不会意外修改golf对象的内容。const关键字表示g是一个常量引用,即在函数中无法修改g的值,只能读取它的内容。这有助于提高代码的可读性和安全性,同时避免意外的数据修改。

使用引用可以避免在函数调用时进行对象的复制,提高程序的效率。如果不使用引用,而是直接传递golf对象作为参数,则会触发对象的拷贝构造函数,将整个对象复制一份传递给函数。而使用引用只是传递对象的地址,不会触发拷贝构造函数,避免了不必要的开销。因此,使用引用可以在保证数据不被修改的前提下提高程序的性能。

题目:9.2 

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

9.9清单如下:(本质就是统计字符)

#include<iostream>
using namespace std;

const int ArSize = 10;

void strcount(const char* str);


int main()
{
	char input[ArSize];
	char next;
	cout << "输入一行:\n";
	cin.get(input, ArSize);

	while (cin)
	{
		cin.get(next);
		while (next != '\n')
		{
			cin.get(next);
		}

		strcount(input);
		cout << "输入下一行(输入空行退出):\n";
		cin.get(input, ArSize);
	}

	cout << "Bye\n";
	
	system("pause");
	return 0;
}

void strcount(const char* str)
{
	static int total = 0;//一直持续性的增加,程序不关闭就不释放
	int count = 0;

	cout << "\"" << str << "\" 包含字符数为";
	while (*str++)
	{
		count++;
	}
	total += count;
	cout << count << endl;
	cout << "总共的字符数为:" << total << endl;
}

代码: 

void strcount(const string str)
{
    static int total = 0;
    int count = 0;

    cout << "\"" << str.c_str() << "\" contains ";
    while (str[count])
    {
        count++;
    }
    total += count;
    cout << count << " characters\n";
    cout << total << " characters total\n";
}
void main()
{
    string input;

    cout << "输入一行:\n";
    getline(cin, input);
    while (cin)
    {
        strcount(input);
        cout << "输入下一行(输入空行退出):\n";
        getline(cin, input);
        if (input == "")
        {
            break;
        }
    }

    cout << "Bye\n";
    return;
}

问题1:while(cin)如何理解?

 在C++中,while(cin)是一种常见的用法,它利用了输入流对象cin的隐式转换为布尔值的特性。在C++中,输入流对象cin会在发生错误或到达文件末尾时返回false,否则返回true。因此,while(cin)的含义是在输入流对象cin有效时(即没有发生错误且没有到达文件末尾),就会一直执行循环。

这种用法通常用于循环读取用户的输入,直到用户输入特定的结束标志(例如空行)。在这种情况下,while(cin)可以作为一个方便的循环条件,让程序持续接收用户输入。

问题2:getline()用法 

 getline 是 C++ 中用于从输入流中读取一行数据的函数。它的用法如下: 

#include <iostream>
#include <string>

int main() {
    std::string line;
    
    // 从标准输入流中读取一行数据
    std::getline(std::cin, line);
    
    // 打印读取的数据
    std::cout << "You entered: " << line << std::endl;
    
    return 0;
}