Get index of current element in C++ range-based for-loop
Solution 1
Assuming str
is a std::string
or other object with contiguous storage:
std::cin >> str;
for (char& c : str)
if (c == 'b') v.push_back(&c - &str[0]);
Solution 2
Maybe it's enough to have a variable i
?
unsigned i = 0;
for ( char c : str ) {
if ( c == 'b' ) vector.push_back(i);
++i;
}
That way you don't have to change the range-based loop.
Solution 3
The range loop will not give you the index. It is meant to abstract away such concepts, and just let you iterate through the collection.
Solution 4
What you are describing is known as an 'each with index' operation in other languages. Doing some quick googling, it seems that other than the 'old-school for loop', you have some rather complicated solutions involving C++0x lambas or possibly some Boost provided gems.
EDIT: As an example, see this question
Solution 5
In C++ 20, I use initializer like this:
for(unsigned short i = 0; string item : nilai){
cout << i << "." << "address " << &item << " -> " << item << endl;
i++;
}
So, your case will be like:
for (unsigned short i = 0; char c : str ) {
if ( c == 'b' ) vector.push_back(i);
++i;
}
I don't know what 'vector' mean in your case, and what is push_back().
Don't forget to add -std=c++20
(I just use g++ for compiling, so i don't know much about other compiler). You can also start the 'i' value from 1 if you want to. I think it's elegant enough
Shane Hsu
Interested in OS X/iOS Development, algorithmic, and competitive programming.
Updated on July 09, 2022Comments
-
Shane Hsu almost 2 years
My code is as follows:
std::cin >> str; for ( char c : str ) if ( c == 'b' ) vector.push_back(i) //while i is the index of c in str
Is this doable? Or I will have to go with the old-school for loop?
-
Shane Hsu over 11 yearsIt's a solution, but it's not elegant. Also, I think it will be pointless as it's implementing traditional for loop in a range-based one.
-
Daniel Frey over 11 yearsMaybe it's not elegant, but it's the baseline wrt complexity, readability, overhead, etc. for all other upcoming solutions/work-arounds.
-
Shane Hsu over 11 yearsIt sure seems complicated, but it's definitely worth learning! Thank! I will look into it.
-
Shane Hsu over 11 yearsSure. But I really think there should be a constant
index
in C++ Range-Based for loop. -
Daniel Frey over 11 yearsYou asked about the current language status, where something like
index
does not exist. Whether and how the language could be extended is a different question and does not belong here. -
Shane Hsu over 11 yearsNice! I was thinking that vectors can use something like
it - vector.begin()
, and you solved my problem! Thanks! -
mskfisher over 9 yearsThis does not answer the question. The OP wanted the numeric index of the instances of 'b', not the instances themselves.
-
gr4nt3d over 8 yearsThanks! I got
&it - &vector[0]
to compile. But is there a nice way such as @ShaneHsu 's comment? I figured out, I had to use&it - vector.begin()
using iterators such asconst initializer_list<double>& it
. However, in a loop such asfor(const pair<double, int>& it : vector_of_pairs)
this yields an error: no match for ‘operator-’ (operand types are ‘const pair<double, int>*’ and vector<pair<double, int> >::const_iterator . How can I get the address of the iterator ? (Note that the former is in a ctor, whereas the latter is in a const method) -
Tomasz Gandor over 7 yearsOne problem with this - the i variable is scoped outside the loop. In case of the traditional for, there is a place where you can declare extra variables, when they are all of the same type (as your main 'loop variable').
-
Steven Lu over 6 yearsNote if the underlying storage changes into no longer a vector type, it will break. Likely your integer based semantics would also then break... so this isnt a strong point against doing this. But it does feel like you'd be strengthening your commitment to contiguous storage by doing this.
-
Steven Lu over 6 years@gr4nt3d your question appears to be about how you cannot obtain an ordering out of an iterator for an associative type, which (say it's a hashtable) pretty much has no ordering, you can only do stuff like check its equality to
container.end()
, or fetch the next one, etc. See stackoverflow.com/a/43680932/340947 -
gr4nt3d about 6 years@StevenLu, I don't get your point; I was referring to plain
std::vector
(at least telling from the comment, as it's been quite some time since then). As such it would have the ordering that I need, but apparently the expression&it - vector_of_pairs.begin()
did not work even though I'd expect the pointer arithmetic to work, as it is contiguously stored. However, I cannot recall the exact case anymore. -
Steven Lu about 6 yearsThe difference seems to be between getting the address of the first element of the vector Vs. getting the begin() iterator. I’m not too sure on why or what exactly the limitations are but direct arithmetic on iterators seems to not work
-
zeeMonkeez over 5 yearsNote that C++20 will allow declaration of
i
in thefor
statement: open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0614r1.html . @TomaszGandor for that, you'd encapsulate thefor
loop with the declaration ofI
in braces.