C++ 如何固定一个 array 的元素并遍历另一个 vector 查找匹配项?
技术老齐
可以用嵌套循环查找共同车型:外层依次取出 mycars 中的车型,内层遍历 yourcars。找到相同车型后输出,再用 break 退出内层循环,继续检查下一个车型。
带空格的名称需要用 std::getline(std::cin, yourcar) 读取整行。执行 std::cin >> n 后,要先清除当前行剩余的内容,再读取车型。
原代码的问题
原来的比较方式:
mycars[i] == yourcars.at(i)
只比较两个容器中位置相同的元素。如果 "911 targa" 在两个列表中的位置不同,就找不到匹配。两个容器长度不同时,还可能发生越界访问。
输入部分也有两个问题:
getline(cin, yourcar, ' ');
cin >> yourcar;
getline的第三个参数是分隔符。指定' '后,读取会在遇到空格时停止。- 随后的
cin >> yourcar会再次读取并覆盖yourcar,同样无法读入完整的带空格名称。
cin >> n 通常还会留下用户按回车产生的换行符。此时直接调用 getline,第一次读到的可能就是空字符串。
修改后的完整代码
代码保留原来的普通数组,用范围 for 循环遍历,需要 C++11 或更高版本。
#include <iostream>
#include <limits>
#include <string>
#include <vector>
int main() {
const std::string mycars[] = {
"MX5", "560sec", "560sl", "sl65", "lp500",
"f40", "demon", "6*6", "g550 cab", "u5000",
"slk500", "sl600", "lc79", "sls", "slr",
"valkyrie", "cls", "911 targa", "firebird"
};
std::vector<std::string> yourcars;
std::cout << "My dream cars are:\n";
for (const auto& car : mycars) {
std::cout << car << '\n';
}
int n = 0;
std::cout << "\nHow many dream cars do you have?\n";
if (!(std::cin >> n) || n < 0) {
std::cerr << "Please enter a non-negative integer.\n";
return 1;
}
// 丢弃数量所在行的剩余内容,包括换行符。
std::cin.ignore(
std::numeric_limits<std::streamsize>::max(), '\n'
);
// 每行输入一个完整的车型名称。
for (int i = 0; i < n; ++i) {
std::string yourcar;
std::cout << "Enter dream car " << i + 1 << ":\n";
if (!std::getline(std::cin, yourcar)) {
std::cerr << "Failed to read a car name.\n";
return 1;
}
yourcars.push_back(yourcar);
}
bool foundAny = false;
for (const auto& mycar : mycars) {
for (const auto& yourcar : yourcars) {
if (mycar == yourcar) {
std::cout << "We both share a dream car! It is: "
<< mycar << '\n';
foundAny = true;
break;
}
}
}
if (!foundAny) {
std::cout << "We do not share any dream cars.\n";
}
return 0;
}
嵌套循环如何完成匹配
外层循环每次取出一个车型,赋给 mycar。内层循环再逐个取出 yourcars 中的元素,与当前的 mycar 比较:
for (const auto& mycar : mycars) {
for (const auto& yourcar : yourcars) {
if (mycar == yourcar) {
// 找到了当前车型。
break;
}
}
}
break 只退出最近一层循环,所以找到匹配后,外层循环会继续处理下一个 mycar。即使用户重复输入同一车型,当前 mycar 也只会输出一次。
foundAny 用来记录整个比较过程中是否找到过匹配。只有完成所有比较,才能判断是否需要输出“没有共同车型”。某一对元素不相等,不能说明两个列表完全没有交集。
例如,依次输入:
3
911 targa
MX5
other car
比较部分会按 mycars 的顺序输出:
We both share a dream car! It is: MX5
We both share a dream car! It is: 911 targa
还需要注意什么
- 不需要
n++。用户输入多少辆车,循环就读取多少行。 - 原数组有 19 个元素,
i < 18会漏掉最后一个。范围for循环可以直接遍历全部元素。 - 原代码在
main开头声明的int i;没有初始化。for (int i = ...)中的i是另一个局部变量,因此后面的if (i > yourcars.size())使用了未初始化的值,应删除这套分支。 std::string的==比较区分大小写,也会比较空格。"MX5"与"mx5"不相等,getline保留的名称首尾空格也会影响匹配。- 输入时,数量和每个车型名称各占一行。读取数量后调用一次
ignore,之后连续使用getline即可。
备注:内容仅供参考。
