【问题标题】:C++ random number same sequence every timeC ++随机数每次都相同的序列
【发布时间】:2021-09-04 14:28:57
【问题描述】:

我写这个是为了生成一个随机密码:

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;

string read(string value) { //read value
    ifstream input;
    int olength;
    string line = "", output = "";
    size_t pos;
    bool a = true;
    int i = 0;
    input.open("pg_options.txt");
    if (!input.is_open()) {
        cout << "pg_options.txt missing.";
        return "error";
    }
    while (getline(input, line)) {
        pos = line.find(value);
        if (pos != string::npos) {
            while (a == true) {
                if (line[i] == '=') {
                    i++;
                    break;
                }
                else {
                    i++;
                }
            }
            olength = line.length() - value.length() - 1;
            for (int i2 = 0; i2 < olength; i2++) {
                output += line[i];
                i++;
            }
        }
    }
    input.close();
    return output;
}

char randupper() { //generate random upper case character
    char uppercase[26] = { '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' };
    int i = rand() % 26;
    return uppercase[i];
}

char randlower() { //generate random lower case character
    char lowercase[26] = { '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' };
    int i = rand() % 26;
    return lowercase[i];
}

char randspecial() { //generate random special character
    char special[7] = { '!', '#', '$', '%', '&', '*', '?' };
    int i = rand() % 7;
    return special[i];
}

char randnumbers() { //generate random number
    char numbers[10] = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };
    int i = rand() % 10;
    return numbers[i];
}

void generate() { //generate the password
    string output = "";
    int i1=0, digits = 0, upper = 0, lower = 0, special = 0, numbers = 0;
    digits = stoi(read("digits")); //get digits
    if (read("include_upper_case") == "true") { //determine number of upper case characters
        upper = rand() % (digits / 2) + 1;
        digits -= upper;
    }
    if (read("include_lower_case") == "true") {
        lower = rand() % (digits / 2) + 1;
        digits -= lower;
    }
    if (read("include_special_characters") == "true") {
        special = rand() % (digits / 2) + 1;
        digits -= special;
    }
    if (read("include_numbers") == "true") {
        numbers = digits;
    }
    else { //if numbers not included
        if (read("include_upper_case") == "true") {
            upper += digits;
        }
        else if (read("include_lower_case") == "true") {
            lower += digits;
        }
        else if (read("include_special_characters") == "true") {
            special += digits;
        }
        else {
            cout << "error generating, please check your options.";
            return;
        }
    }
    for (int i = 0; i < stoi(read("digits")); i++) {
        i1 = rand() % 4;
        if (i1 == 0) { //if uppercase
            if (upper > 0) {
                output += randupper();
                upper--;
            }
            else {
                i--;
            }
        }
        else if (i1 == 1) {
            if (lower > 0) {
                output += randlower();
                lower--;
            }
            else {
                i--;
            }
        }
        else if (i1 == 2) {
            if (special > 0) {
                output += randspecial();
                special--;
            }
            else {
                i--;
            }
        }
        else if (i1 == 3) {
            if (numbers > 0) {
                output += randnumbers();
                numbers--;
            }
            else {
                i--;
            }
        }
    }
    cout << output;
}

int main() {
    generate();
    return 0;
}

pg_options.txt:

include_special_characters=true
include_upper_case=true
include_lower_case=true
include_numbers=true
digits=10

但是,它每次运行都会生成相同的东西,即HM*nfx375g,因此它具有相同的随机数序列。 (在 generate() 中,upper 始终为 2,lower 始终为 4,special 始终为 1,numbers 始终为 3...) 有没有可以每次生成不同随机数的函数?

【问题讨论】:

  • 这并没有解决问题,而是养成使用有意义的值初始化对象的习惯,而不是默认初始化它们并立即覆盖默认值。在这种情况下,这意味着将ifstream input; ... input.open("pg_options.txt"); 更改为ifstream input("pg_options.txt");。此外,您不必致电input.close();。析构函数会这样做。
  • C++ 社区中对伪随机数感兴趣的主要力量是 Monte-Carlo 物理模拟人员,他们需要可重复性,除非明确要求相反。但在您的情况下,通常您会使用高分辨率时钟的输出为随机数生成器播种,如下所述:SO-q34490599

标签: c++ random


【解决方案1】:

需要为随机生成器播种以具有随机起点。在您的情况下,需要在使用rand() 之前通过调用srand() 来完成,例如:

#include <cstdlib>
#include <ctime>
using namespace std;

int main() {
    srand(time(0)); // <-- add this!
    generate();
    return 0;
}

但是,生成随机数的首选 C++ 方法是使用 &lt;random&gt; 头文件中可用的函数和类型。 srand()rand() 基本上是 C 的剩余部分。

看这个例子:

#include <iostream>
#include <vector>
#include <string>
#include <random>

// get 'entropy' from device that generates random numbers itself
// to seed a mersenne twister (pseudo) random generator
static std::mt19937 generator(std::random_device{}());

char random_lowercase_char()
{
    static std::uniform_int_distribution<std::size_t> distribution('a', 'z');
    return static_cast<char>(distribution(generator));
}

char random_uppercase_char()
{
    static std::uniform_int_distribution<std::size_t> distribution('A', 'Z');
    return static_cast<char>(distribution(generator));
}

char random_number_char()
{
    static std::uniform_int_distribution<std::size_t> distribution('0', '9');
    return static_cast<char>(distribution(generator));
}

char random_special_char()
{
    static std::vector<char> specials{ '!', '#', '$', '%', '&', '*', '?' };
    static std::uniform_int_distribution<std::size_t> distribution(0, specials.size()-1);
    auto index = (distribution(generator));
    return specials[index];
}

int main()
{
    for (int i = 0; i < 40; i++)
    {
        std::cout << random_lowercase_char();
        std::cout << random_uppercase_char();
        std::cout << random_number_char();
        std::cout << random_special_char();
        std::cout << std::endl;
    }
}

【讨论】:

  • 虽然这是一个很好的解决方案,但您没有解释为什么 OP 的原始代码一开始就不起作用。您应该在提供修复之前解释问题,以便 OP 从他们的错误中吸取教训。
  • @RemyLebeau 很公平 :) 我应该指出随机生成器需要播种才能真正随机 ;) 在这种情况下,它是由 std::random_device() 完成的,或者在他的情况下应该打电话给 srand。
  • @RemyLebeau 我很高兴 :) 谢谢
  • 前两个 random_xxxx_char 函数命名错误。他们不能保证只产生字母。至少存在一种字符编码,其中大写字母不连续,小写字母不连续。问题中的代码正确处理。
  • @PeteBecker 有趣,从来不知道。 :) 甚至我多年来看到的所有 constexpr 都愉快地使用 [a-z]、[A-Z]。不过应该很容易解决。
【解决方案2】:

首先添加&lt;ctime&gt;

然后在使用rand() 生成任何随机数之前使用srand(time(NULL));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-08
    • 1970-01-01
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多