确定地生成C中的蛮力置换

确定地生成C中的蛮力置换,c,algorithm,hash,permutation,C,Algorithm,Hash,Permutation,我正在用C写一个bruteforce hashcracker 出于明显的原因,我想生成任意符号的排列。然而,我也希望能够从给定的点“重新开始”生成置换;ie需要可序列化或确定性(不确定单词是什么) 例如,如果符号只是a-z,它看起来像这样: perm(1) => 'a' perm(2) => 'b' perm(27) => 'aa' perm(28) => 'ab' 等等 不幸的是,我对c不是很有经验,所以计算逻辑有点棘手。我想我想数一数当前排列中的字符数——比如说

我正在用C写一个bruteforce hashcracker

出于明显的原因,我想生成任意符号的排列。然而,我也希望能够从给定的点“重新开始”生成置换;ie需要可序列化或确定性(不确定单词是什么)

例如,如果符号只是a-z,它看起来像这样:

perm(1)  => 'a'
perm(2)  => 'b'
perm(27) => 'aa'
perm(28) => 'ab'
等等

不幸的是,我对c不是很有经验,所以计算逻辑有点棘手。我想我想数一数当前排列中的字符数——比如说,我们试图找到“aa”之后的下一个排列。因为我们有两个字符,我们从除以26^1=26开始,发现我们可以用一个余数除以一次。这意味着最左边的字符应该是a,最右边的字符应该是a+1=b,这表示“ab”。然而,这有点棘手:如果我们从“az”开始,我们需要转换为“ba”,如果我们从“zz”开始,我们需要转换为“aaa”

如果不需要从给定的点开始,我只需要使用一堆for循环

我的数据类型是char*,因此在我们需要预先添加一个新字符以查找下一个排列的情况下,这是否意味着我们需要为char*(因为它正在获得一个字符)分配新内存


感谢您提供的帮助

据我所知,您希望获取一个字符串并添加1,这样“a”+1将生成“b”,而“z”+1将生成“a”,并为下一个数字添加一个载波。如果没有“下一个数字”,则需要一个值为“a”的新数字

它可以通过多种方式实现。下面的方法就像一个简单的ripple载波加法

#include <stdio.h>
#include <string.h>

#define MAX 100

void nextValue(char* current)
{
    char a[MAX] = { 0 };
    size_t len = strlen(current);
    if (len >= MAX-1)
    {
        printf("Input too long\n");
        exit(1);
    }
    size_t i;
    char carry = 1;
    for(i=0; i<len;++i)
    {
        char temp = carry+current[len-1-i];
        if (temp > 'z')
        {
            carry = 1;
            a[i] = 'a';
        }
        else
        {
            carry = 0;
            a[i] = temp;
        }

    }
    if (carry)
    {
        a[i] = 'a';
    }

    len = strlen(a);
    for(i=0; i<len;++i)
    {
        current[i] = a[len-1-i];
    }

}

int main(void) {
    char p[MAX] = "az";
    printf("%s\n", p);
    nextValue(p);
    printf("%s\n", p);
    return 0;
}
#包括
#包括
#定义最大值100
void nextValue(字符*当前)
{
字符a[MAX]={0};
尺寸长度=标准长度(当前);
如果(len>=MAX-1)
{
printf(“输入太长\n”);
出口(1);
}
尺寸i;
字符进位=1;
对于(i=0;i'z')
{
进位=1;
a[i]=“a”;
}
其他的
{
进位=0;
a[i]=温度;
}
}
如果(携带)
{
a[i]=“a”;
}
len=strlen(a);
对于(i=0;i 0&¤t[i]='z')
{
当前[i]=“a”;
--一,;
}
如果(i>0 | |当前[0]!='z')
{
++当前[i];
返回;
}
当前[0]=“a”;
如果(len==MAX-1)
{
//没有空间了
返回;
}
//将新的“a”放在当前
memmove(当前+1,当前,len+1);
当前[0]=“a”;
}
内部主(空){
字符p[MAX]=“zz”;
printf(“%s\n”,p);
次值(p);
printf(“%s\n”,p);
返回0;
}

不完全符合您的要求,但它完成了任务。它将(给足够的时间)产生所有可能的字母a-z字符串。它也满足了您的要求,能够继续您停止的地方。但是,您将无法获得重新启动它的号码。您必须使用字符串

这是一种非常快速的方法。因为你提到你想用这个暴力,它比把一个数字转换成一个字符串要好得多。在大多数情况下(96%),唯一的操作是递增字符

void next(char *s)
{
    if(*s == 'z') {
        *s='a';
        next(s+1);
    } else if(*s == 0)
        *s='a';
    else
        (*s)++;
}
它接受一个字符串
s
,并假设它的形式是以任意数量的字母a-z开头,然后用零填充。没有进行错误检查

我使用以下主要工具对其进行了测试:

char s[30]="a"; 
for(int i=0; i<100; i++) {
    printf("%s ", s);
    next(s);
}

我不明白你为什么从
az
bz
,而不是从
az
ba
。什么时候才能完成从
ba
by
的顺序?我不明白为什么“bz”跟在“az”后面,这没有意义。没有这些,你只是在打印一个数字。但是没有使用符号“0”、“1”。。。您正在使用符号“a”、“b”。。。你们用的不是10垒,而是26垒。嗨,你们说得对。“az”应转换为“ba”。我将编辑原始帖子。这些被称为组合。排列是另一回事。@gilleain:不,OP所称的“排列”实际上与电子表格中用于标识列的排列类似。不完全是以26为基数的数字,因为有一个讨厌的零位,你需要知道有多少前导零。也先尝试了这种方法,但过了一段时间,我意识到处理零位数所带来的问题是不值得的,所以我改变了方法,将一个字符串更改为下一个字符串。简单得多。以10为基数的数字有10位数字。它们是0,1,2,3,4,5,6,7,8,9,10,11,而不是0,1,2,3,4,5,6,7,8,9,00,01。。。您如何将00、01等纳入该计划?@n.m.现在我明白您的意思了。你是对的。现在我正在记录每个间隔执行的尝试次数(散列计算),但是我可以很容易地将其更改为输出当前字符串。这个解决方案正是我所需要的。如果我想让它从aa->ab改为aa->ab,需要更长时间吗?同样在最后一个else块中,c样式字符串的递增是如何工作的?这就是它从aa->ba变为aa->ab的原因吗?变为aa->ab并不难,但除非你真的需要它,否则会使事情复杂化。重写
next
函数需要在添加新字符后立即移动整个当前字符串。一个杂乱无章的解决办法是写在字符数组的中间,并跟踪它的起始位置。第三种选择是,使用一些函数简单地反转字符串。但是正如你所看到的,除非你需要它,否则这是不必要的工作,只会使代码更复杂,可能更慢,而没有任何实际的收益。我在最后一个else块中所做的只是增加字符
s
指向,所以是的,这就是它从aa到ba的原因。
char s[30]="a"; 
for(int i=0; i<100; i++) {
    printf("%s ", s);
    next(s);
}
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 aa ba ca da ea fa ga ha ia ja ka la ma na oa pa qa ra sa ta ua va wa xa ya za ab bb cb db eb fb gb hb ib jb kb lb mb nb ob pb qb rb sb tb ub vb wb xb yb zb ac bc cc dc ec fc gc hc ic jc kc lc mc nc oc pc qc rc sc tc uc vc