How to efficiently fill-in a structure with vectors? - c++

I am not expert in C++ but I believe this is not the most elegant solution:
#include <iostream>
#include <vector>
struct coord {
int x;
int y;
};
int main()
{ std::vector<int> a {1,2,3,4,5};
std::vector<int> b {10,20,30,40,50};
int i;
std::vector<coord> loc (5);
for (i=0;i<5;i++)
{ loc[i].x = a[i];
loc[i].y = b[i];
}
return 0;
}
Does anyone has a better solution ?

It looks like you are using C++11. While I'm not 100% sure this should work:
std::vector<coord> loc { {1, 10}, {2, 20}, {3, 30}, {4, 40}, {5, 50} };

What are you trying to accomplish by creating two vectors just to fill one vector? Your method is inefficient when it comes to declaring two independent vectors to assign into one single vector, and also messy. Remove the two vectors and set the values of your vector using brackets
= { {val1,val2} {val1,val2} {val1,val2} }
But if you would like to stick with your vector filling method and HAVE to use a vector, just one one vector that holds both the values of a and b and loop as such
//check to make sure size is even
for(int i = 0; i < vect.size(); i +=2)
{
vect[i].x = a[i];
vect[i].y = a[i+1];
}

Related

How to determine at compile time if two vectors have the same length in C++?

Let's say I have the following code:
// A function that modifies the values in the 2 vectors
// But it needs the 2 vectors to have the same length
void compute(std::vector<int> &prev_state, std::vector<int> &curr_state);
int main() {
std::vector<int> a = {1, 2, 3};
std::vector<int> b = {4, 5};
a.push_back(3);
b.push_back(6);
b.push_back(7);
for (int i = 0; i < 1000000; i++) {
compute(a, b);
}
}
I would like to determine at compile time if when I call compute, the 2 vectors have the same length. For example, the following code should fail at compile time:
// A function that modifies the values in the 2 vectors
// But it needs the 2 vectors to have the same length
void compute(std::vector<int> &prev_state, std::vector<int> &curr_state);
int main() {
std::vector<int> a = {1, 2, 3};
std::vector<int> b = {4, 5};
a.push_back(3);
b.push_back(6);
for (int i = 0; i < 1000000; i++) {
// THIS SHOULD FAIL AT COMPILE TIME BECAUSE a.size() IS 4 AND b.size() IS 5
compute(a, b);
}
}
I know there is at least a runtime solution for this: adding an if condition that checks the sizes of the vectors. But, if I call the compute times a lot, that might cost me performance.
I know there's a solution with std::array instead of std::vector:
// A function that modifies the values in the 2 vectors
// But it needs the 2 vectors to have the same length
template <size_t N>
void compute(std::array<int, N> &prev_state, std::array<int, N> &curr_state);
int main() {
std::array<int, 64> a = {1, 2, 3};
std::array<int, 64> b = {4, 5};
for (int i = 0; i < 1000000; i++) {
compute(a, b);
}
}
But this is too restrictive, as you have to establish the array's length at initialization. And it would generate a different function for every array length for which the function is called. I don't want this. I just want the compiler to check that the lengths are equal when I call compute.
I understand that from just using a std::vector it's impossible because there are ways to modify the vector such that we don't know the length at runtime. But we might still be able to determine that 2 vectors have the same length. For example:
int main() {
// Here, we know a.size() is 3
std::vector<int> a = {1, 2, 3};
std::vector<int> b = {4, 5, 6, 7};
int n;
std::cin >> n;
while(n--) {
a.push_back(n);
b.push_back(n);
}
b.pop();
// Here, a and b have both length n + 3
// I would like the compiler to determine that they have the same length
// Even if it doesn't know n
}
I understand that it's a hard problem for the compiler to determine the size of the vector. At least, I want to know is if there are any type hints or features that C++ has that limits the operations that we can do on a vector, such that its length can be determined at compile time.
Tl;DR
My questions are:
Given a vector, after applying some operations on it, can the compiler determine its length?
If not, is there a way to limit the operations on the vector such that the compiler
can determine its length?
Can the compiler determine if 2 vectors have the same length?
Does C++ have any compile time features that can help us check if a relation between two objects holds?
Use a single vector.
struct states_type
{
int prev;
int curr;
};
void compute(std::vector<states_type> &states);
int main() {
std::vector<states_type> a;
a.push_back({1,4});
a.push_back({2,5});
a.push_back({3,6});
for (int i = 0; i < 1000000; i++) {
compute(a);
}
}

A good way to construct a vector of 2d array

