顺序密钥生成

时间:2010-01-14 20:46:38

标签: c++ string increment

现在,我正在开发一个需要生成顺序文本密钥的项目。我需要使用对应于某个键的整数为密钥生成器设定种子,构造函数将其转换为密钥。

我的密钥生成器重载增量运算符,以便字符串直接递增,而不是我以前一直在增加索引值,然后将索引转换为我想要生成的每个键的键。

我的问题是我在生成密钥时想要使用的字符集有限。我必须找到要增加的键中的字符,找出它在我的字符集中的位置,找到集合中的下一个字符,然后用该集合中的下一个字符替换键中的字符。

这是我的代码:

// Not the full charset
std::string charset = "abcdefghijklmnopqrstuvwxyz0123456789"; 
std::string key;

key.push_back(charset[0]);

for(unsigned int place = 0; place < key.length(); place++)
{
    if(key[place] == charset[charset.length() - 1])
    {
        // Overflow, reset char at place
        key[place] = charset[0];

        if((key.length() - 1) < (place + 1))
        {
            // Carry, no space, insert char
            key.insert(key.begin(), charset[0]);
            break;
        }
        else
        {
            // Space available, increment next char
            continue;
        }
    }
    else
    {
        // Increment char at place
        key[place] = charset[charset.find(key[place]) + 1];
        break;
    }
}

在分析中,我发现搜索操作确实减慢了速度。有没有更快的方法呢?我想过从字符集中创建链接列表,但在我这样做之前,我想对此进行一些输入。

5 个答案:

答案 0 :(得分:3)

为什么你没有反向翻译数组呢?数组索引将是字符,数组中的值将是其数值(或指向另一个数组的索引)。

key[place] = charset[reverse_charset[key[place]] + 1];

答案 1 :(得分:2)

这是广义基本转换问题的另一个版本,n = 36。

您要做的是将您的密钥视为无符号整数,并查看您作为该密钥的基本36(a-z + 0-9)表示形式发布的“字符串”。

发出密钥然后将“下一个密钥”值转换为base36字符串,然后递增下一个键值。

要进行转换,请执行相同的操作,将任何整数转换为十六进制表示,但在模数学上交换36而不是16。我会将此作为练习留给读者。 :)

答案 2 :(得分:1)

您可以存储与键长度相同的向量,其中向量中的每个元素都是键中相应字符的字符集中的索引。

例如,如果key[0]为'c',则thisVector[0]将为2,因为'c'是字符集中的第3个字符。

然后将对该整数向量执行所有操作,从而消除了对字符串进行find操作的必要性。

答案 3 :(得分:1)

我不确定我是否理解你想要做的事情但是这里有一个小程序控制台程序,它使用你的字符集作为数字在基数36中打印出一系列36 * 36 * 36个3位数字键。所以它从aaa开始,到999结束。

#include <stdio.h>
typedef int Number;
const size_t N = 3;
size_t B = 36;
Number key[N] = {0};
bool carry = false;
char A[] = "abcdefghifjlmnopqrstuvwxyz0123456789";

void incr(size_t i)
{
    if(!carry)
    {
        return;
    }
    ++key[i];
    if(key[i] == B)
    {
        key[i] = 0;
    }
    else
    {
        carry = false;
    }
}

void Incr()
{
    carry = true;
    size_t i = 0;
    while(carry)
    {
        incr(i++);
    }
}

void Print()
{
    for(int i = N - 1; i >= 0; --i)
    {
        printf("%c", A[key[i]]);
    }
    printf("\n");
}

int _tmain(int argc, _TCHAR* argv[])
{
    for(int i = 0; i < B * B * B; ++i)
    {
        Print();
        Incr();

    }
    return 0;
}

答案 4 :(得分:0)

也许您最好将索引放入charset,然后在需要时将它们转换为实际字符?

这样可以省去搜索字符集中字符的开销。并且将charset索引转换为字符将是一个恒定时间操作,与反向不同。

将您的密钥存储为整数0~N-1的向量,其中N是您的字符集的长度。仅在需要时,即在增量之后,将这些整数转换为实际字符。