C++ Primer 习题(第三章附答案)

练习3.1 略

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

#include <iostream>
#include<string>
using namespace std;

//使用getline一次读入一整行,回车结束
int main()
{
	string line;
	
	cout << " please enter your line ,even space" << endl;
	while (getline(cin, line))   //循环读取,Ctrl+c结束
		cout << line << endl;

	return 0;
}
#include <iostream>
#include<string>
using namespace std;

//使用cin一次读入一单词,空白结束
int main()
{
	string word;
	
	cout << " please enter your word ,not space" << endl;
	while (cin>>word)   //循环读取,Ctrl+c结束
		cout << word<< endl;

	return 0;
}

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

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string word, line;
	cout << " please select the way to read the string " << endl;
	cout << " 1 means read string by word" << endl;
	cout << " 2 means read string by line" << endl;

	char ch;
	cin >> ch;

	if (ch == '1')
	{
		cout << "please enter string :    welcome to c++ family    " << endl;
		cin >> word;
		cout << " system read the string is : " << word << endl;
	}
	else if (ch == '2')
	{
		cout << "please enter string :    welcome to c++ family    " << endl;
		getline(cin, line);
		cout << " system read the string is : " << line << endl;
	}
	else
	{
		cout << "input error,please try again" << endl;
	}
	return 0;
}

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

#include<iostream>
#include<string>
using namespace std;

int main() 
{
	string word1, word2;
	cout << "please enter two strings " << endl;
	cin >> word1 >> word2;
	if (word1 == word2)
	{
		cout << word1 << endl;
	}
	else if (word1>word2)
	{
		cout << word1 << endl;
	}
	else
	{
		cout << word2 << endl;
	}
	return 0;
}
#include<iostream>
#include<string>
using namespace std;

int main() 
{
	string word1, word2;
	cout << "please enter two strings " << endl;
	cin >> word1 >> word2;

	auto len1 = word1.size();
	auto len2 = word2.size();

	if (len1 == len2)
	{
		cout << word1 << endl;
	}
	else if (len1>len2)
	{
		cout << word1 << endl;
	}
	else
	{
		cout << word2 << endl;
	}
	return 0;
}

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

#include<iostream>
#include<string>
using namespace std;

int main() 
{
	string word,result;
	cout << "please enter strings " << endl;
	cout << " Ctrl+z indicates that the input is complete" << endl;
	while (cin>>word)
	{
		result += word;
	}
	cout << result << endl;
	return 0;
}
#include<iostream>
#include<string>
using namespace std;

int main() 
{
	string word,result;
	char space = ' ';
	cout << "please enter strings " << endl;
	cout << " Ctrl+z indicates that the input is complete" << endl;
	while (cin>>word)
	{
		word += space;
		result += word;
	}
	cout << result << endl;
	return 0;
}

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

#include<iostream>
#include<string>
using namespace std;

int main() 
{
	string s;
	cout << "please enter strings ,even space" << endl;
	getline(cin, s);   //读取整行,回车结束

	//利用auto关键字推断字符串中的每一个元素的类型
	//c必须定义为引用类型,否则无法修改字符串内容
	for (auto& c : s)  
	{
		c = 'X';
	}

	cout << s << endl;

	return 0;
}

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

#include<iostream>
#include<string>
using namespace std;

 //就本题而言,将循环控制变量类型设为char不会对结果造成影响
 //因为auto自动推断字符串s的元素类型,结果同样是char
int main() 
{
	string s;
	cout << "please enter strings ,even space" << endl;
	getline(cin, s);   //读取整行,回车结束

	//c必须定义为引用类型,否则无法修改字符串内容
	for (char& c : s)  
	{
		c = 'X';
	}

	cout << s << endl;

	return 0;
}

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

#include<iostream>
#include<string>
using namespace std;

int main() 
{
	string s;
	cout << "please enter strings ,even space" << endl;
	getline(cin, s); 
	int i = 0;

	while (s[i]!='\0')
	{
		s[i] = 'X';
		i++;
	}

	cout << s << endl;
	return 0;
}
#include<iostream>
#include<string>
using namespace std;

int main() 
{
	string s;
	cout << "please enter strings ,even space" << endl;
	getline(cin, s); 
	

	for(int i = 0;i<s.size();i++)
	{
		s[i] = 'X';
	}

	cout << s << endl;
	return 0;
}

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

