'Generate a random byte stream
I'm testing a network program that sends packet to a remote server using UDP/TCP, and for that, I want to generate some random byte streams.
Here's the function:
unsigned char *gen_rdm_bytestream(int num_bytes)
{
unsigned char *stream = malloc(num_bytes);
/*
* here how to generate?
*/
return stream;
}
Solution 1:[1]
For each byte, you can call a random number generator function. The C standard provides the function rand
. Before using it, you should initialize the random sequence with a call to srand
.
gen_rdm_bytestream
may then look something like that:
#include <stdlib.h>
#include <time.h>
unsigned char *gen_rdm_bytestream (size_t num_bytes)
{
unsigned char *stream = malloc (num_bytes);
size_t i;
for (i = 0; i < num_bytes; i++)
{
stream[i] = rand ();
}
return stream;
}
srand ((unsigned int) time (NULL));
Since stream
is unsigned, if the value returned by rand
is greater than UCHAR_MAX
, she will be reduced (modulo UCHAR_MAX
). Therefore you will get pseudo-random numbers between 0 and 255.
Solution 2:[2]
Yes, you have int rand (void);
function in C,
Returns a pseudo-random integral number in the range between 0 and RAND_MAX. RAND_MAX is a constant defined in <cstdlib>.
This number is generated by an algorithm that returns a sequence of apparently non-related numbers each time it is called. This algorithm uses a seed to generate the series, which should be initialized to some distinctive value using function srand().
EDIT:
As you are commenting, I have written a code for you that may help you to demonstrate, How to use rand(), the program and its output are:
#include <stdio.h>
#include <stdlib.h> /* srand, rand */
#include <time.h>
int main (){
int i=0;
srand (time(NULL));
printf("Five rand numbers: \n");
for(i = 1; i <= 5; i++){
printf("\n %d", rand());
}
printf("Five rand numbersb between 2 to 5: \n");
for(i = 1; i <= 5; i++){
printf("\n %d", (2 + rand()%4));
}
return 1;
}
Output:
Five rand numbers:
1482376850
1746468296
1429725746
595545676
1544987577
Five rand numbers, between 2 to 5:
2
5
3
4
3
Solution 3:[3]
Here's a general function for producing random integer values in a given range:
#include <stdlib>
/**
* Assumes srand has already been called
*/
int randInRange( int min, int max )
{
double scale = 1.0 / (RAND_MAX + 1);
double range = max - min + 1;
return min + (int) ( rand() * scale * range );
}
Leveraging this to create unsigned char
values:
u_char randomByte()
{
return (u_char) randInRange( 0, 255 );
}
So,
for ( i = 0; i < numBytes; i++ )
stream[i] = randomByte();
Solution 4:[4]
On UNIX, there is the getrandom system call.
#include <sys/random.h>
#include <stdlib.h>
unsigned char * gen_rdm_bytestream(size_t const num_bytes) {
unsigned char * const stream = malloc(num_bytes);
getrandom(stream, num_bytes, 0);
return stream;
}
Solution 5:[5]
The following is an actually stream (std::istream) and uses the C++11 <random> library.
This is not particularly written to be fast, but it it's fun:
#include <iostream>
#include <string>
#include <array>
#include <algorithm>
#include <random>
class RandomBuf : public std::streambuf
{
private:
size_t m_size;
std::array<char, 64> m_buf;
std::mt19937_64 m_twister;
std::uniform_int_distribution<char> m_dist;
protected:
int_type underflow() override {
if (m_size == 0)
return EOF;
size_t size = std::min(m_size, m_buf.size());
setg(&m_buf[0], &m_buf[0], &m_buf[size]);
for (size_t i = 0; i < size; ++i)
m_buf[i] = m_dist(m_twister);
m_size -= size;
return 0;
}
public:
RandomBuf(size_t size, char b, char e) : m_size(size), m_dist(b, e) { }
};
class Random : public std::istream
{
private:
RandomBuf m_streambuf;
public:
Random(size_t size, char b, char e) : m_streambuf(size, b, e) {
rdbuf(&m_streambuf);
}
};
// Example usage:
int main()
{
Random random(100, 'a', 'z'); // Create an istream that produces 100 pseudo-random characters in the interval ['a', 'z'].
// Read random stream to a string:
std::string str;
random >> str;
// Print result.
std::cout << str << std::endl;
}
The output of this program (exactly, because the standard guarantees that a default constructed Mersenne twister has a given seed):
ugsyakganihodonwmktggixegfszuclgupylingbnscxadzqhjmhhyqtssbmctlpchqfflzfwhvjywmajtnkaxczrmtpnlvwmzxd
EDIT:
For extra bonus points I added a StreamHasher class: https://wandbox.org/permlink/bIDCVTnJjkdafARo
Just the added classes:
class StreamHasherBuf : public std::streambuf
{
private:
size_t m_hash;
std::array<char, 64> m_buf; // The resulting hash value is a function of the size of the array!
static constexpr size_t bufsize = std::tuple_size_v<decltype(m_buf)>;
void add_and_reset_put_area()
{
boost::hash_combine(m_hash, boost::hash_range(pbase(), pptr()));
setp(&m_buf[0], &m_buf[bufsize]);
}
protected:
int_type overflow(int_type c) override
{
if (c != EOF)
{
if (pptr() == epptr())
add_and_reset_put_area();
*pptr() = c;
pbump(1);
}
return 0;
}
public:
StreamHasherBuf() : m_hash(0) { setp(&m_buf[0], &m_buf[bufsize]); }
size_t hash()
{
add_and_reset_put_area();
return m_hash;
}
};
class StreamHasher : public std::ostream
{
private:
StreamHasherBuf m_streambuf;
public:
StreamHasher() { rdbuf(&m_streambuf); }
size_t hash() { return m_streambuf.hash(); }
};
For example
int main()
{
RandomBuf random(100, 'a', 'z'); // Create a streambuf that produces 100 pseudo-random characters in the interval ['a', 'z'].
StreamHasher hasher;
hasher << &random;
std::cout << hasher.hash() << '\n';
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Daniel Marschall |
Solution 3 | John Bode |
Solution 4 | nog642 |
Solution 5 |