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