在结构向量中搜索一个数据成员,然后打印匹配的所有数据成员

Searching a vector of structs for one data member, then printing all data members that match

本文关键字:数据成员 打印 然后 一个 向量 结构 搜索      更新时间:2023-10-16

>我正在尝试搜索csv文件以打印以特定名称找到的数据。 我已经尝试了在这个网站上找到的多个建议,但由于我不断出现错误,似乎没有任何效果。可能是因为我不太明白为什么我的代码不起作用,所以我非常感谢解释。我的代码可以在下面找到:

code removed

首先,你的while循环条件没有错,但可以通过使用运算符bool来简化:

while(inFS)
{
...
}

其次,您对std::find_if的使用不正确。第三个参数必须是签名bool(Record)的可调用对象(可能是const或 ref 限定的(,并将迭代器返回到第一个匹配项。

从您的变量名称和字符串中,我想您想搜索向量中的Records::recip成员。std::find_if是实现此目的的好方法:

auto comp = [&search](Record const& r) { return r.receip == search; };
for (auto it = std::find_if(input.begin(), input.end(), comp);
it != input.end();
it = std::find_if(++it, input.end(), comp))
{
// this loop iterates over all matches for search in Record::receip
Record& record = *it;
std::cout << record << 'n';
}

您使用find_if的方式不正确,您需要使用 lambda 在结构向量中进行自定义搜索。这是更直接的方法:

for(const Record& record : input) // Iterate all records
{
if(record.recip == search) // Check if 'recip' of the record matches the requested one
{
cout << "found";
return 0;
}
}
!= string::npos

不是正确的条件。find_if将迭代器返回到满足条件的第一个元素,如果未找到此类元素,则返回lastlast在你的情况下input.end().

您按getline读取字段,但在输入搜索字符串时,使用格式化输入(空格中断(。如果该字段在文件中包含空格,您将永远无法找到它。

若要简化输入/输出,请考虑将运算符<<>>添加到类中。您当前的while(!inFS.fail())条件不起作用。如果您从文件中读取最后一个Records结构,则fail()将不正确,因此您将尝试读取一个完整的Records(但每一行都失败(。您仍会将错误的Records结构添加到vector中。

作为使用 lambda 的其他建议的替代方案(这很好(,您也可以在Records中添加operator==- 如果您只想能够搜索相同的东西。

另请阅读为什么"使用命名空间 std;"被认为是不好的做法?

例:

#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
struct Records {
std::string year{};
std::string category{};
std::string won{};
std::string recip{};
// added operator to be able to compare a Records with a string
bool operator==(const std::string& Recip) const { return recip == Recip; }
};
// custom streaming operator for reading one `Records` from a stream (like a file)
std::istream& operator>>(std::istream& is, Records& r) {
std::getline(is, r.year, ',') && std::getline(is, r.category, ',') &&
std::getline(is, r.won, ',') && std::getline(is, r.recip);
return is;
}
// custom streaming operator to write a `Records` to a stream
std::ostream& operator<<(std::ostream& os, const Records& r) {
return os << r.year << 'n' << r.category << 'n' << r.won << 'n' << r.recip << 'n';
}
int main() {
std::ifstream inFS("oscars.csv");
if(!inFS) { // in boolean context, inFS will be false if not opened
std::cout << "Failed to open file.n";
return 1;
}
std::vector<Records> input;
Records awardIn;
// use the custom operator>> to extract a "Records" from the file and push it back
// inFS will be false in boolean context if the extraction failed
while(inFS >> awardIn)
input.push_back(awardIn);
std::string search;
std::cout << "Enter recipient: ";
if(std::getline(std::cin, search)) { // check that reading succeed
// with the added operator== you can use a normal std::find
for(auto it = std::find(input.begin(), input.end(), search);
it != input.end(); 
it = std::find(std::next(it), input.end(), search)) 
{
// use the custom operator<< to print the Records
std::cout << *it << "n";
}
}
}