Jawaban:
Jawaban Mehrdad Afshari akan melakukan trik, tetapi saya merasa agak terlalu verbose untuk tugas sederhana ini. Tabel pencarian terkadang dapat melakukan keajaiban:
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
salah. Jika s
adalah string C (NULL dihentikan) maka tanda tangan metode tidak harus memiliki len
parameter di dalamnya. Imo, jika Anda melewatkan panjang sebagai argumen, Anda menganggap array bukan string C. Dengan demikian, jika Anda tidak meneruskan string C ke fungsi, baris tersebut s[len] = 0
dapat memecah hal-hal, karena array akan berubah dari 0 menjadi len-1. Dan bahkan jika Anda melewatkan string C ke fungsi, garis s[len] = 0
akan menjadi berlebihan.
Inilah adaptasi saya atas jawaban Ates Goral menggunakan C ++ 11. Saya telah menambahkan lambda di sini, tetapi prinsipnya adalah Anda bisa meneruskannya dan dengan demikian mengontrol karakter apa yang terkandung dalam string Anda:
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;
}
Berikut ini adalah contoh meneruskan lambda ke fungsi string acak: http://ideone.com/Ya8EKf
Mengapa Anda menggunakan C ++ 11 ?
Sebagai contoh:
#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()
potongan kode pertama Anda?
rand()
lagi. Itu bahkan tidak seragam untuk menangis dengan suara keras ...
Solusi 2p saya:
#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
bukan mt19937
? Kode akan terlihat lebih umum.
std::default_random_engine
bukanlah sesuatu yang saya rasa bagus untuk merekomendasikan karena standar tidak menjamin kualitas, efisiensi atau pengulangan antara implementasi.
sizeof
, ubah auto&
to std::string
, yang memberi Andastd::string::length
std::string
cenderung lambat karena berisi pointer internal ke datanya. Itu berarti tipuan ekstra yang tidak diperlukan array statis. Juga sizeof
tidak pernah bisa lebih lambat daripada std::string::size
karena itu adalah waktu kompilasi yang konstan.
std::size
tidak muncul sampai C++17
dan masih ada banyak orang yang hanya coding C++11/14
sehingga saya akan membiarkannya seperti sekarang.
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;
}
Saya baru saja menguji ini, ini bekerja dengan baik dan tidak memerlukan tabel pencarian. rand_alnum () semacam memaksa keluar alfanumerik tetapi karena memilih 62 dari kemungkinan 256 karakter, itu bukan masalah besar.
#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;
}
Daripada melakukan perulangan secara manual, lebih baik menggunakan algoritma C ++ yang sesuai , dalam hal ini std::generate_n
, dengan penghasil angka acak yang tepat :
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;
}
Ini dekat dengan sesuatu yang saya sebut solusi "kanonik" untuk masalah ini.
Sayangnya, menabur dengan benar generator generik acak C ++ generik (mis. MT19937) benar-benar sulit . Oleh karena itu kode di atas menggunakan fungsi template helper, 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};
}
Ini rumit dan relatif tidak efisien. Untungnya ini digunakan untuk menginisialisasi athread_local
variabel dan oleh karena itu hanya dipanggil sekali per utas.
Akhirnya, yang perlu mencakup untuk di atas adalah:
#include <algorithm>
#include <array>
#include <cstring>
#include <functional>
#include <limits>
#include <random>
#include <string>
Kode di atas menggunakan deduksi argumen templat kelas dan karenanya membutuhkan C ++ 17. Ini dapat diadaptasi sepele untuk versi sebelumnya dengan menambahkan argumen templat yang diperlukan.
std::size_t
untuk menyimpulkan std::uniform_int_distribution
? Saya tidak dapat melihat CTAD lainnya
rng
sebagai parameter default, dengan sesuatu sepertitemplate <typename T = std::mt19937> inline thread_local T default_rng = get_random_generator<T>();
std::uniform_int_distribution<>
, yang akan aman, tetapi mungkin memperingatkan tentang konversi yang ditandatangani -> tidak ditandatangani.
Saya harap ini membantu seseorang.
Diuji di https://www.codechef.com/ide dengan 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()
hanya benar-benar dipanggil sekali pada awal program (lebih disukai hal pertama dalam main()
). Kode ini, seperti apa adanya, akan menghasilkan banyak string "acak" yang identik jika dipanggil dalam loop yang ketat.
#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
bukannyastd::string::value_type[]
Sesuatu yang lebih sederhana dan lebih mendasar jika Anda senang string Anda mengandung karakter yang dapat dicetak:
#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
}
String acak, setiap file run = string berbeda
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
akan menganggap custom_string
memiliki panjang LENGTH_NAME
, tetapi tidak.
Contoh untuk penggunaan 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;
}
Mari kita buat kenyamanan acak lagi!
Saya membuat solusi bagus C ++ 11 header saja. Anda dapat dengan mudah menambahkan satu file header ke proyek Anda dan kemudian menambahkan tes Anda atau menggunakan string acak untuk tujuan lain.
Itu deskripsi singkat, tetapi Anda dapat mengikuti tautan untuk memeriksa kode lengkap. Bagian utama dari solusi adalah di kelas 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
melumpuhkan semua hal acak dan Anda dapat menambahkan fungsionalitas Anda sendiri dengan mudah. Setelah kita miliki Randomer
, sangat mudah untuk menghasilkan string:
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;
}
Tulis saran Anda untuk peningkatan di bawah ini. https://gist.github.com/VjGusev/e6da2cb4d4b0b531c1d009cd1f8904ad
Namun adaptasi lain karena tidak ada jawaban akan mencukupi kebutuhan saya. Pertama-tama jika rand () digunakan untuk menghasilkan angka acak, Anda akan mendapatkan output yang sama di setiap proses. Benih untuk pembangkit bilangan acak harus berupa acak. Dengan C ++ 11 Anda dapat memasukkan pustaka "acak" dan Anda dapat menginisialisasi benih dengan random_device dan mt19937. Benih ini akan disediakan oleh OS dan itu akan cukup acak bagi kami (misalnya: jam). Anda dapat memberikan batasan batas yang disertakan [0,25] dalam kasus saya. Dan yang tak kalah pentingnya, saya hanya membutuhkan string acak huruf kecil jadi saya menggunakan tambahan char. Dengan kumpulan karakter pendekatan tidak berhasil untuk saya.
#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;
}
Jadilah ware saat memanggil fungsi
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();
}
(diadaptasi dari @Ates Goral ) itu akan menghasilkan urutan karakter yang sama setiap kali. Menggunakan
srand(time(NULL));
sebelum memanggil fungsi, meskipun fungsi rand () selalu diunggulkan dengan 1 @kjfletch .
Sebagai contoh:
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';
}