《C++ Primer》第三章小结练习

注意: 一共 45 题,每 10 题一个链接


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

答:实际上就是为使用的标准库中的名称添加 using 声明。这里只重做第 11 页 1.4.1 节的练习 1.9 这一题。

// 头文件
#include <iostream>

// using 声明
using std::endl;
using std::cout;

int main()
{
	int i = 50;
	int sum = 0;
	while (i <= 100)
	{
		sum += i;
		++i;
	}
	cout << sum << endl;

	return 0;
}

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

答:读取一行输入,使用函数 getline() 。读取一个单词,直接使用 cin >> 输入。

读取一行:

// 头文件
#include <iostream>
#include <string>

// using 声明
using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	// 一次读取一行
	string temp;
	while (getline(cin, temp1))
	{
		cout << temp1 << endl;
	}

	return 0;
}

读取一个单词:

// 一次读取一个单词
string temp2;
while (cin >> temp2)
{
	cout << temp2 << endl;
}

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

答:
(1)输入运算符(>>)跳过开头的空白(空格、换行符、制表符等),直到读取第一个非空白字符,然后再次遇到空白结束读取,最后的空白被丢弃。
(2)getline() 函数遇到换行符(‘\n’)时停止读取,并丢弃换行符。

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

答:前面一问只使用关系运算符(== 和 >),第二问除了使用关系运算符(!=),还使用类方法 size() 。

(1)字符串不相等,输出大的字符串

// 头文件
#include <iostream>
#include <string>

// using 声明
using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	// 读取两个字符串
	string s1, s2;
	cin >> s1 >> s2;
	// 判断
	if (s1 == s2)
		cout << "两个字符串相等\n";
	else if (s1 > s2)
		cout << "大的字符串为: " << s1 << endl;
	else
		cout << "大的字符串为: " << s2 << endl;

	return 0;
}

(2)长度不相等,输出长的大的字符串

// 读取两个字符串
string s3, s4;
cin >> s3 >> s4;
// 判断
size_t len3 = s3.size();
size_t len4 = s4.size();
if (len3 > len4)
	cout << "长度大的字符串为: " << s3 << endl;
else if (len3 < len4)
	cout << "长度大的字符串为: " << s4 << endl;
else
	cout << "两个字符串等长";

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

答:使用循环来实现上述操作,只不过前者在循环结束后输出,后者在循环内部输出。

(1)输出连接的大字符串

// 头文件
#include <iostream>
#include <string>

// using 声明
using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	string temp, result;
	// 输入
	while (cin >> temp)
	{
		// 连接
		result += temp;
	}
	// 输出结果
	cout << result << endl;

	return 0;
}

(2)输出每个字符串,用空格分隔

string input;
while (cin >> input)
{
	cout << input << " ";
}
cout << endl;

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

答:使用范围 for 修改对象序列中的元素,需要使用引用。

// 头文件
#include <iostream>
#include <string>

// using 声明
using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	// 输入
	string input("abcdefg);
	// 替换
	for (auto& elem : input)
		elem = 'X';

	return 0;
}

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

答:如果换成 char 类型,则修改的是每个元素的副本,而不是本体。原字符串未发生任何变化。

代码及结果如下:
在这里插入图片描述

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

答:
(1)while 循环

// 头文件
#include <iostream>
#include <string>

// using 声明
using std::endl;
using std::cout;
using std::cin;
using std::string;

int main()
{
	string input("abcdefg");
	// while 循环替换
	decltype(input.size()) i = 0;
	while (i < input.size())
	{
		input[i] = 'X';
	}

	return 0;
}

(2)for 循环

string temp("abcdefg");
// for 循环
decltype(temp.size()) i = 0;
for (; i < temp.size(); ++i)
{
	temp[i] = 'X';
}

我认为使用 for 循环更好,一般而言,如果确定了循环次数则使用 for。循环次数未知则使用 while 循环。

3.9 下面的程序有何作用?它合法吗?如果不合法,为什么?
string s;
cout << s[0] << endl;

答:该程序试图访问字符串 s 的第一个字符。这是不合法的行为,因为该字符串是一个空串,里面没有内容,下标 0 是非法下标。

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

答:使用循环遍历字符串每一个元素,然后使用头文件 cctype 中的 ispunct 判断是否输出当前字符。这里最好使用 getline() 函数进行输入。代码如下:

// 头文件
#include <iostream>
#include <string>

// using 声明
using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	// 输入
	string input;
	getline(cin, input);
	// 去除标点符号
	for (auto& elem : input)
	{
		if (!ispunct(elem))
			cout << elem;
	}
	cout << endl;

	return 0;
}

