#include <iostream>
#include <string>
#include <vector>
int main()
{
std::vector<std::string> str = { "one", "two", "three" };
std::string number;
std::cout << " Type in a number between 0 and 10 : ";
std::cin >> number;
bool number_matches = false;
for (auto i = str.begin(); i != str.end(); ++i)
{
if (number == str[i])
{
number_matches = true;
break;
}
}
std::cout << "\n Is your number, one, two or three? : ";
if (number_matches) std::cout << "Yes";
else std::cout << "No";
}
Here's the error I'm getting:
In function 'int main()':
18:26: error: no match for 'operator[]' (operand types are 'std::vector<std::basic_string<char> >' and '__gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >')
18:26: note: candidates are:
In file included from /usr/include/c++/4.9/vector:64:0,
from 3:
/usr/include/c++/4.9/bits/stl_vector.h:779:7: note: std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::operator[](std::vector<_Tp, _Alloc>::size_type) [with _Tp = std::basic_string<char>; _Alloc = std::allocator<std::basic_string<char> >; std::vector<_Tp, _Alloc>::reference = std::basic_string<char>&; std::vector<_Tp, _Alloc>::size_type = long unsigned int]
operator[](size_type __n) _GLIBCXX_NOEXCEPT
^
/usr/include/c++/4.9/bits/stl_vector.h:779:7: note: no known conversion for argument 1 from '__gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >' to 'std::vector<std::basic_string<char> >::size_type {aka long unsigned int}'
/usr/include/c++/4.9/bits/stl_vector.h:794:7: note: std::vector<_Tp, _Alloc>::const_reference std::vector<_Tp, _Alloc>::operator[](std::vector<_Tp, _Alloc>::size_type) const [with _Tp = std::basic_string<char>; _Alloc = std::allocator<std::basic_string<char> >; std::vector<_Tp, _Alloc>::const_reference = const std::basic_string<char>&; std::vector<_Tp, _Alloc>::size_type = long unsigned int]
operator[](size_type __n) const _GLIBCXX_NOEXCEPT
^
/usr/include/c++/4.9/bits/stl_vector.h:794:7: note: no known conversion for argument 1 from '__gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >' to 'std::vector<std::basic_string<char> >::size_type {aka long unsigned int}'
So I'm guessing I can't use that iterator i to access the vector in the for loop, am I wrong in assuming so? And what's the point in this case if you have an iterator and you can't access anything within the vector with it?
I have the feeling I'm overlooking something quite obvious..
You're using i like it's just an index, but it's an iterator. So it doesn't represent an index but a value and you get the value with the dereference operator *:
if (number == *i)
Although it's more "modern" to write it like this:
1 2 3 4 5
for (constauto& s: str)
if (number == s) {
number_matches = true;
break;
}
str.begin() is an iterator that "points" to str[0]. But it needs to be "dereferenced" to actually get str[0]. You should look up the implementation of an iterator to really understand what's going on.
And the "more modern" way I mentioned above is really just syntactic sugar that automates the loop from begin to end and even automates the dereferencing.
Thank you for taking the time to post this, it indeed makes things a lot clearer for me!
I'm riddled by one last thing though. Using an automatic loop, is there a way to get the number of the nth element that is being accessed? Let me illustrate to make it more concrete.
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::vector<std::string> str = { "zero", "one", "two" };
int string_number = 999;
std::string input;
std::cout << " Type out a number bewteen 0 and 2, all in letters _";
std::cin >> input;
for (constauto& i : str)
{
if (input == i)
{
//I want here to assign the number of the element accessed in the vector to "number"
}
}
std::cout << "\n Number: " << string_number;
}
in other words what I would like to do is the equivalent of:
1 2 3 4 5 6 7
for (int i = 0 ; i < str.size(); ++i)
{
if (str[i] == input)
{
string_number = i;
}
}
Thanks againtry, but I would like to avoid the use of a counter if there is already iterators in my code and vice versa. But I see what you did there, it's quite clever and I'll certainly keep it in mind if I ever need to do something like this :)
Yeah HOOGO it wasn't meant as any sort of adequate alternative but just to highlight perhaps the 'old way thinking' and the need to treat iterators in the 'special' way dutch has shown.
There is nothing wrong with auto but the general theme from experts (IIRC core guideines etc, is be aware of what it means because auto obscures the type we are accustomed to)
It's not my call but FWIW feel free never to use what I wrote - I wouldn't :)
Using an automatic loop, is there a way to get the number of the nth element that is being accessed?
There is no way to do that with the automatic loop (which I think is actually called a "range-based for loop").
Even if you wrote your own iterator with a get_index method it still wouldn't work with the range-based loop since you have no access to the underlying iterator.
The usual way to have access to the index is to use a separate index variable. Of course, at that point you may as well use an old-style index-based loop. But it's somewhat a matter of taste.
1 2 3 4 5 6 7 8 9
unsigned i = 0;
for (constauto& s: str) {
if (s == input) break;
++i;
}
if (i < str.size())
std::cout << "Found at index " << i << '\n';
else
std::cout << "Not found.\n";
If using Visual Studio 2017/2019, hovering the mouse pointer over a variable being declared using auto pops up a tooltip that reveals the underlying data type being used.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#include <iostream>
#include <vector>
int main()
{
std::vector<int> vec { 1, 2, 3, 4, 5 };
// access the elements by iterator
for (auto itr { vec.begin() }; itr != vec.end(); itr++)
{
// auto is using std::vector<int>::iterator
}
// access by value (the vector is essentially copied)
for (auto itr : vec)
{
// auto is using int (the data type of the contained values?)
}
}
I discovered a few minutes ago this intellisense help about VS and auto. I thought I'd share it so auto can become less mysteriously obscuring.
I am NOT suggesting to use (over-use) auto for more than a few select uses, such as range-based for loops and declaring iterators.
@mbozzi, kinda "funny" you should mention this, I was looking at the cppreference page on range-based for loops and noticed the && use of forward referencing.
I was looking at the cppreference page on range-based for loops and noticed the && use of forward referencing. Or is your example using structured binding?
It's a structured binding declaration: auto&& is used to declare the uniquely-named hidden variable whose subobjects are bound by the structured bindings elt and i.
Overall, there are lots of implementations about that have slightly different behavior (and different names).
@Duthomhas implemented one recently; his was named operator,.