=PSET 2 CAESAR= 如何将 ASCII 范围向下转换为 0 到 25 之间的值?
=PSET 2 CAESAR= How do I convert ASCII range down to a value from 0 to 25?
我第一次这样做:
// Convert ASCII range down to a value from 0 to 25
char uppercase[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char lowercase[27] = "abcdefghijklmnopqrstuvwxyz";
char convertedUppercase[27];
char convertedLowercase[27];
for (int i = 0; i <= 26; i++)
{
convertedUppercase[i] = uppercase[i] - 'A';
convertedLowercase[i] = lowercase[i] - 'a';
}
// For each character in the plaintext: (DOESN'T WORK)
for (int i = 0, n = strlen(p); i <= n; i++)
{
// Rotate the character if it's a letter // ci = (pi + k) % 26
if (isalpha(p[i]))
{
if (isupper(p[i]))
{
c[i] = ((p[i]) + k) % 26;
}
else if (islower(p[i]))
{
c[i] = ((p[i]) + k) % 26;
}
}
}
printf("ciphertext: %s\n", c);
但后来我意识到 convertedUppercase
的值就像 0 = NUL 而不是 0 = A。谁能告诉我该怎么做?
编辑:
来自 CS50 Discord:
》凯撒密码公式(p + k) % 26的工作前提是p(明文字符)的值为0 - 25(代表a - z或A - Z)
因此,如果您的纯字符为 'x',则其值为 23,如果您的密钥为 2,则加密字符将为:
(23 + 2) % 26
( 25 ) % 26
= 25 'z'
我有点不知道该怎么做。
如果您提供 MRE,这会容易得多。
我想您正在观察的是,如果您尝试通过 printf()
和 "%s"
.
输出它,您会看到截断的密文
然而,这只是因为任何“A”(即 ciper A,即按键移位后)导致 0(终止字符串输出,作为 '[=14=]'
终止符),而大多数其他字母导致不可打印的字符。
这是因为你只需要按键移动并映射到 0-25,这里需要数字表示(即数字而不是文本密码):
c[i] = ((p[i]) + k) % 26;
为了从数字密码变成文本密码,你需要做
- 将文本转换为数字,
-'A'
- 按键切换,
+k
- 映射到 0-25,
%26
- 将数字转换为文本,
+'A'
即
c[i] = ((p[i]-'A') + k) % 26 + 'A';
例如“Hello World”中的“H”。
- 文本到数字,'H' - 'A' -> 7
- 按键移位,7 + 4 -> 11
- 映射到 0-25、11%26 -> 11
- 数字到文本,11 + 'A' -> 'L' 是密码
例如“Hello World”中的“W”。
- 文本到数字,'W' - 'A' -> 22
- 按键移位,22 + 4 -> 26
- 映射到 0-25、26%26 -> 0
- 数字到文本,0 + 'A' -> 'A' 是密码
我第一次这样做:
// Convert ASCII range down to a value from 0 to 25
char uppercase[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char lowercase[27] = "abcdefghijklmnopqrstuvwxyz";
char convertedUppercase[27];
char convertedLowercase[27];
for (int i = 0; i <= 26; i++)
{
convertedUppercase[i] = uppercase[i] - 'A';
convertedLowercase[i] = lowercase[i] - 'a';
}
// For each character in the plaintext: (DOESN'T WORK)
for (int i = 0, n = strlen(p); i <= n; i++)
{
// Rotate the character if it's a letter // ci = (pi + k) % 26
if (isalpha(p[i]))
{
if (isupper(p[i]))
{
c[i] = ((p[i]) + k) % 26;
}
else if (islower(p[i]))
{
c[i] = ((p[i]) + k) % 26;
}
}
}
printf("ciphertext: %s\n", c);
但后来我意识到 convertedUppercase
的值就像 0 = NUL 而不是 0 = A。谁能告诉我该怎么做?
编辑:
来自 CS50 Discord:
》凯撒密码公式(p + k) % 26的工作前提是p(明文字符)的值为0 - 25(代表a - z或A - Z)
因此,如果您的纯字符为 'x',则其值为 23,如果您的密钥为 2,则加密字符将为:
(23 + 2) % 26
( 25 ) % 26
= 25 'z'
我有点不知道该怎么做。
如果您提供 MRE,这会容易得多。
我想您正在观察的是,如果您尝试通过 printf()
和 "%s"
.
输出它,您会看到截断的密文
然而,这只是因为任何“A”(即 ciper A,即按键移位后)导致 0(终止字符串输出,作为 '[=14=]'
终止符),而大多数其他字母导致不可打印的字符。
这是因为你只需要按键移动并映射到 0-25,这里需要数字表示(即数字而不是文本密码):
c[i] = ((p[i]) + k) % 26;
为了从数字密码变成文本密码,你需要做
- 将文本转换为数字,
-'A'
- 按键切换,
+k
- 映射到 0-25,
%26
- 将数字转换为文本,
+'A'
即
c[i] = ((p[i]-'A') + k) % 26 + 'A';
例如“Hello World”中的“H”。
- 文本到数字,'H' - 'A' -> 7
- 按键移位,7 + 4 -> 11
- 映射到 0-25、11%26 -> 11
- 数字到文本,11 + 'A' -> 'L' 是密码
例如“Hello World”中的“W”。
- 文本到数字,'W' - 'A' -> 22
- 按键移位,22 + 4 -> 26
- 映射到 0-25、26%26 -> 0
- 数字到文本,0 + 'A' -> 'A' 是密码