array of vector<struct> in C++ - c++

I've a vector of structure and it's components, now I want array of this group, below is my code
struct V1
{
USHORT val;
UINT cnt;
USHORT state;
};
struct V2
{
DWORD room;
vector <V1> vref;
bool update_V1(USHORT S1, USHORT S2);
VOID ClearState(USHORT S1);
};
struct V3
{
USHORT block;
vector <V2> V2ref;
bool Update_V2(DWORD S1,USHORT S2,USHORT S3);
VOID ClearState_V2(USHORT S4);
};
struct V4
{
USHORT space;
vector <V3> V3ref;
bool Update_V3(USHORT S1,DWORD S2,USHORT S3);
VOID ClearState_V2(USHORT S4);
};
struct V5
{
USHORT del_1;
vector <V4> V4ref;
bool Update_V4(USHORT S1,USHORT S2,DWORD S3,USHORT S4);
VOID ClearState_V2(USHORT S4);
};
class C1
{
vector<V5> V5ref[2];
bool UpdateGroup(USHORT S1,USHORT S2,USHORT S3,DWORD S4,USHORT S5);
}
bool C1::UpdateGroup(USHORT S1,USHORT S2,USHORT S3,DWORD S4,USHORT S5)
{
vector<V5>::iterator it;
for ( it=V5ref[S5].begin() ; it< V5ref[S5].end(); it++ )
{
if(it->del_1==S2)
{
return grpItr->Update_V4(S1,S2,S3,s4);
}
}
V5 V5local;
V5local.del_1 = S2;
V5local.Update_V4(S1,S2,S3,S4);
V5ref[S5].push_back(V5local);
return true;
}
I tried using vector V5ref[2];
It works for 1st iteration and throws error "assert" for 2nd iteration, what could be the reason. is there any other option to have copies of vectors.
what exactly I want to do is, with parameter S2 being 1, 2, 3, I want diff arrays of the whole vector for S2 = 1, S2 = 2...V5 and it's components should be seperate elements of the array according to S2

I have researched your problem a bit. Since the code is insufficient, we all can only guess what you are doing or not doing there. The debug assertion usually comes if the vector has not enough space allocated. (correct me if I am wrong). So, in this case, before using your vectors, you should use the resize(); method. Here is an example:
struct structure
{
int value1;
char value2;
bool value3;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<structure> vector1;
vector1.resize(1);
vector1[0].value1 = 12;
vector1[0].value2 = 'h';
vector1[0].value3 = true;
return 0;
}
If you test it yourself, you will know that without the vector.resize(1); this won't work at the run-time.

