C++ Primer 第五版 课后章节练习答案 第三章

编译软件为 vs2015。

第三章

练习3.1:

使用恰当的 using 声明重做1.4.1节(第11页)和2.6.2节(第67页)的练习。

解答:

重做1.4.1节:

//练习1.9 编写程序,使用 while 循环将 50 到 100 的整数相加。
#include "stdafx.h"
#include<iostream>
using std::cout;
using std::endl;

int main()
{
	int i = 50, s = 0;
	while (i <= 100) {
		s += i;
		++i;
	}
	cout << "sum from 50 to 100 is " << s << "\n" << endl;
    return 0;
}
//练习1.10 除了++运算符将运算对象的值增加 1 之外,还有一个递减运算符(--)
//实现将值减少 1。编写程序,使用递减运算符在循环中按递减顺序打印出 10 到 0 之间的整数。
#include "stdafx.h"
#include<iostream>
using std::cout;
using std::endl;

int main() 
{
	int i = 11;
	while (i > 0) {
		--i;
		cout << i << endl;
	}
	return 0;
}
//练习1.11 编写程序,提示用户输入两个整数,打印出这两个整数所指定范围内的所有整数
#include "stdafx.h"
#include<iostream>
using std::cin;
using std::cout;
using std::endl;

int main()
{
	int a, b, min, max;
	cout << " please input two numbers: " << endl;
	cin >> a >> b;
	if (a >= b)
		min = b, max = a;
	else
		min = a, max = b;
	cout << " between " << min << " to " << max << " is: \n";
	while (min <= max) {
		cout << min << endl;
		++min;
	}
	return 0;
}

重做2.4.1节: 

对于此节练习,只需要在前面加上 using std:: 声明,下面仅给出一个程序例子,其余则相同。可对照前面第二章的程序修改。

//用自己定义的 Sales_data 类改写练习1.20。读取一组书籍销售记录并将结果打印到标准输出上
#include "stdafx.h"
#include<iostream>
#include<string>
using std::cin;
using std::cout;
using std::endl;
using std::string;

struct Sales_data {
	string bookNo;//书号ISBN
	unsigned unit_sold = 0;//销售量
	double revenue = 0.0;//销售额
};

int main()
{
	Sales_data book;
	double price = 0.0;//销售单价
					   //首先读入书号ISBN、销售量、单价
	cin >> book.bookNo >> book.unit_sold >> price;
	//计算销售额并打印结果到标准输出上
	book.revenue = book.unit_sold*price;
	cout << book.bookNo << " total revenue is " << book.revenue << endl;
	return 0;
}

练习3.2: 

编写一段程序,从标准输入中一次读入一整行,然后修改该程序使其一次读入一个词。 

解答: 

//一次读入一整行
#include "stdafx.h"
#include<iostream>
#include<string>
using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	string line;
	while (getline(cin, line))
		cout << "\n" << line << endl;
    return 0;
}

 

//每次读取一个词
#include "stdafx.h"
#include<iostream>
#include<string>
using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	string word;
	cout << " please input your word " << endl;
	while (cin >> word)
		cout << "\n" << word << endl;
	return 0;
}

 

练习3.3:

请说明 string 类的输入运算符和 getline 函数分别是如何处理空白字符的。

解答:

 string 对象会自动忽略开头的空白(即空格符、换行符、制表符等)并从第一个真正的字符开始读起,直到遇见下一处空白为止。返回的结果中不包括空白符。

getline 函数则在读取整行时可以包括空白符,只要遇到换行符就结束并返回结果。返回的结果中也可以包括空白符。

练习3.4:

编写一段程序读入两个字符串,比较其是否相等并输出结果。如果不相等,输出较大的那个字符串。改写上述程序,比较输入的 两个字符串是否等长,如果不等长,输出长度较大的那个字符串。

解答: 

//比较字符串大小
#include "stdafx.h"
#include<iostream>
#include<string>
using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	string a, b;
	cout << " please input two strings \n " << endl;
	cin >> a >> b;
	if (a == b)
		cout << " the strings you input are equal! " << a << "\n" << endl;
	else {
		if (a > b)
			cout << " the larger string is " << a << endl;
		else
			cout << " the larger string is " << b << endl;
	}
    return 0;
}

当输入字符串不相等时:(注意大小写敏感)

 

当输入字符串相等时:

//比较字符串长度
#include "stdafx.h"
#include<iostream>
#include<string>
using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	string a, b;
	cout << " please input two strings \n " << endl;
	cin >> a >> b;
	if (a.size() == b.size())
		cout << " the length of strings you input are equal! "
		<< " and the length is " << a.size() << "\n" << endl;
	else {
		if (a.size() > b.size())
			cout << " the larger length is " << a << " and length is " << a.size() << endl;
		else
			cout << " the larger length is " << b << " and length is " << b.size() << endl;
	}
	return 0;
}

 当长度不相等时:

当长度相等时:

