Convert int array to std::vector<int*> - c++

I'm trying to "convert" an integer C style array to std::vector<int*> without using a for loop, or rather insert pointers of all array items in a vector.
I'm currently implementing this by doing the follow:
for (size_t i = 0; i < 5; i++)
{
vector.push_back(&values[i]);
}
Is it possible to implement this by using std::vector::insert() and std::being/end?

std::transform is a useful algorithm in <algorithm> for copying values between containers that aren't implicitly compatible but for which you can provide a transformation function.
Here is an example of how you could populate a std::vector<int*> from a std::array<int, N>
int values[5] = { 1,2,3,4,5 };
std::vector<int*> v1;
std::transform(
std::begin(values), std::end(values), // Copy from
std::back_inserter(v1), // Copy to
[](auto& i) { // Transformation function
return &i;
});
Edit : Changed std::array<int, 5> to int[5] to account for edits in the question.

The code below is rather fancy way to do what you want, but it is generic and it doesn't use for loop - it just passes pointers of array's elements to vector constructor:
template<class T, size_t ... Ints, size_t N>
std::vector<T*> makePtrsHelper(std::array<T,N>& arr, std::index_sequence<Ints...>) {
return std::vector<T*>{ & std::get<Ints>(arr)... };
// vector ctor taking pointers to array's elements
}
template<class T, size_t N>
std::vector<T*> makePtrs(std::array<T,N>& array) {
return makePtrsHelper(array, std::make_index_sequence<N>{});
}
int main(){
std::array<int,5> ar{1,2,3,4,5};
std::vector<int*> v = makePtrs(ar);
Live demo

Note: as pointed out in comments my below answer is wrongly related to vector<int> not vector<int*> which was asked for in question.
Solution with std::copy and C-style array:
int ar[] = {1,2,3,4,3,2,1};
std::vector<int> vec;
std::copy(ar, ar+sizeof(ar)/sizeof(ar[0]), back_inserter(vec));

Related

How to add an unsigned char array after one unsigned char array and return a unsigned char pointer point to the combined new array? [duplicate]

How do I concatenate two std::vectors?
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
If you are using C++11, and wish to move the elements rather than merely copying them, you can use std::move_iterator along with insert (or copy):
#include <vector>
#include <iostream>
#include <iterator>
int main(int argc, char** argv) {
std::vector<int> dest{1,2,3,4,5};
std::vector<int> src{6,7,8,9,10};
// Move elements from src to dest.
// src is left in undefined but safe-to-destruct state.
dest.insert(
dest.end(),
std::make_move_iterator(src.begin()),
std::make_move_iterator(src.end())
);
// Print out concatenated vector.
std::copy(
dest.begin(),
dest.end(),
std::ostream_iterator<int>(std::cout, "\n")
);
return 0;
}
This will not be more efficient for the example with ints, since moving them is no more efficient than copying them, but for a data structure with optimized moves, it can avoid copying unnecessary state:
#include <vector>
#include <iostream>
#include <iterator>
int main(int argc, char** argv) {
std::vector<std::vector<int>> dest{{1,2,3,4,5}, {3,4}};
std::vector<std::vector<int>> src{{6,7,8,9,10}};
// Move elements from src to dest.
// src is left in undefined but safe-to-destruct state.
dest.insert(
dest.end(),
std::make_move_iterator(src.begin()),
std::make_move_iterator(src.end())
);
return 0;
}
After the move, src's element is left in an undefined but safe-to-destruct state, and its former elements were transfered directly to dest's new element at the end.
I would use the insert function, something like:
vector<int> a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
Or you could use:
std::copy(source.begin(), source.end(), std::back_inserter(destination));
This pattern is useful if the two vectors don't contain exactly the same type of thing, because you can use something instead of std::back_inserter to convert from one type to the other.
With C++11, I'd prefer following to append vector b to a:
std::move(b.begin(), b.end(), std::back_inserter(a));
when a and b are not overlapped, and b is not going to be used anymore.
This is std::move from <algorithm>, not the usual std::move from <utility>.
std::vector<int> first;
std::vector<int> second;
first.insert(first.end(), second.begin(), second.end());
I prefer one that is already mentioned:
a.insert(a.end(), b.begin(), b.end());
But if you use C++11, there is one more generic way:
a.insert(std::end(a), std::begin(b), std::end(b));
Also, not part of a question, but it is advisable to use reserve before appending for better performance. And if you are concatenating vector with itself, without reserving it fails, so you always should reserve.
So basically what you need:
template <typename T>
void Append(std::vector<T>& a, const std::vector<T>& b)
{
a.reserve(a.size() + b.size());
a.insert(a.end(), b.begin(), b.end());
}
With range v3, you may have a lazy concatenation:
ranges::view::concat(v1, v2)
Demo.
A general performance boost for concatenate is to check the size of the vectors. And merge/insert the smaller one with the larger one.
//vector<int> v1,v2;
if(v1.size()>v2.size()) {
v1.insert(v1.end(),v2.begin(),v2.end());
} else {
v2.insert(v2.end(),v1.begin(),v1.end());
}
If you want to be able to concatenate vectors concisely, you could overload the += operator.
template <typename T>
std::vector<T>& operator +=(std::vector<T>& vector1, const std::vector<T>& vector2) {
vector1.insert(vector1.end(), vector2.begin(), vector2.end());
return vector1;
}
Then you can call it like this:
vector1 += vector2;
There is an algorithm std::merge from C++17, which is very easy to use when the input vectors are sorted,
Below is the example:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
//DATA
std::vector<int> v1{2,4,6,8};
std::vector<int> v2{12,14,16,18};
//MERGE
std::vector<int> dst;
std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst));
//PRINT
for(auto item:dst)
std::cout<<item<<" ";
return 0;
}
You should use vector::insert
v1.insert(v1.end(), v2.begin(), v2.end());
If you are interested in strong exception guarantee (when copy constructor can throw an exception):
template<typename T>
inline void append_copy(std::vector<T>& v1, const std::vector<T>& v2)
{
const auto orig_v1_size = v1.size();
v1.reserve(orig_v1_size + v2.size());
try
{
v1.insert(v1.end(), v2.begin(), v2.end());
}
catch(...)
{
v1.erase(v1.begin() + orig_v1_size, v1.end());
throw;
}
}
Similar append_move with strong guarantee can't be implemented in general if vector element's move constructor can throw (which is unlikely but still).
If your goal is simply to iterate over the range of values for read-only purposes, an alternative is to wrap both vectors around a proxy (O(1)) instead of copying them (O(n)), so they are promptly seen as a single, contiguous one.
std::vector<int> A{ 1, 2, 3, 4, 5};
std::vector<int> B{ 10, 20, 30 };
VecProxy<int> AB(A, B); // ----> O(1)!
for (size_t i = 0; i < AB.size(); i++)
std::cout << AB[i] << " "; // ----> 1 2 3 4 5 10 20 30
Refer to https://stackoverflow.com/a/55838758/2379625 for more details, including the 'VecProxy' implementation as well as pros & cons.
Add this one to your header file:
template <typename T> vector<T> concat(vector<T> &a, vector<T> &b) {
vector<T> ret = vector<T>();
copy(a.begin(), a.end(), back_inserter(ret));
copy(b.begin(), b.end(), back_inserter(ret));
return ret;
}
and use it this way:
vector<int> a = vector<int>();
vector<int> b = vector<int>();
a.push_back(1);
a.push_back(2);
b.push_back(62);
vector<int> r = concat(a, b);
r will contain [1,2,62]
Using C++20 you can get rid of begin() and end() with ranges.
#include <ranges>
std::ranges::copy(vec2, std::back_inserter(vec1));
or if you want to move elements:
std::ranges::move(vec2, std::back_inserter(vec1));
Here's a general purpose solution using C++11 move semantics:
template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, const std::vector<T>& rhs)
{
if (lhs.empty()) return rhs;
if (rhs.empty()) return lhs;
std::vector<T> result {};
result.reserve(lhs.size() + rhs.size());
result.insert(result.cend(), lhs.cbegin(), lhs.cend());
result.insert(result.cend(), rhs.cbegin(), rhs.cend());
return result;
}
template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, const std::vector<T>& rhs)
{
lhs.insert(lhs.cend(), rhs.cbegin(), rhs.cend());
return std::move(lhs);
}
template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, std::vector<T>&& rhs)
{
rhs.insert(rhs.cbegin(), lhs.cbegin(), lhs.cend());
return std::move(rhs);
}
template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, std::vector<T>&& rhs)
{
if (lhs.empty()) return std::move(rhs);
lhs.insert(lhs.cend(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
return std::move(lhs);
}
Note how this differs from appending to a vector.
You can prepare your own template for + operator:
template <typename T>
inline T operator+(const T & a, const T & b)
{
T res = a;
res.insert(res.end(), b.begin(), b.end());
return res;
}
Next thing - just use +:
vector<int> a{1, 2, 3, 4};
vector<int> b{5, 6, 7, 8};
for (auto x: a + b)
cout << x << " ";
cout << endl;
This example gives output:
1 2 3 4 5 6 7 8
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));
I've implemented this function which concatenates any number of containers, moving from rvalue-references and copying otherwise
namespace internal {
// Implementation detail of Concatenate, appends to a pre-reserved vector, copying or moving if
// appropriate
template<typename Target, typename Head, typename... Tail>
void AppendNoReserve(Target* target, Head&& head, Tail&&... tail) {
// Currently, require each homogenous inputs. If there is demand, we could probably implement a
// version that outputs a vector whose value_type is the common_type of all the containers
// passed to it, and call it ConvertingConcatenate.
static_assert(
std::is_same_v<
typename std::decay_t<Target>::value_type,
typename std::decay_t<Head>::value_type>,
"Concatenate requires each container passed to it to have the same value_type");
if constexpr (std::is_lvalue_reference_v<Head>) {
std::copy(head.begin(), head.end(), std::back_inserter(*target));
} else {
std::move(head.begin(), head.end(), std::back_inserter(*target));
}
if constexpr (sizeof...(Tail) > 0) {
AppendNoReserve(target, std::forward<Tail>(tail)...);
}
}
template<typename Head, typename... Tail>
size_t TotalSize(const Head& head, const Tail&... tail) {
if constexpr (sizeof...(Tail) > 0) {
return head.size() + TotalSize(tail...);
} else {
return head.size();
}
}
} // namespace internal
/// Concatenate the provided containers into a single vector. Moves from rvalue references, copies
/// otherwise.
template<typename Head, typename... Tail>
auto Concatenate(Head&& head, Tail&&... tail) {
size_t totalSize = internal::TotalSize(head, tail...);
std::vector<typename std::decay_t<Head>::value_type> result;
result.reserve(totalSize);
internal::AppendNoReserve(&result, std::forward<Head>(head), std::forward<Tail>(tail)...);
return result;
}
This solution might be a bit complicated, but boost-range has also some other nice things to offer.
#include <iostream>
#include <vector>
#include <boost/range/algorithm/copy.hpp>
int main(int, char**) {
std::vector<int> a = { 1,2,3 };
std::vector<int> b = { 4,5,6 };
boost::copy(b, std::back_inserter(a));
for (auto& iter : a) {
std::cout << iter << " ";
}
return EXIT_SUCCESS;
}
Often ones intention is to combine vector a and b just iterate over it doing some operation. In this case, there is the ridiculous simple join function.
#include <iostream>
#include <vector>
#include <boost/range/join.hpp>
#include <boost/range/algorithm/copy.hpp>
int main(int, char**) {
std::vector<int> a = { 1,2,3 };
std::vector<int> b = { 4,5,6 };
std::vector<int> c = { 7,8,9 };
// Just creates an iterator
for (auto& iter : boost::join(a, boost::join(b, c))) {
std::cout << iter << " ";
}
std::cout << "\n";
// Can also be used to create a copy
std::vector<int> d;
boost::copy(boost::join(a, boost::join(b, c)), std::back_inserter(d));
for (auto& iter : d) {
std::cout << iter << " ";
}
return EXIT_SUCCESS;
}
For large vectors this might be an advantage, as there is no copying. It can be also used for copying an generalizes easily to more than one container.
For some reason there is nothing like boost::join(a,b,c), which could be reasonable.
For containers which offer push_back (string, vector, deque, ...):
std::copy(std::begin(input), std::end(input), std::back_inserter(output))
and
for containers which offer insert (maps, sets):
std::copy(std::begin(input), std::end(input), std::inserter(output, output.end()))
If what you're looking for is a way to append a vector to another after creation, vector::insert is your best bet, as has been answered several times, for example:
vector<int> first = {13};
const vector<int> second = {42};
first.insert(first.end(), second.cbegin(), second.cend());
Sadly there's no way to construct a const vector<int>, as above you must construct and then insert.
If what you're actually looking for is a container to hold the concatenation of these two vector<int>s, there may be something better available to you, if:
Your vector contains primitives
Your contained primitives are of size 32-bit or smaller
You want a const container
If the above are all true, I'd suggest using the basic_string who's char_type matches the size of the primitive contained in your vector. You should include a static_assert in your code to validate these sizes stay consistent:
static_assert(sizeof(char32_t) == sizeof(int));
With this holding true you can just do:
const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());
For more information on the differences between string and vector you can look here: https://stackoverflow.com/a/35558008/2642059
For a live example of this code you can look here: http://ideone.com/7Iww3I
You can do it with pre-implemented STL algorithms using a template for a polymorphic type use.
#include <iostream>
#include <vector>
#include <algorithm>
template<typename T>
void concat(std::vector<T>& valuesa, std::vector<T>& valuesb){
for_each(valuesb.begin(), valuesb.end(), [&](int value){ valuesa.push_back(value);});
}
int main()
{
std::vector<int> values_p={1,2,3,4,5};
std::vector<int> values_s={6,7};
concat(values_p, values_s);
for(auto& it : values_p){
std::cout<<it<<std::endl;
}
return 0;
}
You can clear the second vector if you don't want to use it further (clear() method).
Concatenate two std::vector-s with for loop in one std::vector.
std::vector <int> v1 {1, 2, 3}; //declare vector1
std::vector <int> v2 {4, 5}; //declare vector2
std::vector <int> suma; //declare vector suma
for(int i = 0; i < v1.size(); i++) //for loop 1
{
suma.push_back(v1[i]);
}
for(int i = 0; i< v2.size(); i++) //for loop 2
{
suma.push_back(v2[i]);
}
for(int i = 0; i < suma.size(); i++) //for loop 3-output
{
std::cout << suma[i];
}
To be honest, you could fast concatenate two vectors by copy elements from two vectors into the other one or just only append one of two vectors!. It depends on your aim.
Method 1: Assign new vector with its size is the sum of two original vectors' size.
vector<int> concat_vector = vector<int>();
concat_vector.setcapacity(vector_A.size() + vector_B.size());
// Loop for copy elements in two vectors into concat_vector
Method 2: Append vector A by adding/inserting elements of vector B.
// Loop for insert elements of vector_B into vector_A with insert()
function: vector_A.insert(vector_A .end(), vector_B.cbegin(), vector_B.cend());
Try, create two vectors and add second vector to first vector,
code:
std::vector<int> v1{1,2,3};
std::vector<int> v2{4,5};
for(int i = 0; i<v2.size();i++)
{
v1.push_back(v2[i]);
}
v1:1,2,3.
Description:
While i int not v2 size, push back element , index i in v1 vector.