3.11 下面的范围 for 语句合法吗?如果合法,c 的类型是什么?
const string s = “Keep out!”;
for (auto& c : s) { /* … */ }

答:该程序段从语法上来说是合法的,s 是字符串常量,则 auto 对 c 推断的类型是常量引用。即 const char& 。但是,只能使用 c 的值,不能修改 c 的值。

3.12 下列 vector 对象的定义有不正确的吗?如果有,请指出来。对于正确的,描述其执行结果;对于不正确的,请说明错误的原因。
(a)vector<vector<int>> ivec;
(b)vector<string> svec = ivec;
(c)vecotr<string> svec(10, “null”);

答:a. 正确,创建了一个名为 ivec 的 vector 对象,其中每个元素均为 vector<int> 对象。
b. 错误,svec 中元素类型为 string ,与 ivec 的元素类型不符,不能用 ivec 来初始化 svec 。
c. 正确,创建了一个名为 svec 的 vector 对象,其元素类型为 string,包含 10 个元素大小,每个元素的值均为字符串 “null” 。

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

(a) vecotr<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" };

答:v1 没有元素。v2 包含 1 个元素,其值为 10 。v3 包含 10 个元素,其值均为 42 。v4 包含 1个元素,其值为 10 。v5 包含 2 个元素,其值分别为 10 和 42 。v6 包含 10 个元素,其值均为空字符串。v7 包含 10 个元素,其值均为字符串 “hi” 。

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

答:使用循环和 vector 容器的 push_back() 方法。

// 头文件
#include <iostream>
#include <vector>

// using 声明
using std::cin;
using std::cout;
using std::endl;
using std::vector;

int main()
{
	// 创建容器,插入数据
	vector<int> vt_i;
	int input;
	while (cin >> input)
	{
		vt_i.push_back(input);
	}

	return 0;
}

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

答:头文件多包含一个 string 。

// 头文件
#include <iostream>
#include <vector>
#include <string>

// using 声明
using std::cin;
using std::cout;
using std::endl;
using std::vector;
using std::string;

int main()
{
	// 创建容器,插入数据
	vector<string> vt_str;
	string input;
	while (cin >> input)
	{
		vt_str.push_back(input);
	}

	return 0;
}

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

答:检验时需要使用 vector 的 size() 方法,和范围 for 循环。

检验代码:

// 头文件
#include <iostream>
#include <string>
#include <vector>

// using 声明
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

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" };

	cout << "v1 size: " << v1.size() << endl << endl;

	cout << "v2 size: " << v2.size() << endl;
	for (auto elem : v2)
		cout << elem << " ";
	cout << endl << endl;

	cout << "v3 size: " << v3.size() << endl;
	for (auto elem : v3)
		cout << elem << " ";
	cout << endl << endl;

	cout << "v4 size: " << v4.size() << endl;
	for (auto elem : v4)
		cout << elem << " ";
	cout << endl << endl;

	cout << "v5 size: " << v5.size() << endl;
	for (auto elem : v5)
		cout << elem << " ";
	cout << endl << endl;

	cout << "v6 size: " << v6.size() << endl;
	for (auto elem : v6)
		cout << elem << " ";
	cout << endl << endl;

	cout << "v7 size: " << v7.size() << endl;
	for (auto elem : v7)
		cout << elem << " ";
	cout << endl << endl;

	return 0;
}

运行结果:
在这里插入图片描述

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

答:读入单词的时候使用循环和 vector 的 push_back() 方法,改大写的时候使用范围 for 和头文件 cctype 中的 toupper() 函数。

// 头文件
#include <iostream>
#include <string>
#include <vector>
#include <cctype>

// using 声明
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
	// 所需对象
	string input;
	vector<string> vt_str;
	// 输入
	while (cin >> input)
		vt_str.push_back(input);
	// 改大写
	for (auto& elem : vt_str)
	{
		for (auto& ch : elem)
			ch = toupper(ch);
	}

	return 0;
}

如果想通过运行程序来检验的话,如果你使用的是 visual studio 2022 ,在输入最后一个字符串后,需按下 Ctrl+Z 键,表示文件尾结束。

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

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

答:不合法,第一条语句创建 vector<int> 对象,但是其中没有元素,不能使用下标对其进行访问。vector 对象(以及 string 对象)的下标运算符可用于访问已存在的元素,而不能用于添加元素。添加元素应使用 vector 的 push_back 方法,在末尾添加元素。修改代码如下:

vector<int> ivec;
ivec.push_back(42);

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