#include<iostream>
#include<string>
using namespace std;

//程序愿意是输出字符串s的首字符,但程序是错误的
//因为初始状态下没有给s赋任何初值,所以s的内容为空,当然也就不存在首字符,下标0是非法的
//但在visual studio编译并不会发生编译错误
int main() 
{
	string s;
	cout <<s[0] << endl;
	return 0;
}

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

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

using namespace std;
int main()
{
	string s;
	cout << "Please enter a string ,the best contain certain punctuation" << endl;
	getline(cin, s);

	for (auto& c : s)
	{
		if (!ispunct(c))
			cout << c;
	}
	cout << endl;
	return 0;
}

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

using namespace std;
int main()
{
	string s,result;
	cout << "Please enter a string ,the best contain certain punctuation" << endl;
	getline(cin, s);

	for (decltype(s.size())i = 0; i < s.size(); i++)
	{
		if (!ispunct(s[i]))
			result += s[i];
	}
	cout << result<<endl;
	return 0;
}

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

#include<iostream>
#include<string>

//s是一个常量字符串,则c的推断类型是常量引用,即c所绑定的对象值不能改变
using namespace std;
int main()
{
	const string s = "keep out!";
	
	for (auto&c:s)
	{
		{/*...*/}
	}
	return 0;
}

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

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

using namespace std;
int main()
{
	//定义了一个名为ivec的vector对象,其中的每个元素都是vector<int>对象
	vector<vector<int>> ivec;

	//错误,svec的元素类型是string,而ivec的元素类型是int,因此不能使用ivec初始化sevc。
	vector<string> svec = ivec;

	//定义了一个名为svec的vector对象,其中含有10个元素,每个元素都是字符串null
	vector<string> svec(10, "null");
}

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

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

using namespace std;
int main()
{
	// 元素数量为0
	vector<int> v1;

	//元素数量为10,每一个元素都被初始化为0
	vector<int> v2(10);

	//元素数量为10,每一个元素都被初始化为42
	vector<int> v3(10, 42);

	//元素数量为1,元素的值为10
	vector<int> v4{ 10 };

	//元素数量为2,两个元素值为10,42
	vector<int> v5{ 10, 42 };

	//元素数量为10,每一个元素都被初始化为空串
	vector<string> v6{ 10 };

	//元素数量为10,每一个元素都被初始化为hi
	vector<string> v7{ 10 ,"hi" };

	return 0;
}

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

#include<iostream>
#include<vector>

using namespace std;

int main()
{
	vector<int> vint;  //元素类型为int的vector对象
	int i;             //记录用户的输入值
	char cont = 'y'; 
	
	while (cin >> i)
	{
		vint.push_back(i); //向vector对象中添加元素
		cout << "do you want to continue" << endl;
		cout << "y or n" << endl;
		cin >> cont;
		if (cont!='y'&&cont!='Y')
		{
			break;
		}
	}

	for (auto mem : vint)   //使用范围for循环语句遍历vint中的每个元素
	{
		cout << mem << endl;
	}
	return 0;
}

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

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

using namespace std;

int main()
{
	vector<string> vstring;  //元素类型为int的vector对象
	string s;                //记录用户的输入值
	char cont = 'y';

	while (cin >> s)
	{
		vstring.push_back(s); //向vector对象中添加元素
		cout << "do you want to continue" << endl;
		cout << "y or n" << endl;
		cin >> cont;
		if (cont!='y'&&cont!='Y')
		{
			break;
		}
	}

	for (auto mem : vstring)   //使用范围for循环语句遍历vstring中的每个元素
	{
		cout << mem << endl;
	}
	return 0;
}

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

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

using namespace std;

struct ivec
{
	vector<int> a;
	vector<string> b;
};