At any given time, a std::vector<> has a constraint, size which is the maximum element number you can access + 1, and a constraint capacity which is how many elements it can contain before it has to move the data to a larger memory allocation.
size determines what you can access. When the vector is created, you cannot access anything. vec[0] is illegal when the vector is empty.
#include <vector>
#include <iostream>
int main()
{
std::vector<int> vec;
std::cout << "initially, vec.size = " << vec.size() << ", cap = " << vec.capacity() << "\n";
// initially, the vector is empty.
// std::cout << vec[0] << '\n'; // undefined behavior, probably a crash
// you can only ever access vec[n] where v < vec.size(),
// this vector is empty, so size() == 0
// Lets add a number to the vector.
vec.push_back(5);
std::cout << "now, vec.size = " << vec.size() << ", cap = " << vec.capacity()
std::cout << "vec[0] = " << vec[0] << '\n';
// std::cout << vec[1] << '\n'; // undefined behavior because 1 >= size()
vec.resize(5);
std::cout << "resized, vec.size = " << vec.size() << ", cap = " << vec.capacity()
vec[1] = 1; // valid, resize made space for vec[0] .. vec[4]
vec[2] = 2;
for (auto it = vec.begin(), end = vec.end(); it != end; ++it)
std::cout << *it << '\n';
return 0;
}
push_back does "vec.resize(vec.size() + 1)" for you, and then inserts the value being 'push_back'ed into the new slot.
resize attempts to make room for extra elements -- if size is 3 and you say resize(5) it will try to make room for 2 new elements.
If the result causes size to exceed capacity then the vector allocates a new array, copies the old data over into it, and releases the old array. This can become very expensive. If you know roughly how big your vector is going to become, you can avoid this relocation by calling reserve()
#include <iostream>
#include <vector>
using std::cout;
struct Stud // will always tell you when it reproduces
{
int m_i;
Stud() : m_i(-1) {}
Stud(int i) : m_i(i) {}
Stud(const Stud& rhs) : m_i(rhs.m_i) { cout << "Copying(Ctor) " << m_i << '\n'; }
Stud& operator=(const Stud& rhs) { m_i = rhs.m_i; cout << "Copying(=) " << m_i << '\n'; return *this; }
};
int main()
{
std::vector<Stud> studs;
studs.push_back(0);
studs.push_back(1);
studs.reserve(5);
studs.push_back(5); // remember, this adds to the back.
studs.push_back(6);
std::cout << "size of studs " << studs.size();
return 0;
}
Based on this
bool Update_V4(USHORT S1,USHORT S2,DWORD S3,USHORT S4);
I am guessing that you are trying to simulate multi-dimensional arrays of some kind, and you are doing something like
V4Ref[S1]
without checking
if (S1 < V4Ref.size())
C++ has a function 'assert' which will cause a Debug build application to terminate if a condition is not met.
#include <cassert>
#include <vector>
int main()
{
std::vector<int> vec;
assert(vec.size() == 0);
vec.push_back(1);
vec.resize(5);
vec.push_back(5);
assert(vec.size() == 10); // expect to crash here.
return 0;
}
You could use this to help catch bad sizes:
bool V4::Update_V4(USHORT S1,USHORT S2,DWORD S3,USHORT S4)
{
assert(S1 < V4ref.size());
return V4ref[S1].Update_V3(S2, S3, S4);
}

Related

C++ - Merging two sorted vectors of different, unique types with a common attribute into a new sorted vector

There are two types, A and B. These types both have a common attribute, a key.
There are two vectors of type A and B. These vectors are sorted by key ascending. The vectors are unique in regards to their keys - ie if a key is present in A_vect it is guaranteed to not be present in B_vect and vice versa.
The goal is to take the keys in vector A_vect, construct new B types and put them into B_vect, such that B contains it's original keys and it's new keys. The new B_vect should also be sorted.
I have this code snippet so far:
#include <iostream>
#include <vector>
#include <algorithm>
struct A
{
A(int i)
{
key = i;
}
int key;
};
struct B
{
B(int i)
{
key = i;
}
B()
{
}
int key;
};
int main()
{
std::vector<A> a_diff_sorted_vect = {1, 3};
std::vector<B> b_sorted_vect = {2, 4};
std::transform
(
a_diff_sorted_vect.begin(), a_diff_sorted_vect.end(),
std::back_inserter(b_sorted_vect),
[](const A &a) -> B
{
B b;
b.key = a.key;
return b;
}
);
std::cout << "Printing b_sorted_vect" << "\n";
for(auto element : b_sorted_vect)
{
std::cout << std::to_string(element.key) << "\n";
}
std::cout << "Finished printing b_sorted_vect" << "\n";
/*
std::sort
(
b_sorted_vect.begin(),
b_sorted_vect.end(),
[](B lhs, B rhs)
{
return lhs.key < rhs.key;
}
);
std::cout << "Printing b_sorted_vect" << "\n";
for(auto element : b_sorted_vect)
{
std::cout << std::to_string(element.key) << "\n";
}
std::cout << "Finished printing b_sorted_vect" << "\n";
*/
return 0;
}
Output:
2
4
1
3
Desired output:
1
2
3
4
Ideally I would like to avoid the top-down std::sort at the end, as I think there might be a more efficient way to do that during construction and merging. The std::sort is my current solution.
The use of a third temporary vector might be necessary, which is fine.
This should be done with C++11, using boost if necessary.

C++ Abstract Classes and Inheritance

