Filling a vector of bytes with random bytes - c++

I wanted to fill a std::vector<BYTE> with random or pseudo-random bytes of data. I have written (in other word, find it) the following source code in the stackoverflow but it doesn't compile in my Visual Studio.
#include <Windows.h>
#include <vector>
#include <random>
#include <climits>
#include <algorithm>
#include <functional>
using random_bytes_engine = std::independent_bits_engine<std::default_random_engine, CHAR_BIT, BYTE>;
int main()
{
random_bytes_engine rbe;
std::vector<BYTE> data(1000);
std::generate(data.begin(), data.end(), std::ref(rbe));
}
When I try to compile the above code Visual studio give me the following errors:
Error C2338 note: char, signed char, unsigned char, char8_t, int8_t,
and uint8_t are not allowed Messaging
Error C2338 invalid template argument for independent_bits_engine:
N4659 29.6.1.1 [rand.req.genl]/1f requires one of unsigned short,
unsigned int, unsigned long, or unsigned long long Messaging.

The BYTE type, which is just an alias for unsigned char, is not an allowed type for UIntType parameter of
template<class Engine, std::size_t W, class UIntType>
class independent_bits_engine;
The standard, [rand.req.genl]/1.f, reads:
Throughout this subclause [rand], the effect of instantiating a template:
...
that has a template type parameter named UIntType is undefined unless the corresponding template argument is cv-unqualified and is one of unsigned short, unsigned int, unsigned long, or unsigned long long.

The answer from Evg is correct.
If you really want to have random bytes only, I would use a custom generator function that generates values between [-128, 127] or any desired range.
For instance:
#include <iostream>
#include <Windows.h>
#include <vector>
#include <random>
#include <algorithm>
#include <limits>
int main()
{
std::random_device r;
std::default_random_engine randomEngine(r());
std::uniform_int_distribution<int> uniformDist(CHAR_MIN, CHAR_MAX);
std::vector<BYTE> data(1000);
std::generate(data.begin(), data.end(), [&uniformDist, &randomEngine] () {
return (BYTE) uniformDist(randomEngine);
});
for (auto i : data) {
std::cout << int(i) << std::endl;
}
return 0;
}
References:
https://en.cppreference.com/w/cpp/numeric/random
https://en.cppreference.com/w/cpp/algorithm/generate

Just do this instead:
using random_bytes_engine = std::independent_bits_engine<std::default_random_engine, 32, uint32_t>;
Turns the engine into a 32-bit random number generator, but using it to initialize a vector of BYTEs works just fine.

Related

Serializing variadic template tuple in C++ [duplicate]

I need to write a function to convert tuple to byte array.
The type of tuple may include int, long, double, std::string, char*,etc.
The size and type of tuple are arbitrary, such as
std:tuple<string, int, double> t1("abc", 1, 1.3);
or
std:tuple<char*, int, int, float, double, string> t2("abc", 1, 2, 1.3, 1.4, "hello");
I want use these tuple as input, and the byte array as return value. What should I do ?
There is also the brilliant C++ API for message pack which supports tuples natively
#include <string>
#include <sstream>
#include <tuple>
#include <msgpack.hpp>
int main() {
auto t = std::make_tuple("1", 1, 1.0);
auto buffer = std::stringstream{};
// easy peezy
msgpack::pack(buffer, t);
auto tuple_as_string = buffer.str();
}
You can use Boost Serialization for this task together with a small extension for std::tuple. However, it doesn't turn it into a byte array by default, but into something else. There is also binary_oarchive. Perhaps this fits your needs.
#include <fstream>
#include <tuple>
#include <boost/archive/text_oarchive.hpp>
#include "serialize_tuple.h" // https://github.com/Sydius/serialize-tuple
int main()
{
auto t = std::make_tuple(42,3.14,'a');
std::ofstream ofs("test.dat");
boost::archive::text_oarchive oa(ofs);
oa << t;
}

