Converting from a std::vector<int> to a char[] C++ - c++

If I have an integer vector (std::vector) is there an easy way to convert everything in that vector to a char array(char[]) so (1,2,3) -> ('1','2','3')
This is what I have tried, but it doesn't work:
std::vector<int> v;
for(int i = 1; i < 10; i++){
v.push_back(i);
}
char *a = &v[0];

std::transform is the right tool for the job :
std::vector<int> iv {1, 2, 3, 4, 5, 6};
char ca[10] {};
using std::begin;
using std::end;
std::transform(begin(iv), end(iv), begin(ca), [](int i) { return '0' + i; });
If you don't need ca to be a C-style array, I'd recommend using std::array or std::vector instead. The latter needs std::back_inserter(ca) in place of begin(ca).

It can be as simple as this
std::vector<int> v { 1, 2, 3 };
std::vector<char> c;
for( int i : v ) c.push_back( '0' + i );
to realize why your way does not work you need to learn how integers and symbls represented on your platform.

Why not store it in char vector initially?
std::vector<char> v;
for(int i = 1; i < 10; i++){
v.push_back(i + '0');
}
Trick from: https://stackoverflow.com/a/2279401/47351

You can use std::transform with std::back_inserter, maybe something like this:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> vI{0,1,2,3,4,5,6,7,8,9};
std::vector<char> vC;
std::transform(vI.begin(), vI.end(), std::back_inserter(vC), [](const int &i){ return '0'+i; });
for(const auto &i: vC)
{
std::cout << i << std::endl;
}
return 0;
}

If you've already got the numbers in a vector then you can use std::transform and a back_inserter:
std::vector<int> v;
std::vector<char> c;
std::transform(v.begin(), v.end(), std::back_inserter(c), [](int i){return '0' + i;});
However, why not just say:
std::vector<char> v;
for(char i = '0'; i < '9'; i++)
{
v.push_back(i);
}

Related

Create a vector with repeated entries of each Element

I want to expand a given vector by repeating every entry three times. For example, if the vector is [5,7]. The output vector should be [5 5 5 7 7 7]
#include<iostream.h>
#include<vector.h>
int main(void)
{
std::vector<int> x;
x.push_back(5);
x.push_back(7);
x.insert(x.end(), x.begin(), x.begin() + 1);
return 0;
}
This didnt work out. Any help would be appreciated.
A simple approach is to loop over the vector and create a new one:
std::vector<int> vec{5, 7};
// create a new vector
std::vector<int> new_vec;
new_vec.reserve(vec.size() * 3);
for (auto elem : vec) {
for (std::size_t i = 0; i < 3; ++i) {
new_vec.push_back(elem);
}
}
I don't know how simple code you want, but for example this works.
#include<iostream>
#include<vector>
int main(void)
{
std::vector<int> x;
x.push_back(5);
x.push_back(7);
for (std::vector<int>::iterator it = x.end(); it != x.begin(); )
{
it--;
it = x.insert(it, 2, *it);
}
// print the vector to check
for (size_t i = 0; i < x.size(); i++) std::cout << x[i] << " ";
std::cout << std::endl;
return 0;
}
Maybe something like this could help you achieve that:
#include <iostream>
#include <algorithm>
#include <vector>
template<typename T>
std::vector<T> RepeateEntryNumberOfTimes(std::vector<T> input, std::uint16_t numberOfTimes)
{
std::vector<T> result;
std::for_each(input.begin(), input.end(), [&result, numberOfTimes](T item){
for(std::uint16_t numberOfReps = 0; numberOfReps != numberOfTimes; ++numberOfReps)
{
result.push_back(item);
}
});
return result;
}
See godbolt example: https://godbolt.org/z/ns9o3b
Your code has problem since it inserting elements to same vector.
Modification of vector invalidates old iterators, so your code has undefined behavior.
Even ignoring this error, logic of your code doesn't seem to do what you are expecting.
template<typename In, typename Out>
Out replicate_elements(In b, In e, size_t n, Out o)
{
while(b != e) {
o = std::fill_n(o, n, *b++);
}
return o;
}
std::vector<int> foo(const std::vector<int>& x)
{
std::vector<int> r;
r.reserve(x.size() * 3);
replicate_elements(x.begin(), x.end(), 3, std::back_inserter(r));
return r;
}
https://www.godbolt.org/z/zvE5TG

