编译软件为 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 关键字可以使得程序更加简洁方便,且更容易避免在定义过程中类型定义出现错误的情况。