Respuestas:
La respuesta de Mehrdad Afshari haría el truco, pero lo encontré demasiado detallado para esta simple tarea. Las tablas de consulta a veces pueden hacer maravillas:
void gen_random(char *s, const int len) {
static const char alphanum[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < len; ++i) {
s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
}
s[len] = 0;
}
s[len] = 0
es incorrecta. Si se s
trata de una cadena C (terminada en NULL), la firma del método no tendría que tener el len
parámetro. Imo, si está pasando la longitud como argumento, está asumiendo que la matriz no es una cadena C. Por lo tanto, si no está pasando una cadena C a la función, la línea s[len] = 0
podría romper cosas, ya que la matriz pasaría de 0 a len-1. E incluso si está pasando una cadena C a la función, la línea s[len] = 0
sería redundante.
Aquí está mi adaptación de la respuesta de Ates Goral usando C ++ 11. He agregado el lambda aquí, pero el principio es que puedes pasarlo y así controlar qué caracteres contiene tu cadena:
std::string random_string( size_t length )
{
auto randchar = []() -> char
{
const char charset[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
const size_t max_index = (sizeof(charset) - 1);
return charset[ rand() % max_index ];
};
std::string str(length,0);
std::generate_n( str.begin(), length, randchar );
return str;
}
Aquí hay un ejemplo de pasar una lambda a la función de cadena aleatoria: http://ideone.com/Ya8EKf
¿Por qué usarías C ++ 11 ?
Por ejemplo:
#include <iostream>
#include <vector>
#include <random>
#include <functional> //for std::function
#include <algorithm> //for std::generate_n
typedef std::vector<char> char_array;
char_array charset()
{
//Change this to suit
return char_array(
{'0','1','2','3','4',
'5','6','7','8','9',
'A','B','C','D','E','F',
'G','H','I','J','K',
'L','M','N','O','P',
'Q','R','S','T','U',
'V','W','X','Y','Z',
'a','b','c','d','e','f',
'g','h','i','j','k',
'l','m','n','o','p',
'q','r','s','t','u',
'v','w','x','y','z'
});
};
// given a function that generates a random character,
// return a string of the requested length
std::string random_string( size_t length, std::function<char(void)> rand_char )
{
std::string str(length,0);
std::generate_n( str.begin(), length, rand_char );
return str;
}
int main()
{
//0) create the character set.
// yes, you can use an array here,
// but a function is cleaner and more flexible
const auto ch_set = charset();
//1) create a non-deterministic random number generator
std::default_random_engine rng(std::random_device{}());
//2) create a random number "shaper" that will give
// us uniformly distributed indices into the character set
std::uniform_int_distribution<> dist(0, ch_set.size()-1);
//3) create a function that ties them together, to get:
// a non-deterministic uniform distribution from the
// character set of your choice.
auto randchar = [ ch_set,&dist,&rng ](){return ch_set[ dist(rng) ];};
//4) set the length of the string you want and profit!
auto length = 5;
std::cout<<random_string(length,randchar)<<std::endl;
return 0;
}
rand()
en su primer fragmento de código?
rand()
. Ni siquiera es uniforme por el
Mi solución 2p:
#include <random>
#include <string>
std::string random_string(std::string::size_type length)
{
static auto& chrs = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
thread_local static std::mt19937 rg{std::random_device{}()};
thread_local static std::uniform_int_distribution<std::string::size_type> pick(0, sizeof(chrs) - 2);
std::string s;
s.reserve(length);
while(length--)
s += chrs[pick(rg)];
return s;
}
default_random_engine
lugar de mt19937
? El código se vería más genérico.
std::default_random_engine
no es algo que me guste recomendar, ya que el estándar no garantiza su calidad, eficiencia o repetibilidad entre implementaciones.
sizeof
, cambie el auto&
a std::string
, que le dastd::string::length
std::string
probablemente sea más lento porque contiene un puntero interno a sus datos. Eso significaría una indirección adicional que una matriz estática no requiere. Además sizeof
, nunca puede ser más lento que std::string::size
porque es una constante de tiempo de compilación.
std::size
, no apareció hasta C++17
y todavía hay mucha gente que solo codifica, C++11/14
así que lo dejaré como está por ahora.
void gen_random(char *s, size_t len) {
for (size_t i = 0; i < len; ++i) {
int randomChar = rand()%(26+26+10);
if (randomChar < 26)
s[i] = 'a' + randomChar;
else if (randomChar < 26+26)
s[i] = 'A' + randomChar - 26;
else
s[i] = '0' + randomChar - 26 - 26;
}
s[len] = 0;
}
Acabo de probar esto, funciona bien y no requiere una tabla de búsqueda. rand_alnum () elimina las alfanuméricas, pero debido a que selecciona 62 de los 256 caracteres posibles, no es gran cosa.
#include <cstdlib> // for rand()
#include <cctype> // for isalnum()
#include <algorithm> // for back_inserter
#include <string>
char
rand_alnum()
{
char c;
while (!std::isalnum(c = static_cast<char>(std::rand())))
;
return c;
}
std::string
rand_alnum_str (std::string::size_type sz)
{
std::string s;
s.reserve (sz);
generate_n (std::back_inserter(s), sz, rand_alnum);
return s;
}
En lugar de realizar un bucle manual, prefiera usar el algoritmo C ++ apropiado , en este caso std::generate_n
, con un generador de números aleatorios adecuado :
auto generate_random_alphanumeric_string(std::size_t len) -> std::string {
static constexpr auto chars =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
thread_local auto rng = random_generator<>();
auto dist = std::uniform_int_distribution{{}, std::strlen(chars) - 1};
auto result = std::string(len, '\0');
std::generate_n(begin(result), len, [&]() { return chars[dist(rng)]; });
return result;
}
Esto está cerca de algo que yo llamaría la solución "canónica" para este problema.
Desafortunadamente, sembrar correctamente un generador genérico de números aleatorios C ++ (por ejemplo, MT19937) es realmente difícil . Por lo tanto, el código anterior utiliza una plantilla de función auxiliar random_generator
:
template <typename T = std::mt19937>
auto random_generator() -> T {
auto constexpr seed_bits = sizeof(typename T::result_type) * T::state_size;
auto constexpr seed_len = seed_bits / std::numeric_limits<std::seed_seq::result_type>::digits;
auto seed = std::array<std::seed_seq::result_type, seed_len>{};
auto dev = std::random_device{};
std::generate_n(begin(seed), seed_len, std::ref(dev));
auto seed_seq = std::seed_seq(begin(seed), end(seed));
return T{seed_seq};
}
Esto es complejo y relativamente ineficiente. Afortunadamente, se usa para inicializar una thread_local
variable y, por lo tanto, solo se invoca una vez por subproceso.
Finalmente, los elementos necesarios para lo anterior son:
#include <algorithm>
#include <array>
#include <cstring>
#include <functional>
#include <limits>
#include <random>
#include <string>
El código anterior utiliza la deducción de argumentos de plantilla de clase y, por lo tanto, requiere C ++ 17. Se puede adaptar trivialmente para versiones anteriores agregando los argumentos de plantilla requeridos.
std::size_t
de std::uniform_int_distribution
? No puedo ver ninguna otra CTAD
rng
como un parámetro predeterminado, con algo comotemplate <typename T = std::mt19937> inline thread_local T default_rng = get_random_generator<T>();
std::uniform_int_distribution<>
, lo que sería seguro, pero podría advertir sobre la conversión firmada -> sin firmar.
Espero que esto ayude a alguien.
Probado en https://www.codechef.com/ide con C ++ 4.9.2
#include <iostream>
#include <string>
#include <stdlib.h> /* srand, rand */
using namespace std;
string RandomString(int len)
{
string str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
string newstr;
int pos;
while(newstr.size() != len) {
pos = ((rand() % (str.size() - 1)));
newstr += str.substr(pos,1);
}
return newstr;
}
int main()
{
srand(time(0));
string random_str = RandomString(100);
cout << "random_str : " << random_str << endl;
}
Output:
random_str : DNAT1LAmbJYO0GvVo4LGqYpNcyK3eZ6t0IN3dYpHtRfwheSYipoZOf04gK7OwFIwXg2BHsSBMB84rceaTTCtBC0uZ8JWPdVxKXBd
RandomString(100)
! ;-)
std::srand()
que solo se debe llamar una vez al comienzo del programa (preferiblemente lo primero main()
). El código, tal como está, generará muchas cadenas "aleatorias" idénticas si se llama en un bucle cerrado.
#include <iostream>
#include <string>
#include <random>
std::string generateRandomId(size_t length = 0)
{
static const std::string allowed_chars {"123456789BCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz"};
static thread_local std::default_random_engine randomEngine(std::random_device{}());
static thread_local std::uniform_int_distribution<int> randomDistribution(0, allowed_chars.size() - 1);
std::string id(length ? length : 32, '\0');
for (std::string::value_type& c : id) {
c = allowed_chars[randomDistribution(randomEngine)];
}
return id;
}
int main()
{
std::cout << generateRandomId() << std::endl;
}
std::string
lugar destd::string::value_type[]
Algo aún más simple y más básico en caso de que esté contento de que su cadena contenga caracteres imprimibles:
#include <time.h> // we'll use time for the seed
#include <string.h> // this is for strcpy
void randomString(int size, char* output) // pass the destination size and the destination itself
{
srand(time(NULL)); // seed with time
char src[size];
size = rand() % size; // this randomises the size (optional)
src[size] = '\0'; // start with the end of the string...
// ...and work your way backwards
while(--size > -1)
src[size] = (rand() % 94) + 32; // generate a string ranging from the space character to ~ (tilde)
strcpy(output, src); // store the random string
}
Cadena aleatoria, cada archivo de ejecución = cadena diferente
auto randchar = []() -> char
{
const char charset[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
const size_t max_index = (sizeof(charset) - 1);
return charset[randomGenerator(0, max_index)];
};
std::string custom_string;
size_t LENGTH_NAME = 6 // length of name
generate_n(custom_string.begin(), LENGTH_NAME, randchar);
std::generate_n
asumirá que custom_string
tiene longitud LENGTH_NAME
, pero no lo hace.
Ejemplo de uso de Qt :)
QString random_string(int length=32, QString allow_symbols=QString("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")) {
QString result;
qsrand(QTime::currentTime().msec());
for (int i = 0; i < length; ++i) {
result.append(allow_symbols.at(qrand() % (allow_symbols.length())));
}
return result;
}
¡Hagamos que el azar sea conveniente nuevamente!
Creé una buena solución de solo encabezado C ++ 11. Puede agregar fácilmente un archivo de encabezado a su proyecto y luego agregar sus pruebas o usar cadenas aleatorias para otros fines.
Esa es una descripción rápida, pero puede seguir el enlace para verificar el código completo. La parte principal de la solución está en la clase Randomer:
class Randomer {
// random seed by default
std::mt19937 gen_;
std::uniform_int_distribution<size_t> dist_;
public:
/* ... some convenience ctors ... */
Randomer(size_t min, size_t max, unsigned int seed = std::random_device{}())
: gen_{seed}, dist_{min, max} {
}
// if you want predictable numbers
void SetSeed(unsigned int seed) {
gen_.seed(seed);
}
size_t operator()() {
return dist_(gen_);
}
};
Randomer
encapsula todas las cosas al azar y puede agregarle su propia funcionalidad fácilmente. Después de que tenemos Randomer
, es muy fácil generar cadenas:
std::string GenerateString(size_t len) {
std::string str;
auto rand_char = [](){ return alphabet[randomer()]; };
std::generate_n(std::back_inserter(str), len, rand_char);
return str;
}
Escriba sus sugerencias de mejora a continuación. https://gist.github.com/VjGusev/e6da2cb4d4b0b531c1d009cd1f8904ad
Otra adaptación más porque ninguna de las respuestas sería suficiente para mis necesidades. En primer lugar, si se usa rand () para generar números aleatorios, obtendrá la misma salida en cada ejecución. La semilla para el generador de números aleatorios tiene que ser algún tipo de aleatorio. Con C ++ 11 puede incluir una biblioteca "aleatoria" y puede inicializar la semilla con random_device y mt19937. Esta semilla será suministrada por el sistema operativo y será lo suficientemente aleatoria para nosotros (por ejemplo: reloj). Puede dar un rango límites están incluidos [0,25] en mi caso. Y por último, pero no menos importante, solo necesitaba una cadena aleatoria de letras minúsculas, así que utilicé la adición de caracteres. Con un enfoque de grupo de personajes no funcionó para mí.
#include <random>
void gen_random(char *s, const int len){
static std::random_device rd;
static std::mt19937 mt(rd());
static std::uniform_int_distribution<int> dist(0, 25);
for (int i = 0; i < len; ++i) {
s[i] = 'a' + dist(mt);
}
s[len] = 0;
}
//C++ Simple Code
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<char> alphanum =
{'0','1','2','3','4',
'5','6','7','8','9',
'A','B','C','D','E','F',
'G','H','I','J','K',
'L','M','N','O','P',
'Q','R','S','T','U',
'V','W','X','Y','Z',
'a','b','c','d','e','f',
'g','h','i','j','k',
'l','m','n','o','p',
'q','r','s','t','u',
'v','w','x','y','z'
};
string s="";
int len=5;
srand(time(0));
for (int i = 0; i <len; i++) {
int t=alphanum.size()-1;
int idx=rand()%t;
s+= alphanum[idx];
}
cout<<s<<" ";
return 0;
}
Tenga cuidado al llamar a la función
string gen_random(const int len) {
static const char alphanum[] = "0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
stringstream ss;
for (int i = 0; i < len; ++i) {
ss << alphanum[rand() % (sizeof(alphanum) - 1)];
}
return ss.str();
}
(adaptado de @Ates Goral ) dará como resultado la misma secuencia de caracteres cada vez. Utilizar
srand(time(NULL));
antes de llamar a la función, aunque la función rand () siempre se siembra con 1 @kjfletch .
Por ejemplo:
void SerialNumberGenerator() {
srand(time(NULL));
for (int i = 0; i < 5; i++) {
cout << gen_random(10) << endl;
}
}
#include <iostream>
#include <string>
#include <stdlib.h>
int main()
{
int size;
std::cout << "Enter size : ";
std::cin >> size;
std::string str;
for (int i = 0; i < size; i++)
{
auto d = rand() % 26 + 'a';
str.push_back(d);
}
for (int i = 0; i < size; i++)
{
std::cout << str[i] << '\t';
}
return 0;
}
void strGetRandomAlphaNum(char *sStr, unsigned int iLen)
{
char Syms[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
unsigned int Ind = 0;
srand(time(NULL) + rand());
while(Ind < iLen)
{
sStr[Ind++] = Syms[rand()%62];
}
sStr[iLen] = '\0';
}