What I want to do is
double A[2][2] = {
{4, 7},
{2, 6}
};
std::vector<double[2][2]> B;
for (int i = 1; i <= 5; i++)
{
B.push_back(A);
}
But C++ cannot store an array in std::vector, what is the proper (speed) way to do that? Is A[2][2] faster than std::arraydue to cache coherency?
std::array is probably the best way to go here. It should preform nearly identically to the C style array you've got:
#include <array>
#include <vector>
int main() {
using Array2d = std::array<std::array<double, 2>, 2>;
Array2d A = {{{4, 7}, {2, 6}}};
std::vector<Array2d> B;
for (int i = 1; i <= 5; i++) {
B.push_back(A);
}
}

How to push_back() C array into std::vector [duplicate]

This question already has answers here:
Correct way to work with vector of arrays
(4 answers)
Closed 2 years ago.
This doesn't compile:
vector<int[2]> v;
int p[2] = {1, 2};
v.push_back(p); //< compile error here
https://godbolt.org/z/Kabq8Y
What's the alternative? I don't want to use std::array.
The std::vector declaration on itself compiles. It's the push_back that doesn't compile.
You could use a structure containing an array, or a structure containing two integers, if you really don't want to use std::array:
struct coords {
int x, y;
};
vector<coords> v;
coords c = {1, 2};
v.push_back(c);
alternatively, as mentioned, you could use a structure containing an array:
struct coords {
int x[2];
};
vector<coords> v;
coords c = {1, 2};
v.push_back(c);
Use std::array:
vector<std::array<int, 2>> v;
std::array<int, 2> p = {1, 2};
v.push_back(p);
I think you should check the C++ reference for vectors.
http://www.cplusplus.com/reference/vector/vector/vector/
You can see in the example, there is explained every way you can initialize a vector.
I think that for your case you need to do:
std::vector<int> v({ 1, 2 });
v.push_back(3);
As an alternative, as you explicitly state that std::array is not to be used, you could use pointers, it's kind of an oddball solution but it would work:
#include <iostream>
#include <vector>
int main()
{
const int SIZE = 2;
std::vector<int*> v;
static int p[SIZE] = {1, 2}; //extended lifetime, static storage duration
int *ptr[SIZE]; //array of pointers, one for each member of the array
for(int i = 0; i < SIZE; i++){
ptr[i] = &p[i]; //assign pointers
}
v.push_back(*ptr); //insert pointer to the beginning of ptr
for(auto& n : v){
for(int i = 0; i < SIZE; i++){
std::cout << n[i] << " "; //output: 1 2
}
}
}

set multiple array variables at the same time (c++)