I have this problem I'm trying to solve. Basically the base class has the function map, which takes a vector as input and outputs the final vector after some mapping function, in this case - f, has been performed. However, I'm really lost as to why when I print out 2*testVector - test1 in the main function, I get proper output, i.e. 6, -182 etc... but when I print out 2*testVector - test 2, it's still the same vector.
This happens both when I create "DoubleElements" twice or just call the same "DoubleElements" pointer twice (it only ever performs 1 map). Am I fundamentally missing some understanding? Any help is appreciated!
#include <iostream>
#include <vector>
using namespace std;
class RecursiveBase {
public:
vector<int> map(vector<int> baseVector) {
static int iter = 0;
// Base case, return the final vector.
if (iter == 5) {
return baseVector;
// Replace the element with the old element mapped to the function.
} else {
baseVector[iter] = this->f(baseVector[iter]);
iter++;
return map(baseVector);
}
}
private:
virtual int f(int value) = 0;
};
class DoubleElements: public RecursiveBase {
private:
int f(int value) {
return 3*value;
}
};
int main() {
vector<int> testVector, o1, o2;
testVector.push_back(3);
testVector.push_back(-91);
testVector.push_back(-42);
testVector.push_back(-16);
testVector.push_back(13);
DoubleElements de;
DoubleElements de1;
RecursiveBase *test1 = &de;
RecursiveBase *test2 = &de1;
o1 = test1->map(testVector);
o2 = test2->map(testVector);
std::cout << "2*testVector - test1" << std::endl;
for (unsigned int iter = 0; iter < o1.size(); iter++) {
std::cout << o1[iter] << std::endl;
}
std::cout << "2*testVector - test2" << std::endl;
for (unsigned int iter = 0; iter < o2.size(); iter++) {
std::cout << o2[iter] << std::endl;
}
}
static int iter = 0;
You should avoid declaring local static variables in methods unless 100% necessary.
The first call will increment iter to 5, but on the next call, iter, since it's static, will not reset it's value to 0.
As an example, a simple program like:
void test()
{
static int x = 0;
++x;
cout << x << endl;
}
int main()
{
test();
test();
return 0;
}
Will output
1
2
From class.static.data/1:
A static data member is not part of the subobjects of a class.
For iter is static. It is part of the class RecursiveBase NOT part of the RecursiveBase objects.
To fix it, reset iter to 0:
if (iter == 5) {
iter = 0; // reset iter
return baseVector;
}
OUTPUT
2*testVector - test1
9
-273
-126
-48
39
2*testVector - test2
9
-273
-126
-48
39
You can only ever call RecursiveBase::map once as it stands, because the iter is static. You also assume that you will only ever call it with a 5 element std::vector<int>, at which point std::array<int, 5> is a better choice.
If you want a recursive solution, instead pass the index as an additional parameter
public:
std::vector<int> map(std::vector<int> vec) {
return do_map(vec, 0);
}
private:
std::vector<int> do_map(std::vector<int> & vec, std::size_t index) {
if (index == vec.size()) { return vec; }
vec[index] = f(vec[index]);
return do_map(vec, ++index);
}
But that's still a gratuitous use of recursion. A much better solution is
public:
std::vector<int> map(std::vector<int> vec) {
std::transform(vec.begin(), vec.end(), vec.begin(), [this](int i) { return f(i); });
return vec;
}
You also have superfluous RecursiveBase * in your main
int main() {
std::vector<int> testVector{3, -91, -42, -16, 13};
DoubleElements de;
DoubleElements de1;
// declare at point of initialisation
// don't need ->
auto o1 = de.map(testVector);
auto o2 = de1.map(testVector);
std::cout << "2*testVector - test1" << std::endl;
for (unsigned int iter = 0; iter < o1.size(); iter++) {
std::cout << o1[iter] << std::endl;
}
std::cout << "2*testVector - test2" << std::endl;
for (unsigned int iter = 0; iter < o2.size(); iter++) {
std::cout << o2[iter] << std::endl;
}
return 0;
}

How to determine size from (nested) std::initializer_list?

