C++Primer第五版中文版 第3章 练习题答案

练习3.1:

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

答:

  • 1.4.1 节
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

int main()
{
	//使用 while 循环将 50 到 100 的整数相加
	int sum = 0, val = 50;
	while (val <= 100) {
		sum += val;
		++val;
	}
	cout << "Sum of 50 to 100 inclusive is " << sum << endl;

	//打印出 10 到 0 之间的整数
	val = 9;
	while (val >= 1) {
		cout << "Countdown: " << val << endl;
		--val;
	}

	//提示用户输入两个整数
	//打印出这两个整数所指定的范围内的所有整数
	cout << "Enter two numbers to specify putout range: " << endl;
	int start = 0, end = 0;
	cin >> start >> end;
	while (start <= end) {
		cout << "Putout: " << start << endl;
		++start;
	}

	return 0;
}
  • 2.6.2节
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::cerr;
using std::cin;
using std::string;

struct Sales_data {
	string itemID;
	int quantity{ 0 };
	double price{ 0.0 };
	double income{ 0.0 };
};
int main()
{
	Sales_data dataTotal;
	if (cin >> dataTotal.itemID >> dataTotal.quantity >> dataTotal.price) {
		dataTotal.income = dataTotal.quantity*dataTotal.price;

		Sales_data data;
		int cnt = 1;
		while (cin >> data.itemID >> data.quantity >> data.price) {
			data.income = data.quantity*data.price;

			if (dataTotal.itemID == data.itemID) {
				dataTotal.quantity += data.quantity;
				dataTotal.income += data.income;
				++cnt;
			}
			else {
				cout << dataTotal.itemID << " " << dataTotal.quantity << " "
					<< dataTotal.income << " "
					<< dataTotal.income / dataTotal.quantity << " " << cnt << endl;

				dataTotal.itemID = data.itemID;
				dataTotal.quantity = data.quantity;
				dataTotal.income = data.income;
				cnt = 1;
			}
		}

		// 输出最后一条记录
		cout << dataTotal.itemID << " " << dataTotal.quantity << " "
			<< dataTotal.income << " "
			<< dataTotal.income / dataTotal.quantity << " " << cnt << endl;
	}
	else {
		cerr << "No data?!" << endl;
		return -1;
	}
	return 0;
}

练习3.2:

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

答:

#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::cin;
using std::string;
using std::getline;

int main()
{
	string str;
	//一次读入一整行
	getline(cin, str);
	cout << str << endl;

	return 0;
}
  • 修改后:
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::cin;
using std::string;

int main()
{
	string str;
	//一次读入一个词
	cin >> str;
	cout << str << endl;

	return 0;
}

练习3.3:

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

答:

  • string类的输入运算符(>>):
  • 当使用输入运算符(>>)从输入流读取数据到string对象时,它会自动忽略前导空白字符(如空格、制表符和换行符)。然后,它会继续读取字符,直到遇到下一个空白字符为止。遇到空白字符后,输入运算符会停止读取,这意味着空白字符不会包含在结果字符串中。
  • getline函数:
  • getline函数的行为与输入运算符(>>)不同。当使用getline从输入流读取数据到string对象时,它会读取所有字符,包括空白字符,直到遇到换行符(默认情况下)为止。换行符不会包含在结果字符串中。

练习 3.4:

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

答:

#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::cin;
using std::string;
using std::getline;

int main()
{
	string strOne, strTwo;
	//output the larger 
	getline(cin, strOne);
	getline(cin, strTwo);
	if (strOne == strTwo)
		cout << "They're the same string." << endl;
	else if (strOne > strTwo)
		cout << "The larger: " << strOne << endl;
	else
		cout << "The larger: " << strTwo << endl;

	return 0;
}
  • 改写后:
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::cin;
using std::string;
using std::getline;

int main()
{
	string strOne, strTwo;
	//Output the longer
	getline(cin, strOne);
	getline(cin, strTwo);
	if (strOne.size() == strTwo.size())
		cout << "They're the same length." << endl;
	else if (strOne.size() > strTwo.size())
		cout << "The longer: " << strOne << endl;
	else
		cout << "The longer: " << strTwo << endl;

	return 0;
}

练习 3.5:

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

答:

#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::cin;
using std::string;
using std::getline;

