0

So I have a .txt file that I'm pushing into a vector, and that's worked all right. I'm trying to take user input (string), and find a match in the vector. This i my code so far:

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <list>

using namespace std;

struct customer{
  string name;
  float disc;
};

class customer_list {
  vector<customer> custlist;

public:
  void load(string fname){
   ifstream list;
   list.open ("customers.txt");
   customer c;
   double val = 0;
   if (list.is_open()){
     while (! list.eof() ){
       list >> c.name;
       custlist.push_back(c);
       list >> c.disc;
       custlist.push_back(c);
       val++;
     }
   }
     list.close();
     int val2 = custlist.size()/val;

     for (int j=0; j < custlist.size() - 2; j+= val2){
         cout << " Name: " << custlist[j].name << endl;
         cout << " Discount: " << custlist[j+1].disc << endl;
     }
  }


bool in_list(string & query){ //return true if query in list, false otherwise
  if (find (custlist.begin(), custlist.end(), query) !=custlist.end()){
    cout << "Welcome back," << query << "." <<endl;
    return true;
  }else{
    cout << "No Matches found." << endl;
    return false;
  }
 }
};

int main (){

customer_list a;
string name;

a.load("customers.txt");

cout << "What is your name?" << endl;
cin >> name;

a.in_list(name);
}

I get this error when run:

In file included from prt2.cpp:1:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iostream:38:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ios:216:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__locale:15:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string:439:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:865:22: error: invalid operands
      to binary expression ('customer' and 'const std::__1::basic_string<char>')
        if (*__first == __value_)
            ~~~~~~~~ ^  ~~~~~~~~
prt2.cpp:46:15: note: in instantiation of function template specialization 'std::__1::find<std::__1::__wrap_iter<customer *>,
      std::__1::basic_string<char> >' requested here
          if (find (custlist.begin(), custlist.end(), query) !=custlist.end()){
              ^
1 error generated.

Any help appreciated! Thanks.

  • 1
    Well, the first thing I'd fix is this `while (! list.eof() )`; [**its wrong**](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong). – WhozCraig May 16 '15 at 18:09
  • Can you explain how it's wrong? Because if I take out the void in_list and run it without mentioning that void it works. – SwizzleStix617 May 16 '15 at 18:13
  • Ahhhh. That's smart; I hadn't realized that. Thank you. And I'm sorry I didn't realize that was a link; I'm new here :). So generally the while statement should be while ( .txt << can still be read) { do all this code } – SwizzleStix617 May 16 '15 at 18:22

3 Answers3

1

Your find is comparing apples to oranges. The search value sought with std::find must be of the same or convertible to, the type of the sequence, That isn't strictly true, but usually is practiced. You can circumvent that with an equivalence operator that compares the two values (operator ==), even if they're different types, but that madness really isn't needed. Regardless, you're searching for a std::string in a customer-filled jungle.

You can step around that by using other search methods, such as std::find_if and a custom qualifying lamda expression:

Like this:

bool in_list(const string & s)
{
    if (std::find_if(custlist.begin(), custlist.end(),
            [&s](const customer& c) { return c.name == s; }) != custlist.end())
    {
        cout << "Welcome back," << s << "." <<endl;
        return true;
    }

    cout << "No Matches found." << endl;
    return false;
}

There are other ways, of course.

Anyway, best of luck.

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • May I ask what the [&s] is doing on the 4th line? – SwizzleStix617 May 16 '15 at 18:37
  • Its capturing the `s` reference into the lambda so it can be used within the body of the comparator we' writing. [Read more about lambda's here](http://en.cppreference.com/w/cpp/language/lambda). In short, its what makes `c.name == s;` possible. Without it, the compiler wouldn't know what `s` was inside that function. – WhozCraig May 16 '15 at 18:40
0

You need to include : #include <algorithm>

to use std::find correctly.

And it will works.

You can also improuve this part of your code :

   if (list.is_open()){
 while (! list.eof() ){
   list >> c.name;
   custlist.push_back(c);
   list >> c.disc;
   custlist.push_back(c);
   val++;
 }}

By using this:

   if (list.is_open()){
 while (! list.eof() ){
   list >> c.name;
   list >> c.disc;
   custlist.push_back(c);
   val++;
 }}

because you use 2 elem of your vector to store only one elem, example if you have yop 42.42, you will have in your vector :

  • vector[0].name = "yop";
  • vector[0].disc = undifined_value;
  • vector[1].name = "";
  • vector[1].disc = 42.42;

After the correction you will have:

  • vector[0].name = "yop";
  • vector[0].disc = 42.42;

To use the function std::find on a structure you have to add also this function :

bool operator==(const customer &c, const string &name){
return (c.name == name);
}

std::find will call this function to check the values.

ar-ms
  • 735
  • 6
  • 14
0

You simply need to use operator overloading, for you are using vectors with customized type, however the method std::find() in vector can only compare value in primitive types. Try the following function:

bool operator ==(const customer_list& other) const{
  return other.name==this->name;
}