注意: 字符串大小和字符串长度大小不同,有可能字符串较大但其长度较小。字符串大小的比较是 string 对象中第一对相异字符比较的结果。

 练习3.5:

编写一段程序从标准输入中读入多个字符串并将它们连接在一起,输出连接成的大字符串。然后修改上述程序,用空格把输入的多个字符分隔开来。 

 解答:

//输出连接起来的字符串
#include "stdafx.h"
#include<iostream>
#include<string>
using std::cin;
using std::cout;
using std::endl;
using std::string;


int main()
{
	string word, line;
	cout << " please input your words! " << endl;
	while (cin >> word) {
		line += word;
		if (word == ".")
			break;
	}
	cout << " the result of strings combination " << "\n" << line << endl;
    return 0;
}

 

//输出连接起来的字符串,并用空格隔开
#include "stdafx.h"
#include<iostream>
#include<string>
using std::cin;
using std::cout;
using std::endl;
using std::string;


int main()
{
	string word, line;
	cout << " please input your words! " << endl;
	while (cin >> word) {
		line = line + " " + word;
		if (word == ".")
			break;
	}
	cout << " the result of strings combination " << "\n" << line << endl;
	return 0;
}

练习3.6: 

 编写一段程序,使用范围 for 语句将字符串内所有字符用 X 代替。

解答: 

#include "stdafx.h"
#include<iostream>
#include<string>
using std::cin;
using std::cout;
using std::endl;
using std::string;


int main()
{
	string word("Hello World!");
	cout << word << endl;
	for (auto &c : word)
		c = 'X';
	cout << word << endl;
	return 0;
}

 

 练习3.7:

就上一题完成的程序而言 ,如果将循环控制变量的类型设为 char 将发生什么?先估计一下结果,然后实际编程进行验证。 

解答:

不会出现不同,auto 通过编译器自动决定变量 c 的类型,c 的范围是 string 对象,所以其类型就是char。

#include "stdafx.h"
#include<iostream>
#include<string>
using std::cin;
using std::cout;
using std::endl;
using std::string;


int main()
{
	string word("Hello World!");
	cout << word << "\n" << endl;
	for (char &c : word)
		c = 'X';
	cout << word << "\n" << endl;
	return 0;
}

 练习3.8:

分别用传统的 while 循环和 for 循环重写第一题的程序,你觉得哪种形式更好呢?为什么?

解答: 

#include "stdafx.h"
#include<iostream>
#include<string>
using std::cout;
using std::endl;
using std::string;


int main()
{
	string word("Hello World!");
	cout << " orginal: " << word << "\n" << endl;
	string::size_type n = 0;//n 的类型是 size_type
	while (n < word.size()) {
		word[n] = 'X';
		++n;
	}
	cout << " using while: " << word << "\n" << endl;
	for (n = 0; n < word.size(); ++n)
		word[n] = 'X';
	cout << " using for: " << word << "\n" << endl;
	return 0;
}

我个人比较喜欢第二种形式,将 n 的所有范围写在条件中。程序看起来更清晰简洁。

练习3.9: 

下面的程序有何作用?它合法吗?如果不合法,为什么?

string s;

cout << s[ 0 ] << endl;

解答: 

 该程序的作用是输出字符串 s 中的第一位字符,但由于 s 未被赋予初值,其为空串,所以 s[ 0 ] 是未定义的,程序不合法。

练习3.10: 

编写一段程序,读入一个包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分。 

解答:

#include "stdafx.h"
#include<iostream>
#include<string>
using std::cin;
using std::cout;
using std::endl;
using std::string;


int main()
{
	string word, s;
	cout << " please input your word with punctuation characters! " << " \n " << endl;
	getline(cin, word);
		for (auto &c : word)//对于 Word 中的每一个字符 c
			if (!ispunct(c))//当 c 不是标点符号时
				s += c;//将 c 存入空字符串 s 中
		    cout << "\n" << endl;
			cout << s << "\n" << endl;//将新保存不带有标点符号的字符串 s 输出
    return 0;
}

练习3.11: 

下面的范围 for 语句合法吗?如果合法,c 的类型是什么?

const string s = " keep out!";

for  (auto &c:s){ /*......*/ }

解答:

 c 的类型字符型常量引用,若范围 for 之后的语句不改变 c 的值,则合法。

练习3.12:

下列 vector 对象的定义有不正确的吗?如果有,请指出来。对于正确的,描述其执行结果;对于不正确的,说明其错误的原因。

(a)vector<vector<int>> ivec;

(b)vector<string> svec = ivec;

(c)vector<string> svec( 10,"null");

 解答:

(a)合法。(注意c++11新标准取消了 vector 右侧 ">>"之间的空格符),ivec 为 vector 对象 ;

(b)不合法。svec 的类型是 string,而 ivec 的类型是 int ,类型不匹配不能用于初始化;

(c)合法。svec 内有 10 个元素,每个元素的初始值均为 null;

 练习3.13:

下列的 vector 对象个包含多少个元素?这些元素的值分别是多少?

(a)vector<int> v1;

(b)vector<int> v2(10);

(c)vector<int> v3(10,42);

(d)vector<int> v4{10};

(e)vector<int> v5{10,42};

(f)vector<string> v6{10};

(g)vector<string> v7{10,"hi"};

解答:

(a)v1 初始状态为空,不包含元素;

(b) v2 包含 10 个元素,每个元素的值都为 0;

(c)v3 包含 10 个元素,每个元素的值都为 42;

(d)v4 包含 1 个元素,其值为 10;

(e)v5 包含两个元素,其值分别为 10 ,42;

(f)v6 包含 10 个元素,元素的值由类默认初始化;

(g)v7 包含 10 个元素,元素的值都为 hi;

 练习3.14:

编写一段程序,用 cin 读入一组整数并把它们存入一个 vector 对象。

解答:

#include "stdafx.h"
#include<iostream>
#include<vector>
using std::cin;
using std::cout;
using std::endl;
using std::vector;


int main()
{
	cout << " please input your numbers: " << endl;
	int v1;
	vector<int> v2;
	while(cin >> v1);
	v2.push_back(v1);
    return 0;
}

 练习3.15:

改写上题的程序,不过这次读入的是字符串。

解答:

#include "stdafx.h"
#include<iostream>
#include<string>
#include<vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;


int main()
{
	cout << " please input your strings: " << endl;
	string v1;
	vector<string> v2;
	while (cin >> v1);
	v2.push_back(v1);
	return 0;
}

 练习3.16:

编写一段程序,把练习3.13中 vector 对象的容量和具体的内容输出出来。检验你之前的回答是否正确,如果不对,回过头来重新学习3.3.1节(第87页)直到弄明白错在何处为止。

解答:

#include "stdafx.h"
#include<iostream>
#include<string>
#include<vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;


int main()
{
	vector<int> v1;
	if (v1.empty())
		cout << " the vector is empty!" << endl;
	else {
		cout << " v1 value:" << " ";
		for (decltype(v1.size()) i = 0; i <= (v1.size() - 1); ++i)
			cout << v1[i] << " ";
	}
	cout << " size of v1:" << v1.size() << "\n" << endl;

	vector<int> v2(10);
	if (v2.empty())
		cout << " the vector is empty!" << endl;
	else {
		cout << " v2 value:" << " ";
		for (decltype(v2.size()) i = 0; i <= (v2.size() - 1); ++i)
			cout << v2[i] << " ";
	}
	cout << " size of v2:" << v2.size() << "\n" << endl;

	vector<int> v3(10, 42);
	if (v3.empty())
		cout << " the vector is empty!" << endl;
	else {
		cout << " v3 value:" << " ";
		for (decltype(v3.size()) i = 0; i <= (v3.size() - 1); ++i)
			cout << v3[i] << " ";
	}
	cout << " size of v3:" << v3.size() << "\n" << endl;

	vector<int> v4{ 10 };
	if (v4.empty())
		cout << " the vector is empty!" << endl;
	else {
		cout << " v4 value:" << " ";
		for (decltype(v4.size()) i = 0; i <= (v4.size() - 1); ++i)
			cout << v4[i] << " ";
	}
	cout << " size of v4:" << v4.size() << "\n" << endl;

	vector<int> v5{ 10,42 };
	if (v5.empty())
		cout << " the vector is empty!" << endl;
	else {
		cout << " v5 value:" << " ";
		for (decltype(v5.size()) i = 0; i <= (v5.size() - 1); ++i)
			cout << v5[i] << " ";
	}
	cout << " size of v5:" << v5.size() << "\n" << endl;

	vector<string> v6{ 10 };
	if (v6.empty())
		cout << " the vector is empty!" << endl;
	else {
		cout << " v6 value:" << " ";
		for (decltype(v6.size()) i = 0; i <= (v6.size() - 1); ++i)
			cout << v6[i] << " ";
	}
	cout << " size of v6:" << v6.size() << "\n" << endl;

	vector<string> v7{ 10,"hi" };
	if (v7.empty())
		cout << " the vector is empty!" << endl;
	else {
		cout << " v7 value:" << " ";
		for (decltype(v7.size()) i = 0; i <= (v7.size() - 1); ++i)
			cout << v7[i] << " ";
	}
	cout << " size of v7:" << v7.size() << "\n" << endl;
    return 0;
}

练习3.17:

从 cin 读入一组词并把他们存入一个 vector 对象。然后设法把所有词都改写为大写形式。输出改变后的结果,每个词占一行。

解答: 

#include "stdafx.h"
#include<iostream>
#include<string>
#include<vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;


int main()
{
	string s;
	vector<string> vec;
	cout << " please imput your words: " << endl;
	while (cin >> s)
	vec.push_back(s);
	for (auto &svec : vec) //此时的 svec 表示字符串
		for (auto &c : svec)//对于 svec 中的任意字符 c
			c = toupper(c);// toupper 函数只能处理字符
	for (auto v : vec)
		cout << v << "\n" << endl;
		return 0;
}

 练习3.18:

下面的程序合法吗?如果不合法,你准备如何修改?

vector<int> ivec;

ivec[0] = 42;

解答:

程序不合法。ivec 没有被初始化,其不包含任何元素,则 ivec[0] 不存在。

修改:

vector<int> ivec{ 0 };//先用 0 作为 ivec 的初始值

ivec[0] = 42; 

练习3.19:

如果想定义一个含有 10 个元素的 vector 对象,所有元素的值都是 42,请列举出三种不同的实现方法。哪种方法更好呢?为什么? 

解答:

#include "stdafx.h"
#include<iostream>
#include<vector>
using std::cout;
using std::endl;
using std::vector;


int main()
{
	vector<int> v1(10, 42);
	vector<int> v2{ 42,42,42,42,42,42,42,42,42,42 };
	vector<int> v3;
	for (decltype(v3.size()) i = 0; i <= 9; ++i) {
		int n = 42;
		v3.push_back(n);
		cout << v3[i] << endl;
	}
    return 0;
}

我更喜欢第一种方式,简单直接,可以看出元素个数以及内容。 对于存储多个重复元素的 vector 对象,使用第一种最方便。

练习3.20:

读入一组整数并把它们存入一个 vector 对象,将每对相邻整数的和输出出来。改写你的程序,这次要求先输出第 1 个和最后 1 个元素的和,接着输出第 2 个和倒数第 2 个元素的和,以此类推。

解答:

#include "stdafx.h"
#include<iostream>
#include<string>
#include<vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
	int num;
	vector<int> vec;
	cout << " please input your numbers: " << endl;
	while (cin >> num) 
		vec.push_back(num);
	//判断数据个数
	if (vec.empty()) {
		cout << " there is no numbers! " << endl;
		return -1;
	}
	if (vec.size() == 1) {
		cout << " there are just one number: " << vec[0] << " , No adjacent numbers! " << endl;
		}
	else {
		//计算相邻两队数据的和
		cout << " add two adjacent numbers: " << endl;
		for (decltype(vec.size()) i = 1; i < vec.size(); ++i)
			cout << vec[i - 1] + vec[i] << " ";
	}
	cout << endl;

	//计算读入数据的第一个加最后一个,第二个加倒数第二个,以此类推
	//此程序中默认奇数个数据将中间剩余的与自己相加
	cout << " the first add the last: " << endl;
	decltype(vec.size())  n = vec.size();
	if (n % 2 == 0)//判断数据个数的奇偶
		n = n / 2;
	else
		n = n / 2 + 1;
	for (decltype(vec.size()) j = 0; j < n; ++j)
		cout << vec[j] + vec[vec.size() - 1 - j] << " ";
	cout << endl;
    return 0;
}

练习3.21:

请使用迭代器重做3.3.3节(第94页)的第一个练习。

解答:

//用迭代器重做3.16节练习
#include "stdafx.h"
#include<iostream>
#include<string>
#include<vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;


int main()
{
	vector<int> v1;
	if (v1.empty())
		cout << " the vector is empty!" << endl;
	else {
		cout << " v1 value:" << " ";
		for (auto it = v1.cbegin(); it != v1.cend(); ++it)
			cout << *it << " ";
	}
	cout << " size of v1:" << v1.size() << "\n" << endl;

	vector<int> v2(10);
	if (v2.empty())
		cout << " the vector is empty!" << endl;
	else {
		cout << " v2 value:" << " ";
		for (auto it = v2.cbegin(); it != v2.cend(); ++it)
			cout << *it << " ";
	}
	cout << " size of v2:" << v2.size() << "\n" << endl;

	vector<int> v3(10, 42);
	if (v3.empty())
		cout << " the vector is empty!" << endl;
	else {
		cout << " v3 value:" << " ";
		for (auto it = v3.cbegin(); it != v3.cend(); ++it)
			cout << *it << " ";
	}
	cout << " size of v3:" << v3.size() << "\n" << endl;

	vector<int> v4{ 10 };
	if (v4.empty())
		cout << " the vector is empty!" << endl;
	else {
		cout << " v4 value:" << " ";
		for (auto it = v4.cbegin(); it != v4.cend(); ++it)
			cout << *it << " ";
	}
	cout << " size of v4:" << v4.size() << "\n" << endl;

	vector<int> v5{ 10,42 };
	if (v5.empty())
		cout << " the vector is empty!" << endl;
	else {
		cout << " v5 value:" << " ";
		for (auto it = v5.cbegin(); it != v5.cend(); ++it)
			cout << *it << " ";
	}
	cout << " size of v5:" << v5.size() << "\n" << endl;

	vector<string> v6{ 10 };
	if (v6.empty())
		cout << " the vector is empty!" << endl;
	else {
		cout << " v6 value:" << " ";
		for (auto it = v6.cbegin(); it != v6.cend(); ++it){
			if (it->empty())//等价于 (*it).empty()
				cout << " Null ";
			else
				cout << *it << " ";
	}
	}
	cout << " size of v6:" << v6.size() << "\n" << endl;

	vector<string> v7{ 10,"hi" };
	if (v7.empty())
		cout << " the vector is empty!" << endl;
	else {
		cout << " v7 value:" << " ";
		for (auto it = v7.cbegin(); it != v7.cend(); ++it) {
			if (it->empty())
				cout << " Null ";
			else
				cout << *it << " ";
		}
	}
	cout << " size of v7:" << v7.size() << "\n" << endl;
	return 0;
}