struct svec
{
	vector<string> b;
};

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

	struct ivec iarr[] = { {v1},{v2},{v3},{v4},{v5} };
	struct svec sarr[] = { {v6},{v7} };
	int ilen = sizeof(iarr) / sizeof(iarr[0]);
	int slen = sizeof(sarr) / sizeof(sarr[0]);

	for (int i = 0; i < ilen; i++)
	{
		cout << "\nv"<<i+1<< "元素个数为" << iarr[i].a.size()<<endl;
		if (iarr[i].a.size()>0)
		{
			cout << "v" << i+1 << "的元素分别是: " << endl;
			for (auto e:iarr[i].a)
			{
				cout << e << " " ;
			}
			cout << endl;
		}
	}
	for (int i = 0; i < slen; i++)
	{
		cout << "\nv" << i+6 << "元素个数为" << sarr[i].b.size() << endl;
		if (sarr[i].b.size() > 0)
		{
			cout << "v" << i+6 << "的元素分别是: " << endl;
			for (auto e : sarr[i].b)
			{
				cout << e << " ";
			}
			cout << endl;
		}
	}
	return 0;
}

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

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

using namespace std;

int main()
{
	vector<string> vstring;    
	string s;
	char cont = 'y';
	cout << "please enter the first word" << endl;

	while (cin>>s)
	{
		vstring.push_back(s);
		cout << "whether to continue" << endl;
		cin >> cont;
		if (cont !='y' && cont !='Y')
		{
			break;
		}
		cout << "please enter next word" << endl;
	}
	cout << "Converted result are " << endl;
	for (auto &mem:vstring)
	{
		for (auto& c : mem)
		{
			c = toupper(c);
		}
		cout << mem << endl;
	}
	return 0;
}

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

#include<iostream>
#include<vector>
using namespace std;

int main()
{
	vector<int>ivec;
	ivec[0] = 42;     
	//vector对象的下标运算符只能用于访问已经存在的元素,而不能用于添加元素

	//修改为
	vector<int>ivec;
	ivec.push_back(42);

	return 0;
}

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

#include<iostream>
#include<vector>
using namespace std;

int main()
{
	//思路一:先定义一个空的vector对象,然后添加对象
	vector<int>vint;
	for (int i = 0; i < 10; i++)
	{
		vint.push_back(42);
	}

	//思路二:列表初始化,罗列出全部的10个元素值
	vector<int>vint = { 42,42,42,42,42,42,42,42,42,42 };

	//思路三:用花括号给出所有元素值
	vector<int>vint { 42,42,42,42,42,42,42,42,42,42 };

	//思路四:定义的时候使用参数指定元素个数及重复的值
	vector<int>vint(10,42);

	//思路五:先指定元素个数,再利用范围for依次赋值
	vector<int>vint (10);
	for (auto& i : vint)
	{
		i = 42;
	}
	
	return 0;
}

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

#include<iostream>
#include<vector>
using namespace std;

int main()
{
	vector<int> vint;
	int ival;
	cout << "please enter a set of numbers" << endl;

	while (cin>>ival)
	{
		vint.push_back(ival);
	}

	if (vint.size()==0)
	{
		cout << "no elements" << endl;
		return -1;
	}

	cout << "the sum of two adiacent items is" << endl;

	//利用decltype推断i的类型
	for (decltype(vint.size()) i = 0; i < vint.size()-1; i+=2)
	{
		//求相邻两项的和
		cout << vint[i] + vint[i + 1] << endl;
	}
	//如果元素数是奇数,单独处理最后一个元素
	if (vint.size() % 2 != 0)
	{
		cout << vint[vint.size() - 1] << endl;
	}
	return 0;
}
#include<iostream>
#include<vector>
using namespace std;

int main()
{
	vector<int> vint;
	int ival;
	cout << "please enter a set of numbers" << endl;

	while (cin>>ival)
	{
		vint.push_back(ival);
	}

	if (vint.size()==0)
	{
		cout << "no elements" << endl;
		return -1;
	}

	cout << "The sum of the first and last two items is" << endl;

	//利用decltype推断i的类型
	for (decltype(vint.size()) i = 0; i < vint.size()/2; i++)
	{
		//求首尾两项的和
		cout << vint[i] + vint[vint.size()-i-1] << endl;
	}
	//如果元素数是奇数,单独处理最后一个元素
	if (vint.size() % 2 != 0)
	{
		cout << vint[vint.size() / 2] << endl;
	}
	return 0;
}

3.21 请使用迭代器重做3.3.3节的第一个练习

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

using namespace std;

struct ivec
{
	vector<int> a;
	vector<string> b;
};

