How to rewrite this index way code using iterators.

This is a exercise on C++ Primer 5th. P112

I am asked to write the following code from using index to using iterator.
1
2
3
4
5
6
vector<unsigned> scores(11, 0);
unsigned grade;
while (cin >> grade) {
    if (grade <= 100)
        ++scores[grade / 10];
}


It's aim is to cluster scores by 10. like I give 4, 5, 10, 99, then the scores vector would hold 2 1 0 0 0 0 0 0 1 0
That's awkward.

You need to use std::advance to increment the iterator returned from scores.begin(), which is not the best.
http://en.cppreference.com/w/cpp/iterator/advance
std::advance is similar to it + n or or it++.

I think this exercise is awkward, too. I haven't find a way to realize it.
anyone help
Last edited on
is this ok?

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
#include <string>
#include <iostream>
#include <cstdlib>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
	vector<unsigned> scores(11, 0);
	unsigned grade;

	while (cin >> grade) 
	{
    
		if (grade <= 100)
		{	
			unsigned result = grade/10;
			auto &vi = scores.begin() + result;
			
			std::cout << "grade " << result << std::endl;
			std::cout << "old value " << *vi << std::endl;

			*vi+=1;
			unsigned new_val = *vi;

			std::cout << "iterator value " << new_val << std::endl;			
			
		}
		else
		{
			break;
		}
			
	}


	std::cout << std::endl;
	std::cout << std::endl;

	for (int i=0; i < scores.size(); i++)
	{
		std::cout << scores[i] << std::endl;
	}

	int x;
	cin >> x;

	return 0;
}
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
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

int main()
{
    std::vector< unsigned int > scores(11) ;
    unsigned int grade ;

    while( std::cin >> grade )
    {
        const auto n = std::min( grade, 100U ) / 10 ;

        // option one: requires random access iterator
        const auto iterb = scores.begin() ;
        ++iterb[n] ;

        // option two: requires random access iterator
        const auto itern = scores.begin() + n ;
        ++*itern ;

        // option three: random access iterator is not required
        auto iterf = scores.begin() ;
        std::advance( iterf, n ) ;
        ++*iterf ;
    }
}
thanks, ic now. I think this exercise is not that good, using iterator way is much more complex than using subscripts.
There's also std::next(), which makes life a lot easier over std::advance().

I notice that none of the given solutions behave like the original code snippet.

There are other ways of thinking about it too... Given the original design this is definitely less efficient, but it is a valid transform:

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 <functional>
#include <iostream>
#include <iterator>
#include <numeric>
#include <set>
#include <vector>
using namespace std;

int main()
{
  vector <unsigned> scores( 11, 0 );

  {
    multiset <unsigned> scoreset;
    transform( 
      istream_iterator <unsigned> ( cin ),
      istream_iterator <unsigned> (),
      inserter( scoreset, scoreset.begin() ),
      bind( divides <unsigned> (), placeholders::_1, 10 )
    );
    iota( scores.begin(), scores.end(), 0 );
    for (unsigned& score: scores)
      score = scoreset.count( score );
  }
  
  for (unsigned x: scores)
    cout << x << " ";
}

Enjoy!
Topic archived. No new replies allowed.