How to access different members of vector in a function - c++

#include <vector>
int main()
{
vector <class> abc;
}
when pressing some key
vector.push_back(class());
each loop
draw(vector)// what should the parameters be?
draw function
draw(vector,sizeofvector)
{
for (int x=0;x< sizeofvector;x++)
{draw vector[x];}
}
how should the parameters look? should i be passing an *abc?

In modern C++ this can be answered without correcting your errors:
for (const auto & x : vector) { draw(x); }
Alternatively (still in C++11):
for (auto it = vector.cbegin(), end = vector.cend(); it != end; ++it)
{
draw(*it);
}
This might work in C++98/03, too:
for (std::size_t i = 0, end = vector.size(); i != end; ++i) { draw(vector[i]); }

If you don't intend to modify the vector, you usually pass it by const reference.
void draw(const std::vector<T>& v)
{
for (int x = 0; x < v.size(); x++)
{
// draw v[x];
}
}
You can also use iterators (this is often preferable).
void draw(const std::vector<T>& v)
{
for (std::vector<T>::const_iterator x = v.begin(); x != v.end(); ++x)
{
// draw *x;
}
}
The reason you don't pass it by value (draw(std::vector<T> v)) is because that would cause the entire vector to be copied every time you call the function, which is obviously incredibly inefficient. References mean that you just refer to the existing vector rather than creating a new one.

std::vector is the type. You need to pass in an instance, so in your case:
draw(abc);
I also agree that your function should have prototype:
void draw( const std::vector<class> & v );

#include <algorithm>
#include <vector>
#include <iostream>
void addOne(int& value)
{
value++;
}
void print(int& value)
{
std::cout << value;
}
int main()
{
std::vector<int> myVector;
myVector.push_back(1);
myVector.push_back(2);
myVector.push_back(3);
std::for_each(myVector.begin(), myVector.end(), addOne);
std::for_each(myVector.begin(), myVector.end(), print);
}
Output: 234
wrote by hand, compiler errors possible

Related

c++11: Why a const reference vector cannot be traversed? [duplicate]

I'm writing program for graphs. In this program I have a method which has to return vertices inside the weak component originating at vertex. I am getting: Error "vector iterators incompatible"
struct graph {
std::vector <std::vector<int>> gr;
};
std::vector<int> weak_component(const graph& g, int vertex) {
std::vector<int> ret;
stack<int> s;
s.push(vertex);
vector<int>::iterator j;
bool* used = new bool[g.gr.size()];
while (!s.empty()) {
int hodn=s.top();
s.pop();
used[hodn] = true;
for (j == g.gr[hodn].begin(); j != g.gr[hodn].end(); j++) {
if (!used[*j]) {
s.push(*j);
ret.push_back(*j);
}
}
}
return ret;
}
What's wrong with it?
Since you are taking g as a const graph&, this means g.gr is treated as const inside your function. begin on a const vector<T> returns a const_iterator. (also you used == instead of = for assignment)
for (std::vector<int>::const_iterator j = g.gr[hodn].begin(); ...)
But with C++11 or newer you may as well use auto to avoid this
for (auto j = g.gr[hodn].begin(); ...)
or a range-based for:
for (auto&& e : g.gr) {
if (!used[e]) {
s.push(e);
ret.push_back(e);
}
}

vector iterators incompatible with const vector&

I'm writing program for graphs. In this program I have a method which has to return vertices inside the weak component originating at vertex. I am getting: Error "vector iterators incompatible"
struct graph {
std::vector <std::vector<int>> gr;
};
std::vector<int> weak_component(const graph& g, int vertex) {
std::vector<int> ret;
stack<int> s;
s.push(vertex);
vector<int>::iterator j;
bool* used = new bool[g.gr.size()];
while (!s.empty()) {
int hodn=s.top();
s.pop();
used[hodn] = true;
for (j == g.gr[hodn].begin(); j != g.gr[hodn].end(); j++) {
if (!used[*j]) {
s.push(*j);
ret.push_back(*j);
}
}
}
return ret;
}
What's wrong with it?
Since you are taking g as a const graph&, this means g.gr is treated as const inside your function. begin on a const vector<T> returns a const_iterator. (also you used == instead of = for assignment)
for (std::vector<int>::const_iterator j = g.gr[hodn].begin(); ...)
But with C++11 or newer you may as well use auto to avoid this
for (auto j = g.gr[hodn].begin(); ...)
or a range-based for:
for (auto&& e : g.gr) {
if (!used[e]) {
s.push(e);
ret.push_back(e);
}
}

Push_Front Pop_Back for C++ Vector