答:
(1)列表初始化:

vector<int> vt_i = {42,42,42,42,42,42,42,42,42,42};

(2)构造函数:

vector<int> vt_i(10, 42);

(3)先定义空的 vector 对象,再插入元素

vector<int> vt_i;
for (int i = 0; i < 10; ++i)
	vt_i.push_back(42);

当元素个数确定且每个元素的值都相同时,应使用方法(2),简洁直观。而方法(3)比较灵活,适合元素个数不确定和元素值不相同等情况。

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

答:
(1)相邻元素之和

// 头文件
#include <iostream>
#include <vector>

// using 声明
using std::cin;
using std::cout;
using std::endl;
using std::vector;

int main()
{
	// 所需变量
	int input;
	vector<int> vt_i;
	// 输入
	while (cin >> input)
		vt_i.push_back(input);
	// 遍历输入输出相邻之和
	decltype(vt_i.size()) i = 0;
	auto size = vt_i.size();
	for (; i < size; i += 2)
	{
		cout << vt_i[i] + vt_i[i + 1] << " ";
	}
	// 如果元素个数为奇数,单独处理最后一个元素
	if (size % 2 == 1)
		cout << vt_i[size - 1] << " ";
	cout << endl;

	return 0;
}

(2)前后对应元素之和

// 所需变量
int input;
vector<int> vt_i;
// 输入
while (cin >> input)
	vt_i.push_back(input);
// 遍历输入输出前后对应元素之和
decltype(vt_i.size()) left = 0;
auto right = vt_i.size() - 1;
while (left < right)
{
	cout << vt_i[left] + vt_i[right] << " ";
	// 下一组
	++left;
	--right;
}
// 如果元素个数为奇数,单独处理最后中间元素
if (vt_i.size() % 2 == 1)
	cout << vt_i[vt_i.size() / 2] << " ";
cout << endl;

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

答:切记更新迭代器指向下一个位置。

// 头文件
#include <iostream>
#include <string>
#include <vector>

// using 声明
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

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" };

	cout << "v1 size: " << v1.size() << endl << endl;

	cout << "v2 size: " << v2.size() << endl;
	auto it2 = v2.begin();
	while (it2 != v2.end())
	{
		cout << *it2 << " ";
		++it2;
	}
	cout << endl << endl;

	cout << "v3 size: " << v3.size() << endl;
	auto it3 = v3.begin();
	while (it3 != v3.end())
	{
		cout << *it3 << " ";
		++it3;
	}
	cout << endl << endl;

	cout << "v4 size: " << v4.size() << endl;
	auto it4 = v4.begin();
	while (it4 != v4.end())
	{
		cout << *it4 << " ";
		++it4;
	}
	cout << endl << endl;

	cout << "v5 size: " << v5.size() << endl;
	auto it5 = v5.begin();
	while (it5 != v5.end())
	{
		cout << *it5 << " ";
		++it5;
	}
	cout << endl << endl;

	cout << "v6 size: " << v6.size() << endl;
	auto it6 = v6.begin();
	while (it6 != v6.end())
	{
		cout << *it6 << " ";
		++it6;
	}
	cout << endl << endl;

	cout << "v7 size: " << v7.size() << endl;
	auto it7 = v7.begin();
	while (it7 != v7.end())
	{
		cout << *it7 << " ";
		++it7;
	}
	cout << endl << endl;

	return 0;
}

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

答:这里需要使用 cctype 头文件中的函数,需包含该文件。这里就只给出主要代码。

for (auto it = text.begin(); it != text.end(); ++it)
{
	// 如果是字母则转大写
	if (isalpha(*it))
		*it = toupper(*it);
	
	cout << *it;
}

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

答:改变对象的值,使用普通迭代器。

// 头文件
#include <iostream>
#include <vector>

// using 声明
using std::cout;
using std::endl;
using std::vector;

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

	// 元素值乘以 2
	vector<int>::iterator it = vt_i.begin();
	while (it != vt_i.end())
	{
		*it *= 2;
		++it;
	}
	// 输出
	it = vt_i.begin();
	while (it != vt_i.end())
	{
		cout << *it << " ";
		++it;
	}

	return 0;
}

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

答:需要同时使用首尾两个迭代器。注意: 使用尾后迭代器的时候得到的是最后一个元素的下一个位置,需要往前面诺一个位置才是最后一个元素。

// 头文件
#include <iostream>
#include <vector>

// using 声明
using std::cin;
using std::cout;
using std::endl;
using std::vector;

