【问题标题】:Why does my random string generator produce too short strings?为什么我的随机字符串生成器生成的字符串太短?
【发布时间】:2018-05-30 00:44:09
【问题描述】:

我写了一个返回随机字符串的简单函数。

std::string cache::generateCacheName()
{
    static const char pool[] = "0123456789abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    std::string r;
    std::random_device rd;
    std::mt19937 eng(rd());
    std::uniform_int_distribution<> distr(0, sizeof(pool) - 1);
    for (int i = 0; i < 48; i++)
        r += pool[distr(eng)];
    return r;
}

但是,有时它会返回一个随机短于 48 个字符的字符串。

我已经在sizeof(pool) 后面添加了- 1,试图避免从pool 添加空终止符,但这并没有改变任何东西。

我哪里做错了?

【问题讨论】:

  • 这是一个很好的选择,可以通过调试器单步执行以查看问题所在,并查看您实际添加到该字符串的内容。
  • 您是如何确定字符串少于 48 个字符的?
  • @PeteBecker 通过多次调用此方法,其中大约一半最终变得太短,长度变化很大。
  • 在对字符串进行索引时应始终考虑空字符串。所以如果pool 是"",那么sizeof(pool) 是1. 1-1 == 0,而pool[0] 在这种情况下是......
  • “...其中大约一半的结尾太短...”不是您确定字符串结尾太短的方式。

标签: c++ string random


【解决方案1】:

a) 给定字符串文字“123”,大小为 4,因为它是一个由 4 个 const 字符组成的数组,计算空值。

b) 当你从那个大小中减去 1 时,你得到 3。

c) 当你有一个包含 3 个元素的数组时,第 3 个元素的偏移量为 2。

d) std::uniform_int_distribution 在闭区间 [a,b] 上定义。也就是说,直到并包括两个端点形成a到b。

e) 当您选择一个随机数并且它恰好是该间隔中的最大值(在本例中为 3)时,您从池中获取尾随空字节并将其插入到您的字符串中。您可能希望最大值为 2,而不是 3。

因此,如果恰好选择了分布中的最大数字,则您的字符串很短。也许你的代码使用 strlen(pool)-1 会更清晰,只要它不为空。

【讨论】:

  • 0 是std::string 类型对象中的有效字符值。循环看起来不错,并创建了一个包含 48 个字符的字符串对象。您可能是对的,调用此函数的代码不喜欢嵌入的 nul 字符,但问题中没有足够的信息来确定。
  • @PeteBecker 有。 sizeof(aStringEndingInANullTerminator) -1 始终是空终止符。这包含在他的发行版中。
  • @zzxyz 我认为 Pete 的观点是 std::string 比通常预期的更“类似容器”,并且在字符串中间存储嵌入的空值是完全有效的。如果您将这些空值解释为比它们实际具有更多的含义,那么它只是一个问题(这很常见)这是我猜 OP 遇到的问题。
  • 啊,是的!鉴于我与 C 代码的大量交互,这一点对我来说一直是学术性的,但足够公平。道歉。
  • 这是一个完美的例子,说明constexpr std::string_viewconst char[] 更好Live on Coliru
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-01
  • 2011-06-30
  • 1970-01-01
  • 2011-05-20
相关资源
最近更新 更多