struct svec
{
	vector<string> b;
};

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

	struct ivec iarr[] = { {v1},{v2},{v3},{v4},{v5} };
	struct svec sarr[] = { {v6},{v7} };
	int ilen = sizeof(iarr) / sizeof(iarr[0]);
	int slen = sizeof(sarr) / sizeof(sarr[0]);

	//本题只需输出vector对象的内容而无需对其元素进行更改,所以使用是迭代器是cbegin和cend,而非begin和end
	for (int i = 0; i < ilen; i++)
	{
		cout << "\nv" << i + 1 << "元素个数为" << iarr[i].a.size() << endl;
		if (iarr[i].a.cbegin() != iarr[i].a.cend())
		{
			cout << "v" << i + 1 << "的元素分别是: " << endl;
			for (auto it = iarr[i].a.cbegin();it!= iarr[i].a.cend();it++)
			{
				cout << *it << " ";
			}
			cout << endl;
		}
	}
	for (int i = 0; i < slen; i++)
	{
		cout << "\nv" << i + 6 << "元素个数为" << sarr[i].b.size() << endl;
		if (sarr[i].b.cbegin() != sarr[i].b.cend())
		{
			cout << "v" << i + 6 << "的元素分别是: " << endl;
			for (auto it = sarr[i].b.cbegin(); it != sarr[i].b.cend(); it++)
			{
				cout << *it << " ";
			}
			cout << endl;
		}
	}
	return 0;
}

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

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

using namespace std;

int main()
{
	vector<string> text;
	string s;
	//利用getline读取一句话,直接回车产生一个空串,表示段落结束
	while (getline(cin,s))
	{
		text.push_back(s);   //逐个添加到text中
	}
	//利用迭代器遍历全部字符串,遇空串停止循环
	for (auto it = text.begin(); it != text.end()&&!it->empty(); it++)
	{
		//利用迭代器遍历当前字符串
		for (auto it2 = it->begin();  it2 != it->end();it2++)
		{
			*it2 = toupper(*it2);  //利用toupper改写成大写形式
		}
		cout << *it << endl;       //输出当前字符串
	}
	return 0;
}

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

#include<iostream>
#include<vector>
#include<ctime>
#include<cstdlib>

using namespace std;

int main()
{
	vector<int> vint;
	srand((unsigned)time(NULL));  //生成随机数种子
	for (int i = 0; i < 10; i++)
	{
		//每次循环生成一个1000以内的随机数并添加到vint中
		vint.push_back(rand() % 1000);
	}
	cout << "The 10 randomly generated numbers are" << endl;

	//利用常量迭代器读取原始数据
	for (auto it  = vint.cbegin();it!=vint.cend();it++)
	{
		cout << *it <<" " ;
	}
	cout << endl;
	cout << "The 10 numbers after doubling are" << endl;

	//利用非常量迭代器修改vint内容并输出
	for (auto it = vint.begin(); it != vint.end(); it++)
	{
		*it *= 2;
		cout << *it << " ";
	}
	cout << endl;
	return 0;
}

3.24 请使用迭代器重做3.3.3.节最后一个练习

#include<iostream>
#include<vector>
using namespace std;

int main()
{
	vector<int> vint;
	int ival;
	cout << "please enter a set of numbers" << endl;

	while (cin >> ival)
	{
		vint.push_back(ival);
	}

	if (vint.cbegin() == vint.cend())
	{
		cout << "no elements" << endl;
		return -1;
	}

	cout << "the sum of two adiacent items is" << endl;

	//利用auto推断i的类型
	for (auto it = vint.cbegin(); it !=vint.cend()-1; it++)
	{
		//求相邻两项的和
		cout << (*it + *(++it)) << endl;
	}
	//如果元素数是奇数,单独处理最后一个元素
	if (vint.size() % 2 != 0)
	{
		cout << *(vint.cend()-1) << endl;
	}
	return 0;
}
#include<iostream>
#include<vector>
using namespace std;

