【C++ Primer】第三章:字符串、向量与数组
这一章介绍C++标准库中最重要的几个工具:string
、vector
和数组,以及迭代器的概念。
3.1 命名空间的using声明
在使用标准库组件之前,我们先简化一下命名空间的使用:
#include <iostream>// using声明:这样就不需要每次都写std::
using std::cout;
using std::endl;
using std::cin;// 或者使用using namespace(在小型程序中方便,大型项目不推荐)
// using namespace std;int main()
{cout << "Hello, World!" << endl; // 不再需要std::return 0;
}
3.2 标准库类型string
string
表示可变长的字符序列,是C风格字符串的现代替代品。
定义和初始化string
#include <iostream>
#include <string> // 必须包含string头文件using std::cout;
using std::endl;
using std::string;int main()
{// 各种初始化方式string s1; // 默认初始化,空字符串string s2 = "hello"; // 拷贝初始化string s3("world"); // 直接初始化string s4(5, 'c'); // s4的内容是"ccccc"string s5 = s2; // s5是s2的副本cout << "s1: '" << s1 << "'" << endl;cout << "s2: " << s2 << endl;cout << "s4: " << s4 << endl;return 0;
}
string操作
#include <iostream>
#include <string>using std::cout;
using std::endl;
using std::string;int main()
{string s = "hello";// 基本操作cout << "s.empty(): " << s.empty() << endl; // 0 (false)cout << "s.size(): " << s.size() << endl; // 5cout << "s.length(): " << s.length() << endl; // 5 (与size()相同)// 比较操作string s2 = "world";cout << "s == s2: " << (s == s2) << endl; // 0cout << "s < s2: " << (s < s2) << endl; // 1 (字典序比较)// 赋值和拼接s = "new string"; // 赋值s2 = s + " concatenated"; // 拼接s += "!"; // 追加cout << "s: " << s << endl;cout << "s2: " << s2 << endl;return 0;
}
处理string中的字符
#include <iostream>
#include <string>
#include <cctype> // 字符处理函数using std::cout;
using std::endl;
using std::string;int main()
{string s = "Hello, World!";// 范围for循环处理每个字符(C++11)for (auto c : s) {cout << c << " ";}cout << endl;// 使用引用修改字符串for (auto &c : s) {c = std::toupper(c); // 转换为大写}cout << "大写: " << s << endl;// 使用下标运算符s[0] = 'h'; // 修改第一个字符cout << "修改后: " << s << endl;// 统计标点符号数量string text = "Hello, World!!!";int punct_count = 0;for (auto c : text) {if (std::ispunct(c)) {punct_count++;}}cout << "标点符号数量: " << punct_count << endl;return 0;
}
3.3 标准库类型vector
vector
表示对象的集合,所有对象的类型都相同,是动态数组的现代替代品。
定义和初始化vector
#include <iostream>
#include <vector> // 必须包含vector头文件using std::cout;
using std::endl;
using std::vector;
using std::string;int main()
{// 各种初始化方式vector<int> ivec; // 空vector,保存intvector<string> svec; // 空vector,保存string// 列表初始化(C++11)vector<int> v1 = {1, 2, 3, 4, 5};vector<string> v2 = {"hello", "world"};// 创建指定数量的元素vector<int> v3(10, 1); // 10个1vector<string> v4(5, "hi"); // 5个"hi"// 值初始化vector<int> v5(10); // 10个0vector<string> v6(10); // 10个空stringcout << "v1大小: " << v1.size() << endl;cout << "v3大小: " << v3.size() << endl;return 0;
}
向vector添加元素
#include <iostream>
#include <vector>using std::cout;
using std::endl;
using std::vector;int main()
{vector<int> v;// 使用push_back添加元素for (int i = 0; i < 10; i++) {v.push_back(i * i); // 添加平方数}cout << "vector大小: " << v.size() << endl;cout << "vector内容: ";for (auto i : v) {cout << i << " ";}cout << endl;// 读取成绩并统计分数段vector<unsigned> scores(11, 0); // 11个分数段,初始为0unsigned grade;// 模拟输入成绩vector<unsigned> grades = {42, 65, 95, 100, 39, 67, 95, 76, 88, 76, 83, 92, 76};for (auto g : grades) {if (g <= 100) {++scores[g/10]; // 对应分数段计数加1}}cout << "分数段统计:" << endl;for (int i = 0; i < scores.size(); i++) {cout << i * 10 << "-" << i * 10 + 9 << ": " << scores[i] << endl;}return 0;
}
vector操作
#include <iostream>
#include <vector>using std::cout;
using std::endl;
using std::vector;int main()
{vector<int> v = {1, 2, 3, 4, 5};// 访问元素cout << "v[0]: " << v[0] << endl;cout << "v.front(): " << v.front() << endl; // 第一个元素cout << "v.back(): " << v.back() << endl; // 最后一个元素// 修改元素v[0] = 10;v.back() = 50;// 添加和删除元素v.push_back(6); // 在末尾添加v.pop_back(); // 删除末尾元素cout << "修改后: ";for (auto i : v) {cout << i << " ";}cout << endl;// 比较vectorvector<int> v2 = {10, 2, 3, 4, 50};cout << "v == v2: " << (v == v2) << endl;return 0;
}
3.4 迭代器介绍
迭代器提供了一种通用的机制来访问容器中的元素。
使用迭代器
#include <iostream>
#include <vector>
#include <string>using std::cout;
using std::endl;
using std::vector;
using std::string;int main()
{string s = "hello world";vector<int> ivec = {1, 2, 3, 4, 5};// 使用迭代器遍历stringcout << "字符串字符: ";for (auto it = s.begin(); it != s.end(); ++it) {cout << *it << " ";}cout << endl;// 使用迭代器遍历vectorcout << "vector元素: ";for (auto it = ivec.begin(); it != ivec.end(); ++it) {cout << *it << " ";}cout << endl;// 迭代器类型vector<int>::iterator it1; // 可读写vector<int>的元素vector<int>::const_iterator it2; // 只能读,不能写// 使用迭代器修改元素for (auto it = ivec.begin(); it != ivec.end(); ++it) {*it *= 2; // 每个元素乘以2}cout << "修改后: ";for (auto it = ivec.begin(); it != ivec.end(); ++it) {cout << *it << " ";}cout << endl;return 0;
}
迭代器运算
#include <iostream>
#include <vector>using std::cout;
using std::endl;
using std::vector;int main()
{vector<int> ivec = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};// 使用迭代器进行二分搜索int target = 5;auto beg = ivec.begin();auto end = ivec.end();auto mid = beg + (end - beg) / 2; // 中间点while (mid != end && *mid != target) {if (target < *mid) {end = mid;} else {beg = mid + 1;}mid = beg + (end - beg) / 2;}if (mid != end) {cout << "找到 " << target << " 在位置 " << (mid - ivec.begin()) << endl;} else {cout << "没有找到 " << target << endl;}return 0;
}
3.5 数组
数组是固定大小的同类元素集合。
定义和初始化数组
#include <iostream>using std::cout;
using std::endl;int main()
{// 数组声明int arr1[10]; // 10个整数的数组,未初始化int arr2[5] = {1, 2, 3}; // 前3个元素初始化,后2个为0int arr3[] = {1, 2, 3, 4}; // 维度为4的数组// 字符数组char ca1[] = {'C', '+', '+'}; // 维度3,没有空字符char ca2[] = {'C', '+', '+', '\0'}; // 维度4,显式空字符char ca3[] = "C++"; // 维度4,自动添加空字符// 数组不允许拷贝和赋值// int arr4[] = arr3; // 错误!不能用一个数组初始化另一个数组// 复杂的数组声明int *ptrs[10]; // ptrs是含有10个整型指针的数组int (*Parray)[10] = &arr2; // Parray指向一个含有10个整数的数组int (&arrRef)[5] = arr2; // arrRef引用一个含有5个整数的数组cout << "arr2[0]: " << arr2[0] << endl;cout << "arr2[4]: " << arr2[4] << endl;return 0;
}
访问数组元素
#include <iostream>using std::cout;
using std::endl;int main()
{int scores[] = {95, 87, 72, 64, 98, 56, 83, 91, 76, 88};// 使用范围for循环(C++11)cout << "所有分数: ";for (auto score : scores) {cout << score << " ";}cout << endl;// 使用下标int total = 0;for (size_t i = 0; i < 10; ++i) {total += scores[i];}cout << "平均分: " << total / 10.0 << endl;// 统计不及格人数int fail_count = 0;for (auto score : scores) {if (score < 60) {++fail_count;}}cout << "不及格人数: " << fail_count << endl;return 0;
}
指针和数组
#include <iostream>using std::cout;
using std::endl;int main()
{int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};// 数组名在很多情况下会被转换成指针int *p = arr; // p指向arr的第一个元素cout << "*p: " << *p << endl; // 0cout << "p[1]: " << p[1] << endl; // 1cout << "*(p + 3): " << *(p + 3) << endl; // 3// 指针运算int *end = &arr[10]; // 指向arr尾后位置的指针for (int *ptr = arr; ptr != end; ++ptr) {cout << *ptr << " ";}cout << endl;// 标准库函数begin和end(C++11)int *beg = std::begin(arr); // 指向arr首元素的指针int *last = std::end(arr); // 指向arr尾后位置的指针// 使用指针遍历数组cout << "使用指针遍历: ";for (int *ptr = beg; ptr != last; ++ptr) {cout << *ptr << " ";}cout << endl;return 0;
}
C风格字符串
#include <iostream>
#include <cstring> // C风格字符串函数using std::cout;
using std::endl;int main()
{const char str1[] = "Hello";const char str2[] = "World";// C风格字符串函数char result[20];std::strcpy(result, str1); // 拷贝str1到resultstd::strcat(result, " "); // 拼接空格std::strcat(result, str2); // 拼接str2cout << "拼接结果: " << result << endl;cout << "字符串长度: " << std::strlen(result) << endl;cout << "比较str1和str2: " << std::strcmp(str1, str2) << endl;return 0;
}
📝 第三章关键要点总结
-
string vs C风格字符串:
- 优先使用
string
,更安全、更方便 string
自动管理内存,支持动态增长
- 优先使用
-
vector vs 数组:
- 优先使用
vector
,更灵活、更安全 vector
支持动态增长,数组大小固定
- 优先使用
-
迭代器:
- 提供统一的容器访问接口
begin()
指向第一个元素,end()
指向尾后位置- 支持
++
、--
、*
等操作
-
现代C++特性:
- 范围
for
循环:for (auto x : container)
- 列表初始化:
{1, 2, 3}
auto
类型推断
- 范围
这一章的内容非常实用,string
和vector
是现代C++编程中最常用的工具之一。多练习使用它们,会让你后续的学习轻松很多!