练习3.22:

修改之前那个输出 text 第一段的程序,首先把 text 的第一段全部都改成大写形式,然后在输出它。

解答: 

#include "stdafx.h"
#include<string>
#include<vector>
#include<iostream>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;


int main()
{
	cout << " please input your words: " << endl;
	string word;
	vector<string> text;
	while (getline(cin,word)) 
		text.push_back(word);
	for (auto it = text.begin(); it != text.end() && !it->empty(); ++it) {
		for (auto &c : *it)
			c = toupper(c);
		cout << *it << endl;
	}
    return 0;
}

//还可以先将字符串变成大写形式在存入 vector,然后输出,两种方式结果相同
int main()
{
	cout << " please input your words: " << endl;
	string word;
	vector<string> text;
	while (getline(cin, word)) {
		for(auto &c:word)
			c = toupper(c);
		text.push_back(word);
	}
	for (auto it = text.begin(); it != text.end() && !it->empty(); ++it) 
		cout << *it << endl;
	return 0;
}

 (注意:空格符与空字符串的区别!)

 练习3.23:

编写一段程序,创建一个含有 10 个整数的 vector 对象,然后使用迭代器将所有元素都变成原来的两倍。输出 vector 对象的内容,检验程序是否正确。

#include "stdafx.h"
#include<string>
#include<iostream>
#include<vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;


int main()
{
	int v;
	vector<int> v1;
	cout << " please input your integers: " << endl;
	while(cin >> v)
	v1.push_back(v);
	for (auto it = v1.begin(); it != v1.end(); ++it) {
		*it = 2 * (*it);
		cout << *it << " ";
	}
	cout << endl;
    return 0;
}	

练习3.24:

请使用迭代器重做3.3.3节(第94页)的最后一个练习。

解答:

#include "stdafx.h"
#include<iostream>
#include<string>
#include<vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
	cout << " please input your numbers: " << endl;
	int i, a1, a2;
	vector<int> vec;
	while (cin >> i)
		vec.push_back(i);
	//计算相邻两个的和
	if (vec.begin() == vec.end()) {
		cout << " there are no numbers!" << endl;
		return -1;
	}
	if ((vec.end() - vec.begin()) == 1) {
		cout << " there is just one number: " << vec[0] 
			<< " , No adjacent numbers!" << endl;
	}
	else {
		cout << " add two adjacent numbers: " << endl;
		for (auto beg = vec.begin(); (beg + 1) != vec.end(); ++beg) {
			a1 = *beg + *(beg + 1);
			cout << a1 << " ";
		}
		cout << endl;

		//计算第一个加最后一个,第二个加倒数第二个,以此类推
		//此程序中默认奇数个数据将中间剩余的与自己相加
		cout << " the first add the last: " << endl;
		auto end = vec.end();
		for (auto beg = vec.begin(); (beg + 1) <= end; ++beg) {
            //此时应该包括(beg+1)=end 的情况,因此用<=
			a2 = *beg + *(end - 1);
			--end;
			cout << a2 << " ";
		}
		cout << endl;
	}
    return 0;
}

 (当没有输入整数时)

(当只输入一个整数时)

(一般情况)

练习3.25:

3.3.3节(第93页)划分分段数的程序是使用下标运算符实现的,请利用迭代器改写该程序并实现完全相同的功能。 

解答: 

#include "stdafx.h"
#include<iostream>
#include<string>
#include<vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
	cout << " please input the scores: " << endl;
	vector<unsigned> scores(11, 0);
	unsigned grade;
	int n = 0;

	while (cin >> grade) {
		if (grade <= 100)
			n = grade / 10;
		auto it = scores.begin();
		*(it + n) += 1;//令迭代器指向的对应的成绩段的元素值加一
	}
	for (auto &sc : scores)
		cout << sc << " ";
	cout << endl;
    return 0;
}

(我们输入与书上的例子相同的分数,查看结果,与书上一致) 

练习3.26:

在 100 页的二分搜索程序中,为什么用的是 mid = beg + ( end - beg ) / 2,而非 mid = ( beg + end ) / 2;?

解答: 

因为在 vector 运算中,两个迭代器相加毫无意义,只支持两个迭代器相减或者是某一迭代器与一整数值相加、减的操作。 