int main()
{
	vector<int> vint;
	int ival;
	cout << "please enter a set of numbers" << endl;

	while (cin >> ival)
	{
		vint.push_back(ival);
	}

	if (vint.cbegin() == vint.cend())
	{
		cout << "no elements" << endl;
		return -1;
	}

	cout << "The sum of the first and last two items is" << endl;

	//利用auto推断it的类型
	auto beg = vint.cbegin();
	auto end = vint.cend();

	for (auto it = beg; it != beg +(end-beg) / 2; it++)
	{
		//求首尾两项的和
		//begin指向容器的首元素而end指向容器最后一个元素的下一个位置
		cout << *it + *(beg+(end-it)-1) << endl;
	}
	//如果元素数是奇数,单独处理最后一个元素
	if (vint.size() % 2 != 0)
	{
		cout << *(beg + (end - beg) / 2) << endl;
	}
	return 0;
}

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

#include<iostream>
#include<vector>

using namespace std;

int main()
{
	//该vector对象记录各分段的人数,初始值均为0
	vector<unsigned> vus(11);
	auto it = vus.begin();
	int ival;
	cout << "请输入一组成绩(0~100):" << endl;
	while (cin>>ival)
	{
		if (ival<101)
		{
			++* (it + ival / 10);
		}
	}
	cout << "您总计输入了" << vus.size() << "个成绩" << endl;
	cout << "各分数段的人数分布是(成绩从低到高):" << endl;
	
	//利用迭代器遍历vus的元素并逐个输出
	for (it; it!=vus.end() ; it++)
	{
		cout << *it << " ";
	}
	cout << endl;
	return 0;
}

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

//迭代器的加法不存在,所以mid = (beg+end)/2;不合法。
//mid = beg+(end-beg)/2的含义是,先计算end-beg的值得到容器中的元素个数,然后控制迭代器从开始处向右移动二分之一容器的长度,从而得到容器正中间的元素。

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

#include<iostream>
using namespace std;

unsigned buf_size = 1024;

int main()
{
	//非法,buf_size是一个普通的无符号数,不是常量,不能作为数组的维度
	int ia[buf_size];

	//合法,4*7-14 = 14是一个常量表达式
	int ia[4 * 7 - 14];

	//非法,text_size()是一个普通的函数调用,没有被定义为constexpr,不能作为数组的维度
	int ia[text_size()];

	//非法,当使用字符串初始化数组时,默认在尾部添加一个空字符'\0',算上这个符号该字符共有12个字符
	//但是字符数组st的维度只有11,无法容纳题目中的字符串
	char st[11] = "fundamental";
}


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

#include<iostream>

using namespace std;
//string类本身接受无参数的初始化方式,所以不论数组定义在函数内还是函数外都默认为初始化为空串
//数组ia定义在函数体之外,ia的所有元素默认为初始化为0;
//ia2定义在main()函数的内部,将不被初始化,如果程序试图拷贝或输出未初始化的变量,将遇到未定义的奇异值。

//定义在全局作用域中的数组
string sa[10];
int ia[10];

int main()
{
	//定义在局部作用域中的数组
	string sa2[10];
	int ia2[10];
	for (auto c:sa)
	{
		cout << c << " ";
	}
	cout << endl;

	for (auto c : ia)
	{
		cout << c << " ";
	}
	cout << endl;

	for (auto c : sa2)
	{
		cout << c << " ";
	}
	cout << endl;

	for (auto c : ia2)
	{
		cout << c << " ";
	}
	cout << endl;
	return 0;
}

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

//数组与vecotr的相似之处是都能存放类型相同的对象,且这些对象本身没有名字,需要通过其所在位置访问
//数组与vector的最大不同是,数组的大小固定不变,不能随意向数组中增加额外的元素,虽然在某些情景下运行时性能较好,但是与vector相比损失了灵活性

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

#include<iostream>

using namespace std;

//本题愿意是创建一个包含10个整数的数组,并把数组的每个元素初始化为元素的下标志。
//源程序在for循环终止条件有错,数组的下标志应该大于等于0而小于数组的大小
//修改为for (size_t ix = 0; ix < array_size; ++ix)
int main()
{
	constexpr size_t array_size = 10;
	int ia[array_size];
	for (size_t ix = 1; ix <= array_size; ++ix)
	{
		ia[ix] = ix;
	}
	return 0;
}

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

#include<iostream>

using namespace std;

int main()
{
	//常量sz作为数组的维度
	const int sz = 10;
	int a[sz];

	//通过for循环为数组元素赋值
	for (int i = 0; i < sz; i++)
	{
		a[i] = i;
	}

	//通过范围for循环输出数组的全部元素
	for (auto val : a)
	{
		cout << val << " ";
	}
	cout << endl;
	return 0;
}

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