How to convert tuple to byte array in c++11

I need to write a function to convert tuple to byte array.
The type of tuple may include int, long, double, std::string, char*,etc.
The size and type of tuple are arbitrary, such as
std:tuple<string, int, double> t1("abc", 1, 1.3);
or
std:tuple<char*, int, int, float, double, string> t2("abc", 1, 2, 1.3, 1.4, "hello");
I want use these tuple as input, and the byte array as return value. What should I do ?
There is also the brilliant C++ API for message pack which supports tuples natively
#include <string>
#include <sstream>
#include <tuple>
#include <msgpack.hpp>
int main() {
auto t = std::make_tuple("1", 1, 1.0);
auto buffer = std::stringstream{};
// easy peezy
msgpack::pack(buffer, t);
auto tuple_as_string = buffer.str();
}
You can use Boost Serialization for this task together with a small extension for std::tuple. However, it doesn't turn it into a byte array by default, but into something else. There is also binary_oarchive. Perhaps this fits your needs.
#include <fstream>
#include <tuple>
#include <boost/archive/text_oarchive.hpp>
#include "serialize_tuple.h" // https://github.com/Sydius/serialize-tuple
int main()
{
auto t = std::make_tuple(42,3.14,'a');
std::ofstream ofs("test.dat");
boost::archive::text_oarchive oa(ofs);
oa << t;
}

boost::lexical_cast<signed char> cannot handle negative numbers?

This short C++ program behaves in a way which baffles me:
#include <cassert>
#include <iostream>
#include <string>
#include <boost/lexical_cast.hpp>
int main(void) {
signed char c = -2;
assert(c == -2);
c = boost::lexical_cast<signed char>(std::string("-2"));
std::cout << c << "\n";
}
Using g++ 5.2.1 and boost-1.58.0, I get:
terminate called after throwing an instance of 'boost::exception_detail::clone_impl >'
what(): bad lexical cast: source type value could not be interpreted as target
Why can't Boost cast from string "-2" to signed char given that the value -2 is representable by this type?
The solution is to use Boost:
#include <boost/lexical_cast.hpp>
#include <boost/numeric/conversion/cast.hpp>
int tmp = boost::lexical_cast<int>(std::string("-2"));
char c = boost::numeric_cast<signed char>(tmp);

weird gcc behavior with unsigned ints

#include <iostream>
#include <cstdint>
#include <cstdio>
using namespace std;
int main()
{
uint16_t ii;
std::cin >> ii;
printf("%d\n", ii);
}
When I give input 5 the output is also 5. But when I change the type of ii to uint8_t, I do not get 5 but 53 which seems to be the ASCII value of 5. Is this expected?
uint8_t is allowed (but not required) to be a typedef for char (if it happens to be unsigned) or unsigned char. And input of those is done as characters not numbers. So this is valid but not required behaviour.

Generating very large Random numbers using Boost library

I am using boost library for generating very very large Random numbers in the range [0-2^32-1]. But boost library is not working well with this range. It just displaying an error message "Assertion failed min_arg<=max_arg"
Kindly help me out ! here is the code:
#include <iostream>
#include <ctime>
#include <cmath>
#include "boost/random.hpp"
#include <stdint.h>
using namespace std;
int main()
{
long double rangeMin = 0;
long long int rangeMax = (pow(2.0,32.0)-1);
typedef boost::uniform_int<> NumberDistribution;
typedef boost::mt19937 RandomNumberGenerator;
typedef boost::variate_generator<RandomNumberGenerator&,
NumberDistribution> Generator;
NumberDistribution distribution(rangeMin, rangeMax);
RandomNumberGenerator generator;
Generator numberGenerator(generator, distribution);
generator.seed(time(0)); // seed with the current time
cout << numberGenerator() <<endl;
return 0;
}
As per documentation, the default value of the template parameter of boost::uniform_int is int. If you want to generate long long int's, you'll need to use boost::uniform_int<long long int>.