how to save vector from c++ to c [duplicate]

How do I convert a std::vector<double> to a double array[]?
There's a fairly simple trick to do so, since the spec now guarantees vectors store their elements contiguously:
std::vector<double> v;
double* a = &v[0];
What for? You need to clarify: Do you need a pointer to the first element of an array, or an array?
If you're calling an API function that expects the former, you can do do_something(&v[0], v.size()), where v is a vector of doubles. The elements of a vector are contiguous.
Otherwise, you just have to copy each element:
double arr[100];
std::copy(v.begin(), v.end(), arr);
Ensure not only thar arr is big enough, but that arr gets filled up, or you have uninitialized values.
For C++11, vector.data() will do the trick.
vector<double> thevector;
//...
double *thearray = &thevector[0];
This is guaranteed to work by the standard, however there are some caveats: in particular take care to only use thearray while thevector is in scope.
As to std::vector<int> vec, vec to get int*, you can use two method:
int* arr = &vec[0];
int* arr = vec.data();
If you want to convert any type T vector to T* array, just replace the above int to T.
I will show you why does the above two works, for good understanding?
std::vector is a dynamic array essentially.
Main data member as below:
template <class T, class Alloc = allocator<T>>
class vector{
public:
typedef T value_type;
typedef T* iterator;
typedef T* pointer;
//.......
private:
pointer start_;
pointer finish_;
pointer end_of_storage_;
public:
vector():start_(0), finish_(0), end_of_storage_(0){}
//......
}
The range (start_, end_of_storage_) is all the array memory the vector allocate;
The range(start_, finish_) is all the array memory the vector used;
The range(finish_, end_of_storage_) is the backup array memory.
For example, as to a vector vec. which has {9, 9, 1, 2, 3, 4} is pointer may like the below.
So &vec[0] = start_ (address.) (start_ is equivalent to int* array head)
In c++11 the data() member function just return start_
pointer data()
{
return start_; //(equivalent to `value_type*`, array head)
}
Vectors effectively are arrays under the skin. If you have a function:
void f( double a[]);
you can call it like this:
vector <double> v;
v.push_back( 1.23 )
f( &v[0] );
You should not ever need to convert a vector into an actual array instance.
std::vector<double> vec;
double* arr = vec.data();
We can do this using data() method. C++11 provides this method.
Code Snippet
#include<bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
vector<int>v = {7, 8, 9, 10, 11};
int *arr = v.data();
for(int i=0; i<v.size(); i++)
{
cout<<arr[i]<<" ";
}
return 0;
}
If you have a function, then you probably need this:foo(&array[0], array.size());. If you managed to get into a situation where you need an array then you need to refactor, vectors are basically extended arrays, you should always use them.
You can do some what like this
vector <int> id;
vector <double> v;
if(id.size() > 0)
{
for(int i = 0; i < id.size(); i++)
{
for(int j = 0; j < id.size(); j++)
{
double x = v[i][j];
cout << x << endl;
}
}
}

