I am trying to write a code for BFS in c++ using STL. This is the section of the code i am having trouble with
std::list<int> li=*i;
for (std::list<int>::iterator iter=li.begin(); iter!=li.end();++iter)
{
if (arr[iter]==0)
{
myQ.push(iter);
arr[iter]=1;
Here arr is the array that stores whether or not i have seen the node .i am getting the error
"No match for operator arr[] in arr[iter]
iter is an iterator, so a kind of pointer, not an integer. THis is whiy arr[] does not work, because it expects an integer.
Try with arr[*iter] instead, and your breadth first search will avoid the cycles succesfully.
Please note that you have the same potential issue with your push(iter), if myQ is supposed to contain nodes as well.
You could further improve your design, by defining arr as a set instead of an array/vector.
Your condition would then look like:
if (arr.count(*iter) == 0) {
myQ.push_back(*iter);
arr.insert(*iter); // works for int, but also other data types
}
Iam answering by assuming arr in an integer array.
Any array elemet can be accessed by its integer index only,but not address of integer index.
Here iter is the pointer which can store the address of an integer.
So you have to use '*' to retrieve the value stored at the address to get integer value.
So change array[iter] to array[*iter]..
Hope this will fix your problem.
Here iter is an iterator which is pointer to the list, so for accessing its value you have to write *iter(access value which it is pointing) instead of iter(it is reference).
Try this
std::list<int> li=*i;
for (std::list<int>::iterator iter=li.begin(); iter!=li.end();++iter)
{
if (arr[*iter]==0)
{
myQ.push(*iter);
arr[*iter]=1;
Related
I'm new to vector in C++ and trying to get how it works.
First, I have a vector array:
vector<int>container;
Then I want to get the position of a given number in a vector array.
vector<int>::iterator position;
position = lower_bound(container.begin(), container.end(), temp);
After that, I want to get the value at that position that was returned from lower_bound by
container[position]
But I get the error that
No viable overloaded operator[] for type 'vector'
When I change it into *(position+1), it works fine.
So what is the different between those two?
Welcome to stackoverflow :)
First of all, we should understand what an iterator is. According to the hackingcpp
objects that point to a location
may point to a readable memory address / object
..
There are a lot of containers in C++ STL, such as vector, list, map and others.
A iterator is an abstraction of pointer, which allows you to access elements stored in container, use algorithm(such as sort, find, lower_bound) provided by STL no matter what kind of container we have.
Therefore, the return type of std::lower_bound is an iterator as you know vector<int>::iterator,
You couldn't access an element by calling container[position], there is no such function vector[iterator] provided by vector.
When I change it into *(position+1)
*itreator means return the value of where an iterator points out.
By the way, it's dangerous to do something like this *(position+1).
Since perhaps the given value tmp is in vector, perhaps it's not, so you should check whether the given value tmp is in vector by calling iterator != vector.end().
std::lower_bound returns a ForwardIterator (See: C++ named requirements: LegacyForwardIterator).
You can dereference it just like you would a pointer, eg:
std::vector<int> container;
// ...
auto it = std::lower_bound(container.begin(), container.end(), foo);
if (container.end() == it) {
throw or_something("handle error?");
}
const int x = *it;
const int y = container[std::distance(container.begin(), it)];
In that example x == y is true. (See: Compiler Explorer)
because of not enough reputation I can't comment a post on the the thread:
How to get position of a certain element in strings vector, to use it as an index in ints vector?
I want to know something regarding this answer:
Original answer on thread:
To get a position of an element in a vector knowing an iterator pointing to the element, simply subtract v.begin() from the iterator:
ptrdiff_t pos = find(Names.begin(), Names.end(), old_name_) - Names.begin();
Now you need to check pos against Names.size() to see if it is out of bounds or not:
if(pos >= Names.size()) {
//old_name_ not found
}
vector iterators behave in ways similar to array pointers; most of what you know about pointer arithmetic can be applied to vector iterators as well.
Starting with C++11 you can use std::distance in place of subtraction for both iterators and pointers:
ptrdiff_t pos = distance(Names.begin(), find(Names.begin(), Names.end(), old_name_));
Questions:
How does this exactly work for the compiler? What happens in the background?
I know, that im passing two iterators to the find method, which seems logic: I pass the start and the end position. In between, I'm searching for the element. std::find() returns an iterator of the first element satisfying the value passed as third parameter to the std::find() method. So is std::distance doing nothing else than incrementing in a for loop something like a counter until it reaches the "end-point" iterator?
I could also write:
int index = distance(Names.begin(), find(Names.begin(), Names.end(), old_name_));
Why is it better to use ptrdiff_t than an integer? Someone commented in the original post that it lets you store the distance between any pair of iterators into the same container, even in situations when the result is negative. But I do not really get the point of it. Maybe you could explain that a bit further. (:
I'm coming from C#, where you can use something like (demonstrated on a string):
string test = "Hello World";
int index = test.IndexOf("d");
This seems a lot easier compared to the methods used above in C++. Is there something equivalent in C++?
Thank you very much for your help!
Best regards
Okay, a small problem with, hopefully, a quick, simple solution.
In my school textbook, in a chapter about the STL, it gives a simple sample program to input for using lists and for using an iterator with a list, like so:
#include <list>
#include <iostream>
#include <string>
using namespace std;
int main()
{
list<int> myIntList;
// Insert to the front of the list.
myIntList.push_front(4);
myIntList.push_front(3);
myIntList.push_front(2);
myIntList.push_front(1);
// Insert to the back of the list.
myIntList.push_back(5);
myIntList.push_back(7);
myIntList.push_back(8);
myIntList.push_back(9);
// Forgot to add 6 to the list, insert before 7. But first
// we must get an iterator that refers to the position
// we want to insert 6 at. So do a quick linear search
// of the list to find that position.
list<int>::iterator i = 0;
for( i = myIntList.begin(); i != myIntList.end(); ++i )
if( *i == 7 ) break;
// Insert 6 were 7 is (the iterator I refers to the position
// that 7 is located. This does not overwrite 7; rather it
// inserts 6 between 5 and 7.
myIntList.insert(i, 6);
// Print the list to the console window.
for( i = myIntList.begin(); i != myIntList.end(); ++i )
cout << *i << " "; cout << endl;
}
Now, at the line that says
list<int>::iterator i = 0;
I get an error in VS 2015 that says:
no suitable constructor exists to convert from"int" to "std::_List_iterator<std::_List_val<std::_List simple_types<int>>>"
What is the problem with the code presented, what is the solution, and why is this a problem to begin with? <-(I'll even settle with a simple grammatical error).
The value 0 may not be a valid value for an iterator. Try either removing the assignment or assigning the iterator to myIntList.begin().
The iterator may not be able to be treated as an index, like with a vector or array. Usually linked lists are not accessed by index; you have to traverse from the beginning.
What is the problem with the code presented
A simple typo in the example.
what is the solution
Replace this line:
list<int>::iterator i = 0;
With this instead:
list<int>::iterator i;
why is this a problem to begin with?
You cannot initialize an iterator with an integer value. Only the container knows what its iterators refer to, so only the container can initialize them. All you can do is request an iterator from a container, assign an iterator to another iterator, and increment/decrement/dereference an iterator. That is all.
From http://www.cplusplus.com/reference/iterator/:
An iterator is any object that, pointing to some element in a range of elements (such as an array or a container), has the ability to iterate through the elements of that range using a set of operators (with at least the increment (++) and dereference (*) operators).
This means that an iterator should be able to do the following:
Return the object it's currently "pointing" to (using the * operator)
Change itself to "point" to the next object in its list (using the ++ operator)
A reason for the existence of the iterator as a data type is to create a general way of interacting with different kinds of lists. However, this means that different lists will implement their iterators differently.
In many circumstances, initializing an iterator to a number doesn't make sense because of the implementation under the hood. As a result, we don't define an assignment operator with our iterator type std::vector<int>::iterator on the left and an int on the right. So when you try to assign your iterator to an integral value, list<int>::iterator i = 0; your compiler throws an error.
Let's look at an example where assigning an iterator to 0 doesn't make sense. You could implement an iterator for std::vector<int> as a pointer to an element in your vector. In this case:
* dereferences the pointer stored in vector<int>::iterator and returns its value.
++ modifies the pointer stored in vector<int>::iterator to point at the next element in the list.
However, assigning this pointer to 0 would be the same as assigning it to NULL, and dereferencing it no longer returns a valid element in your vector. (In fact, dereferencing NULL will cause an error!)
To avoid this error, simply make sure that you always assign your iterator to a value of the same type. In the STL, this is usually accomplished by using .begin() to return an iterator that points to the first element in your list.
I am not proficient in C++ but I am converting a short script to PHP
for(auto it = First; it != Last; ++it)
{
Result += *it;
}
From this snippet, I can speculate this simply means
Result = Result + it
where * is a reference to the pointer of the loop.
That said I see this symbol used outside of loops and in some cases I see variables without this symbol both in and outside of loops which puts holes in my theory.
Again I am trying to RTFM but I am unsure what I am searching for.
Both First and Last are iterator objects, representing a generalization of pointers in C++ Standard Library. Additionally, the two iterators reference the same collection, and Last can be reached from First by incrementing the iterator*.
Result is some sort of accumulator. If it is of numeric type, += means Result = Result + *it, where *it is whatever the iterator is pointing to. In other words, Result accumulates the total of elements of the collection between First, inclusive, and Last, exclusive. If First points to the beginning of an array and Last points to one-past-the-end of an array of numeric type, your code would be equivalent to calling PHP array_sum() on the array.
However, Result is not required to be numeric. For example, it could be a std::string, in which case += represents appending the value to the string.
* In terms of pointers and arrays this would be "pointing to the same array," and "Last points to a higher index of the array than First."
I believe your speculation is incorrect.
it, first and last are either iterators or pointers. Iterators are C++ objects that can be used to iterator over containers. For basic usage, they behave much like pointers, and can be dereferenced the same way.
For example:
std::vector<int> myList;
...
// Search for the number 10 in the list.
std::vector<int>::iterator it = std::find(myList.begin(), myList.end(), 10);
// If the number 10 was found in the list, change the value to 11.
if (it != myList.end())
*it = 11; //< Similar to pointer syntax.
In your specific example, the Result variable has a value added to it. To get that value, your code uses the * operator to get the value from the iterator.
The same concept applies to pointers. although iterators and pointers are very different concepts, accessing their values is very similar.
I have an array of points like this:
CArray<CPoint,CPoint> points;
And I need to reverse the order of the points. I've tried this method:
std::reverse( &points[0], &points[0] + points.GetSize() );
And it works. Then I've tried this other method:
std::reverse( &points[0], &points[points.GetUpperBound()] );
But it doesn't work: the last item is not ordered correctly. Why?
That is because STL algorithms take ranges in the form [b, e) (that is, e exclusive), whereas the function you used returns the position of the last actual last element.
It should be further noted that your second form is even more problematic in the case where the array is empty. The function, according to the documentation, returns -1 in this case. BOOM!
The documentation says that GetUpperBound() returns the index of the last element, so &points[points.GetUpperBound()] represents an iterator to the last element, while STL algorithms require half-open ranges like [begin, end), that is, end must point directly after the last element.
First, while STL's algorithms (including std::reverse()) are designed to work fine with STL containers or STL-compatible containers (i.e. those providing STL-compatible iterators), I'm not sure about combining them with MFC containers.
Certainly, MFC containers were not designed with STL algorithm compatibility in mind.
I'd suggest to move your code from using MFC containers like CArray to more modern containers like std::vector.
That said, in the second case here:
std::reverse( &points[0], &points[points.GetUpperBound()] );
the second "iterator" argument that you pass to std::reverse() is not pointing to one-past the last valid item (like in the first case of &points[0] + points.GetSize()), but it's actually pointing to the last valid item.
In fact, CArray::GetUpperBound() returns the last valid index (from MSDN documentation):
Because array indexes are zero-based, this function returns a value 1
less than GetSize.
You may be tempted to use something like &points[points.GetSize()] or &points[points.GetUpperBound() + 1], but those would fail, since CArray overloads operator[], implementing bound checking at least in debug builds.
And with these aforementioned alternatives, you end up using an index out of the valid range.
But, let me repeat: consider moving your code from CArray to std::vector. You can still use MFC for the front-end GUI of your application; but for the "core" of your application, for the "business logic", using modern C++ and STL containers is a better option.
You could reverse the array link this using a stack:
#include <stack>
using namespace std;
void ReverseArray(CArray<CPoint,CPoint> points, int n)
{
// create an empty stack of integers
stack<CPoint,CPoint> stack;
// push each array element into a stack
for (int i = 0; i < n; i++) {
stack.push(points[i]);
}
// start from index 0
int index = 0;
// pop values from the stack until it becomes empty
while (!stack.empty())
{
// assign each popped item back to the original array
points[index++] = stack.top();
stack.pop();
}
}
For details, please see https://www.techiedelight.com/reverse-an-array-cpp/