我正在用C编写一个暴力破解者。
出于显而易见的原因,我想生成任意符号的排列。但是,我还希望能够“重新启动”从给定点生成排列;即它需要是可序列化的或确定性的(不确定这个词是什么)。
因此,例如,如果符号只是a-z,它看起来像这样:
perm(1) => 'a'
perm(2) => 'b'
perm(27) => 'aa'
perm(28) => 'ab'
等等。
不幸的是我对c不太熟悉,所以解决这个问题有点棘手。我想我想计算当前排列中的字符数 - 让我们说我们试图找到'aa'之后的下一个排列。由于我们有两个字符,我们首先除以26 ^ 1 = 26,并发现我们可以用一个余数除一次。这意味着最左边的字符应该是a,最右边的字符应该是+ 1 = b,给我们'ab'。然而这有点棘手:如果我们以“az”开头,我们需要转换为“ba”,如果我们以“zz”开头,我们需要转换为“aaa”。
如果没有要求能够从给定点开始,我只会使用一堆for循环。
我的数据类型是一个char *,所以在我们需要添加一个新字符来查找下一个排列的情况下,这是否意味着我们需要为char *分配新的内存(因为它获得了一个字符)? / p>
感谢您的帮助
答案 0 :(得分:-1)
据我所知,你想要一个字符串并添加1,以便' +1导致' b'和' +1' +1导致' a'和下一个数字的载体。如果没有"下一个数字",您需要一个值为' a'的新数字。
它可以通过多种方式实现。下面的方法就像一个简单的波纹载波添加。
#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;
}
另一种方法 - 也许是表现更好的方法 - 是检查&#39; z&#39;的输入字符串。从最后一个角色开始。只有在所有字符都是&#39; z&#39;时,才需要插入&#39; a&#39;在前。类似的东西:
#include <stdio.h>
#include <string.h>
#define MAX 100
void nextValue(char* current)
{
size_t len = strlen(current);
size_t i = len - 1;
while(i > 0 && current[i] == 'z')
{
current[i] = 'a';
--i;
}
if (i > 0 || current[0] != 'z')
{
++current[i];
return;
}
current[0] = 'a';
if (len == MAX-1)
{
// No more space
return;
}
// Place a new 'a' in front of current
memmove(current+1, current, len+1);
current[0] = 'a';
}
int main(void) {
char p[MAX] = "zz";
printf("%s\n", p);
nextValue(p);
printf("%s\n", p);
return 0;
}
答案 1 :(得分:-1)
不完全符合您的要求,但它完成了工作。它将(给定足够的时间)用字母a-z产生所有可能的字符串。它也符合您的要求,能够在您停止的地方继续。但是,您将无法从中重新启动它。你必须使用字符串。
这是一种非常快速的方法。既然你提到你想把它用于蛮力,那么比将数字转换为字符串要好得多。在大多数情况下(96%),唯一的操作是递增一个字符。
s
它需要一个字符串char s[30]="a";
for(int i=0; i<100; i++) {
printf("%s ", s);
next(s);
}
并假设它在表单上以任意数量的字母a-z开头,然后用零填充。没有进行错误检查。
我用这个主要测试了它:
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
输出:
select * from TableName
where monthname(modified_date) between monthname(a.modified_date)= "March"
and monthname(modified_date)="June" ;