use std:array as an argument of function

I have seen here :http://www.cplusplus.com/doc/tutorial/arrays/
that
int[N] is the same as std::array<int,N> in C++.
I would like to use this notation in order to avoid to pass N as an argument of a function.
I would like to do something like that
returnedType function(array tab)
instead of
returnedType function(int tab, int N)
but i can't make the type array because i must write array<int,N> and i don't know N in advance.
Has Somebody a solution?
Make the function a function template, like so:
template <size_t N>
void function(std::array<int, N> arr)
{
// do something with arr
}
and call it like:
int main()
{
std::array<int, 3> a;
function(a);
std::array<int, 15> b;
function(b);
}
if you do not know the size in advance, std::vector is what you want
//function taking vector:
int MyFunc(const std::vector<int>& vec)
{
//.. do stuff
return 5;
}
std::vector<int> myvec;
//add somme entries:
myvec.push_back(1);
myvec.push_back(2);
myvec.push_back(3);
//call function:
int res = MyFunc(myvec);

Writing contents of a int array into a vector

I want to write contents of an array into a vector.
int A[]={10,20,30,40,50,60,70,80,90};
vector<int> my_vector;
Earlier I used to copy the contents of array A into another array B using memcpy. I want to use my_vector instead of array B
How to write contents of array A into my_vector in one shot without a for loop?
Using C++ 2011 you want to use
std::copy(std::begin(A), std::end(A), std::back_inserter(my_vector));
... or
std::vector<int> my_vector(std::begin(A), std::end(A));
... or, actually:
std::vector<int> my_vector({ 10, 20, 30, 40, 50, 60, 70, 80, 90 });
If you don't have C++ 2011, you want to define
namespace whatever {
template <typename T, int Size>
T* begin(T (&array)[Size]) { return array; }
template <typename T, int Size>
T* end(T (&array)[Size]) { return array + Size; }
}
and use whatever::begin() and whatever::end() together with one of the first two approaches.
#include <algorithm>
#include <vector>
int main() {
int A[]={10,20,30,40,50,60,70,80,90};
std::vector<int> my_vector;
unsigned size = sizeof(A)/sizeof(int);
std::copy(&A[0],&A[size],std::back_inserter(my_vector));
}
C++11 is much simpler.
#include <vector>
#include <algorithm>
int main() {
int A[]={10,20,30,40,50,60,70,80,90};
std::vector<int> my_vector(std::begin(A),std::end(A));
}
You can use memcpy, or use such initialization in C++98/03.
int A[]={10,20,30,40,50,60,70,80,90};
vector<int> my_vector(A, A + sizeof(A) / sizeof(*A));
Also you can use algorithm, such as copy.
std::copy(A, A + sizeof(A) / sizeof(*A), std::back_inserter(my_vector));
In C++11, use std::begin(A), std::end(A) for begin and end of array.

