为什么我的哈希程序没有通过测试
Why does my hashing program fail the tests
任务:
要在系统中注册,每个居民都必须提供一个密码。密码由拉丁字母(大写和小写)以及0到9的数字组成,即总共可以使用62个字符。密码长度为 5 到 20 个字符。密码以加密形式存储在数据库中,按照以下算法进行加密:
- 统计大写拉丁字母的个数b。对于密码中的每个大写字母字符,循环右移 bb 个字符(例如,如果 b=3,则 D 字符转换为 G 字符,Y 字符转换为 B 字符)。
- 同样,对于密码中的每个小写字符,循环右移m个字符,其中m是密码中小写字母的个数。
为了在数据库中快速搜索用户,使用以下算法为每个加密密码计算哈希函数:
- 所有62个字符都是有序的,数字在前,然后是小写字母,然后是大写字母。
- 每个字符都分配了一个代码 - 该序列中字符的编号,从 0 开始。因此,数字代码与其值匹配,小写字母代码 a-10、b-11 等。
- 所有代码求和,求和s除以数p和q的余数。得到的一对数字 (smodp,smodq) 将是哈希函数的值。
如果碰撞很少发生,即哈希函数的值匹配不同的密码,则认为哈希函数是好的。
约翰想出了一个新密码。同时,数据库中已经有nn个密码,想避免冲突。约翰会成功吗?
输入数据
第一行包含一个字符串,表示 John 的密码。
第二行包含一个整数 n——数据库中密码的数量。
第三行包含整数 p 和 q。以下行以未加密的形式存储密码。
输出数据
一个整数是散列函数与约翰密码的散列函数匹配的密码的个数。
示例输入:
AabB1cd
5
13 17
Nik143pasw
qeAom1
q1w2e3r4t
aBoba2012
N33iEj
示例输出:
2
注:
与 John 的哈希函数匹配的密码会突出显示。
处理约翰的密码:
循环移位后:CefD1gh(大写字母移位2,小写字母移位4)
字符编码之和为38+14+15+39+1+16+17=140
哈希函数等于 (10,4)
您的代码中存在一些逻辑问题。当您将大写和小写字符旋转为它们的“加密”形式时,您将遍历密码两次,有时会错误地旋转字符。仅以行
为例
if (pas[i] + big >= 'A' && pas[i] + big <= 'Z') pas[i] = pas[i] + big;
考虑 pas[i] == '9'
和 big == 8
的情况。您最终会将所有 9
转换为 A
。
现在考虑下一个循环中的行
if (pas[i] + small >= 'a' && pas[i] + small <= 'z') pas[i] = pas[i] + small;
如果 small
足够大,它将类似地将一些大写字母转换为小写字母。
你也可以把这两个问题结合起来。考虑 pas[i]
原来是 Y
,big
是 1,little
是 7 的情况。你将变换 Y --> Z
,然后在下一步变换Z --> a
.
- 将您的单个大型主要功能划分并抽象为较小的功能块。这将允许您单独推理每个部分,而不是试图将整个
main()
留在脑海中。人类的短期记忆是有限的。
一些建议的功能包括
bool is_upper(char c)
bool is_lower(char c)
bool is_numeric(char c)
char rotate_upper(char c, int steps)
char rotate_lower(char c, int steps)
- 与其在转换步骤中遍历密码两次,不如考虑遍历密码一次。如果字符是大写的,则进行相应的转换。如果是小写,则进行相应的转换。这将防止您重复旋转某些数字。
结合以上所有内容,您的主要功能的两个加密循环可以从:
for (int i = 0; i < pas.length(); i++)
{
if (pas[i] + big >= 'A' && pas[i] + big <= 'Z') pas[i] = pas[i] + big;
else if (pas[i] >= 'A' && pas[i] <= 'Z') {
int tempVar = big;
while (tempVar > 0) {
if (pas[i] == 'Z') {
pas[i] = 'A';
tempVar = tempVar - 1;
}
tempVar = tempVar - 1;
pas[i] = pas[i] + 1;
}
}
}
for (int i = 0; i < pas.length(); i++)
{
if (pas[i] + small >= 'a' && pas[i] + small <= 'z') pas[i] = pas[i] + small;
else if (pas[i] >= 'a' && pas[i] <= 'z') {
int tempVar = small;
while (tempVar > 0) {
if (pas[i] == 'z') {
pas[i] = 'a';
tempVar = tempVar - 1;
}
pas[i] = pas[i] + 1;
tempVar = tempVar - 1;
}
}
}
到
for (int i = 0; i < pas.length(); i++) {
char c = pas[i];
if (is_upper(c)) {
pas[i] = rotate_upper(c, big);
}
else if (is_lower(c)) {
pas[i] = rotate_lower(c, small);
}
}
您可以将 30 行代码转换为不到 10 行。这对于您、开发人员和任何潜在的审阅者来说都更容易阅读。
任务:
要在系统中注册,每个居民都必须提供一个密码。密码由拉丁字母(大写和小写)以及0到9的数字组成,即总共可以使用62个字符。密码长度为 5 到 20 个字符。密码以加密形式存储在数据库中,按照以下算法进行加密:
- 统计大写拉丁字母的个数b。对于密码中的每个大写字母字符,循环右移 bb 个字符(例如,如果 b=3,则 D 字符转换为 G 字符,Y 字符转换为 B 字符)。
- 同样,对于密码中的每个小写字符,循环右移m个字符,其中m是密码中小写字母的个数。
为了在数据库中快速搜索用户,使用以下算法为每个加密密码计算哈希函数:
- 所有62个字符都是有序的,数字在前,然后是小写字母,然后是大写字母。
- 每个字符都分配了一个代码 - 该序列中字符的编号,从 0 开始。因此,数字代码与其值匹配,小写字母代码 a-10、b-11 等。
- 所有代码求和,求和s除以数p和q的余数。得到的一对数字 (smodp,smodq) 将是哈希函数的值。
如果碰撞很少发生,即哈希函数的值匹配不同的密码,则认为哈希函数是好的。
约翰想出了一个新密码。同时,数据库中已经有nn个密码,想避免冲突。约翰会成功吗?
输入数据
第一行包含一个字符串,表示 John 的密码。 第二行包含一个整数 n——数据库中密码的数量。 第三行包含整数 p 和 q。以下行以未加密的形式存储密码。
输出数据
一个整数是散列函数与约翰密码的散列函数匹配的密码的个数。
示例输入:
AabB1cd
5
13 17
Nik143pasw
qeAom1
q1w2e3r4t
aBoba2012
N33iEj
示例输出:
2
注:
与 John 的哈希函数匹配的密码会突出显示。
处理约翰的密码: 循环移位后:CefD1gh(大写字母移位2,小写字母移位4) 字符编码之和为38+14+15+39+1+16+17=140 哈希函数等于 (10,4)
您的代码中存在一些逻辑问题。当您将大写和小写字符旋转为它们的“加密”形式时,您将遍历密码两次,有时会错误地旋转字符。仅以行
为例if (pas[i] + big >= 'A' && pas[i] + big <= 'Z') pas[i] = pas[i] + big;
考虑 pas[i] == '9'
和 big == 8
的情况。您最终会将所有 9
转换为 A
。
现在考虑下一个循环中的行
if (pas[i] + small >= 'a' && pas[i] + small <= 'z') pas[i] = pas[i] + small;
如果 small
足够大,它将类似地将一些大写字母转换为小写字母。
你也可以把这两个问题结合起来。考虑 pas[i]
原来是 Y
,big
是 1,little
是 7 的情况。你将变换 Y --> Z
,然后在下一步变换Z --> a
.
- 将您的单个大型主要功能划分并抽象为较小的功能块。这将允许您单独推理每个部分,而不是试图将整个
main()
留在脑海中。人类的短期记忆是有限的。
一些建议的功能包括
bool is_upper(char c)
bool is_lower(char c)
bool is_numeric(char c)
char rotate_upper(char c, int steps)
char rotate_lower(char c, int steps)
- 与其在转换步骤中遍历密码两次,不如考虑遍历密码一次。如果字符是大写的,则进行相应的转换。如果是小写,则进行相应的转换。这将防止您重复旋转某些数字。
结合以上所有内容,您的主要功能的两个加密循环可以从:
for (int i = 0; i < pas.length(); i++)
{
if (pas[i] + big >= 'A' && pas[i] + big <= 'Z') pas[i] = pas[i] + big;
else if (pas[i] >= 'A' && pas[i] <= 'Z') {
int tempVar = big;
while (tempVar > 0) {
if (pas[i] == 'Z') {
pas[i] = 'A';
tempVar = tempVar - 1;
}
tempVar = tempVar - 1;
pas[i] = pas[i] + 1;
}
}
}
for (int i = 0; i < pas.length(); i++)
{
if (pas[i] + small >= 'a' && pas[i] + small <= 'z') pas[i] = pas[i] + small;
else if (pas[i] >= 'a' && pas[i] <= 'z') {
int tempVar = small;
while (tempVar > 0) {
if (pas[i] == 'z') {
pas[i] = 'a';
tempVar = tempVar - 1;
}
pas[i] = pas[i] + 1;
tempVar = tempVar - 1;
}
}
}
到
for (int i = 0; i < pas.length(); i++) {
char c = pas[i];
if (is_upper(c)) {
pas[i] = rotate_upper(c, big);
}
else if (is_lower(c)) {
pas[i] = rotate_lower(c, small);
}
}
您可以将 30 行代码转换为不到 10 行。这对于您、开发人员和任何潜在的审阅者来说都更容易阅读。