New to C++ and trying to wrap my head around initializer_list.
I'm making a Matrix class that effectively stores a 2d array of double values. I don't get the project on a structural level. Like okay we make a Matrix class that essentially stores a 2D array of data. But it needs to be able to store any size array, so it must use a dynamically allocated array. But std::array isn't allowed.
I have no idea how to access the items in the i_list. If they're passed in like
Matrix a = {{1, 2}, {3, 4}};
then according to the documentation I've seen, my only options for interaction with that information in the constructor are list.begin() which either points to the {1, 2} and list.end() which points to the {3,4}
std::vector and std::array are prohibited by the project description, and non-dynamic arrays obviously can't take in variables for size.
So how do I make this able to read a matrix of any size, and how do I take those values from my i_list and store them into something nondynamic?
I'm envisioning something like
Matrix::Matrix(const initializer_list & list) {
double * mat[/*somehow find out size without dynamic allocation*/];
for (double* i : mat) {
*i = list[i]; //not how i_list works apparently
}
}
Project description says:
You MAY NOT use library classes such as std::array, std::vector, std::list, etc. for this project. You must implement your Matrix class internally using a dynamically allocated array
initializer_lists are very cheap containers of [references to] temporary objects.
You can iterate over them as if they were arrays. In addition they also have a size() member so you can query their size.
Here is an example of passing a '2d' initializer_list to a function (which could easily be an constructor):
#include <initializer_list>
#include <iostream>
using list_of_doubles = std::initializer_list<double>;
using list_of_list_of_doubles = std::initializer_list<list_of_doubles>;
void info(list_of_list_of_doubles lld)
{
std::cout << "{\n";
for (auto& ld : lld) {
std::cout << " {";
auto sep = " ";
for (auto& d : ld) {
std::cout << sep << d;
sep = ", ";
}
std::cout << " }\n";
}
std::cout << "}\n";
}
int main()
{
info({
{ 1,2,3 },
{ 4.0, 5.0, 6.0 }
});
}
expected output:
{
{ 1, 2, 3 }
{ 4, 5, 6 }
}
Printing out the contents of the list is pretty simple, but what if I want to save them non-dynamically? I'm making a class constructor, and I want to have access to that data.
OK, so the requirement is that the storage in the class is non-dynamic (i.e. a fixed size).
I am going to make some assumptions:
let's say that the target class is a 3x3 matrix
any non-specified items in the initializer_list should be assumed to be zero.
passing in more than 3 rows or columns is a logic error and should cause an exception to be raised
Here's one (of many) ways:
#include <initializer_list>
#include <iostream>
#include <stdexcept>
#include <algorithm>
using list_of_doubles = std::initializer_list<double>;
using list_of_list_of_doubles = std::initializer_list<list_of_doubles>;
struct matrix
{
matrix(list_of_list_of_doubles lld)
: _storage {}
{
if (lld.size() > 3)
throw std::invalid_argument("too many rows");
auto row_idx = std::size_t { 0 };
for (auto& row : lld) {
if (row.size() > 3)
throw std::invalid_argument("too many columns");
std::copy(std::begin(row), std::end(row), std::begin(_storage[row_idx]));
++row_idx;
}
}
double _storage[3][3];
};
std::ostream& operator<<(std::ostream& os, const matrix& m)
{
std::cout << "{\n";
for (auto& ld : m._storage) {
std::cout << " {";
auto sep = " ";
for (auto& d : ld) {
std::cout << sep << d;
sep = ", ";
}
std::cout << " }\n";
}
return std::cout << "}";
}
int main()
{
matrix m({
{ 1,2,3 },
{ 4.1, 5.2, 6.3 },
{ 2.01, 4.5 } // ,0
});
std::cout << m << std::endl;
}
but I wanted a dynamically-sized 2-d array...
Oh go on then...
#include <initializer_list>
#include <iostream>
#include <algorithm>
#include <numeric>
using list_of_doubles = std::initializer_list<double>;
using list_of_list_of_doubles = std::initializer_list<list_of_doubles>;
std::size_t total_extent(const list_of_list_of_doubles& lld)
{
return std::accumulate(std::begin(lld), std::end(lld), std::size_t(0),
[](auto tot, auto& container) {
return tot + container.size();
});
}
struct matrix
{
using value_storage = std::unique_ptr<double[]>;
using index_storage = std::unique_ptr<std::size_t>;
matrix(list_of_list_of_doubles lld)
: _total_extent { total_extent(lld) }
, _rows { lld.size() }
, _indecies { new std::size_t[_rows] }
, _storage { new double [_total_extent] }
{
auto istorage = _storage.get();
auto iindex = _indecies.get();
for (auto& row : lld) {
*iindex++ = istorage - _storage.get();
istorage = std::copy(std::begin(row), std::end(row), istorage);
}
}
std::size_t rows() const {
return _rows;
}
const double* column(std::size_t row) const {
return std::addressof(_storage[_indecies[row]]);
}
std::size_t column_size(std::size_t row) const {
return row == _rows - 1
? _total_extent - _indecies[row]
: _indecies[row + 1] - _indecies[row];
}
std::size_t _total_extent, _rows;
std::unique_ptr<std::size_t[]> _indecies;
std::unique_ptr<double[]> _storage;
};
std::ostream& operator<<(std::ostream& os, const matrix& m)
{
std::cout << "{\n";
for (std::size_t row = 0 ; row < m.rows() ; ++row) {
std::cout << " {";
auto sep = " ";
for (std::size_t col = 0 ; col < m.column_size(row) ; ++col) {
std::cout << sep << m.column(row)[col];
sep = ", ";
}
std::cout << " }\n";
}
return std::cout << "}";
}
int main()
{
matrix m({
{ 1,2,3 },
{ 4.1, 5.2, 6.3 },
{ 2.01, 4.5 } // ,0
});
std::cout << m << std::endl;
}
Perhaps, you are looking for something like this:
struct Matrix {
Matrix(std::initializer_list<std::initializer_list<double>> m) {
int max=0;
for (auto l: m)
if (m.size()>max)
max= m.size();
std::cout << "your matriz seems to be: "
<< m.size() << ' ' << max << std::endl;
}
};

