I have a vector of elements of type uint8 which I am copying into one std::array. After some operations again I need to copy the elements from std::array to a vector.Please find the code below
/******************************************************************************
Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C, C++, Python, Java, PHP, Ruby, Perl,
C#, VB, Swift, Pascal, Fortran, Haskell, Objective-C, Assembly, HTML, CSS, JS, SQLite, Prolog.
Code, Compile, Run and Debug online from anywhere in world.
*******************************************************************************/
#include <iostream>
#include <vector>
#include <array>
#include <cstdint>
#include <limits>
#include <algorithm>
std::array<std::uint32_t, 5> elem_arr ;
void copy_from_vector(std::vector<std::uint32_t> elem_vec)
{
std::copy(elem_vec.begin(),elem_vec.end(),elem_arr.begin());
}
std::vector<std::uint32_t> copy_from_array()
{
std::vector<std::uint32_t> ele_vec_copy {elem_arr.begin(),elem_arr.end()};
return ele_vec_copy;
}
int main()
{
std::vector<std::uint32_t> ele_vec {1,2,3};
copy_from_vector(ele_vec);
auto ele_vec_copy = copy_from_array();
for(auto ele : ele_vec_copy)
std::cout << ele << std::endl;
return 0;
}
output:
======
1
2
3
0
0
Now the problem is my array size is 5 but vector having only 3 elements. when I copy the elements from the array to a new vector I am getting extra 2 zeros. How can I get the output as below
output:
======
1
2
3
You could copy by size of vector.
#include <iostream>
#include <vector>
#include <array>
#include <cstdint>
#include <limits>
#include <algorithm>
int main()
{
std::array<std::uint32_t, 5> elem_arr ;
std::vector<std::uint32_t> ele_vec {1,2,3};
std::copy(ele_vec.begin(),ele_vec.end(),elem_arr.begin());
std::vector<std::uint32_t> ele_vec_copy { elem_arr.begin() , elem_arr.begin() + ele_vec.size() };
for(auto ele : ele_vec_copy)
std::cout << ele << std::endl;
return 0;
}
run online
After you edited the question
It is not possible to know how many elements used/set in std::array but this feature could be mimic by choosing a unique value which represents the element is null or not set like nullptr. But it comes with a constraint, you must not use the unique value at somewhere else in the array.
So the possible implementation is :
#include <iostream>
#include <vector>
#include <array>
#include <cstdint>
#include <limits>
#include <algorithm>
#include <limits>
std::array<std::uint32_t, 5> elem_arr;
void copy_from_vector(std::vector<std::uint32_t> elem_vec)
{
std::copy(elem_vec.begin(),elem_vec.end(),elem_arr.begin());
}
std::vector<std::uint32_t> copy_from_array()
{
std::vector<std::uint32_t> ele_vec_copy;
std::copy_if( elem_arr.begin() , elem_arr.end() ,
std::back_inserter( ele_vec_copy ) ,
[]( std::uint32_t val ) {
return val != std::numeric_limits<std::uint32_t>::max();
} );
return ele_vec_copy;
}
int main()
{
elem_arr.fill( std::numeric_limits<std::uint32_t>::max() );
std::vector<std::uint32_t> ele_vec {1,2,3};
copy_from_vector(ele_vec);
auto ele_vec_copy = copy_from_array();
for(auto ele : ele_vec_copy)
std::cout << ele << std::endl;
return 0;
}
run online
Or store the elements as std::optional and don't copy null elements.
Possible implementation is :
#include <iostream>
#include <vector>
#include <array>
#include <cstdint>
#include <limits>
#include <algorithm>
#include <limits>
#include <optional>
std::array<std::optional<std::uint32_t>, 5> elem_arr;
void copy_from_vector(std::vector<std::uint32_t> elem_vec)
{
std::transform( elem_vec.begin() , elem_vec.end() ,
elem_arr.begin() ,
[]( auto val ) { return std::optional<std::uint32_t>{ val }; }
);
}
std::vector<std::uint32_t> copy_from_array()
{
std::vector<std::uint32_t> ele_vec_copy;
std::vector<std::optional<std::uint32_t>> non_null_elements;
std::copy_if( elem_arr.begin() , elem_arr.end() ,
std::back_inserter( non_null_elements ) ,
[]( auto val ) {
return val;
} );
std::transform( non_null_elements.begin(), non_null_elements.end() ,
std::back_inserter( ele_vec_copy ) ,
[]( auto val ) { return *val; }
);
return ele_vec_copy;
}
int main()
{
std::vector<std::uint32_t> ele_vec {1,2,3};
copy_from_vector(ele_vec);
auto ele_vec_copy = copy_from_array();
for(auto ele : ele_vec_copy)
std::cout << ele << std::endl;
return 0;
}
run online
Related
I am searching for a specif element K in a vector. Instead of getting
1
0
I got
0
0
When I used the same code directly in the main () without the class, I got right results.
#include <iostream>
#include <sys/resource.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <algorithm>
#include <vector>
using namespace std;
class Answer
{
public:
static bool exists(int ints[], int size, int k)
{
std::vector<int> v( ints, ints + sizeof(ints)/sizeof(ints[0]) ) ;
auto result1 = std::find(v.begin(), v.end(), k);
if (result1 != v.end()) {
return true;
} else {
return false;
}
}
};
int main()
{
int ints[] = { -9, 14, 37, 102 };
cout << Answer::exists(ints, 4, 102) << endl; // 1
cout << Answer::exists(ints, 4, 36) << endl; // 0
return 0;
}
You cannot obtain the number of elements in an array once you have passed it to a function since it will decay to a pointer. So instead of
std::vector<int> v(ints, ints + sizeof(ints) / sizeof(ints[0]));
use the 2nd parameter size:
std::vector<int> v(ints, ints + size);
As #WhozCraig pointed out in the comments to your question there is no need for a temporary vector since you can use std::find() on arrays perfectly fine:
class Answer
{
public:
static bool exists(int ints[], int size, int k)
{
auto result = std::find(ints, ints + size, k);
return result != ints + size;
}
};
I have a map like std::map<std::string, std::vector<int> >. I want to create one vector out of all the sub-vectors from values of the map. I can do it using the loops but I wanted to use the boost::range library where I can pipe the input of one transform to another so that the code is more readable and succinct. I tried something like below but needed some help to do it correctly.
Thank you
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <iterator>
#include <vector>
#include <map>
#include <iostream>
struct GetMapValue
{
template<typename T1, typename T2>
const T2& operator()( const std::pair<T1,T2>& key_val ) const
{
return key_val.second;
}
};
struct GetINTs
{
GetINTs(std::vector<int> aVec1)
{
aMyVec = aVec1;
}
void operator()( const std::vector<int>& val )
{
aMyVec.insert( val.end(), val.begin(), aMyVec.end() );
}
private:
std::vector<int> aMyVec;
};
int main(){
std::map<std::string, std::vector<int> > x;
std::vector<int> y, z;
std::vector<int> temp;
temp.push_back(1);
temp.push_back(1);
x.insert(std::make_pair("one", temp));
temp.clear();
temp.push_back(2);
temp.push_back(2);
x.insert(std::make_pair("two", temp));
temp.clear();
temp.push_back(3);
temp.push_back(3);
x.insert(std::make_pair("three", temp));
boost::copy( x | boost::adaptors::transformed(GetMapValue), std::back_inserter(y) );
boost::copy( y | boost::adaptors::transformed(GetINTs), std::back_inserter(z) );
}
The adaptor already exists and is called
boost::adaptors::map_keys
boost::adaptors::map_values
Here's a sample:
Live On Coliru
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <iostream>
#include <iterator>
#include <vector>
#include <string>
#include <map>
int main() {
std::map<std::string, std::vector<int> > x {
{ "hello", { 1,2,3 } },
{ "world", { 4,5,6 } },
};
boost::copy(x | boost::adaptors::map_keys, std::ostream_iterator<std::string>(std::cout << "Keys: ", " "));
for (auto& vec : x | boost::adaptors::map_values)
boost::copy(vec, std::ostream_iterator<int>(std::cout << "\nValues: ", " "));
}
Prints
Keys: hello world
Values: 1 2 3
Values: 4 5 6
I want to increase each element in a std::vector<size_t> with length 256 by one, but depending on same position of a std::bitset<256> (if equal 1).
Code below can be edited / compiled here.
My question is, can I get away from the for loop and get in some fast logical operator?
#include <iostream>
#include <bitset>
#include <vector>
#include <iterator>
#include <algorithm>
#define SIZE 3
int main() {
size_t size=SIZE;
std::vector<size_t> v(SIZE); v={3,0,7};
std::bitset<SIZE> b("110");
for (size_t i=0; i<size; ++i)
{
if (b[size-1-i]) // reverse
{
++v[i];
}
}
std::copy ( v.begin()
, v.end()
, std::ostream_iterator<size_t>(std::cout, ",") );
// 3+1,0+1,7+0
// => 4,1,7
return 0;
}
Since bitset doesn't have iterators we can't simply use std::transform. But we can create iterator-like wrapper around size_t and use it like index:
#include <iostream>
#include <bitset>
#include <vector>
#include <iterator>
#include <algorithm>
#define SIZE 3
class IntegralIterator
{
public:
IntegralIterator(size_t v = 0) : value(v) {}
size_t operator*()
{
return value;
}
IntegralIterator& operator++()
{
++value;
return *this;
}
private:
size_t value;
};
int main() {
size_t size=SIZE;
std::vector<size_t> v(SIZE); v={3,0,7};
std::bitset<SIZE> b("110");
std::transform(v.begin(), v.end(), IntegralIterator(), v.begin(),
[&](size_t s, size_t index)
{
return s + b[size-1-index];
});
std::copy(v.begin(), v.end(),
std::ostream_iterator<size_t>(std::cout, ",") );
return 0;
}
I am keeping reading Stanford tutorials and currently solving tasks on STL. The task is to write a function which accepts a map with names of films and their rankings. This function should return a set container with top 3 films according to critics review. Here is my solution:
#include <iostream>
#include <set>
#include <map>
#include <numeric>
#include <iterator>
#include <string>
using namespace std;
struct compare {
bool operator() (const double& a, const double& b) const {
return (a > b);
}
};
set <string> list(map <double, string, compare>& films) {
set <string> critics;
map<double, string, compare> ::iterator it = films.begin();
if (films.size() <= 3) {
critics.insert(films.begin()->second, films.end()->second);
}
else {
for (int i = 0; i < 3; ++i, ++it){
critics.insert(it->second);
}
};
return critics;
}
int main() {
map <double, string, compare> films;
films[5.0] = "a";
films[8.0] = "b";
films[10.0] = "c";
films[7.4] = "d";
set <string> critics = list(films);
copy(critics.begin(), critics.end(), ostream_iterator <string>(cout, " "));
cin.get();
}
Unfortunately, it keeps on throwing out an error:
error C2675: unary '++' : 'std::string' does not define this operator or a conversion to a type acceptable to the predefined operator
I have read MSDN documentation on the error but as I am new to this could not understand the meaning of the problem. Could you, please, hint me at that?
This statement
critics.insert(films.begin()->second, films.end()->second);
is invalid. The compiler consideres arguments films.begin()->second and films.end()->second of type std::string as a pair of iterators and tries to apply operator ++. Of course this results in an error.
You should use standard algorithm std::transform with std::insert_iterator that to copy strings from the map to the set.
Here is a demonstrative program that shows the approach
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <algorithm>
#include <iterator>
#include <functional>
int main()
{
std::map<double, std::string, std::greater<double>> m =
{
{ 2.2, "B" }, { 1.1, "A" }, { 4.4, "D" }, { 5.5, "E" }, { 3.3, "C" }
};
for ( const auto &p : m )
{
std::cout << p.first << '\t' << p.second << std::endl;
}
std::set<std::string> s;
std::transform( m.begin(), std::next( m.begin(), 3 ),
std::inserter( s, s.end() ),
[]( const auto &p ) { return p.second; } );
for ( const auto &t : s ) std::cout << t << ' ';
std::cout << std::endl;
return 0;
}
The program output is
5.5 E
4.4 D
3.3 C
2.2 B
1.1 A
C D E
I would like to know if there is an elegant way or a built-in function to convert vector<double> to vector<string>. What I've done is simple
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
std::vector<std::string> doubeVecToStr(const std::vector<double>& vec)
{
std::vector<std::string> tempStr;
for (unsigned int i(0); i < vec.size(); ++i){
std::ostringstream doubleStr;
doubleStr << vec[i];
tempStr.push_back(doubleStr.str());
}
return tempStr;
}
int main( int argc, char* argv[] )
{
std::vector<double> doubleVec;
doubleVec.push_back(1.0);
doubleVec.push_back(2.1);
doubleVec.push_back(3.2);
std::vector<std::string> doubleStr;
doubleStr = doubeVecToStr(doubleVec);
for (unsigned int i(0); i < doubleStr.size(); ++i)
std::cout << doubleStr[i] << " ";
std::cout << std::endl;
return 0;
}
There are many ways, but a standard solution is to use std::transform with a lambda using std::to_string for the conversion :
std::transform(std::begin(doubleVec),
std::end(doubleVec),
std::back_inserter(doubleStr),
[](double d) { return std::to_string(d); }
);
And you can wrap that in a function template to make it work with any Standard compliant container :
template<class IteratorIn, class IteratorOut>
void to_string(IteratorIn first, IteratorIn last, IteratorOut out)
{
std::transform(first, last, out,
[](typename std::iterator_traits<IteratorIn>::value_type d) { return std::to_string(d); } );
}
Or in C++14, with a generic lambda :
template<class IteratorIn, class IteratorOut>
void to_string(IteratorIn first, IteratorIn last, IteratorOut out)
{
std::transform(first, last, out, [](auto d) { return std::to_string(d); } );
}
And call it with any container (i.e. it works with std::list<int>, for instance) :
to_string(std::begin(doubleVec), std::end(doubleVec), std::back_inserter(doubleStr));
Notes :
If you don't have a C++11 compiler, write your own to_string function template :
Example:
template<class T>
std::string my_to_string(T v)
{
std::stringstream ss;
ss << v;
return ss.str();
}
And use it in a similar way :
std::transform(doubleVec.begin(),
doubleVec.end(),
std::back_inserter(doubleStr),
my_to_string<double> );
You should reserve() the memory in the output vector to avoid reallocations during std::transform() :
e.g. do this :
std::vector<std::string> stringVec;
stringVec.reserve(v.size()); // reserve space for v.size() elements
Live demo
Using copy and ostream_iterator:
#include <vector>
#include <iostream>
#include <sstream>
#include <iterator>
int main()
{
std::vector<double> numbers{1.0, 2.1, 3.2};
std::stringstream output;
std::copy(numbers.begin(), numbers.end(), std::ostream_iterator<double>(output, " "));
std::cout << output.str() << std::endl;
}
In general, if you have a container of T and want to create a container of U from the container of T, as others have mentioned the algorithm to look for is std::transform.
If you are not using C++ 11, Here is std::transform usage:
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <iterator>
#include <sstream>
std::string Transformer(double d)
{
std::ostringstream doubleStr;
doubleStr << d;
return doubleStr.str();
}
int main()
{
std::vector<double> doubleVec;
doubleVec.push_back(1.0);
doubleVec.push_back(2.1);
doubleVec.push_back(3.2);
std::vector<std::string> doubleStr;
std::transform(doubleVec.begin(), doubleVec.end(), std::back_inserter(doubleStr), Transformer);
std::copy(doubleStr.begin(), doubleStr.end(), std::ostream_iterator<std::string>(std::cout, " "));
}
Output:
1 2.1 3.2