I'm trying to make an ASCII art using C++, and having some problems in arrays.
Is there any way to set multiple array variables at the same time?
Let me be more specific.
When you initialize an array, you can do this way.
int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
By the way shown above, you can set 10 array variables at the same time.
However, I want to (re) set some of the array variables like this?
a[1] = 3;
a[4] = 2;
a[5] = 2;
a[7] = 2;
Since there is NO rule in the variables, I can't do
for(int i=0; i<10; i++) a[i] = i+1;
fill(n);
I can't use an for statement or the fill, fill_n function, since there is no regularity.
To sum up,
Is there any way to set more than 1 array variables at the same time? (Like the second code snipplet above?
Given a index-value mapping list, and assign it one by one.
template<typename T, size_t N>
void Update(T(&arr)[N], const std::vector<std::pair<size_t, T>>& mappings)
{
for (const auto& mapping : mappings)
if(mapping.first < N)
arr[mapping.first] = arr[mapping.second];
}
int main()
{
int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Update(arr, { {1, 3}, {4, 2}, {5, 2}, {7, 2} });
return 0;
}
As far as I'm aware without a pattern a control structure is kind of redundant, you might be better served reading from a file.
// for user input
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
for (int i = 0; i < 10; i++) {
cout << "Please input your value for array index " << i << endl;
cin >> arr[i];
}
// for manual input in initalization
int arr[10] = { 0, 3, 2, 2, 2, 5, 6, 7, 8, 9 };
However a better approach might be to read it from a file, http://www.cplusplus.com/forum/general/58945/ Read "TheMassiveChipmunk"'s post there for exactly how to do it.
Assuming you know which indices you will be changing upfront you can use a separate index array:
int ind[4]= {1,4,5,7};
..and an accompanying array with values
int new_val[4] = {3,2,2,2};
The you can use the following for loop to assign the values:
for (int i=0; i<4; i++)
arr[ind[i]] = new_val[i];
You should also use some variable signifying the number of indices to be changed like int val_num = 4 instead of plain number 4.
Changes that are defined in runtime to an array can be easily implemented by using a list to save tuples that represent the changes you want to make. As an example, we can write:
#include <tuple>
#include <list>
#include <iostream>
using namespace std;
typedef tuple <int, int> Change;
int main() {
int a[5] = {1,2,3,4,5};
list<Change> changes;
//represents changing the 2-th entry to 8.
Change change(2,8);
changes.push_back(change);
for(auto current_change: changes)
a[get<0>(current_change)] = get<1>(current_change);
cout << a[2] << '\n';
}
Prints 8.

Pushing an array into a vector

I've a 2d array, say A[2][3]={{1,2,3},{4,5,6}}; and I want to push it into a 2D vector(vector of vectors). I know you can use two for loops to push the elements one by on on to the first vector and then push that into the another vector which makes it 2d vector but I was wondering if there is any way in C++ to do this in a single loop. For example I want to do something like this:
myvector.pushback(A[1]+3); // where 3 is the size or number of columns in the array.
I understand this is not a correct code but I put this just for understanding purpose. Thanks
The new C++0x standard defines initializer_lists which allows you to:
vector<vector<int>> myvector = {{1,2,3},{4,5,6}};
gcc 4.3+ and some other compilers have partial C++0x support.
for gcc 4.3+ you could enable c++0x support by adding the flag -std=c++0x
Its not the best way to have your static data represented like that. However, if your compiler vendor supports C++ tr1 then you could do:
#include <tr1/array> // or #include <array>
...
typedef vector<vector<int> > vector2d;
vector2d myvector;
// initialize the vectors
myvector.push_back(vector<int>());
myvector.push_back(vector<int>());
typedef std::array<std::array<int, 3>, 2> array2d;
array2d array = {{1,2,3},{4,5,6}};
array2d::const_iterator ai = array.begin(), ae = array.end();
for (vector2d::iterator i = myvector.begin(), e = myvector.end()
; i != e && ai != ae
; i++, a++)
{
// reserve vector space
i->reserve(array.size());
// copy array content to vector
std::copy(ai.begin(), ai->end(), i->begin());
}
You can use vector::assign (pointers to array elements are valid iterators):
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
std::vector<std::vector<int> > v(2);
for (size_t i = 0; i < 2; ++i)
v[i].assign(a[i], a[i] + 3);
This is a little tricky, but you could use template recursion to help you in having the assignment done almost completely at compile-time. I understand that's not exactly what you are looking for, but I think it's worthwhile :-)
Here's the code:
#include <vector>
using namespace std;
typedef vector<vector<int> > vector2d;
template<size_t K, size_t M, size_t N>
struct v_copy {
static void copy(vector2d& v, int(&a)[M][N])
{
v[K - 1].assign(a[K - 1], a[K - 1] + N);
v_copy<K - 1, M, N>::copy(v, a);
}
};
template<size_t M, size_t N>
struct v_copy<1, M, N> {
static void copy(vector2d& v, int(&a)[M][N])
{
v[0].assign(a[0], a[0] + N);
}
};
template<size_t M, size_t N>
void copy_2d(vector2d& v, int(&a)[M][N])
{
v_copy<M, M, N>::copy(v, a);
}
int main()
{
int A[2][3] = {{0, 1, 2}, {10, 11, 12}};
vector2d vector(2);
copy_2d(vector, A);
}
it needed a struct because in C++ you can't do partial specialization of functions. BTW , compiling it with gcc version 4.5.0, this code produces the same assembly as
vector[1].assign(A[1], A[1] + 3);
vector[0].assign(A[0], A[0] + 3);
It should not be very hard to have it compile with different types of 2-dimensions arrays.
If you want to push the data into vector of vectors, you have to write something like this:
vector<int> inner;
vector< vector<int> >outer;
...
outer.pushback(inner);
I think there is no way to do it in a single loop.
If you want to use just one vector (something similar like you written), then you can do it in a single loop:
int A[2][3]={{1,2,3},{4,5,6}};
int* p = A[0];
std::vector<int> inner;
std::vector< std::vector<int> >outer;
for(int i = 0; i < 6; ++i)
{
inner.push_back(*p++);
}
It's kind of cheating, but you could take advantage of the vector constructor to do one of the loops for you:
#include <vector>
int main() {
const int XMAX = 2, YMAX = 3;
int A[XMAX][YMAX] = {{1,2,3}, {4,5,6}};
std::vector<std::vector<int> > v;
for (size_t x = 0; x < XMAX; ++x) {
v.push_back(std::vector<int>(&A[x][0], &A[x][YMAX]));
}
}
You can resize vectors and then use copy.
int A[2][3]={{1,2,3},{4,5,6}};
std::vector< std::vector<int> > vec;
vec.resize(2);
for (int i=0; i<2; i++)
{
vec[i].resize(3);
std::copy(A[i], A[i]+3, vec[i].begin());
}
Is it practical? Definetly not.
Hm... I can produce a partial answer but not a full one.
int elementCount = 6; // I wonder if this can be done somehow with sizeof(A) * sizeof(A[0])
int* end = A + elementCount;
for(int* current = A; current < end; ++current) {
myvector.pushback(*current);
}
No. The only thing you can do is leverage existing loop functions so that you only have to write one or zero of your own loops.