int main()
{
	string strTotal, str;

	//Link strings
	while (getline(cin, str))
		strTotal += str;
	cout << strTotal << endl;

	return 0;
}
  • 修改后:
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::cin;
using std::string;
using std::getline;

int main()
{
	string strTotal, str;
	//Link strings with spaces
	while (getline(cin, str)) {
		if (!strTotal.empty())
			strTotal += " ";
		strTotal += str;
	}
	cout << strTotal << endl;

	return 0;
}

练习 3.6:

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

答:

#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::cin;
using std::string;
using std::getline;

int main()
{
	string str;
	getline(cin, str);
	for (auto &c : str)
		c = 'X';
	cout << str << endl;
	return 0;
}

练习3.7:

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

答:

  • 如果将循环变量的类型设置为 char, c将会是字符串中字符的拷贝,对它进行的修改不会影响原始字符串。

练习 3.8:

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

答:

  • 对于这个例子,我个人更倾向于使用 for 循环,因为代码更紧凑,将循环变量的声明、初始化、更新和条件检查都放在一行。这种写法在简单的情况下,如此例,可读性较好。
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::cin;
using std::string;
using std::getline;

int main()
{
	string str;
	//using wihle
	getline(cin, str);
	decltype(str.size()) index = 0;
	while (index < str.size()) {
		str[index] = 'X';
		++index;
	}

	cout << str << endl;

	//using for
	getline(cin, str);
	for (decltype(str.size()) index = 0; index < str.size(); ++index)
		str[index] = 'X';

	cout << str << endl;
	return 0;
}

练习 3.9:

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

	string s;
	cout << s[0] << endl;

答:

  • 这个程序试图输出字符串s的第一个字符。但是s是一个空字符串。在尝试访问空字符串的任何字符时,会产生未定义行为。所以,程序是不合法的。

练习 3.10:

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

答:

#include <iostream>
#include <string>
#include <cctype>

using std::cout;
using std::endl;
using std::cin;
using std::string;
using std::getline;
using std::ispunct;

int main()
{
	string str="Hello,World!!!";
	for (auto c : str)
		if (!ispunct(c))
			cout << c;

	cout << endl;
	return 0;
}

练习 3.11:

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

	const string s = "Keep out!";
	for (auto &c : s) {/* ... */ };

答:

  • 合法,c 的类型是 const char& 。

练习 3.12:

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

	(a) vector<vector<int>> ivec;
	(b) vector<string> svec = ivec;
	(c) vector<string> svec(10, "null");

答:

  • (a)在C++11标准是正确的。ivec 是一个空的二维int向量。
  • (b)是不正确的。vector<vector> 和 vector 是不兼容的类型,所以这个定义是错误的。
  • ©是正确的。这里定义了一个名为 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)空的int向量 (b)10个0 ©10个42 (d)1个10 (e)2个元素,10和42 (f)10个默认初始化string (g)10个字符串 “hi”

练习3.14:

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

答:

#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::cin;
using std::vector;

int main()
{

	vector<int>digits;

	//Input loop
	{
		for (int number = 0; cin >> number;)
			digits.push_back(number);
	}

	//Output loop
	{
		for (auto i : digits)
			cout << i << endl;
	}

	return 0;
}

练习3.15:

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

答:

#include <iostream>
#include <vector>
#include <string>

using std::cout;
using std::endl;
using std::cin;
using std::vector;
using std::string;

int main()
{

	vector<string>text;

	//Input loop
	{
		for (string word; cin >> word;)
			text.push_back(word);
	}

	//Output loop
	{
		for (auto i : text)
			cout << i << endl;
	}

	return 0;
}

练习 3.16:

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

答:

#include <iostream>
#include <vector>
#include <string>

using std::cout;
using std::endl;
using std::vector;
using std::string;

int main() {
	vector<int> v1;
	vector<int> v2(10);
	vector<int> v3(10, 42);
	vector<int> v4{ 10 };
	vector<int> v5{ 10,42 };
	vector<string> v6{ 10 };
	vector<string> v7{ 10,"hi" };

	vector<vector<int>> intVecs{ v1,v2,v3,v4,v5 };
	vector<vector<string>>strVecs{ v6,v7 };

	for (const auto& intVec : intVecs) {
		cout << "Size: " << intVec.size() << ", Content: { ";
		for (const auto& elem : intVec) {
			cout << elem << ' ';
		}
		cout << "}" << endl;
	}

	for (const auto& strVec : strVecs) {
		cout << "Size: " << strVec.size() << ", Content: { ";
		for (const auto& elem : strVec) {
			cout << elem << ' ';
		}
		cout << "}" << endl;
	}

	return 0;
}

