我正在使用CS50课程习题集2学习C,该课程使用crypt函数蛮力猜测密码。当前正在编写一个函数,该函数打印一定长度的所有可能的字符串,例如:
aa
ab
...
az
ba
...
zy
zz
我已经编写了一个相当简单的递归函数来做到这一点:
#include <cs50.h>
#include <stdio.h>
#include <crypt.h>
#include <string.h>
void stringcycler(int n, int passLength, char *pass)
// Scrolls through all lowercase letter combinations for a string of length passLength
// Expects an integer value of the length of the strng as both n and passLength
// Also expects a char* array of length passLength with all chars set to 'a' (and a null character)
{
if(n != 0)
{
for(pass[passLength - n] = 'a'; pass[passLength - n] < 'z'; pass[passLength - n]++)
{
stringcycler(n-1, passLength, pass);
printf("%s\n", pass);
// return 0;
}
}
}
int main()
{
// Initialise char *c, and scroll through letters
int passLength = 2; // The number of characters you want to brute force guess
char pass[passLength + 1]; // Add 1 for the null character
int i;
for(i = 0; i < passLength; i++) pass[i] = 'a'; // Set every char in pass to 'a'
pass[passLength] = '\0'; // Set null character at the end of string
stringcycler(passLength, passLength, pass);
return 0;
}
它在大多数情况下都有效,但仅适用于yz。每当它看到z时,它基本上都会跳过,因此它转到yz,然后再也不会将za更改为zz。如果我在for循环行中添加=:
pass[passLength - n] < 'z';
即。
pass[passLength - n] <= 'z';
然后在混合中打印“ {”字符。有什么帮助吗?另一个问题是,我该如何更改它以使其也适用于所有大小写组合,是否有一种整齐的方法呢?
答案 0 :(得分:0)
您从递归返回后进行打印,但是当递归到达字符串的末尾(或您的情况下开始)时,您应该进行打印。换句话说,打印应该是递归的替代分支:
void stringcycler(int n, int len, char *pass)
{
if (n != 0) {
for (pass[len - n] = 'a'; pass[len - n] <= 'z'; pass[len - n]++) {
stringcycler(n - 1, len, pass);
}
} else {
printf("%s ", pass);
}
}
if
部分在向下递归时构造字符串。 else
部分使用所构造的字符串执行某些操作。 (当然,您必须在循环中包含'z'
。您的原始代码只会在最后一个位置打印z,因为它会在递归返回后打印,这意味着char缓冲区处于不会(重新)进入循环。
答案 1 :(得分:0)
以下是用于生成密码的通用回溯算法。这里的想法是想象为给定的char数组ConditionParseException
填充插槽。我们将为数组a
的给定位置k
生成可能的候选对象。我已将候选人选为小写的ASCII字母a
和大写的ASCII字母a-z
。如果要包含其他ASCII字符,只需相应地修改Construct_candidates函数。
数组填满后,即k变成A-Z
,我们知道我们已经生成了密码,可以按需处理它,我只是在这里打印了密码。
可以调整PASS_LEN宏的值以生成任意长度的密码。
PASS_LEN