I'm trying to keep a vector of commands so that it keeps 10 most recent. I have a push_back and a pop_back, but how do I delete the oldest without shifting everything in a for loop? Is erase the only way to do this?
Use std::deque which is a vector-like container that's good at removal and insertion at both ends.
If you're amenable to using boost, I'd recommend looking at circular_buffer, which deals with this exact problem extremely efficiently (it avoids moving elements around unnecessarily, and instead just manipulates a couple of pointers):
// Create a circular buffer with a capacity for 3 integers.
boost::circular_buffer<int> cb(3);
// Insert threee elements into the buffer.
cb.push_back(1);
cb.push_back(2);
cb.push_back(3);
cb.push_back(4);
cb.push_back(5);
The last two ops simply overwrite the elements of the first two.
Write a wrapper around a vector to give yourself a circular buffer. Something like this:
include <vector>
/**
Circular vector wrapper
When the vector is full, old data is overwritten
*/
class cCircularVector
{
public:
// An iterator that points to the physical begining of the vector
typedef std::vector< short >::iterator iterator;
iterator begin() { return myVector.begin(); }
iterator end() { return myVector.end(); }
// The size ( capacity ) of the vector
int size() { return (int) myVector.size(); }
void clear() { myVector.clear(); next = 0; }
void resize( int s ) { myVector.resize( s ); }
// Constructor, specifying the capacity
cCircularVector( int capacity )
: next( 0 )
{
myVector.resize( capacity );
}
// Add new data, over-writing oldest if full
void push_back( short v )
{
myVector[ next] = v;
advance();
}
int getNext()
{
return next;
}
private:
std::vector< short > myVector;
int next;
void advance()
{
next++;
if( next == (int)myVector.size() )
next = 0;
}
};
What about something like this:
http://ideone.com/SLSNpc
Note: It's just a base, you still need to work a bit on it. The idea is that it's easy to use because it has it's own iterator, which will give you the output you want. As you can see the last value inserted is the one shown first, which I'm guessing is what you want.
#include <iostream>
#include <vector>
template<class T, size_t MaxSize>
class TopN
{
public:
void push_back(T v)
{
if (m_vector.size() < MaxSize)
m_vector.push_back(v);
else
m_vector[m_pos] = v;
if (++m_pos == MaxSize)
m_pos = 0;
}
class DummyIterator
{
public:
TopN &r; // a direct reference to our boss.
int p, m; // m: how many elements we can pull from vector, p: position of the cursor.
DummyIterator(TopN& t) : r(t), p(t.m_pos), m(t.m_vector.size()){}
operator bool() const { return (m > 0); }
T& operator *()
{
static T e = 0; // this could be removed
if (m <= 0) // if someone tries to extract data from an empty vector
return e; // instead of throwing an error, we return a dummy value
m--;
if (--p < 0)
p = MaxSize - 1;
return r.m_vector[p];
}
};
decltype(auto) begin() { return m_vector.begin(); }
decltype(auto) end() { return m_vector.end(); }
DummyIterator get_dummy_iterator()
{
return DummyIterator(*this);
}
private:
std::vector<T> m_vector;
int m_pos = 0;
};
template<typename T, size_t S>
void show(TopN<T,S>& t)
{
for (auto it = t.get_dummy_iterator(); it; )
std::cout << *it << '\t';
std::cout << std::endl;
};
int main(int argc, char* argv[])
{
TopN<int,10> top10;
for (int i = 1; i <= 10; i++)
top10.push_back(5 * i);
show(top10);
top10.push_back(60);
show(top10);
top10.push_back(65);
show(top10);
return 0;
}

sub-vector modifies original vector

I want to extract a sub-vector. Then modify its elements which affects the original vector. My sample code below:
#include <vector>
#include <iostream>
using namespace std;
void printvec(vector<int>& v){
for(int i = 0;i < v.size();i++) {cout << v[i] << " ";}
cout << endl;
}
int main(){
vector<int> original;
for(int i = 1;i <= 10;i++) original.push_back(i);
printvec(original);
vector<int> subvector(original.begin()+4, original.end()-2);
subvector[0]=0;
subvector[1]=0;
printvec(subvector);
printvec(original);
return 0;
}
In above code, subvector does not modify vector. Can some one point me to an elegant way to make a subvector which modifies original vector (hopefully without explicit use of pointers if possible).
If you don't want to use a pointer, you could create a slice class to forward the work to - which will just be a pair of iterators and whatever other operations you might need:
template <typename T>
class slice {
using iterator = typename T::iterator;
using reference = typename std::iterator_traits<iterator>::reference;
slice(iterator first, iterator last)
: first(first), last(last)
{ }
reference operator[](size_t idx)
{
return *std::next(first, idx);
}
iterator begin() const { return first; }
iterator end() const { return last; }
private:
iterator first, last;
};
With that, you can do your slicing thusly:
slice<vector<int>> subvector(original.begin()+4, original.end()-2);
subvector[0]=0; // changes original[4]
subvector[1]=0; // changes original[5]
If you change your printvec to take an arbitrary container and use a range-for to iterate over it, you can print the subvector too. It will contain:
0 0 7 8
The line:
vector<int> subvector(original.begin()+4, original.end()-2);
creates a new vector and copies the elements from original.begin()+4 to original.end()-2 to the new one. Even with pointers, there is no way I would call elegant to achieve what you want, because many change to the original vector (rezise / push_back) could potentially invalidate the pointers to its elements.
Depending on the exact functionality you want to implement, you can use a class like this:
#include <vector>
#include <iostream>
using namespace std;
template<class T>
class Subvector {
std::vector<T>*const vec;
size_t start;
size_t end;
public:
Subvector(std::vector<T>& vector, size_t start, size_t end) :
vec(&vector),
start(start),
end(end)
{}
size_t size() const { return end - start; }
T& operator[](size_t i) {
return (*vec)[start + i];
}
const T& operator[](size_t i) const {
return (*vec)[start + i];
}
};
template<class VEC>
void printvec(const VEC& v){
for (int i = 0; i < v.size(); i++) { cout << v[i] << " "; }
cout << endl;
}
int main(){
vector<int> original;
for (int i = 1; i <= 10; i++) original.push_back(i);
printvec(original);
Subvector<int> subvector(original,4, original.size() - 2);
subvector[0] = 0;
subvector[1] = 0;
printvec(subvector);
printvec(original);
return 0;
}