#include<iostream>

using namespace std;

int main()
{
	//常量sz作为数组的维度
	const int sz = 10;
	int a[sz],b[sz];

	//通过for循环为数组元素赋值
	for (int i = 0; i < sz; i++)
	{
		a[i] = i;
	}
	for (int j = 0; j < sz;j++)
	{
		b[j] = a[j];
	}

	//通过范围for循环输出数组的全部元素
	for (auto val : b)
	{
		cout << val << " ";
	}
	cout << endl;
	return 0;
}
#include<iostream>
#include<vector>
using namespace std;

int main()
{
	const int sz = 10;
	vector<int> val1, val2;

	//通过for循环为vector对象的元素赋值
	for (int i = 0; i < sz; i++)
	{
		val1.push_back(i);
	}
	for (int j = 0; j < sz; j++)
	{
		val2.push_back(val1[j]);
	}

	//通过范围for循环输出vector对象的全部元素
	for (auto a : val2)
	{
		cout << a << " ";
	}
	cout << endl;
	return 0;
}

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

//该程序对scores执行了列表初始化,为所有元素赋初值0,这样在后续统计时将会从0开始计算各个分数段的人数
//如果不初始化scores,则该数组会含有未定义的数值,这是因为scores是定义在函数内部的整型数组,不会执行默认初始化。

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

p1+=p2-p1;
//如果p1和p2指向同一个数组中的元素,则该条语句令p1指向p2原来所指的元素。
//从语法上来讲,即使p1和p2指向的元素不属于同一个数组,但只要p1与p2的类型相同,该语句也是合法的。
//如果p1和p2的类型不同,则编译时报错

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

#include<iostream>
using namespace std;

int main()
{
	const int sz = 10;
	int a[sz], i = 0;

	//通过for循环为数组元素赋值
	for (i; i < 10; i++)
	{
		a[i] = i;
	}
	cout << "初始状态下数组的内容为:" << endl;
	for (auto s : a)
	{
		cout << s << " ";
	}
	cout << endl;

	int* p = begin(a);    //令p指向数组首元素
	while (p!=end(a))
	{
		*p = 0;           //修改p所指元素的值
		p++;              //p向后移动一位
	}
	cout << "修改后的数组内容是: " << endl;

	//通过范围for循环输出数组的全部元素
	for (auto s : a)
	{
		cout << s << " ";
	}
	cout << endl;
	return 0;
}

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

#include<iostream>
#include<ctime>
#include<cstdlib>
using namespace std;

int main()
{
	const int sz = 5;
	int a[sz], b[sz], i;
	srand((unsigned)time(NULL));   //生成随机数种子

	//通过for循环为数组元素赋值
	for (i = 0; i < sz; i++)
	{
		a[i] = rand() % 10;
	}
	cout << "系统数据已经生成,请输入您猜测的5个数字(0~9),可以重复:" << endl;
	int uval;
	//通过for循环为数组元素赋值
	for (i = 0; i < sz; i++)
	{
		if (cin >> uval)
		{
			b[i] = uval;
		}
	}

	cout << "系统生成的数据是:" << endl;
	for (auto c : a)
	{
		cout << c << " ";
	}
	cout << endl;
	cout << "您猜测数数据是:" << endl;
	for (auto d : b)
	{
		cout << d << " ";
	}
	cout << endl;

	//令p和q分别指向数组a和b的首元素
	int* p = begin(a), * q = begin(b);
	while (p!=end(a)&&q!=end(b))
	{
		if (*p != *q)
		{
			cout << "您的猜测有误,两个数组不相等" << endl;
			return -1;
		}
		p++;
		q++;
	}
	cout << "恭喜您全部猜对了" << endl;
	return 0;
}
#include<iostream>
#include<ctime>
#include<cstdlib>
#include<vector>
using namespace std;