练习 3.17:

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

答:

#include <iostream>
#include <vector>
#include <string>
#include <cctype>

using std::cout;
using std::endl;
using std::cin;
using std::vector;
using std::string;

int main() {
	vector<string> words;
	string word;

	//从 cin 读入一组词并把它们存入一个 vector 对象
	while (cin >> word) {
		words.push_back(word);
	}

	//把所有词都改写为大写形式
	for (auto &w : words) {
		for (auto &c : w) {
			c = toupper(c);
		}
	}

	//输出改变后的结果,每个词占一行
	for (const auto &w : words) {
		cout << w << endl;
	}
	return 0;
}

练习 3.18:

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

	vector<int> ivec;
	ivec[0] = 42;

答:

  • 不合法,以下为修改:
vector<int> ivec{ 42 };

练习3.19:

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

答:

	//方法1
	vector<int> vec_1(10, 42);
	//方法2
	vector<int> vec_2{ 42,42,42,42,42,42,42,42,42,42 };
	//方法3
	vector<int> vec_3;
	for (int i = 0; i < 10; ++i) {
		vec_3.push_back(42);
	}
  • 方法1更好,方法1在一行代码中简洁明了地完成了任务,可读性较高。而且一开始就分配了足够的内存,避免了可能的内存重新分配,因此在性能上可能更优。

练习 3.20:

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

答:

#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::cin;
using std::vector;

int main() {
	int number;
	vector<int> numbers;

	// 读入整数并存入vector对象
	while (cin >> number) {
		numbers.push_back(number);
	}

	//输出每对相邻整数的和
	cout << "Sum of adjacent elements:" << endl;
	for (size_t i = 1; i < numbers.size(); ++i) {
		cout << numbers[i - 1] + numbers[i] << endl;
	}

	//输出首尾对应整数的和
	cout << "Sum of first and last elements and so on:" << endl;
	for (size_t i = 0, j = numbers.size() - 1; i <= j; ++i, --j) {
		if (i == j) {
			cout << numbers[i] << endl;
		} else {
			cout << numbers[i] + numbers[j] << endl;
		}
	}

	return 0;
}

练习 3.21:

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

答:

#include <iostream>
#include <vector>
#include <string>

using std::cout;
using std::endl;
using std::vector;
using std::string;

int main() {
	vector<int> v1;
	vector<int> v2(10);
	vector<int> v3(10, 42);
	vector<int> v4{ 10 };
	vector<int> v5{ 10,42 };
	vector<string> v6{ 10 };
	vector<string> v7{ 10,"hi" };

	vector<vector<int>> intVecs{ v1,v2,v3,v4,v5 };
	vector<vector<string>>strVecs{ v6,v7 };

	for (auto intVec = intVecs.cbegin(); intVec != intVecs.cend(); ++intVec) {
		cout << "Size: " << intVec->size() << ", Content: { ";
		for (const auto& elem : *intVec) {
			cout << elem << ' ';
		}
		cout << "}" << endl;
	}

	for (auto strVec = strVecs.cbegin(); strVec != strVecs.cend(); ++strVec) {
		cout << "Size: " << strVec->size() << ", Content: { ";
		for (auto elem = strVec->cbegin(); elem != strVec->cend(); ++elem) {
			cout << *elem << ' ';
		}
		cout << "}" << endl;
	}

	return 0;
}

练习 3.22:

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

答:

#include <iostream>
#include <string>
#include <vector>
#include <cctype>

using std::cout;
using std::endl;
using std::vector;
using std::string;
using std::toupper;
int main() {
	string s;
	string y{ "These words will not be output." };
	vector<string>text(10, "some ");
	text.push_back(s);
	text.push_back(y);

	//输出全都修改成大写形式的 text 第一段。
	for (auto it = text.begin();
	it != text.end() && !it->empty(); ++it) {
		for (auto &c : *it) {
			c = toupper(c);
		}
		cout << *it << endl;
	}

	return 0;
}

