!= string::npos
is not the correct condition. find_if
returns an iterator to the first element satisfying the condition or last
if no such element is found. last
is in your case input.end()
.
You read the fields by getline
, but when you enter the search string, you use formatted input (breaking on space). If the field contained a space in the file, you'd never be able to find it.
To make input/output easier, consider adding operator <<
and >>
to your class. Your current while(!inFS.fail())
condition does not work. If you read the last Records
struct from the file, fail()
will not be true and you'll therefor try to read one complete Records
(but failing on every line). You'll still add the erroneous Records
struct to the vector
.
As an alternative to the other suggestions using a lambda (which is nice) you could also add operator==
to your Records
- if you only want to be able to search for the same thing.
Also, read Why is “using namespace std;” considered bad practice?
Example:
#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";
}
}
}