[数据结构·C++语法] 处理未知长度或多组数据
针对你在期末考试或 LeetCode 刷题中遇到的“未知长度多组数据录入”的情况,C++ 有几种标准的处理模式。
C++ 处理未知长度/多组数据录入的常用模板
在数据结构考试或算法题(OJ/LeetCode)中,通常没有明确告诉你“一共有多少个数字”,而是说“直到输入结束”或“输入为0时停止”。以下是标准解决方案:
1. 利用 cin 的返回值 (C++ 标准写法)
cin >> x 表达式在 C++ 中会返回输入流对象本身。在 while 循环条件中,它会被隐式转换为 bool 类型。
- 如果读取成功,返回
true。 - 如果遇到 EOF (End Of File) 或格式错误,返回
false。
场景 A:每次读取一个数
1 | int x; |
int a, b;
// 只有当 a 和 b 都成功读取时,才进入循环
while (cin >> a >> b) {
// 处理边 (a, b)
addEdge(a, b);
}1
2
3
4
5
6
7
8
9
## 2. 利用 `scanf` 的返回值 (C 语言风格 / 高性能)
在输入数据量极大(超过 $10^5$ 级别)时,scanf 比 cin 快。
scanf 返回成功读取的变量个数。如果遇到文件结束符,它会返回宏 EOF (通常是 -1)。
C++
int x;
// 只要返回值不等于 EOF,就说明还有数据
while (scanf("%d", &x) != EOF) {
// 处理 x
process(x);
}1
2
3
4
5
6
7
## 3. 特定停止条件 (Sentinel Value)
有时候题目会规定:“输入 0 结束”或“输入 -1 结束”。
C++
int x;
while (cin >> x && x != 0) {
// 注意:这里的逻辑是,读取了 x,且 x 不为 0 时才进入
// 如果输入 0,循环直接终止
process(x);
}1
2
3
4
5
6
7
## 4. 整行读取 (针对字符串)
如果你需要读入一行带空格的字符串,直到文件结束。
C++
string line;
while (getline(cin, line)) {
// line 中包含了整行内容(不含换行符)
process(line);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
---
## ⚠️ 重要提示:在本地 IDE 如何结束输入?
在 LeetCode 或学校 OJ 上,系统会自动发送 EOF 信号。但在你本地的 VSCode 或 CLion 的控制台里,程序会一直等待输入。你需要手动输入 **EOF**:
- **Windows:** 输入完数据后,按 `Ctrl + Z`,然后回车。
- **Mac / Linux:** 输入完数据后,按 `Ctrl + D`。
---
## 🔥 实战应用:未知长度数据构建链表
结合你正在复习的链表,这是考试中建立链表的标准模板(使用**尾插法**,保证链表顺序与输入顺序一致):
C++
include
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(nullptr) {}
};
int main() {
// 1. 创建虚拟头节点 (Dummy Head),简化操作
ListNode dummyHead = new ListNode(0);
ListNode tail = dummyHead; // tail 永远指向链表最后一个节点
int val;
std::cout << "请输入一组整数 (Windows按Ctrl+Z结束, Mac按Ctrl+D结束):" << std::endl;
// 2. 核心循环:读取直到 EOF
while (std::cin >> val) {
ListNode* newNode = new ListNode(val);
tail->next = newNode; // 链接
tail = newNode; // 更新尾指针
}
// 3. 此时链表构建完成,头节点是 dummyHead->next
ListNode* realHead = dummyHead->next;
// (可选) 遍历打印验证
ListNode* p = realHead;
while (p != nullptr) {
std::cout << p->val << " -> ";
p = p->next;
}
std::cout << "NULL" << std::endl;
return 0;
}
```