练习 3.23:

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

答:

#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::vector;

int main() {
	vector<int> numbers = { 1,2,3,4,5,6,7,8,9,10 };

	for (auto it = numbers.begin(); it != numbers.end(); ++it) {
		*it *= 2;
	}

	//输出修改后的元素
	for (const auto &num : numbers) {
		cout << num << " ";
	}
	cout << endl;

	return 0;
}

练习 3.24:

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

答:

#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::cin;
using std::vector;

int main() {
	int number;
	vector<int> numbers;

	// 读入整数并存入vector对象
	while (cin >> number) {
		numbers.push_back(number);
	}

	//输出每对相邻整数的和
	cout << "Sum of adjacent elements:" << endl;

	for (auto i = numbers.cbegin()+1; i != numbers.cend(); ++i) {
		cout << *(i - 1) + *i << endl;
	}

	//输出首尾对应整数的和
	cout << "Sum of first and last elements and so on:" << endl;
	for (auto i = numbers.cbegin(), j = numbers.cend() - 1; i < j; ++i, --j) {
		if (i == j) {
			cout << *i << endl;
		}
		else {
			cout << *i + *j << endl;
		}
	}

	return 0;
}

练习 3.25:

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

答:

#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::cin;
using std::vector;

int main() {
	vector<unsigned> scores(11, 0);
	unsigned grade;
	while (cin >> grade) {
		if (grade <= 100) {
			auto it = scores.begin() + (grade / 10);
			++(*it);
		}
	}

	//输出结果
	for (const auto &score : scores) {
		cout << score << " ";
	}
	cout << endl;

	return 0;
}

练习 3.26:

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

答:

  • 迭代器之间不能执行加法运算,会导致编译错误。

练习 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) 非法。数组的大小必须是一个常量表达式。
  • (b) 合法。这个表达式是一个常量表达式。
  • © 非法。数组的大小必须是一个常量表达式。txt_size()的返回值在编译时无法确定。
  • (d) 非法。字符串 “fundamental” 包括空字符 ‘\0’ 一共有 12 个字符,而数组 st 的大小只有 11。

练习 3.28:

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

string sa[10];
int ia[10];
int main() {
	string sa2[10];
	int ia2[10];
}

答:

  • sa 中的元素都是空字符串。 ia 中的元素都是0。 sa2 中的元素都是空字符串。 ia2 中的元素都是未定义的。

练习3.29:

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

答:

  • 固定大小:数组的大小在声明时就确定了,无法在运行时动态改变。而vector可以自动调整大小以适应数据的增长。
  • 少量的成员函数:数组提供的操作有限,而vector作为一个类,提供了丰富的成员函数以方便地操作数据。
  • 不易传递给函数:将数组作为参数传递给函数时,传递的是指向数组首元素的指针,丢失了数组大小信息。vector可以通过传递引用或const引用轻松地保留其大小信息。

练习 3.30:

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

	constexpr size_t array_size = 10;
	int ia[array_size];
	for (size_t ix = 1; ix <= array_size; ++ix)
		ia[ix] = ix;

答:

  • ia 的有效索引范围是 0 到 array_size - 1。然而,循环条件是 ix <= array_size,这意味着当 ix == array_size 时,依然会执行循环体。这将导致数组越界,访问非法的内存区域。

练习 3.31:

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

答:

#include <iostream>

int main() {
	constexpr size_t array_size = 10;
	int arr[array_size];

	for (size_t i = 0; i < array_size; ++i) {
		arr[i] = i;
	}

	return 0;
}

练习3.32:

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

答:

#include <iostream>
#include <vector>

using std::vector;

int main() {
	//使用数组实现
	constexpr size_t array_size = 10;
	int arr1[array_size];
	int arr2[array_size];

	for (size_t i = 0; i < array_size; ++i) {
		arr1[i] = i;
	}

	for (size_t i = 0; i < array_size; ++i) {
		arr2[i] = arr1[i];
	}

	//使用vector实现
	vector<int> vec1;
	for (int i = 0; i < array_size; ++i) {
		vec1.push_back(i);
	}

	vector<int>vec2(array_size);

	for (size_t i = 0; i < array_size; ++i) {
		vec2[i] = vec1[i];
	}

	return 0;
}