练习3.27:

假设 txt_size 是一个无参数的函数,它的返回值是 int。请回答下列哪个定义是非法的?为什么?

unsigned buf_size = 1024;

(a)int ia[ buf_size ];

(b)int ia[ 4 * 7 - 14 ];

(c)int ia[ txt_size( ) ];

(d)char st[ 11 ] = "fundamental";

解答: 

(a)非法;buf_size 不是常量表达式。

(b)合法。

(c)非法;txt_size( ) 的返回值不是常量表达式。

(d)非法;没有空间存放空字符。

练习3.28:

下列数组中元素的值是什么?

string sa[ 10 ];

int ia[ 10 ];

int main(){

     string sa2[ 10 ];

     int       ia2[ 10 ];

解答:

 由于 string 不是内置类型,未指定初始值的情况下将被显示初始化为默认值,sa、sa2 内含有 10 个空字符串;int 为内置类型,其在函数体内部定义时,若未指定初始值,则其值是未定义的。ia 被显示初始化,含有 10 个 0,ia2 内部含有 10 个元素,均未被定义。

练习3.29:

相比于 vector 来说,数组有哪些缺点,请列举一些。

 解答:

相对于 vector,数组大小在一开始就被确定且不能改变,不能随意向其中添加元素。

其次不能将数组的内容直接拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值。

数组的维度必须是常量表达式,定义过程中容易出现非法定义。

练习3.30:

指出下面代码中的索引错误。

constexpr size_t array_size = 10;

int ia[ array_size ];

for(size_t ix = 1;ix <= array_size;++ix)

ia[ ix ] = ix;

解答: 

数组的索引从 0 开始,所以范围 for 语句中当 ix = array_size 时,会出现溢出错误,因此不可使其等于。可用 " < " 或 " != "

练习3.31:

编写一段程序,定义一个含有 10 个 int 的数组,令每个元素的值就是其下标值。

解答:

#include "stdafx.h"
#include<iostream>
using std::cout;
using std::endl;

int main()
{
	const unsigned sz = 10;
	int ia[sz];
	for (size_t ix = 0; ix != 10; ++ix) 
		ia[ix] = ix;
		for (auto i : ia)
			cout << i << " ";
	cout << endl;
    return 0;
}

练习3.32:

将上一题刚刚创建的数组拷贝给另外一个数组。利用 vector 重写程序,实现类似的功能。 

解答:

#include "stdafx.h"
#include<iostream>
#include<vector>
using std::cout;
using std::endl;
using std::vector;

int main()
{
	//创建一个数组,令元素等于其下标值,并拷贝给另一个数组
	int ia[10];  
	int ib[10];
	for (size_t ix = 0; ix != 10; ++ix) {
		ia[ix] = ix;
		ib[ix] = ia[ix];
	}
	for (auto i : ib)    
		cout << i << " ";  
	cout << endl;     

	//创建一个向量,令元素等于其下标值,并拷贝给另一向量
	vector<int> vec(10, 0);
	vector<int> svec(10, 0);
	for (decltype(vec.size()) n = 0; n != vec.size(); ++n) {
		vec[n] = n;
		//svec[n] = vec[n];
		svec = vec;//在 vector 中可以用其中一个向量初始化另一个向量
	}
	for (auto c : svec)
		cout << c << " ";
	cout << endl;
    return 0;
}

 

练习3.33:

对于 104 页的程序来说,如果不初始化 scores 将发生什么?

解答: 

unsigned 是内置类型,可以看出 scores 被定义在函数体内部,若不进行初始化,则含有未定义的元素。 

练习3.34:

假定 P1 和 P2 指向同一个数组中的元素,则下面程序的功能是什么?什么情况下该程序是非法的?
P1 += P2 - p1;

解答:

程序的功能就是将 P1 移动到 P2 的位置,即  P1 = P2;当 P1 、P2 中任意一个是非法的,此程序就是非法的。

练习3.35:

编写一段程序,利用指针将数组中的元素置为 0;

解答:

#include "stdafx.h"
#include<iterator>
#include<iostream>
using std::end;
using std::cout;
using std::endl;

int main()
{
	int a1[5] = { 7,8,6,5,4 };
	cout << " a1 before: ";
	for (auto c : a1)
		cout << c << " ";
	cout << endl;
	int *e = end(a1);
	cout << " a1 after:  ";
	for (int *p = a1; p != e; ++p) {
		*p = 0;
		cout << *p << " ";
	}
	cout << endl;
    return 0;
}

(为了对比首先将数组设置了不为零的初始值,然后利用指针将其置零) 

练习3.36:

编写一段程序,比较两个数组是否相等。再写一段程序,比较两个 vector 对象是否相等。

解答:

#include "stdafx.h"
#include<iostream>
#include<iterator>
#include<vector>
using std::cout;
using std::endl;
using std::begin;
using std::end;
using std::vector;


int main()
{
	//判断两个数组是否相等
	int a1[5] = { 0,1,2,3,4 };
	int a2[5] = { 0,2,2,3,4 };
	int *b1 = begin(a1), *e1 = end(a1);
	int *b2 = begin(a2), *e2 = end(a2);
	if ((e1 - b1) != (e2 - b2)) {
		cout << " the two arrays are not equal, size is different! " << endl;
		return -1;
	}
	int k = 0;
	for (int i = 0; i != (e1 - b1); ++i) 
		if (*(b1 + i) == *(b2 + i))
			++k;
	if (k == (e1 - b1))
		cout << " the two arrays are equal. " << endl;
	else
		cout << " the two arrays are not equal! " << endl;


	//判断两个向量是否相等
	vector<int> v1 = { 1,2,3,4,5 };
	vector<int> v2 = { 1,2,3,4,5 };
	if (v1 == v2)
		cout << " the two vectors are equal. " << endl;
	else
		cout << " the two vectors are not equal! " << endl;
	return 0;
}

练习3.37:

下面的程序是何含义,程序的输出结果是什么?

const char ca[ ] = { 'h','e','l','o' };

const char *cp = ca;

while(*cp){

        cout << *cp<< endl;

        ++cp;

解答:

 此程序是设置了一个字符串数组,利用指针 cp 输出其所有元素。输出的结果是“ helo”,while 循环的含义是检测指针是否指向了空字符,即遍历此数组。

练习3.38:

在本节中我们提到,将两个指针相加不但是非法的,而且也没什么意义。请问为什么两个指针相加没什么意义?

解答:

因为两个指针相加,首先结果不能保证其满足在规定的限制范围内,很大可能出现溢出错误。因此是非法的。像两个指针相减表示他们之间的距离,有一个中间差值变量,给指针加上一个整数,可以使其移动,而两个指针相加没有开头和结尾, 结果当然也毫无意义。

练习3.39:

编写一段程序,比较两个 string 对象。再写一段程序,比较两个 C 风格字符串的内容。

解答:

 

#include "stdafx.h"
#include<string>
#include<iostream>
#include<cstring>
using std::cout;
using std::endl;
using std::string;

int main()
{
	//比较两个 string 对象
	string s1 = "hello";
	string s2 = "world";
	if (s1 == s2)
		cout << " They are same! " << endl;
	else if (s1 > s2)
		cout << s1 << " is larger than " << s2 << endl;
	else
		cout << s2 << " is larger than " << s1 << endl;

	//比较两个 C 风格字符串
	const char ca1[] = "hellohello";
	const char ca2[] = "world";//注意字符串比较大小不是比较长度
	if (strcmp(ca1, ca2) == 0)
		cout << " They are same! " << endl;
	else if (strcmp(ca1, ca2) > 0)
		cout << " ca1 is larger than ca2 " << endl;
	else
		cout << " ca2 is larger than ca1 " << endl;
	return 0;
}

练习3.40:

编写一段程序,定义两个字符数组并用字符字面值初始化它们;接着再定义一个字符数组存放两个数组连接的后的结果。使用 strcpy 和 strcat 把前两个数组的内容拷贝到第三数组中。

解答: 

 

#include "stdafx.h"
#include<iostream>
#include<cstring>
#pragma warning(disable:4996)
//vs2015中会显示 strcpy、strcat 函数不安全,用此代码忽略
using std::cout;
using std::endl;

int main()
{
	char ca1[] = "hello";
	char ca2[] = "world";
	//size = strlen(ca1) + strlen(" ") + strlen(ca2) + 1 = 12;
	//可以计算得到新数组的维度至少为 12
	char ca[12];
	strcpy(ca, ca1);
	strcat(ca, " ");
	strcat(ca, ca2);
	cout << "ca1: " << ca1 << "\n " << endl;
	cout << "ca2: " << ca2 << "\n " << endl;
	cout << "ca1+ca2: " << ca << "\n " << endl;
    return 0;
}

 

练习3.41:

编写一段程序,用整型数组初始化一个 vector 对象。

解答:

#include "stdafx.h"
#include<iostream>
#include<vector>
#include<iterator>
using std::cout;
using std::endl;
using std::vector;
using std::begin;
using std::end;

int main()
{
	int arry[5] = { 1,2,3,4,5 };
	vector<int> vec(begin(arry), end(arry));
	for (auto c : vec)
	cout << c << " ";
	cout << endl;
    return 0;
}

练习3.42:

编写一段程序,将含有整数元素的 vector 对象拷贝给一个整型数组。

解答:

#include "stdafx.h"
#include<iostream>
#include<vector>
#include<iterator>
using std::cout;
using std::endl;
using std::vector;
using std::begin;
using std::end;

int main()
{
	vector<int> vec = { 0,1,2,3,4,5 };
	int arry[6];
	int *b = begin(arry);
	int *e = end(arry);
	for (int i = 0; b != e; ++b, ++i) 
		*b = vec[i];
	for (auto c : arry)
		cout << c << " ";
	cout << endl;
    return 0;
}

练习3.43:

编写 3 个不同版本的程序,令其均能输出 ia 的元素。版本1 使用范围 for 语句管迭代过程;版本 2 和版本 3 都使用 普通的 for 语句,其中版本 2 要求用下标运算符,版本 3 要求用指针。此外,在所有 3 个版本的程序中都要直接写出数据类型而不能使用类型别名、auto 关键字或 decltype 关键字。

解答:

#include "stdafx.h"
#include<iostream>
#include<iterator>
using std::cout;
using std::endl;
using std::begin;
using std::end;

int main()
{
	
	int ia[3][4] = {
	{0,1,2,3},
	{4,5,6,7},
	{8,9,10,11}
	};

	//版本1,使用 范围 for 语句
	cout << " version 1: ";
	for (const int(&row)[4] : ia)//注意圆括号的作用,定义的是四元素数组的引用
		for (int col : row)
			cout << col << " ";
	cout << endl;

	//版本2,使用 for 语句及下标运算符
	cout << " version 2: ";
	for (size_t i = 0; i != 3; ++i)
		for (size_t j = 0; j != 4; ++j)
			cout << ia[i][j] << " ";
	cout << endl;

	//版本3,使用 for 语句及指针
	cout << " version 3.1: ";
	for (int(*p)[4] = ia; p != ia + 3; ++p)
		for (int *q = *p; q != *p + 4; ++q)
	cout << *q << " ";
	cout << endl;

	//版本3,还可以使用 begin 和 end 函数
	cout << " version 3.2: ";
	for (int(*p)[4] = begin(ia); p != end(ia); ++p)//p 为指向含有 4 个整数的数组的指针
		for (int *q = begin(*p); q != end(*p); ++q)
			cout << *q << " ";
	cout << endl;
    return 0;
}

 练习3.44:

改写上一个练习中的程序,使用类型别名来代替循环控制变量的类型。

解答: 

#include "stdafx.h"
#include<iostream>
#include<iterator>
using std::cout;
using std::endl;
using std::begin;
using std::end;

using four = int[4];
typedef size_t st;

int main()
{

	int ia[3][4] = {
		{ 0,1,2,3 },
		{ 4,5,6,7 },
		{ 8,9,10,11 }
	};

	//版本1,使用 范围 for 语句
	cout << " version 1: ";
	for (const four &row : ia)//注意圆括号的作用,定义的是四元素数组的引用
		for (int col : row)
			cout << col << " ";
	cout << endl;

	//版本2,使用 for 语句及下标运算符
	cout << " version 2: ";
	for (st i = 0; i != 3; ++i)
		for (st j = 0; j != 4; ++j)
			cout << ia[i][j] << " ";
	cout << endl;

	//版本3,使用 for 语句及指针
	cout << " version 3.1: ";
	for (four *p = ia; p != ia + 3; ++p)
		for (int *q = *p; q != *p + 4; ++q)
			cout << *q << " ";
	cout << endl;

	//版本3,还可以使用 begin 和 end 函数
	cout << " version 3.2: ";
	for (four *p = begin(ia); p != end(ia); ++p)//p 为指向含有 4 个整数的数组的指针
		for (int *q = begin(*p); q != end(*p); ++q)
			cout << *q << " ";
	cout << endl;
	return 0;
}

练习3.45:

再一次改写程序,这次使用 auto 关键字。

解答:

#include "stdafx.h"
#include<iostream>
#include<iterator>
using std::cout;
using std::endl;
using std::begin;
using std::end;

int main()
{

	int ia[3][4] = {
		{ 0,1,2,3 },
		{ 4,5,6,7 },
		{ 8,9,10,11 }
	};

	//版本1,使用 范围 for 语句
	cout << " version 1: ";
	for (auto &row : ia)//注意圆括号的作用,定义的是四元素数组的引用
		for (auto col : row)
			cout << col << " ";
	cout << endl;

	//版本2,使用 for 语句及下标运算符
	cout << " version 2: ";
	for (auto i = 0; i != 3; ++i)
		for (auto j = 0; j != 4; ++j)
			cout << ia[i][j] << " ";
	cout << endl;

	//版本3,使用 for 语句及指针
	cout << " version 3.1: ";
	for (auto p = ia; p != ia + 3; ++p)
		for (auto q = *p; q != *p + 4; ++q)
			cout << *q << " ";
	cout << endl;

	//版本3,还可以使用 begin 和 end 函数
	cout << " version 3.2: ";
	for (auto p = begin(ia); p != end(ia); ++p)//p 为指向含有 4 个整数的数组的指针
		for (auto q = begin(*p); q != end(*p); ++q)
			cout << *q << " ";
	cout << endl;
	return 0;
}

总结:由以上三个练习可以看出使用 auto 关键字可以使得程序更加简洁方便,且更容易避免在定义过程中类型定义出现错误的情况。