Count Function (using vectors)

Jan 12, 2010 at 2:22pm
Here is an example I took from the docs here:-
1
2
3
4
// counting elements in array:
  int myints[] = {10,20,30,30,20,10,10,20};   // 8 elements
  mycount = (int) count (myints, myints+8, 10);
  cout << "10 appears " << mycount << " times.\n";

Output
10 appears 3 times.


So, instead of myints, if I use a vector, it should not make much difference in usage of count()?
1
2
3
4
std::vector<int> myvector = {10,20,30,30,20,10,10,20}; //just assume it can be initialized this way
myvector_count = (int) count (myvector.begin(), myvector.begin()+8, 10);
//OR
myvector_count = (int) count (myvector.begin(), myvector.end(), 10);//but I dont wanna use this with end() iterator 


I have problem with understanding the indices. Are these two statements same?

Statement1
myvector_count = (int) count (myvector.begin(), myvector.begin()+8, 10);
Statement2
myvector_count = (int) count (myvector.begin()+1, myvector.begin()+8, 10);


This makes no sense at all!! Ideally if I have 8 elements in the array/vector, I would use this statement
myvector_count = (int) count (myvector.begin(), myvector.begin()+7, 10);


Jan 12, 2010 at 2:36pm
I have problem with understanding the indices. Are these two statements same?

No
Ideally if I have 8 elements in the array/vector, I would use this statement

STL algorithm functions takes two iterators, one pointing at first element and one pointing one past the last element.
That's why in your first example you pass (myints, myints+8), these two are just shorthands for (&myints[0], &myints[8]). Normally you can't index the 8. element in an eight element array, but here STL algorithms requires it.
Jan 12, 2010 at 3:22pm
int myints[] = {10,20,30,30,20,10,10,20};

Its crazy that the STL Algorithm demands this. Its a deviation from the most basic concepts of array access, downright disgraceful from the programmer!

I did not want to use this function to just count from start until end. For example, i want to count how many times 30 appears from element 2 to element 7. CLEARLY, it creates a big confusion and anomaly.
Should I use?
myvector_count = (int) count (myvector.begin()+2, myvector.begin()+7, 30);


Jan 12, 2010 at 4:08pm
Its crazy that the STL Algorithm demands this.

Don't make such statements on things you can't even use. You will see how useful this is.

For example, i want to count how many times 30 appears from element 2 to element 7.

It depends, if element 2 is the second element (myvector[1]), or at the index 2 thus the third element.
If it's the former then count (myvector.begin()+1, myvector.begin()+7, 30);, if the latter then add one to both indexes.

Last edited on Jan 12, 2010 at 4:08pm
Jan 12, 2010 at 4:33pm
[quote="luckycusp"]Its crazy that the STL Algorithm demands this. Its a deviation from the most basic concepts of array access, downright disgraceful from the programmer![/quote]
It is absloutely not a deviation from basic concepts. It exactly conforms to basic concepts.

The STL algorithms take an "iterator" (which can be just a pointer or an accessor functor) to a "first" element and a "one-past the last" element -- essentially giving you the proper ability to splice or section the list for processing.

This is a very important ability in functional programming, and the STL makes it exceedingly easy to do. If you want to do it properly:
1
2
3
4
5
6
7
8
#include <iterator>
#include <vector>

count(
  advance( myvector.begin(), 1 ),  // 1st elt + 1 --> 2nd elt
  advance( myvector.begin(), 7 ),  // 1st elt + 7 --> 8th elt == 7th elt + 1
  30
  );

Remember, nothing is obvious until you learn it. And until you learn, you cannot pass judgement -- you simply don't have all the facts, and consequently, you still lack the understanding to make such judgements.

I understand it is difficult to wrap your brain around it. We all had to do that at some point too. And, having reached enlightenment, you see how few of us hate the STL for something so trivial.

Hope this helps.
Jan 12, 2010 at 4:50pm
You'll find that myints is the beginning of the array, and myints + 8 is one past the end. I don't see that violating any programming notions.

An iterator is a tool for traversing collections. The idea is, the less assumptions you can make about an iterator, the more general it becomes. For many cases, you just need assignment, test for equality and dereference to traverse a collection, this includes really large ones that are larger than the machine address space.

Once you see what the Generic Programming facilities in C++ are, you'll be impressed.
Last edited on Jan 12, 2010 at 4:51pm
Jan 12, 2010 at 8:25pm
You'll find that myints is the beginning of the array, and myints + 8 is one past the end. I don't see that violating any programming notions.


NO, I disagree

a[8] = {11,23,43,45,45,45,23,12};

If I want to access the 8th element, I use a[7] or *(a+7) and NOT *(a+8)

I understand it is difficult to wrap your brain around it. We all had to do that at some point too. And, having reached enlightenment, you see how few of us hate the STL for something so trivial.


Yup, I will try to wrap my brain around for it!! I just got a bit frustrated coz I wrote a very long code(without testing it, as there was some reason for it!). In the long code, I used the iterators thinking they are same as array indices. Now I need to change the whole code taking a lot of care of which index is being used, thats why the harsh comment accusing the STL programmer!

Nevermind, thanks a lot for your inputs.
Jan 12, 2010 at 9:01pm
*(myints.begin() + 7) for a vector accesses the 8th element.

Jan 12, 2010 at 9:12pm
If you intend to call an STL algorithm for a whole container just pass it begin() and end(). No need to compute your own iterators.
Last edited on Jan 12, 2010 at 9:12pm
Jan 12, 2010 at 9:13pm
If you intend to call an STL algorithm for a whole container just pass it begin() and end(). No need to compute your own iterators.

I did not want to use this function to just count from start until end.
Jan 12, 2010 at 9:55pm
I know. But if you are going for the end it's better and more reliable to use end() than iterator arithmetic.
Jan 13, 2010 at 12:03am
I think tummychow is saying that using operator+ is placing an additional requirement that the iterator type be a random access iterator. For instance, if you were to now switch containers to a list, which does not support random access, you would have to modify the code that calls count. Using advance is the best way to go because it is specialized to take advantage of random access iterators when applicable but does not require them.
Last edited on Jan 13, 2010 at 12:07am
Jan 13, 2010 at 1:41am
Not quite although that's a good point. Lists cannot perform random access and so cannot handle iterator arithmetic. I'm just saying that end() is more accurate than begin() + some number.
Jan 13, 2010 at 1:45am
I wouldn't say more accurate; I would say more generic.
Topic archived. No new replies allowed.