练习3.33:

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

答:

  • 如果不初始化scores数组,它将包含未定义的值,这些值取决于内存中的原始内容。当根据输入的grade值递增scores数组中相应的元素时,这些值将被累加,导致统计结果不正确。

练习 3.34:

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

p1 += p2 - p1;

答:

  • 该程序的功能实际上是使指针 p1 指向与 p2 相同的数组元素。如果指针 p1 和 p2 能保证指向同一个数组中的元素,则不必担心产生错误。

习 3.35:

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

答:

#include <iostream>

using std::cout;

int main() {
	int arr[] = { 1, 2, 3, 4, 5 }; // 初始化数组
	int length = sizeof(arr) / sizeof(arr[0]); // 计算数组长度

	// 使用指针遍历数组并将元素置为0
	for (int *p = arr; p < arr + length; ++p) {
		*p = 0;
	}

	// 输出修改后的数组
	for (int i = 0; i < length; ++i) {
		cout << arr[i] << " ";
	}

	return 0;
}

练习 3.36:

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

答:

#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::vector;

int main() {
	//比较两个数组是否相等
	int arr1[] = { 1, 2, 3, 4, 5 };
	int arr2[] = { 1, 2, 3, 4, 5 };
	int length1 = sizeof(arr1) / sizeof(arr1[0]);
	int length2 = sizeof(arr2) / sizeof(arr2[0]);
	bool arrays_are_equal = true;

	if (length1 != length2) {
		arrays_are_equal = false;
	} else {
		for (int i = 0; i < length1; ++i) {
			if (arr1[i] != arr2[i]) {
				arrays_are_equal = false;
				break;
			}
		}
	}

	if (arrays_are_equal) {
		std::cout << "The arrays are equal." << std::endl;
	} else {
		std::cout << "The arrays are not equal." << std::endl;
	}

	//比较两个vector对象是否相等
	std::vector<int> vec1 = { 1, 2, 3, 4, 5 };
	std::vector<int> vec2 = { 1, 2, 3, 4, 5 };

	if (vec1 == vec2) {
		std::cout << "The vectors are equal." << std::endl;
	} else {
		std::cout << "The vectors are not equal." << std::endl;
	}

	return 0;
}

练习 3.37:

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

	const char ca[] = { 'h','e','l','l','o' };
	const char *cp = ca;
	while (*cp) {
		cout << *cp << endl;
		++cp;
	}

答:

  • 这个程序循环输出ca数组内的字符,直到遇到’\0’字符。
  • 然而,这个程序有一个问题:ca数组没有显式地包含一个空字符(‘\0’)。因此,当cp递增到数组ca之外时程序可能会继续输出字符,直到在内存中碰巧遇到一个空字符为止。

练习 3.38:

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

答:

  • 两个指针相加没有意义,原因在于指针的本质。指针是用来存储内存地址的变量,它表示某个对象在内存中的位置。当对两个指针进行加法运算时,实际上是在尝试将两个内存地址相加,这在逻辑上是不合理的。

练习 3.39:

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

答:

#include <iostream>
#include <string>
#include <cstring>

using std::cout;
using std::endl;
using std::string;
using std::strcmp;

int main() {
	//比较两个string对象
	string str1 = "hello";
	string str2 = "world";

	if (str1 == str2) {
		cout << "string objects are equal" << endl;
	}
	else {
		cout << "string objects are not equal" << endl;
	}

	//比较两个C风格字符串的内容
	const char * cstr1 = "hello";
	const char * cstr2 = "world";

	if (strcmp(cstr1, cstr2) == 0) {
		cout << "C-style strings are equal" << endl;
	}
	else {
		std::cout << "C-style strings are not rqual" << endl;
	}

	return 0;
}

练习 3.40:

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

答:

#define _CRT_SECURE_NO_WARNINGS	//Visual Studio编译器可能会因使用strcpy、strcat而报错
#include <iostream>
#include <cstring>

using std::cout;
using std::endl;
using std::strlen;
using std::strcpy;
using std::strcat;