Cannot use .begin() or .end() on an array

The error reads:
request for member 'begin', 'end' in 'arr' which is non class type int[5],
unable to deduce from expression error.
My code:
#include <iostream>
using namespace std;
int main()
{
int * mypointer;
int arr[5] = {1,3,5,7,9};
mypointer = arr;
for(auto it = arr.begin(); it != arr.end(); ++it) {
cout<<*mypointer<<endl;
mypointer++;
}
return 0;
}
Arrays have no member functions as they aren't a class type. This is what the error is saying.
You can use std::begin(arr) and std::end(arr) from the <iterator> header instead. This also works with types that do have .begin() and .end() members, via overloading:
#include <array>
#include <vector>
#include <iterator>
int main()
{
int c_array[5] = {};
std::array<int, 5> cpp_array = {};
std::vector<int> cpp_dynarray(5);
auto c_array_begin = std::begin(c_array); // = c_array + 0
auto c_array_end = std::end(c_array); // = c_array + 5
auto cpp_array_begin = std::begin(cpp_array); // = cpp_array.begin()
auto cpp_array_end = std::end(cpp_array); // = cpp_array.end()
auto cpp_dynarray_begin = std::begin(cpp_dynarray); // = cpp_dynarray.begin()
auto cpp_dynarray_end = std::end(cpp_dynarray); // = cpp_dynarray.end()
}
For a standard fixed-length C array, you can just write
int c_array[] = {1,3,5,7,9}, acc = 0;
for (auto it : c_array) {
acc += it;
}
The compiler does the behind-the-scenes work, eliminating the need to create all those begin and end iterators.
In C++, arrays are not classes and therefore do not have any member methods. They do behave like pointers in some contexts. You can take advantage of this by modifying your code:
#include <iostream>
using namespace std;
int main()
{
int * mypointer;
const int SIZE = 5;
int arr[SIZE] = {1,3,5,7,9};
mypointer = arr;
for(auto it = arr; it != arr + SIZE; ++it) {
cout<<*mypointer<<endl;
mypointer++;
}
return 0;
}
Of course, this means that mypointer and it both contain the same address, so you don't need both of them.
One thing I'd like to point out for you is that you really don't have to maintain a separate int* to use in dereferencing the array elements, apart from the whole member thing others have well pointed out.
Using a more modern approach, the code is both more readable, as well as safer:
#include <iostream>
#include <algorithm>
#include <array>
#include <iterator>
using namespace std;
int main()
{
std::array<int, 5> cpp_array{1,3,5,7,9};
// Simple walk the container elements.
for( auto elem : cpp_array )
cout << elem << endl;
// Arbitrary element processing on the container.
std::for_each( begin(cpp_array), end(cpp_array), [](int& elem) {
elem *= 2; // double the element.
cout << elem << endl;
});
}
Using the lambda in the second example allows you to conveniently perform arbitrary processing on the elements, if needed. In this example, I'm just showing doubling each element, but you can do something more meaningful within the lambda body instead.
Hope this makes sense and helps.
Perhaps here is a cleaner way to do it using templates and lambdas in c++14:
Define:
template<typename Iterator, typename Funct>
void my_assign_to_each(Iterator start, Iterator stop, Funct f) {
while (start != stop) {
*start = f();
++start;
}
}
template<typename Iterator, typename Funct>
void my_read_from_each(Iterator start, Iterator stop, Funct f) {
while (start != stop) {
f(*start);
++start;
}
}
And then in main:
int x[10];
srand(time(0));
my_assign_to_each(x, x+10, [] () -> int { int rn{}; rn = rand(); return rn; });
my_read_from_each(x, x+10, [] (int value) { std::cout << value << std::endl; });
int common_value{18};
my_assign_to_each(x, x+10, [&common_value] () -> int { return common_value; });
my_read_from_each(x, x+10, [] (int value) { std::cout << value << std::endl; });
Quite late but I think it's worth to mention that:
void findavgTime(int n)
{
int wt1[n];
fill_wt(wt1,n); //Any method that puts the elements into wt1
int wt2[3];
int sum = accumulate(begin(wt1), end(wt1), 0); // Fails but wt2[3] will pass. Reason: variable-sized array type ‘int [n]’ is not a valid template argument)
}