int main()
{
	// 所需变量
	vector<int> vt_i;
	int input = 0;
	// 输入
	while (cin >> input)
		vt_i.push_back(input);
	// 使用迭代器输出前后对应元素的和
	auto begin = vt_i.begin();
	auto end = vt_i.end() - 1;
	while (begin < end)
	{
		cout << *begin + *end << " ";
		++begin;
		--end;
	}
	// 单独处理中间元素
	if (begin == end)
		cout << *begin << endl;

	return 0;
}

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

答:定义一个迭代器变量获取首元素的位置,然后加上对分数除以 10 的距离,得到对应分数的分段。

// 头文件
#include <iostream>
#include <vector>

// using 声明
using std::cin;
using std::cout;
using std::endl;
using std::vector;

int main()
{
	// 每个分数层次的人数
	vector<int> scores(11, 0);
	// 输入分数并划分层次
	auto it = scores.begin();
	int input;
	while (cin >> input)
	{
		if (input <= 100)
			++(*(it + input / 10));
	}

	return 0;
}

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

答:C++并没有定义两个迭代器的加法运算,实际上两个迭代器相加是没有意义的。而C++定义了两个迭代器的减法运算,结果是两个迭代器之间的距离。所以后者表达式无效,而前者表达式先计算 (end - beg) / 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() ];  (c)char st[11] = “fundamental”;

答:a. 错误,数组的大小必须使用常量表达式。
c. 错误,数组的大小必须使用常量表达式。
d. 错误,用字符串字面值初始化字符数组时,需计算结尾的空字符,所以一共需要 12 个字节的空间,实际上数组的大小只有 11 个字节。

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

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

答:sa 和 ia 均为全局数组,sa 中所有元素均为空字符串,ia 中所有元素均为 0 。sa2 和 ia2 均为局部数组,sa2 中所有元素均为空字符串,ia2 中所有元素均为随机值。

3.29 相比于 vector 来说,数组有哪些缺点?

答:
(1)创建数字时需要声明数组的大小,且只能使用常量表达式,并且数组大小一旦确定就不能更改,不能随意向数组中添加元素。
(2)vector 可以使用类方法 size() 获取容器长度,而数组除了使用 char 数组存储字符串时可以使用 strlen() 函数获取数组长度外,其他数组只能通过 sizeof(array) / sizeof(array[0]) 的方式计算数组的长度。

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 开始,最大比数组的长度小 1 。该程序遍历数组,下标从 1 开始,跳过了第一个元素,且下标最大值达到了数组的长度,导致下标越界。

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

答:

int arr_i[10] = { 0 };
for (int i = 0; i < 10; ++i)
	arr_i[i] = i;

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

答:不能直接使用一个数组给另一个数组赋值,需使用循环,对其中每一个元素进行拷贝。而 vector 重载了赋值运算符,可以直接使用。

// 头文件
#include <iostream>
#include <vector>

// using 声明
using std::cin;
using std::cout;
using std::endl;
using std::vector;

int main()
{
	// 创建数组并赋值
	int arr_i1[10] = { 0 };
	for (int i = 0; i < 10; ++i)
	{
		arr_i1[i] = i;
	}
	// 拷贝该数组到另一个数组
	int copy_i[10] = { 0 };
	for (int i = 0; i < 10; ++i)
	{
		copy_i[i] = arr_i1[i];
	}

	// 使用 vector 重写并完全实现上面代码的功能
	vector<int> vt_i;
	for (int i = 0; i < 10; ++i)
	{
		vt_i.push_back(i);
	}
	// 拷贝
	vector<int> copy;
	copy = vt_i;

	return 0;
}

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

答:scores 是局部数组,若不初始化其内存放的是随机值,导致程序执行结果不是预期结果。

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

p1 += p2 - p1;

答:如果 p1 和 p2 指向同一个数组中的元素,则该条语句令 p1 指向 p2 原来所指向的元素。从语法上来说,及时 p1 和 p2 指向的元素不属于同一个数组,但只要 p1 和 p2 的类型相同,该语句也是合法的。如果两个指针的类型不同,则编译器会报错。

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

答:

int arr_i[10]  = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int* pi = arr_i;
int* end = pi + 10;
// 将数组元素设置为 0 
while (pi != end)
{
	*pi = 0;
	++pi;
}

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

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

答:由于字符数组 ca 的末尾没有字符串,则该循环输出完字符数组 ca 的内容之后,继续往后面输出,直到遇到空字符为止。

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

答:指针存储的是其指向对象的地址,把任何两个地址相加都没有什么实际意义。而对两个指向同一个数组的指针进行减法操作,得到的就是两个指针之间的距离。

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