int main() {
	//定义两个字符数组并用字符串字面值初始化它们
	char arr1[] = "Hello";
	char arr2[] = "World";

	//计算arr1和arr2的长度,包括空字符
	constexpr size_t arr1_length = sizeof(arr1) / sizeof(arr1[0]);
	constexpr size_t arr2_length = sizeof(arr2) / sizeof(arr2[0]);

	//定义第三个字符数组,长度等于arr1和arr2的长度之和减去一个空字符
	char arr3[arr1_length + arr2_length - 1];

	//使用 strcpy 将 arr1 的内容包括空字符拷贝到 arr3 中
	strcpy(arr3, arr1);

	//使用 strcat 将 arr2 的内容从 arr3 的空字符处开始追加
	strcat(arr3, arr2);

	//输出结果
	cout << "Combined string:" << arr3 << endl;

	return 0;
}

练习 3.41:

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

答:

#include <iostream>
#include <vector>
#include <iterator>

int main() {
	int int_arr[] = { 0,1,2,3,4,5 };

	// 用整型数组初始化 vector 对象
	std::vector<int> ivec(std::begin(int_arr), std::end(int_arr));

	// 输出 vector 对象的内容
	for (auto i : ivec) {
		std::cout << i << " ";
	}

	return 0;
}

练习 3.42:

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

答:

#include <iostream>
#include <vector>

int main() {
	std::vector<int> vec = { 1, 2, 3, 4, 5 };
	const size_t vec_size = 5;  // 提前知道 vector 的大小
	int arr[vec_size];

	// 使用循环将vector的元素拷贝到数组中
	for (size_t i = 0; i < vec.size(); ++i) {
		arr[i] = vec[i];
	}

	// 输出数组的内容
	for (size_t i = 0; i < sizeof(arr)/sizeof(arr[0]); ++i) {
		std::cout << "arr[" << i << "] = " << arr[i] << std::endl;
	}

	return 0;
}

练习3.43:

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

答:

#include <iostream>

using std::cout;
using std::endl;

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

	//用范围for循环输出ia的元素
	for (const int(&row)[colCnt] : ia) {
		for (int col : row) {
			cout << col << ' ';
		}
		cout << endl;
	}
	cout << endl;

	//用下标for循环输出ia的元素
	for (size_t i = 0; i != rowCnt; ++i) {
		for (size_t j = 0; j != colCnt; ++j) {
			cout << ia[i][j] << ' ' ;
		}
		cout << endl;
	}
	cout << endl;

	//用指针for循环输出ia的元素
	for (const int(*p)[colCnt] = ia; p != ia + rowCnt; ++p) {
		for (const int *q = *p; q < *p + colCnt; ++q) {
			cout << *q << ' ';
		}
		cout << endl;
	}
	cout << endl;

	return 0;
}

练习3.44:

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

答:

#include <iostream>

using std::cout;
using std::endl;

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

	//定义类型别名
	using int_array = const int[colCnt];

	//用范围for循环输出ia的元素
	for (int_array &row : ia) {
		for (int col : row) {
			cout << col << ' ';
		}
		cout << endl;
	}
	cout << endl;

	//用下标for循环输出ia的元素
	for (size_t i = 0; i != rowCnt; ++i) {
		for (size_t j = 0; j != colCnt; ++j) {
			cout << ia[i][j] << ' ';
		}
		cout << endl;
	}
	cout << endl;

	//用指针for循环输出ia的元素
	for (int_array *p = ia; p != ia + rowCnt; ++p) {
		for (const int *q = *p; q < *p + colCnt; ++q) {
			cout << *q << ' ';
		}
		cout << endl;
	}
	cout << endl;

	return 0;
}

练习3.45:

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

答:

#include <iostream>

using std::cout;
using std::endl;

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

	//用范围for循环输出ia的元素
	for (auto &row : ia) {
		for (int col : row) {
			cout << col << ' ';
		}
		cout << endl;
	}
	cout << endl;

	//用下标for循环输出ia的元素
	for (size_t i = 0; i != rowCnt; ++i) {
		for (size_t j = 0; j != colCnt; ++j) {
			cout << ia[i][j] << ' ';
		}
		cout << endl;
	}
	cout << endl;

	//用指针for循环输出ia的元素
	for (auto p = ia; p != ia + rowCnt; ++p) {
		for (const int *q = *p; q < *p + colCnt; ++q) {
			cout << *q << ' ';
		}
		cout << endl;
	}
	cout << endl;

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值