How to Subtract the first element in a vector from another first element in another vector?

I have 2 vectors of ints.
say the first one has (2,1).
and the second one (1,1).
I am trying to subtract numbers like this:
2 - 1,
1 - 1
then I need to add these 2 numbers so the final answer would be 1.
I've tried a for loop, but it's subtracting each number from each element, instead of only the first one.
This is what I've tried so far.
vector<int> temp;
for(unsigned i =0; i < Vec1.size(); i++)
for(unsigned o =0; o < Vec2.size(); o++)
temp.push_back(Vec1.at(i).nums- Vec2.at(o).nums);
//where nums, are just the numbers showed above
The output as you would expect is :
1
1
0
0
and I need it to be:
1
0
then I can just do a for loop to add all the ints together.
Any help, would be greatly appreciated!
I've tried a for loop, but it's subtracting each number from each element, instead of only the first one.
You are not doing it the right way. You have been using cascaded for loops and hence, you are subtracting each element of first vector from each element of second vector.
There are two ways to correctly implement:
One involves writing your own functions to subtract two vector and then adding elements of the result.
#include <iostream>
#include <vector>
std::vector<int> subtract(const std::vector<int>& a, const std::vector<int>& b)
{
std::vector<int> result;
const int SIZE = std::min(a.size(), b.size());
for (int i = 0; i < SIZE; i++)
result.push_back(a[i] - b[i]);
return result;
}
int addAllElements(const std::vector<int>& a)
{
int result = 0;
for (auto i: a)
result += i;
return result;
}
int main(void)
{
std::vector<int> a = {2, 1};
std::vector<int> b = {1, 1};
std::cout << "Result is " << addAllElements(subtract(a, b)) << std::endl;
return 0;
}
The other method (preferred) involves using STL:
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
int main(void)
{
std::vector<int> a = { 2, 1 };
std::vector<int> b = { 1, 1 };
std::vector<int> result;
std::transform(std::begin(a), std::end(a), std::begin(b), std::back_inserter(result), [](const auto a, const auto b)
{
return a - b;
}
);
int sumAllElements = std::accumulate(result.begin(), result.end(), 0);
std::cout << "Result is " << sumAllElements << std::endl;
return 0;
}
The above code uses lambda expression. To know more about them, see this link.
std::accumulate sums all the elements of the container and std::transform performs the transformation (specified in it's fifth argument) on two vectors and put the result in a different vector. We have used lambda expression to perform the required sub operation.
EDIT:
To implement it without lambda is also easy. You can use function pointers.
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
double subtract(const double a, const double b)
{
return a - b;
}
int main(void)
{
std::vector<int> a = { 2, 1 };
std::vector<int> b = { 1, 1 };
std::vector<int> result;
std::transform(std::begin(a), std::end(a), std::begin(b), std::back_inserter(result), subtract);
int sumAllElements = std::accumulate(result.begin(), result.end(), 0);
std::cout << "Result is " << sumAllElements << std::endl;
return 0;
}
There are various advantages of using lambda expression.
NOTE:
You can also use std::minus instead of defining you own function. Like this:
std::transform(std::begin(a), std::end(a), std::begin(b), std::back_inserter(result), std::minus<int>());
In C++17, you can combine std::transform and std::reduce/std::accumulate calls with std::transform_reduce:
const std::vector<int> vec1 {2, 1};
const std::vector<int> vec2 {1, 1};
auto res = std::transform_reduce(vec1.begin(), vec1.end(),
vec2.begin(),
0,
std::plus<>(),
std::minus<>());
Demo
Here is an example using the STL:
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
int main() {
std::vector<int> vec1 {2, 1};
std::vector<int> vec2 {1, 1};
std::vector<int> temp;
std::transform(begin(vec1), std::end(vec1), std::begin(vec2),
std::back_inserter(temp), [](const auto a, const auto b) {return a - b;});
auto sum = std::accumulate(temp.begin(), temp.end(), 0);
std::cout << "Result: " << sum << "\n";
return 0;
}

Functors and iteration trough vector

I'm trying to get into 'modern' C++, so I'm trying to learn how to properly use functors, and, subsequently, lambdas.
I think I've understood basic principle behind it, but I'm having trouble to understand how to acquire any element from a vector that is passed to my algorithm.
So, let's say I wish to create a Fibonacci sequence of length N...
struct Adder {
int operator()(int a, int b) {return a+b;}
};
const int N = 10;
int main() {
std::vector<int> vec = {0, 1};
vec.resize(N);
//Old Way
for(int i = 2; i < vec.size(); i++) {
vec[i] = vec[i-1] + vec[i-2];
}
std::transform(vec.begin(), vec.end(), vec.begin(), [](int i){return i*3;}); //single operator given to function, works
// std::transform(vec.begin()+2, vec.end(), vec.begin(), /*here two calls are needed , for a and b operators*/);
return 0;
}
Basically my question is how to activate functor defined in struct Adder? What is the proper way to pass two operators to him?
Adder::operator() should be const. And your Adder functor is unnecessary. Just use std::plus<>.
Since C++17, we have the transform overload that accepts two sequences. So we can do: (you can use Adder{} in place of std::plus<>{} if you want)
std::transform(vec.begin(), vec.end() - 2, vec.begin() + 1, vec.begin() + 2, std::plus<>{});
Minimal example: (live demo)
#include <algorithm>
#include <iostream>
#include <vector>
constexpr int N = 10;
int main()
{
std::vector<int> vec{0, 1};
vec.resize(N);
std::transform(vec.begin(), vec.end() - 2, vec.begin() + 1, vec.begin() + 2, std::plus<>{});
for (int x : vec)
std::cout << x << " ";
std::cout << "\n";
}

How to fill a vector with a range?

How would I fill a vector with the numbers from 1 to 10 in C++? I have this but its not working.
vector<int>test(10);
test={ 1, 10 };
Another using generate:
vector<int>test(10);
int x = 0;
std::generate(test.begin(), test.end(), [&]{ return x++; });
You can use std::iota():
std::vector<int> v(10);
std::iota(v.begin(), v.end(), 1);
Many options. For example,
vector<int> test{1,2,3,4,5,6,7,8,9,10};
or
std::vector<int> test;
test.reserve(10); // prevent some reallocations
for (int i = 1; i < 11; ++i)
test.push_back(i);
or
std::vector<int> test(10);
std::iota(test.begin(), test.end(), 1);
vector<int> vInts;
for (int i=1;i<=10;++i){
vInts.push_back(i);
}
You could use standard algorithm std::iota declared in header <numeric> For example
#include <numeric>
#include <vector>
//...
std::vector<int> v( 10 );
std::iota( v.begin(), v.end(), 1 );

Creating a new C++ subvector?

Say I have a vector with values [1,2,3,4,5,6,7,8,9,10]. I want to create a new vector that refers to, for example, [5,6,7,8]. I imagine this is just a matter of creating a vector with pointers or do I have to push_back all the intermediary values I need?
One of std::vector's constructor accepts a range:
std::vector<int> v;
// Populate v.
for (int i = 1; i <= 10; i++) v.push_back(i);
// Construct v1 from subrange in v.
std::vector<int> v1(v.begin() + 4, v.end() - 2);
This is fairly easy to do with std::valarray instead of a vector:
#include <valarray>
#include <iostream>
#include <iterator>
#include <algorithm>
int main() {
const std::valarray<int> arr={0,1,2,3,4,5,6,7,8,9,10};
const std::valarray<int>& slice = arr[std::slice(5, // start pos
4, // size
1 // stride
)];
}
Which takes a "slice" of the valarray, more generically than a vector.
For a vector you can do it with the constructor that takes two iterators though:
const std::vector<int> arr={0,1,2,3,4,5,6,7,8,9,10};
std::vector<int> slice(arr.begin()+5, arr.begin()+9);
You don't have to use push_back if you don't want to, you can use std::copy:
std::vector<int> subvector;
copy ( v1.begin() + 4, v1.begin() + 8, std::back_inserter(subvector) );
I would do the following:
#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> v;
for(int i = 1;i <= 10;i++) v.push_back(i);
printvec(v);
vector<int> v2(v.begin()+4, v.end()-2);
printvec(v2);
return 0;
}
~