STL - how to find object in list?

Hello!
I have a problem with my code. I have class named Book. When i put objects of class Book to the list i'm doin it like this for ex:

1
2
3
4
5
list<Book>l;
Book b1("Title","number","Y","keyword","Author","year of issue");
l.push_back(b1);
...
...


When i fill it up, i have to find an object which has number=100 (b1.number==100) i can't get into object's fields, don no how to do it. After i find it, i need to change value from "Y" to "N" in list. I was tryin by find or find_if but it never worked, dont know how to write a predicate, any ideas?
Last edited on
A predicate must be either a static function or an object with () overloaded.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class BookNumber100PredObj {
  public:
    bool operator () ( const Book &book ) {
      return book.number == 100;
      }
  };

bool BookNumber100PredFn( const Book &book ) {
  return book.number == 100;
  }

...

list<Book>::iterator found = find_if( l.begin(), l.end(), BookNumber100PredObj() );

or

list<Book>::iterator found = find_if( l.begin(), l.end(), BookNumber100PredFn );


I presume that number is an integer in the above code. However, your constructor seems to think that number is a string. Make sure you test correctly.

Hope this helps.
Last edited on
Thanx!
But is it possible to make that 100 as a parameter to the function? like BookNumber100PredObj(150) - which gonna find book with field number==150?
Where should i paste the code? Before or after my class where i want to use that predicate?
And i have errors when i'm tryin to test it :-(
1
2
3
4
expected `,' or `...' before '&' token 
ISO C++ forbids declaration of `Book' with no type 
In member function `bool BookNumber100PredObj::operator()(int)':
`book' undeclared (first use this function) 

And what do i have to do when find_if give me iterator to that object to change the value of field book.avaible=="Y" to book.avaible=="N"?
Last edited on
Yes, it is possible, but doing so is fairly advanced and you still seem confused about using find_if().

I'll give you the advanced answer, but if this is homework be aware that your professor will probably fail you if you turn it in (because it is far advanced over what you know right now).

C++ is an "imperative" language. There is another paradigm called "functional". The STL provides some functional constructs. In the functional terminology, a "predicate" is a function that returns true or false based upon its arguments. There are unary predicates (takes one argument) and binary predicates (takes two arguments), etc.

The find_if() algorithm takes a unary predicate. The argument is of type "book" and the predicate returns true if the book's number field matches some specified number (hard-coded into the predicate function).

However, you want to use a binary predicate, where you specify both the book and the number to find. Fortunately, the STL provides a nifty little template function that takes a binary predicate and turns it into a unary predicate. (This is the functional part, because it is doing functional composition, called "currying".) The compositor function is called bind2nd() (that is, bind the second argument into the binary predicate to produce a unary predicate). It takes a little bit for this to sink-in.

So, the goal is to produce what the STL calls an "Adaptable Binary Predicate" (which is a fancy way of saying a binary template function that can be used to produce a unary function. It actually takes _three_ template arguments, because the return type must be specified also... but it still is just a binary predicate). Here's an "adaptable" binary predicate:
1
2
3
4
5
6
7
#include <functional>

struct BookNumber: public std::binary_function< Book, int, bool > {
  bool operator () ( const Book &book, const int &number ) const {
    return book.number == number;
    }
  };

Now that we have that out of the way, we can use it to actually find a specific book:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <list>

...

// The list of books
std::list<Book> books;

...

// Ask the user what book number to find
int number;
std::cout << "What number of book would you like to find? ";
std::cin >> number;

// Find and print every book with the specified number
int num_books_found = 0;
std::list<Book>::iterator result = books.begin();
while (true) {
  result = std::find_if( result, books.end(), std::bind2nd( BookNumber(), number ) );
  if (result == books.end()) break;

  num_books_found++;
  std::cout << setw( 3 ) << num_books_found << ": " << *result << std::endl;

  result++;
  }



I hope this hasn't been a waste of your time.
Last edited on
Topic archived. No new replies allowed.