int main()
{
	const int sz = 5;
	int i;
	vector<int> a, b;
	srand((unsigned)time(NULL));   //生成随机数种子

	//通过for循环为数组元素赋值
	for (i = 0; i < sz; i++)
	{
		a.push_back(rand() % 10);
	}
	cout << "系统数据已经生成,请输入您猜测的5个数字(0~9),可以重复:" << endl;
	int uval;
	//通过for循环为数组元素赋值
	for (i = 0; i < sz; i++)
	{
		if (cin >> uval)
		{
			b.push_back(uval);
		}
	}

	cout << "系统生成的数据是:" << endl;
	for (auto c : a)
	{
		cout << c << " ";
	}
	cout << endl;
	cout << "您猜测数数据是:" << endl;
	for (auto d : b)
	{
		cout << d << " ";
	}
	cout << endl;

	//令it1和it2分别指向vector对象a和b的首元素
	auto it1 = a.cbegin(), it2 = b.cbegin();
	while (it1 !=a.cend()&&it2!=b.cend())
	{
		if (*it1 !=*it2)
		{
			cout << "您的猜测有误,两个数组不相等" << endl;
			return -1;
		}
		it1++;
		it2++;
	}
	cout << "恭喜您全部猜对了" << endl;
	return 0;
}

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

#include<iostream>
using namespace std;

int main()
{
	//定义了一个包含5个字符的常量字符数组
	const char ca[] = { 'h','e','l','l','o'};

	//修改一 const char ca[] = { 'h','e','l','l','o','\0'};

	//修改二 const char ca[] = "hello";

	//定义了一个指向字符常量的指针
	const char* cp = ca;
	//只要指针cp所指的字符不是空字符'\0',循环重复进行
	while (*cp)
	{
		//输出指针当前所指的字符
		cout << *cp << endl;
		//指针向后移动一位
		++cp;
	}
	return 0;
}

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

//指针也是一个对象,与指针相关的属性有3个,分别是指针本身的值、指针所指的对象以及指针本身在内存中的存储位置。它们的含义分别是
//指针本身的值是一个地址值,表示指针所指对象在内存中的存储地址
//指针所指的对象可以通过解引用指针访问
//因为指针也是一个对象,所以指针也存储在内存的某个位置,它有它的地址,这也是为什么有指针的指针的原因
//综上,指针的值是它所指对象的内存地址,如果两个指针加一起,就是把存储地址加一起,显然没有意义
//与之相反,指针的减法是有意义的。如果两个指针指向同一个数组中的不同元素,则它们相减的结果表征了它们所指元素在数组中的距离。

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

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string str1, str2;
	cout << "please enter two strings" << endl;
	cin >> str1 >> str2;

	if (str1>str2)
	{
		cout << "the frist string is greater than the second string " << endl;
	}
	else if (str1<str2)
	{
		cout << "the first string is smaller than the second string " << endl;
	}
	else
	{
		cout << "the first string is equal to the second string " << endl;
	}
	return 0;
}
#include<iostream>
#include<cstring>

using namespace std;

//比较两个c风格字符串
int main()
{
	char str1[80], str2[80];
	cout << "please enter two srings" << endl;
	cin >> str1 >> str2;

	//利用cstring头文件中定义的strcmp函数比较大小
	auto result = strcmp(str1, str2);
	switch (result)
	{
	case 1:
		cout << "the frist string is greater than the second string " << endl;
		break;
	case -1:
		cout << "the first string is smaller than the second string " << endl;
		break;
	case 0:
		cout << "the first string is equal to the second string " << endl;
		break;
	default:
		cout << "undefined result" << endl;
		break;
	}
	return 0;
}

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

#include<iostream>
#include<cstring>
using namespace std;

int main()
{
	char str1[] = "welcome to ";
	char str2[] = "C++ family!";

	//利用strlen函数计算两个字符串的长度,并求得结果字符串的长度
	char result[strlen(str1)+strlen(str2)-1];

	strcpy(result, str1);    //把第一个字符串拷贝到结果字符中
	strcat(result, str2);    //把第二个字符串拼接到结果字符中

	cout << "the first string is " << str1 << endl;
	cout << "the second string is " << str2 << endl;
	cout << "rhe spliced string is " << result << endl;
	return 0;
}

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

#include<iostream>
#include<vector>
#include<ctime>
#include<cstdlib>

using namespace std;