How to convert vector to array

How do I convert a std::vector<double> to a double array[]?
There's a fairly simple trick to do so, since the spec now guarantees vectors store their elements contiguously:
std::vector<double> v;
double* a = &v[0];
What for? You need to clarify: Do you need a pointer to the first element of an array, or an array?
If you're calling an API function that expects the former, you can do do_something(&v[0], v.size()), where v is a vector of doubles. The elements of a vector are contiguous.
Otherwise, you just have to copy each element:
double arr[100];
std::copy(v.begin(), v.end(), arr);
Ensure not only thar arr is big enough, but that arr gets filled up, or you have uninitialized values.
For C++11, vector.data() will do the trick.
vector<double> thevector;
//...
double *thearray = &thevector[0];
This is guaranteed to work by the standard, however there are some caveats: in particular take care to only use thearray while thevector is in scope.
As to std::vector<int> vec, vec to get int*, you can use two method:
int* arr = &vec[0];
int* arr = vec.data();
If you want to convert any type T vector to T* array, just replace the above int to T.
I will show you why does the above two works, for good understanding?
std::vector is a dynamic array essentially.
Main data member as below:
template <class T, class Alloc = allocator<T>>
class vector{
public:
typedef T value_type;
typedef T* iterator;
typedef T* pointer;
//.......
private:
pointer start_;
pointer finish_;
pointer end_of_storage_;
public:
vector():start_(0), finish_(0), end_of_storage_(0){}
//......
}
The range (start_, end_of_storage_) is all the array memory the vector allocate;
The range(start_, finish_) is all the array memory the vector used;
The range(finish_, end_of_storage_) is the backup array memory.
For example, as to a vector vec. which has {9, 9, 1, 2, 3, 4} is pointer may like the below.
So &vec[0] = start_ (address.) (start_ is equivalent to int* array head)
In c++11 the data() member function just return start_
pointer data()
{
return start_; //(equivalent to `value_type*`, array head)
}
Vectors effectively are arrays under the skin. If you have a function:
void f( double a[]);
you can call it like this:
vector <double> v;
v.push_back( 1.23 )
f( &v[0] );
You should not ever need to convert a vector into an actual array instance.
std::vector<double> vec;
double* arr = vec.data();
We can do this using data() method. C++11 provides this method.
Code Snippet
#include<bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
vector<int>v = {7, 8, 9, 10, 11};
int *arr = v.data();
for(int i=0; i<v.size(); i++)
{
cout<<arr[i]<<" ";
}
return 0;
}
If you have a function, then you probably need this:foo(&array[0], array.size());. If you managed to get into a situation where you need an array then you need to refactor, vectors are basically extended arrays, you should always use them.
You can do some what like this
vector <int> id;
vector <double> v;
if(id.size() > 0)
{
for(int i = 0; i < id.size(); i++)
{
for(int j = 0; j < id.size(); j++)
{
double x = v[i][j];
cout << x << endl;
}
}
}