doc/docs/Cpp-Notes-main/Cpp-Primer-exercise/3.字符串、向量和数组.md
sairate 4108f6c42d docs(book): 添加现代 C++教程及相关代码
- 新增现代 C++ 教程的 Preface 章节,包括英文和中文版本
- 添加 C++ Primer 练习代码
- 新增 Learn C++ 教程的 C++ 开发简介章节
- 添加头文件解析文档
- 更新 mkdocs.yml,包含新教程的目录结构
- 修改项目设置,使用 Python 3.10环境
2025-07-06 16:14:43 +08:00

1360 lines
29 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
sort: 3
---
# 字符串、向量和数组
## 练习3.1
使用恰当的using 声明重做 1.4.1节和2.6.2节的练习。
解:
1.4.1
```cpp
#include <iostream>
using std::cout;
using std::endl;
int main() {
int i = 50, sum = 0;
while (i <= 100) {
sum += i;
i += 1;
}
cout << "sum is " << sum << endl;
}
```
2.6.2 类似
## 练习3.2
编写一段程序从标准输入中一次读入一行,然后修改该程序使其一次读入一个词。
解:
一次读入一行:
```cpp
#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
using std::endl;
using std::getline;
int main()
{
string s;
while (getline(cin,s))
{
cout << s << endl;
}
return 0;
}
```
一次读入一个词
```cpp
#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
using std::endl;
using std::getline;
int main()
{
string s;
while (cin >> s)
{
cout << s << endl;
}
return 0;
}
```
## 练习3.3
请说明string类的输入运算符和getline函数分别是如何处理空白字符的。
解:
- 类似`is >> s`的读取string对象会忽略开头的空白(空格符、换行符、制表符等)并从第一个真正的字符开始,直到遇见下一**空白**为止。
- 类似`getline(is, s)`的读取string对象会从输入流中读取字符直到遇见**换行符**为止。
## 练习3.4
编写一段程序读取两个字符串,比较其是否相等并输出结果。如果不相等,输出比较大的那个字符串。改写上述程序,比较输入的两个字符串是否等长,如果不等长,输出长度较大的那个字符串。
解:
```cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
string str1, str2;
cout << "请输入两个字符串" << endl;
cin >> str1;
cin >> str2;
if (str1 == str2) {
cout << "两个字符相等" << endl;
}else if (str1 > str2) {
cout << str1 << endl;
}else {
cout << str2 <<endl;
}
auto len1 = str1.size();
auto len2 = str2.size();
if (len1 == len2) {
cout << str1 << "和" << str2 << "的长度是" << len2 << endl;
}else if (len1 > len2)
cout << str1 << "比" << str2 << "的长度多" << len1 - len2 << endl;
else
cout << str1 << "比" << str2 << "的长度少" << len2 - len1 << endl;
return 0;
}
```
## 练习3.5
编写一段程序从标准输入中读入多个字符串并将他们连接起来,输出连接成的大字符串。然后修改上述程序,用空格把输入的多个字符串分割开来。
解:
未隔开的:
```cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
char cont = 'y';
string s, result;
cout << "请输入字符串" << endl;
while(cin >> s) {
result += s;
cout << "是否继续(y or n)" << endl;
cin >> cont;
if (cont == 'y' || cont == 'Y'){
cout << "请输入下一个字符串" << endl;
}else {
break;
}
}
cout << "拼接后的字符为" <<result << endl;
return 0;
}
```
隔开的:
```cpp
#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
using std::endl;
int main()
{
string result, s;
while (cin >> s)
{
result += s + " ";
}
cout << result << endl;
return 0;
}
```
## 练习3.6
编写一段程序使用范围for语句将字符串内所有字符用X代替。
解:
```cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
cout << "请输入一个字符串" <<endl;
getline(cin, s);
for (auto &c : s) {
c = 'X';
}
cout << s << endl;
return 0;
}
```
## 练习3.7
就上一题完成的程序而言如果将循环控制的变量设置为char将发生什么先估计一下结果然后实际编程进行验证。
解:
如果设置为char那么原来的字符串不会发生改变。使用 auto 自动推断字串符 s 的元素类型,结果同样是 char。
## 练习3.8
分别用while循环和传统for循环重写第一题的程序你觉得哪种形式更好呢为什么
解:
```cpp
#include <iostream>
#include <string>
using namespace std;
// while
int main() {
string s;
cout << "请输入一个字符串" <<endl;
getline(cin, s);
int i = 0;
while (s[i] !='\0') {
s[i] = 'X';
++i;
}
cout << s << endl;
return 0;
}
```
```cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
cout << "请输入一个字符串" <<endl;
getline(cin, s);
for (unsigned int i = 0; i < s.size(); i++) {
s[i] = 'X';
}
cout << s << endl;
return 0;
}
```
范围for语句更好不直接操作索引更简洁直观。
## 练习3.9
下面的程序有何作用?它合法吗?如果不合法?为什么?
```cpp
string s;
cout << s[0] << endl;
```
解:
不合法。使用下标访问空字符串是非法的行为。
## 练习3.10
编写一段程序,读入一个包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分。
解:
```cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
cout << "请输入一个字符串" <<endl;
getline(cin, s);
for (auto c : s) {
if (!ispunct(c))
cout << c
}
cout << endl;
return 0;
}
```
## 练习3.11
下面的范围for语句合法吗如果合法c的类型是什么
```cpp
const string s = "Keep out!";
for(auto &c : s){ /* ... */ }
```
解:
要根据for循环中的代码来看是否合法c是string 对象中字符的引用s是常量。因此如果for循环中的代码重新给c赋值就会非法如果不改变c的值那么合法。
## 练习3.12
下列vector对象的定义有不正确的吗如果有请指出来。对于正确的描述其执行结果对于不正确的说明其错误的原因。
```cpp
vector<vector<int>> ivec; // 在C++11当中合法
vector<string> svec = ivec; // 不合法,类型不一样
vector<string> svec(10, "null"); // 合法
```
## 练习3.13
下列的vector对象各包含多少个元素这些元素的值分别是多少
```cpp
vector<int> v1; // size:0, no values.
vector<int> v2(10); // size:10, value:0
vector<int> v3(10, 42); // size:10, value:42
vector<int> v4{ 10 }; // size:1, value:10
vector<int> v5{ 10, 42 }; // size:2, value:10, 42
vector<string> v6{ 10 }; // size:10, value:""
vector<string> v7{ 10, "hi" }; // size:10, value:"hi"
```
## 练习3.14
编写一段程序用cin读入一组整数并把它们存入一个vector对象。
解:
```cpp
##include <iostream>
#include <string>
#include <vector>
using namespace std;
using std::vector;
int main() {
vector<int> v;
int i;
char cont = 'y';
cout << "请输入数字" << endl;
while(cin >> i) {
v.push_back(i);
cout << "是否继续(y or n)" << endl;
cin >> cont;
if (cont == 'y' || cont == 'Y'){
cout << "请输入下一个整数" << endl;
}else {
break;
}
}
for (auto &m : v)
cout << "输入的整数为" <<m << endl;
return 0;
}
```
## 练习3.15
改写上题程序,不过这次读入的是字符串。
解:
```cpp
#include <iostream>
#include <string>
#include <vector>
using namespace std;
using std::vector;
int main() {
vector<string> v;
string i;
char cont = 'y';
cout << "请输入字符串" << endl;
while(cin >> i) {
v.push_back(i);
cout << "是否继续(y or n)" << endl;
cin >> cont;
if (cont == 'y' || cont == 'Y'){
cout << "请输入下一个字符串" << endl;
}else {
break;
}
}
for (auto &m : v)
cout << m << " ";
cout << endl;
return 0;
}
```
## 练习3.16
编写一段程序把练习3.13中vector对象的容量和具体内容输出出来
解:
```cpp
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<int> v1; // size:0, no values.
vector<int> v2(10); // size:10, value:0
vector<int> v3(10, 42); // size:10, value:42
vector<int> v4{ 10 }; // size:1, value:10
vector<int> v5{ 10, 42 }; // size:2, value:10, 42
vector<string> v6{ 10 }; // size:10, value:""
vector<string> v7{ 10, "hi" }; // size:10, value:"hi"
cout << "v1 size :" << v1.size() << endl;
cout << "v2 size :" << v2.size() << endl;
cout << "v3 size :" << v3.size() << endl;
cout << "v4 size :" << v4.size() << endl;
cout << "v5 size :" << v5.size() << endl;
cout << "v6 size :" << v6.size() << endl;
cout << "v7 size :" << v7.size() << endl;
cout << "v1 content: ";
for (auto i : v1)
{
cout << i << " , ";
}
cout << endl;
cout << "v2 content: ";
for (auto i : v2)
{
cout << i << " , ";
}
cout << endl;
cout << "v3 content: ";
for (auto i : v3)
{
cout << i << " , ";
}
cout << endl;
cout << "v4 content: ";
for (auto i : v4)
{
cout << i << " , ";
}
cout << endl;
cout << "v5 content: ";
for (auto i : v5)
{
cout << i << " , ";
}
cout << endl;
cout << "v6 content: ";
for (auto i : v6)
{
cout << i << " , ";
}
cout << endl;
cout << "v7 content: ";
for (auto i : v7)
{
cout << i << " , ";
}
cout << endl;
return 0;
}
```
## 练习3.17
从cin读入一组词并把它们存入一个vector对象然后设法把所有词都改为大写形式。输出改变后的结果每个词占一行。
解:
```cpp
#include <iostream>
#include <string>
#include <cctype>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::vector;
using std::string;
int main()
{
vector<string> v;
string s;
while (cin >> s)
{
v.push_back(s);
}
for (auto &str : v)
{
for (auto &c : str)
{
c = toupper(c);
}
}
for (auto i : v)
{
cout << i << endl;
}
return 0;
}
```
## 练习3.18
下面的程序合法吗?如果不合法,你准备如何修改?
```cpp
vector<int> ivec;
ivec[0] = 42;
```
解:
不合法。应改为:
```cpp
ivec.push_back(42);
```
## 练习3.19
如果想定义一个含有10个元素的vector对象所有元素的值都是42请例举三种不同的实现方法哪种方式更好呢
如下三种:
```cpp
vector<int> ivec1(10, 42);
vector<int> ivec2{ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
vector<int> ivec3 = { 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
vector<int> ivec4;
for (int i = 0; i < 10; ++i)
ivec4.push_back(42);
```
vector<int> ivec5(10);
for (auto &i : ivec5) {
i = 42;
}
第一种方式简介直观当对象数量多且取值重复时适合使用思路4不限制元素的个数比较灵活。
## 练习3.20
读入一组整数并把他们存入一个vector对象将每对相邻整数的和输出出来。改写你的程序这次要求先输出第一个和最后一个元素的和接着输出第二个和倒数第二个元素的和以此类推。
解:
```cpp
#include <iostream>
#include <string>
#include <vector>
using namespace std;
using std::vector;
int main() {
vector<int> v;
int w;
cout << "请输入数字" << endl;
while (cin >> w) {
v.push_back(w);
}
if (v.size() == 0) {
cout << "没有任何元素" <<endl;
return -1;
}
cout << "相邻一组数的和为:" <<endl;
for(decltype((v.size())) i = 0; i < v.size() - 1; i += 2)
cout << v[i] + v[i + 1] << " ";
if (v.size() % 2 != 0)
cout << v[v.size() - 1];
cout <<endl;
cout << "首尾两项数的和为:" <<endl;
decltype(v.size()) i = 0, j = v.size() - 1;
while (i < j) {
cout << v[i] +v[j] << " ";
++i,--j;
}
if (v.size() % 2 != 0)
cout << v[v.size() / 2];
cout <<endl;
return 0;
}
```
## 练习3.21
请使用迭代器重做3.3.3节的第一个练习。
解:
```cpp
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<int> v1; // size:0, no values.
vector<int> v2(10); // size:10, value:0
vector<int> v3(10, 42); // size:10, value:42
vector<int> v4{ 10 }; // size:1, value:10
vector<int> v5{ 10, 42 }; // size:2, value:10, 42
vector<string> v6{ 10 }; // size:10, value:""
vector<string> v7{ 10, "hi" }; // size:10, value:"hi"
cout << "v1 size :" << v1.size() << endl;
cout << "v2 size :" << v2.size() << endl;
cout << "v3 size :" << v3.size() << endl;
cout << "v4 size :" << v4.size() << endl;
cout << "v5 size :" << v5.size() << endl;
cout << "v6 size :" << v6.size() << endl;
cout << "v7 size :" << v7.size() << endl;
cout << "v1 content: ";
if (v1.cbegin() != v1.cend()) {
for (auto it = v1.cbegin(); it != v1.cend(); it++) {
cout << *it << " , ";
}
cout << endl;
}
cout << "v2 content: ";
if (v2.cbegin() != v2.cend()) {
for (auto it = v2.cbegin(); it != v2.cend(); it++) {
cout << *it << " , ";
}
cout << endl;
}
cout << "v3 content: ";
if (v3.cbegin()!= v3.cend()) {
for (auto it = v3.cbegin(); it != v3.cend(); it++){
cout << *it << " , ";
}
cout << endl;
}
cout << "v4 content: ";
if (v4.cbegin() != v4.cend()) {
for(auto it = v4.cbegin(); it != v4.cend(); it++) {
cout << *it << ",";
}
cout << endl;
}
cout << "v5 content: ";
if (v5.cbegin() != v5.cend()) {
for(auto it = v5.cbegin(); it != v5.cend(); it++) {
cout << *it << ",";
}
cout << endl;
}
cout << "v6 content: ";
if (v6.cbegin() != v6.cend()) {
for(auto it = v6.cbegin(); it != v6.cend(); it++) {
cout << *it << ",";
}
cout << endl;
}
cout << "v7 content: ";
if (v7.cbegin() != v7.cend()) {
for(auto it = v7.cbegin(); it != v7.cend(); it++) {
cout << *it << ",";
}
cout << endl;
}
return 0;
}
```
## 练习3.22
修改之前那个输出text第一段的程序首先把text的第一段全部改成大写形式然后输出它。
解:
```cpp
#include <iostream>
#include <string>
#include <vector>
using namespace std;
using std::vector;
int main() {
vector<string> v;
string w;
cout << "请输入一段话" << endl;
while (getline(cin, w)) { //利用getline读取一句话直接回车产生一个空串表示段落结束
v.push_back(w);
}
for(auto it = v.begin(); it != v.end() && !it -> empty();it++) {
for (auto it2 = it->begin(); it2 != it->end(); it2++){
*it2 = toupper(*it2);
}
cout << *it << endl;
}
return 0;
}
```
## 练习3.23
编写一段程序,创建一个含有10个整数的vector对象,然后使用迭代器将所有元素的值都变成原来的两倍。输出vector对象的内容,检验程序是否正确。
解:
```cpp
#include <iostream>
#include <string>
#include <vector>
using namespace std;
using std::vector;
int main() {
vector<int> words;
for (int i = 0; i < 10; i++) {
words.push_back(rand() % 1000);
}
cout << "随机生成的数字是:" <<endl;
for(auto it = words.begin(); it != words.end() && !words.empty(); it++) {
cout << *it << " ";
}
cout <<endl;
cout << "翻倍后的数字是:" <<endl;
for(auto it = words.begin(); it != words.end() && !words.empty(); it++) {
*it = *it * 2;
cout << *it << " ";
}
return 0;
}
```
## 练习3.24
请使用迭代器重做3.3.3节的最后一个练习。
解:
```cpp
#include <iostream>
#include <string>
#include <cctype>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::vector;
using std::string;
int main()
{
#include <iostream>
#include <string>
#include <vector>
using namespace std;
using std::vector;
int main() {
vector<int> v;
int w;
cout << "请输入数字" << endl;
while (cin >> w) {
v.push_back(w);
}
if (v.cbegin() == v.cend()) {
cout << "没有任何元素" <<endl;
return -1;
}
cout << "首尾两项的和为:" <<endl;
auto begin = v.begin();
auto end = v.end();
for(auto it = begin; it != begin + (end - begin) / 2; it ++){
cout << (*it + *(begin + (end - it) - 1))<< " ";
if (v.size() % 2 != 0)
cout << *(begin + (end - it + 1)/ 2);
cout <<endl;
}
return 0;
}
```
## 练习3.25
3.3.3节划分分数段的程序是使用下标运算符实现的,请利用迭代器改写该程序实现完全相同的功能。
解:
```cpp
#include <iostream>
#include <string>
#include <vector>
using namespace std;
using std::vector;
int main() {
vector<unsigned> v(11);
auto it = v.begin();
int i;
cout << "请输入一组成绩"<<endl;
while(cin >> i) {
if (i < 101) {
++*(it + i / 10);
}
}
cout << "各分数段的人数分布式" << endl;
for (it = v.begin(); it!= v.end();it++) {
cout << *it << " ";
}
cout << endl;
return 0;
}
```
## 练习3.26
在100页的二分搜索程序中为什么用的是 `mid = beg + (end - beg) / 2`, 而非 `mid = (beg + end) / 2 ;` ?
解:
因为两个迭代器相互之间支持的运算只有 `-` ,而没有 `+` ,两个迭代器之间相减的结果代表他们之间的距离;
但是迭代器和迭代器差值(整数值)之间支持 `+`
## 练习3.27
假设`txt_size`是一个无参函数,它的返回值是`int`。请回答下列哪个定义是非法的,为什么?
```cpp
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() 的值必须要到运行时才能得到,没有被定义为`constexpr`,不能作为数组的维度。
- (d) 非法。数组的大小应该是12。
## 练习3.28
下列数组中元素的值是什么?
```cpp
string sa[10];
int ia[10];
int main() {
string sa2[10];
int ia2[10];
}
```
解:
对于内置类型`int`来说,数组`ia`定义在所有函数体之外所有元素默认初始化为0`ia2`定义在main函数的内部将不被初始化如果程序试图拷贝或输出未初始化的变量将遇到未定义的奇异值。
string类本身接收无参数的初始化方式所以不论数组定义在函数内还是函数外都被默认初始化为空串。
## 练习3.29
相比于vector 来说,数组有哪些缺点,请例举一些。
解:
- 数组与vector的相似之处是都能存放类型相同的对象且这些对象本身没有名字需要通过其所在位置访问。
- 数组与vector的最大不同是数组的大小固定不变不能随意向数组中增加额外的元素虽然在某些情境下运行时性能能较好但是与vector相比损失了灵活性。
- 具体来说数组的维度在定义时已经确定如果我们想更改数组的长度只能创建一个更大的新数组然后把原数组的所有有元素复制到新数组中去。我们也无法像vector那样使用 size函数直接获取数组的维度。如果是字符数组可以调用strlen函数得到字符串的长度; 如果是其他数组,只能使用 sizeof(array)/sizeof(array[0])的方式计算数组的维度。
## 练习3.30
指出下面代码中的索引错误。
```cpp
constexpr size_t array_size = 10;
int ia[array_size];
for (size_t ix = 1; ix <= array_size; ++ix)
ia[ix] = ix;
```
解:
`ix`增长到 10 的时候,`ia[ix]`的下标越界。
## 练习3.31
编写一段程序定义一个含有10个int的数组令每个元素的值就是其下标值。
```cpp
#include <iostream>
#include <string>
#include <vector>
using namespace std;
using std::vector;
int main() {
const int sz = 10;
int num[sz];
for (int i = 0; i < sz; i++) {
num[i] = i;
}
for (auto val : num) {
cout << val << " ";
}
cout << endl;
return 0;
}
```
## 练习3.32
将上一题刚刚创建的数组拷贝给另一数组。利用vector重写程序实现类似的功能。
```cpp
#include <iostream>
#include <string>
#include <vector>
using namespace std;
using std::vector;
int main() {
const int sz = 10;
vector<int> num3;
vector<int> num4;
int num1[sz], num2[sz];
for (int i = 0; i < sz; i++) {
num1[i] = i;
}
for (int i = 0; i < sz; i++) {
num2[i] = num1[i];
}
cout << "num2中的值为" << endl;
for (auto val : num2) {
cout << val << " ";
}
cout << endl;
for (int i = 0; i < sz; i++) {
num3.push_back(i);
}
for (int i = 0; i < sz; i++) {
num4.push_back(num3[i]);
}
cout << "num4中的值为" << endl;
for (auto val : num4) {
cout << val << " ";
}
cout << endl;
return 0;
}
```
## 练习3.33
对于104页的程序来说如果不初始化scores将会发生什么
解:
该数组会含有未定义的数值因为scores是定义在函数内部的整型数组不会执行默认初始化。
## 练习3.34
假定`p1``p2` 都指向同一个数组中的元素,则下面程序的功能是什么?什么情况下该程序是非法的?
```cpp
p1 += p2 - p1;
```
解:
`p1` 移动到 `p2` 的位置。
如果`p1``p2`的类型不同,则编译时报错。
## 练习3.35
编写一段程序利用指针将数组中的元素置为0。
解:
```cpp
#include <iostream>
#include <string>
#include <vector>
using namespace std;
using std::vector;
int main() {
const int sz = 10;
int nums[sz];
for (int i = 0; i < sz; i++) {
nums[i] = i;
}
for (auto ptr = nums; ptr != nums + sz; ++ptr) *ptr = 0;
// int *p = begin(nums);
// while (p != end(nums)) {
// *p = 0;
// p++;
// }
for (auto num : nums) {
cout << num << " ";
}
cout << endl;
return 0;
}
```
## 练习3.36
编写一段程序比较两个数组是否相等。再写一段程序比较两个vector对象是否相等。
解:
```cpp
#include <iostream>
#include <vector>
#include <iterator>
using std::begin; using std::end; using std::cout; using std::endl; using std::vector;
// pb point to begin of the array, pe point to end of the array.
bool compare(int* const pb1, int* const pe1, int* const pb2, int* const pe2)
{
if ((pe1 - pb1) != (pe2 - pb2)) // have different size.
return false;
else
{
for (int* i = pb1, *j = pb2; (i != pe1) && (j != pe2); ++i, ++j)
if (*i != *j) return false;
}
return true;
}
int main()
{
int arr1[3] = { 0, 1, 2 };
int arr2[3] = { 0, 2, 4 };
if (compare(begin(arr1), end(arr1), begin(arr2), end(arr2)))
cout << "The two arrays are equal." << endl;
else
cout << "The two arrays are not equal." << endl;
cout << "==========" << endl;
vector<int> vec1 = { 0, 1, 2 };
vector<int> vec2 = { 0, 1, 2 };
if (vec1 == vec2)
cout << "The two vectors are equal." << endl;
else
cout << "The two vectors are not equal." << endl;
return 0;
}
```
## 练习3.37
下面的程序是何含义,程序的输出结果是什么?
```cpp
const char ca[] = { 'h', 'e', 'l', 'l', 'o' };
const char *cp = ca;
while (*cp) {
cout << *cp << endl;
++cp;
}
```
解:
会将ca 字符数组中的元素打印出来。但是因为没有空字符的存在,程序不会退出循环。
## 练习3.38
在本节中我们提到,将两个指针相加不但是非法的,而且也没有什么意义。请问为什么两个指针相加没有意义?
解:
指针的值是它所指对象的内存地址,将两个指针相减可以表示两个指针(在同一数组中)相距的距离,将指针加上一个整数也可以表示移动这个指针到某一位置。但是两个指针相加并没有逻辑上的意义,因此两个指针不能相加。
## 练习3.39
编写一段程序,比较两个 `string` 对象。再编写一段程序比较两个C风格字符串的内容。
解:
```cpp
#include <iostream>
#include <string>
#include <cstring>
using std::cout; using std::endl; using std::string;
int main()
{
// use string.
string s1("Mooophy"), s2("Pezy");
if (s1 == s2)
cout << "same string." << endl;
else if (s1 > s2)
cout << "Mooophy > Pezy" << endl;
else
cout << "Mooophy < Pezy" << endl;
cout << "=========" << endl;
// use C-Style character strings.
const char* cs1 = "Wangyue";
const char* cs2 = "Pezy";
auto result = strcmp(cs1, cs2);
if (result == 0)
cout << "same string." << endl;
else if (result < 0)
cout << "Wangyue < Pezy" << endl;
else
cout << "Wangyue > Pezy" << endl;
return 0;
}
```
## 练习3.40
编写一段程序,定义两个字符数组并用字符串字面值初始化它们;接着再定义一个字符数组存放前面两个数组连接后的结果。使用`strcpy``strcat`把前两个数组的内容拷贝到第三个数组当中。
解:
```cpp
#include <iostream>
#include <cstring>
const char cstr1[]="Hello";
const char cstr2[]="world!";
int main()
{
constexpr size_t new_size = strlen(cstr1) + strlen(" ") + strlen(cstr2) +1;
char cstr3[new_size];
strcpy(cstr3, cstr1);
strcat(cstr3, " ");
strcat(cstr3, cstr2);
std::cout << cstr3 << std::endl;
}
```
## 练习3.41
编写一段程序用整型数组初始化一个vector对象。
```cpp
#include <iostream>
#include <vector>
using std::vector; using std::cout; using std::endl; using std::begin; using std::end;
int main()
{
int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
vector<int> v(begin(arr), end(arr));
for (auto i : v) cout << i << " ";
cout << endl;
return 0;
}
```
## 练习3.42
编写一段程序,将含有整数元素的 `vector` 对象拷贝给一个整型数组。
解:
```cpp
#include <iostream>
#include <vector>
using namespace std;
int main()
{
const int sz = 10;
vector<int> words;
int nums[10];
for (int i = 0; i < sz; i++) {
words.push_back(i);
}
auto it = words.cbegin();
for (auto & val : nums) {
val = *it;
cout << val << " ";
it++;
}
cout << endl;
return 0;
}
```
## 练习3.43
编写3个不同版本的程序令其均能输出`ia`的元素。
版本1使用范围`for`语句管理迭代过程版本2和版本3都使用普通`for`语句其中版本2要求使用下标运算符版本3要求使用指针。
此外在所有3个版本的程序中都要直接写出数据类型而不能使用类型别名、`auto`关键字和`decltype`关键字。
解:
```cpp
#include <iostream>
#include <vector>
using namespace std;
int main()
{
// 范围for语句
int ia[2][2] = {1, 2, 3, 4};
for (int (&row)[2] : ia){
for(int &val : row) {
cout << val << " ";
}
cout << endl;
}
// 普通for语句下标形式
for (int i = 0; i != 2; i++){
for(int j = 0; j != 2; j++) {
cout << ia[i][j] << " ";
}
cout << endl;
}
// 普通for语句指针形式
for (int (*p)[2] = ia; p != ia + 2; p++){
for(int *q = *p; q != *p + 2; q++) {
cout << *q << " ";
}
cout << endl;
}
return 0;
}
```
## 练习3.44
改写上一个练习中的程序,使用类型别名来代替循环控制变量的类型。
解:
```cpp
#include <iostream>
#include <vector>
using namespace std;
using int_array = int[2];
int main()
{
// 范围for语句
int ia[2][2] = {1, 2, 3, 4};
for (int_array &row : ia){
for(int &val : row) {
cout << val << " ";
}
cout << endl;
}
// 普通for语句下标形式
for (int i = 0; i != 2; i++){
for(int j = 0; j != 2; j++) {
cout << ia[i][j] << " ";
}
cout << endl;
}
// 普通for语句指针形式
for (int_array *p = ia; p != ia + 2; p++){
for(int *q = *p; q != *p + 2; q++) {
cout << *q << " ";
}
cout << endl;
}
return 0;
}
```
## 练习3.45
再一次改写程序,这次使用 `auto` 关键字。
解:
```cpp
#include <iostream>
#include <vector>
using namespace std;
using int_array = int[2];
int main()
{
// 范围for语句
int ia[2][2] = {1, 2, 3, 4};
for (auto &row : ia){
for(auto &val : row) {
cout << val << " ";
}
cout << endl;
}
// 普通for语句下标形式
for (auto i = 0; i != 2; i++){
for(auto j = 0; j != 2; j++) {
cout << ia[i][j] << " ";
}
cout << endl;
}
// 普通for语句指针形式
for (auto *p = ia; p != ia + 2; p++){
for(auto *q = *p; q != *p + 2; q++) {
cout << *q << " ";
}
cout << endl;
}
return 0;
}
```