int main()
{
	const int sz = 10;
	int a[sz];
	srand((unsigned)time(NULL));
	cout << "the content of the array is " << endl;
	
	//利用范围for循环遍历数组的每个元素
	for (auto& val : a)
	{
		val = rand() % 100;
		cout << val << " ";
	}
	cout << endl;

	//c++不允许用一个数组初始化另一个数组,也不允许使用vector对象直接初始化数组,但是允许使用数组来初始化vector对象
	//要实现这一目的,只需指明要拷贝区域的首元素地址和尾后地址
	//利用begin和end初始化vector对象
	vector<int>vint(begin(a), end(a));
	cout << "the content of vector is " << endl;

	//利用范围for循环遍历vector的每个对象
	for (auto val : vint)
	{
		cout << val << " ";
	}
	cout << endl;
	return 0;
}

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

#include<iostream>
#include<vector>
#include<ctime>
#include<cstdlib>

using namespace std;

int main()
{
	const int sz = 10;
	vector<int>vint;
	srand((unsigned)time(NULL));
	cout << "the content of vector is " << endl;
	
	//利用for循环遍历vector对象的每个元素
	for (int i = 0; i < sz; i++)
	{
		vint.push_back(rand() % 100);
		cout << vint[i] << " ";
	}
	cout << endl;

	auto it = vint.cbegin();
	int a[sz];
	cout << "the content of array is " << endl;

	//c++允许使用数组直接初始化vector对象,但是不允许使用vector对象初始化数组
	//如果想用vector对象初始化数组,则必须把vector对象的每一个元素逐一赋值给数组
	//利用范围for循环遍历数组的每个元素
	for (auto& val : a)
	{
		val = *it;
		cout << val << " ";
		it++;
	}
	cout << endl;
	return 0;
}

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

#include<iostream>
using namespace std;

int main()
{
	int ia[3][4] = { 0,1,2,3,4,5,6,7,8,9,10,11 };
	cout << "利用范围for语句输出多维数组的内容:" << endl;
	for (int(&row)[4] : ia)
	{
		for (int& col : row)
		{
			cout << col << " ";
		}
		cout << endl;
	}

	cout << "利用普通for语句和下标运算符输出多维数组的内容:" << endl;
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			cout << ia[i][j] << " ";
		}
		cout << endl;
	}

	cout << "利用普通for语句和指针运算符输出多维数组的内容:" << endl;
	for (int(*p)[4] = ia; p != ia + 3; p++)
	{
		for (int* q = *p; q != *p + 4; q++)
		{
			cout << *q << " ";
		}
		cout << endl;
	}
	return 0;
}

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

#include<iostream>
using namespace std;
using int_array = int[4];

int main()
{
	int ia[3][4] = { 0,1,2,3,4,5,6,7,8,9,10,11 };
	cout << "利用范围for语句输出多维数组的内容:" << endl;
	for (int_array&row : ia)
	{
		for (int& col : row)
		{
			cout << col << " ";
		}
		cout << endl;
	}

	cout << "利用普通for语句和下标运算符输出多维数组的内容:" << endl;
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			cout << ia[i][j] << " ";
		}
		cout << endl;
	}

	cout << "利用普通for语句和指针运算符输出多维数组的内容:" << endl;
	for (int_array*p = ia; p != ia + 3; p++)
	{
		for (int* q = *p; q != *p + 4; q++)
		{
			cout << *q << " ";
		}
		cout << endl;
	}
	return 0;
}

3.45 在一次改写程序,这次使用auto关键字

#include<iostream>
using namespace std;

int main()
{
	int ia[3][4] = { 0,1,2,3,4,5,6,7,8,9,10,11 };
	cout << "利用范围for语句输出多维数组的内容:" << endl;
	for (auto&row : ia)
	{
		for (auto& col : row)
		{
			cout << col << " ";
		}
		cout << endl;
	}

	cout << "利用普通for语句和下标运算符输出多维数组的内容:" << endl;
	for (auto i = 0; i < 3; i++)
	{
		for (auto j = 0; j < 4; j++)
		{
			cout << ia[i][j] << " ";
		}
		cout << endl;
	}

	cout << "利用普通for语句和指针运算符输出多维数组的内容:" << endl;
	for (auto p = ia; p != ia + 3; p++)
	{
		for (auto q = *p; q != *p + 4; q++)
		{
			cout << *q << " ";
		}
		cout << endl;
	}
	return 0;
}
  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值