V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
qazwsxkevin
V2EX  ›  C++

从 string 字符串中随机提取字符,组成指定长度的新字符串问题。

  •  
  •   qazwsxkevin · 2023-02-05 23:39:37 +08:00 · 1681 次点击
    这是一个创建于 687 天前的主题,其中的信息可能已经有所发展或是发生改变。
    #include <iostream>
    #include <stdlib.h>
    #include <time.h>
    #include <string>
    
    using namespace std;
    
    int main(int argc, char **argv)
    {
        string allcode = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
       
        srand(time(NULL));
        
        int l = 8; //指定的新字符串长度
        string s;  //新组成的随机字符串
        char cc;   //被抽中的字符
        
        for (int i=0;i<l;i++)
        {
            srand(time(NULL));
            int randNum = rand() % allcode.length();
            cc = letters[randNum];
            s = s + cc;
        }
        cout << s << endl;
        
        // 为啥 s 是一串重复的字符串?
    

    另外一个问题是,观察到 srand(time(NULL))的值是 1 秒内不会变的(在我用的电脑和系统上是这样),
    如果一秒内有很多次循环,这个似乎不太好,应该如何更“真”的保证和上次循环有不同随机?

    6 条回复    2023-02-06 09:14:47 +08:00
    qazwsxkevin
        1
    qazwsxkevin  
    OP
       2023-02-05 23:42:12 +08:00
    by the way ,原本是 python 做这个的,速度有些慢,所以临时找了大学时候的 Dev-C++绿色版搭配旧 GCC 3.4.2 版本,把 python 脚本转成 C++来完成这个事情,C++11 是没有的。。。
    wevsty
        2
    wevsty  
       2023-02-05 23:50:18 +08:00   ❤️ 1
    srand 只调用一次不需要每次循环都重设 srand 。

    如果需要真随机数或者用于加密学等用途请使用平台提供的 API 或者 STL 抽象出来的 std::random_device 。
    但既然不支持 CPP11 ,那么你就只能选择使用平台提供的 API 了。
    AzadCypress
        3
    AzadCypress  
       2023-02-06 00:44:27 +08:00   ❤️ 1
    因为 time(null)返回的是 从 1970 年到现在的 秒数 ,用同一个 seed 初始化的序列肯定是一样的
    srand 一般只调用一次,把 for 循环里的 srand 删除就好了
    qazwsxkevin
        4
    qazwsxkevin  
    OP
       2023-02-06 00:55:55 +08:00
    明白了,所以,
    有啥办法,保证 1 秒内能拿 1 万个不同的种子呢?
    cnbatch
        5
    cnbatch  
       2023-02-06 03:18:22 +08:00
    最佳做法就是换新的编译器( MSVC 或者 GCC 或者 Clang 均可),使用 C++11 的 std::random_device
    (等待答案的这段时间,足够用来下载新版本了)

    cppreference 连示例都列出来了
    https://en.cppreference.com/w/cpp/numeric/random/random_device/random_device
    照抄就能用,只需要按照实际需求改一改 d(0, 9) 的范围就可以了

    顺便扩充点内容:
    cppreference 给出的这段 demo 用了 4 种不同的 std::random_device 初始化版本,对于 MSVC 而言全都一样,初始化参数会自动忽略掉(我猜也许 GCC 和 Clang 在 Windows 都是一样的,若要确定那就需要查源码,我懒得查了),微软自己的文档就有提到‘the values produced are non-deterministic and cryptographically secure, but runs more slowly than generators created from engines and engine adaptors’
    https://learn.microsoft.com/en-us/cpp/standard-library/random-device-class?view=msvc-170
    似乎在暗示 MSVC 的 std::random_device 会尽可能调用硬件生成器
    piku
        6
    piku  
       2023-02-06 09:14:47 +08:00 via Android
    Python 慢?试了一万行 8 随机字母只有 0.128 秒
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1216 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 77ms · UTC 23:28 · PVG 07:28 · LAX 15:28 · JFK 18:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.