答:比较 string 对象可以直接使用关系运算符,而比较两个 c 风格字符串,需要使用头文件 cstring 中的 strcmp() 函数。

// 头文件
#include <iostream>
#include <string>
#include <cstring>

// using 声明
using std::cin;
using std::cout;
using std::endl;
using std::string;

// 符号常量声明
const int SIZE = 20;

int main()
{
	// 创建两个 string 对象
	string s1, s2;
	cin >> s1 >> s2;
	if (s1 > s2)
		cout << "s1 > s2 " << endl;
	else
		cout << "s1 <= s2" << endl;

	// 创建两个 c 风格字符串
	char cs1[SIZE];
	char cs2[SIZE];
	cin >> cs1 >> cs2;
	if (strcmp(cs1, cs2) > 0)
		cout << "cs1 > cs2 " << endl;
	else
		cout << "cs1 <= cs2" << endl;

	return 0;
}

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

答:分别先后使用头文件 cstring 中的 strcpy() 和 strcat() 头文件。

// 头文件
#include <iostream>
#include <cstring>

// using 声明
using std::cin;
using std::cout;
using std::endl;

// 符号常量声明
const int SIZE = 20;

int main()
{
	char cs1[SIZE] = "abc";
	char cs2[SIZE] = "def";
	char result[2 * SIZE];
	// 拷贝拼接
	strcpy(result, cs1);
	strcat(result, cs2);
	
	return 0;
}

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

答:传递要拷贝内容的首指针和尾后指针即可。记得加上头文件和 using 声明等内容。

int arr_i[5] = {1, 2, 3, 4, 5};
vector<int> vt_i(arr_i, arr_i + 5);

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

答:vector 对象拷贝给整型数组,需使用循环拷贝每个元素。

vector<int> vt_i;
// 插入数据
for (int i = 0; i < 10; ++i)
	vt_i.push_back(i);

// 拷贝数据到 int 数组
int arr_i[10];
for (int i = 0; i < 10; ++i)
	arr_i[i] = vt_i[i];

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

答:使用范围 for,如果嵌套多层数组,则除了最内层的数组,其他都要使用引用。

// 头文件
#include <iostream>

// using 声明
using std::cout;
using std::endl;

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

	// 范围 for 遍历
	for (int(&row)[4] : ia)
	{
		for (int& col : row)
			cout << col << " ";
		cout << endl;
	}
	cout << endl;

	// 普通下标遍历
	for (int i = 0; i < 3; ++i)
	{
		for (int j = 0; j < 4; ++j)
			cout << ia[i][j] << " ";
		cout << endl;
	}
	cout << endl;

	// 指针遍历
	for (int(*pr)[4] = ia; pr != ia + 3; ++pr)
	{
		for (int* pc = *pr; pc != *pr + 4; ++pc)
			cout << *pc << " ";
		cout << endl;
	}
	cout << endl;

	return 0;
}

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

答:

// 头文件
#include <iostream>

// using 声明
using std::cout;
using std::endl;

// 类型别名声明
typedef int Array_Int[4];  // 或者 using Array_Int = int[4];

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

	// 范围 for 遍历
	for (Array_Int& row : ia)
	{
		for (int& col : row)
			cout << col << " ";
		cout << endl;
	}
	cout << endl;

	// 普通下标遍历
	for (int i = 0; i < 3; ++i)
	{
		for (int j = 0; j < 4; ++j)
			cout << ia[i][j] << " ";
		cout << endl;
	}
	cout << endl;

	// 指针遍历
	for (Array_Int* pr = ia; pr != ia + 3; ++pr)
	{
		for (int* pc = *pr; pc != *pr + 4; ++pc)
			cout << *pc << " ";
		cout << endl;
	}
	cout << endl;

	return 0;
}

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

答:

// 头文件
#include <iostream>

// using 声明
using std::cout;
using std::endl;

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

	// 范围 for 遍历
	for (auto& row : ia)
	{
		for (auto& col : row)
			cout << col << " ";
		cout << endl;
	}
	cout << endl;

	// 普通下标遍历
	for (auto i = 0; i < 3; ++i)
	{
		for (auto j = 0; j < 4; ++j)
			cout << ia[i][j] << " ";
		cout << endl;
	}
	cout << endl;

	// 指针遍历
	for (auto pr = ia; pr != ia + 3; ++pr)
	{
		for (int* pc = *pr; pc != *pr + 4; ++pc)
			cout << *pc << " ";
		cout << endl;
	}
	cout << endl;

	return 0;
}
  • 33
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值