Change or delete elements of vector

I have following problem. My vector contains pairs of pairs (see example below).
In the example below I will push_back vector with some "random" data.
What will be best solution to delete the vector element if any of their values will be equal i.e. 100 and update value if less than 100.
i.e.
typedef std::pair<int, int> MyMap;
typedef std::pair<MyMap, MyMap> MyPair;
MyMap pair1;
MyMap pair2;
In first example I want to update this pair because pair1.first is less than 100
pair1.first = 0;
pair1.second = 101;
pair2.first = 101;
pair2.second = 101;
In second example I want to delete this pair because pair2.first is equal to 100
pair1.first = 0;
pair1.second = 101;
pair2.first = 100;
pair2.second = 101;
Using functor "check" I am able to delete one or more elements (in this example just one).
It is possible to increase every value of that pair by 1 using std::replace_if function?
Is there any function that will update this value if any of these values will be lower then "X" and delete if any of these values will be equal "X"?
I know how to do it writing my own function but I am curious.
#include "stdafx.h"
#include<algorithm>
#include<vector>
#include<iostream>
typedef std::pair<int, int> MyMap;
typedef std::pair<MyMap, MyMap> MyPair;
void PrintAll(std::vector<MyPair> & v);
void FillVectorWithSomeStuff(std::vector<MyPair> & v, int size);
class check
{
public:
check(int c)
: cmpValue(c)
{
}
bool operator()(const MyPair & mp) const
{
return (mp.first.first == cmpValue);
}
private:
int cmpValue;
};
int _tmain(int argc, _TCHAR* argv[])
{
const int size = 10;
std::vector<MyPair> vecotorOfMaps;
FillVectorWithSomeStuff(vecotorOfMaps, size);
PrintAll(vecotorOfMaps);
std::vector<MyPair>::iterator it = std::find_if(vecotorOfMaps.begin(), vecotorOfMaps.end(), check(0));
if (it != vecotorOfMaps.end()) vecotorOfMaps.erase(it);
PrintAll(vecotorOfMaps);
system("pause");
return 0;
}
std::ostream & operator<<(std::ostream & stream, const MyPair & mp)
{
stream << "First:First = " << mp.first.first << " First.Second = " << mp.first.second << std::endl;
stream << "Second:First = " << mp.second.first << " Second.Second = " << mp.second.second << std::endl;
stream << std::endl;
return stream;
}
void PrintAll(std::vector<MyPair> & v)
{
for (std::vector<MyPair>::iterator it = v.begin(); it != v.end(); ++it)
{
std::cout << *it;
}
}
void FillVectorWithSomeStuff(std::vector<MyPair> & v, int size)
{
for (int i = 0; i < size; ++i)
{
MyMap m1(i + i * 10, i + i * 20);
MyMap m2(i + i * 30, i + i * 40);
MyPair mp(m1, m2);
v.push_back(mp);
}
}
Use std::stable_partition, along with std::for_each:
#include <algorithm>
//...partition the elements in the vector
std::vector<MyPair>::iterator it =
std::stable_partition(vecotorOfMaps.begin(), vecotorOfMaps.end(), check(0));
//erase the ones equal to "check"
vecotorOfMaps.erase(vecotorOfMaps.begin(), it);
// adjust the ones that were left over
for_each(vecotorOfMaps.begin(), vecotorOfMaps.end(), add(1));
Basically, the stable_partition places all the items you will delete in the front of the array (the left side of the partiton it), and all of the other items to the right of it.
Then all that is done is to erase the items on the left of it (since they're equal to 100), and once that's done, go through the resulting vector, adding 1 to eac

STL non-copying wrapper around an existing array?

Is it possible to create an STL-like container, or even just an STL-style iterator, for an existing array of POD-type elements?
For example, suppose I have an array of ints. It would be convenient to be able to call some of the STL functions, such as find_if, count_if, or sort directly on this array.
Non-solution: copying the entire array, or even just references to the elements. The goal is to be very memory- and time-saving while hopefully allowing use of other STL algorithms.
You can call many of the STL algorithms directly on a regular C style array - they were designed for this to work. e.g.,:
int ary[100];
// init ...
std::sort(ary, ary+100); // sorts the array
std::find(ary, ary+100, pred); find some element
I think you'll find that most stuff works just as you would expect.
You can use an inline function template so that you don't have to duplicate the array index
template <typename T, int I>
inline T * array_begin (T (&t)[I])
{
return t;
}
template <typename T, int I>
inline T * array_end (T (&t)[I])
{
return t + I;
}
void foo ()
{
int array[100];
std::find (array_begin (array)
, array_end (array)
, 10);
}
All the STL algorithms use iterators.
A pointer is a valid iterator into an array of objects.
N.B.The end iterator must be one element past the end of the array. Hence the data+5 in the following code.
#include <algorithm>
#include <iostream>
#include <iterator>
int main()
{
int data[] = {4,3,7,5,8};
std::sort(data,data+5);
std::copy(data,data+5,std::ostream_iterator<int>(std::cout,"\t"));
}
You can use Boost.Array to create a C++ array type with STL semantics.
using arrays:
int a[100];
for (int i = 0; i < 100; ++i)
a[i] = 0;
using boost.arrays:
boost::array<int,100> a;
for (boost::array<int,100>::iterator i = a.begin(); i != a.end(); ++i)
*i = 0;
Update: With C++11, you can now use std::array.
A pointer is a valid model of an iterator:
struct Bob
{ int val; };
bool operator<(const Bob& lhs, const Bob& rhs)
{ return lhs.val < rhs.val; }
// let's do a reverse sort
bool pred(const Bob& lhs, const Bob& rhs)
{ return lhs.val > rhs.val; }
bool isBobNumberTwo(const Bob& bob) { return bob.val == 2; }
int main()
{
Bob bobs[4]; // ok, so we have 4 bobs!
const size_t size = sizeof(bobs)/sizeof(Bob);
bobs[0].val = 1; bobs[1].val = 4; bobs[2].val = 2; bobs[3].val = 3;
// sort using std::less<Bob> wich uses operator <
std::sort(bobs, bobs + size);
std::cout << bobs[0].val << std::endl;
std::cout << bobs[1].val << std::endl;
std::cout << bobs[2].val << std::endl;
std::cout << bobs[3].val << std::endl;
// sort using pred
std::sort(bobs, bobs + size, pred);
std::cout << bobs[0].val << std::endl;
std::cout << bobs[1].val << std::endl;
std::cout << bobs[2].val << std::endl;
std::cout << bobs[3].val << std::endl;
//Let's find Bob number 2
Bob* bob = std::find_if(bobs, bobs + size, isBobNumberTwo);
if (bob->val == 2)
std::cout << "Ok, found the right one!\n";
else
std::cout << "Whoops!\n";
return 0;
}