Working with std::algorithm functions

Hi,
Here is the drills of chapter 21 of the book Programming Principles and Practice Using C++ 2nd Ed:
https://s7.postimg.org/s585rhtor/Capture.png

I'm on the drill 6 and have written the code below for that:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <std_lib_facilities_4.h>
using namespace std;

struct Item {	
	bool operator()(const Item& Ix, const Item& Iy) const
	{
		double vx = Ix.value;
		double vy = Iy.value;
		if (vx <= vy) return true; // vx <= vy
	    return false; 
	}

	string name;
	int iid;
	double value;
};

//***************************

int main()
{
	vector<Item> vi;
	ifstream rfile("input.txt");

	if (!rfile) {
		cout << " Failar on opening the file!\n\n";
		system("pause");
		return 1;
	}

	string s;
	int id;
	double value;

	for (size_t i = 0; i < 10; ++i) {
		rfile >> s >> id >> value;
		vi.push_back({ s, id, value });
	}

	sort(vi.begin(), vi.end(), Item());
	reverse(vi.begin(), vi.end());
	
	vi.insert(vi.begin(), { "horse shoe", 99, 12.34 });
	vi.insert(vi.begin(), { "Canon S400", 9988, 499.95 });

	for (auto i = vi.begin(); i < vi.end(); ++i)
		if (i->name == "Tom") {
			vi.erase(i);
			break;
		}
	for (auto i = vi.begin(); i < vi.end(); ++i)
		if (i->name == "Ted") {
			vi.erase(i);
			break;
		}

	for (const auto& v : vi)
		cout << v.name << "  " << v.iid << "  " << v.value << endl;

	cout << "\n";

	system("pause");
	return 0;
}

Please note the two for loops I've used for finding the two items for erasing. It works but I feel that there might be some better way instead of those loops. I tried using the find-if function but it didn't support the '==' operator.

How would you do that drill please?
The solution can also be used for the next drill (7) too.
Last edited on
I tried using the find-if function but it didn't support the '==' operator
You need to overload the == operator in your Item class.

Also it would be a good idea to post your input file.
Thanks for the reply.
This is the content of the input.txt file:

Tom 12 87.2
Jerry 18 65.5
Frank 17 88.12
Jeison 9 83.32
Kate 5 90.5
Loius 3 92.14
Crise 7 94.67
Abbasi 2 99.25
James 1 54.36
Ted 8 75.24
You can actuall remove both items in one loop:
1
2
3
4
5
6
7
8
9
for (auto it = vi.begin(); it != vi.end(); ++it)
{
  if(it->name == "Tom" || it->name == "Ted")
  {
    it = vi.erase(it);
    if (it == vi.end()) // check for last elem
      break;
  }
}
It would probably be better to use the less error prone erase-remove idiom:
https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom
And I think I can use a function object instead of is_odd here:
v.erase( std::remove_if(v.begin(), v.end(), is_odd), v.end() );
with an overloaded operator '=='! Rather complicated as before!

Thanks.
Last edited on
You may use lambda functions:

v.erase( std::remove_if(v.begin(), v.end(), [](const Item &i) { return (i.name == "Tom" || i.name == "Ted"); }), v.end() );
Thank you. It's very handy.
What if I use an std::list instead of the std::vector in the code?
I used it and got 5 errors on algorithm::sort()!

algorithm::sort() takes Random Access Iterators as its arguments.

Are the errors because std::vector::begin and std::vector::end return Random Access Iterators and std::list::begin and std::list::end return Bidirectional Iterators?
Last edited on
Are the errors because std::vector::begin and std::vector::end return Random Access Iterators and std::list::begin and std::list::end return Bidirectional Iterators?
Yes, sort requires Random Access Iterators

To sort a list you can use the sort function of the list.
So it's easier than converting Bidirectional Iterators to Random Access Iterators, yeah?
You can't convert Bidirectional Iterators to Random Access Iterators AFAIK
list.sort is the way to go.
I used this code but it doesn't work as expected:
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <std_lib_facilities_4.h>
using namespace std;

struct Item {	
	bool operator()(const Item& Ix, const Item& Iy) const
	{
		double vx = Ix.value;
		double vy = Iy.value;
		if (vx <= vy) return true; // vx <= vy
	    return false; 
	}

	string name;
	int iid;
	double value;
};

//***************************

int main()
{
	list<Item> li;
	ifstream rfile("input.txt");

	if (!rfile) {
		cout << " Failar on opening the file!\n\n";
		system("pause");
		return 1;
	}

	string s;
	int id;
	double value;

	for (size_t i = 0; i < 10; ++i) {
		rfile >> s >> id >> value;
		li.push_back({ s, id, value });
	}
	
	li.sort(Item());
	reverse(li.begin(), li.end());
	
	li.insert(li.begin(), { "horse shoe", 99, 12.34 });
	li.insert(li.begin(), { "Canon S400", 9988, 499.95 });

	cout << "Size = " << li.size() << "\n\n";

	  // Using lambda expression and the remove_if helper function
	li.erase(remove_if(li.begin(), li.end(), 
		[](const Item& i) { return (i.iid == 3 || i.iid == 5); })
		, li.end() );    

	for (const auto& l : li)
		cout << l.name << "  " << l.iid << "  " << l.value << endl;

	cout << "\nSize = " << li.size() << "\n\n";

	system("pause");
	return 0;
}


I don't know where the problem is! :(
I used this code but it doesn't work as expected:
Hm, what do you expect and what is the actual outcome?

However, your sort function is wrong. See:

http://www.cplusplus.com/reference/list/list/sort/

It is required to use the operator< not operator<=

Also having a member function (operator()) that does not use member variables is not good. On line 40 you have an unnecessary temporary. So change to:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <std_lib_facilities_4.h>
using namespace std;

struct Item {	
	bool operator<(const Item& i) const
	{
	    return (value < i.value); // Note: < not <=
	}

	string name;
	int iid;
	double value;
};

//***************************

int main()
{
	list<Item> li;

...
	
	li.sort();
...


You might consider to overload the operator>> as well.
Thanks for the explanation.
Topic archived. No new replies allowed.