① 程序设计基础 — 第 4 课
string(字符串)和 vector(动态数组)。它们的共同点是:长度自己会涨,还知道自己是多长。
string 就是能自动变长的字符数组,+ 拼接。vector 就是能自动变长的数组,push_back 往后加。.size() 数长度、[i] 取元素,学一个会两个。原生 C 风格字符串 char s[100] 容易越界、操作麻烦。C++ 的 string 是正道:
#include <string> // 别忘了!
string s = "hello";
string t = " world";
string u = s + t; // 拼接!cout << u → "hello world"
cout << s.length(); // 长度:5
cout << s[0]; // 单个字符:'h'(索引从 0 开始)
cout << s.back(); // 最后一个字符:'o'
| 操作 | 代码 | 说明 |
|---|---|---|
| 长度 | s.length() | 字符个数 |
| 拼接 | s + t 或 s += t | 直接加号 |
| 比较 | s == t | 内容相等就 true |
| 取子串 | s.substr(2, 3) | 从下标 2 开始取 3 个 |
| 查找 | s.find("lo") | 返回下标,找不到返 string::npos |
| 清空 | s.clear() | 变回空串 |
| 是否空 | s.empty() | 空串返回 true |
| 末尾加 | s.push_back('!') | 加一个字符 |
string s = "hello";
for (int i = 0; i < s.length(); i++) {
cout << s[i] << " "; // h e l l o
}
// C++ 专属:range-based for(更简洁)
for (char c : s) {
cout << c << " "; // h e l l o
}
cin >> s 读到空格就停。要读一行用 getline(cin, s)。
原生数组 int a[100] 的三个问题 vector 全解决了:
#include <vector>
vector<int> v; // 空的
v.push_back(3); // 往后加:v = {3}
v.push_back(7); // v = {3, 7}
v.push_back(1); // v = {3, 7, 1}
cout << v.size(); // 3(动态大小!)
cout << v[1]; // 7(跟数组一样用)
v.pop_back(); // 删掉最后一个:v = {3, 7}
| 操作 | 代码 |
|---|---|
| 声明 | vector<int> v; |
| 声明+大小 | vector<int> v(5);(5 个 0) |
| 声明+初始值 | vector<int> v(5, -1);(5 个 -1) |
| 末尾加 | v.push_back(x); |
| 末尾删 | v.pop_back(); |
| 大小 | v.size() |
| 清空 | v.clear() |
| 最后元素 | v.back() |
| 首元素 | v.front() |
vector<int> v = {3, 1, 4, 1, 5};
for (int i = 0; i < v.size(); i++) {
cout << v[i] << " "; // 经典方式
}
for (int x : v) { // 更简洁(range-based for)
cout << x << " ";
}
| 原生数组 | vector | |
|---|---|---|
| 大小 | 写死 a[100] | 动态增长 |
| 知道大小? | 需要手动记 | .size() |
| 越界 | 不报错 | 不报错 |
| 何时用 | 大小确定不变 | 绝大多数情况 |
vector,只有明确知道大小且固定时用数组。vector 不会浪费什么性能,省心太多。
int n;
cin >> n;
vector<int> v(n);
for (int i = 0; i < n; i++) cin >> v[i];
for (int i = n - 1; i >= 0; i--) cout << v[i] << " ";
string s;
cin >> s;
bool ok = true;
for (int i = 0; i < s.length() / 2; i++) {
if (s[i] != s[s.length() - 1 - i]) {
ok = false;
break;
}
}
cout << (ok ? "是回文" : "不是回文") << endl;
cin >> s 读不到空格:带空格的整行必须用 getline(cin, s),否则只拿到第一个词。substr(2, 3) 的 3 是「取几个」:不是结束下标,取出来是下标 2、3、4 三个字符。find 找不到返回 string::npos:判断要写 != string::npos,别拿它当普通下标。vector<int> v(5) 已经开好了 5 个 0:这时再 push_back 是第 6 个元素,不是给前 5 个赋值。string s = "abc"; s.push_back('d'); 后 s 是什么?vector<int> v; v.push_back(1); v.pop_back(); cout << v.size(); 输出?cin >> s 输入 "hello world",s 是什么?getline),统计其中大写字母、小写字母和数字各有多少个。Hello123 → 输出:大写 1,小写 4,数字 3isupper(c), islower(c), isdigit(c) 需要 #include <cctype>。
6 → 3 1 4 1 5 4 → 输出 3 1 4 5
卡住时的自查顺序
cout << s; 看看空格后面的内容在不在。for (char c : s) 还是下标?两种都可以,但别再写 i <= s.length() 这种越界条件。int up; 的话,加出来的数是垃圾值。string:+ 拼接、.length()、.substr()、.find(),告别字符数组。vector:.push_back()、.pop_back()、.size(),大小自由增长。for (char c : s) 和 for (int x : v),遍历更简洁。s[0] 是第一个字符,v[v.size() - 1] 是最后一个。vector:只有大小确定且固定时才用原生数组。string、vector 打交道,把它们当数组用就对了。哪一句还不明白 —— 比如「length() 和 size() 有区别吗」「getline 为什么会读到空行」「vector 和数组到底差在哪」—— 直接问。