Vigenere Cipher - 公式解释
Vigenere Cipher - Formula Explanation
首先没有人可以问这种问题所以请原谅我
#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main(int argc, string argv[]) {
string key = argv[1];
int l = strlen(argv[1]);
if (argc != 2) {
return 0;
}
for (int i = 0, n = strlen(key); i < n; i++) {
if (!isalpha(key[i])) {
return 0;
}
key[i] = tolower(key[i]);
key[i] = key[i] - 97;
}
string txt = GetString();
for (int k = 0, p = strlen(txt); k < p; k++) {
if (isalpha(txt[k])) {
if (isupper(txt[k])) {
printf("%c", (((txt[k] - 65) + (key[k % l])) % 26 + 65));
}
if (islower(txt[k])) {
printf("%c", (((txt[k] - 97) + (key[k % l])) % 26 + 97));
}
} else
if (!isalpha(txt[k])) {
printf("%c", txt[k]);
}
}
printf("\n");
return 0;
}
我不太明白这两行代码
key[i] = key[i] - 97;
printf("%c", (((txt[k] - 97) + (key[k % l])) % 26 + 97));
是否有关于我们为什么使用第一个以及第二个如何工作的简单解释?
key[i] = key[i] - 97;
该行的用途是给出键[i],该值表示 ascii 字符的值,它是我们字母表中的索引。然后,'a' 将被赋予值 0,'b' 将被赋予值 1 ....,而 'z' 将被赋予值 25.
至于第二行,
printf("%c", (((txt[k] - 97) + (key[k % l])) % 26 + 97))
它打印 ascii 值为
的字符
(((txt[k] - 97) + (key[k % l])) % 26 + 97))
97的减法与上面解释的目的相同。
%26是模数,即((txt[k] - 97) + (key[k % l]))除以26(整数除法)的余数。然后,再次加上97,将结果的顺序或索引转换为相应的ascii值。
此页面可能会让您更深入地了解 C 中的字符表示。
关于k,i,l的含义,我让你自己去掌握密码的内部功能,但是整个加密发生在你要解释的第二行。
PS : '65' 的部分是一样的,但是用大写字母,因为 'A' ascii 中的值是 65.
用于 Vigenere 密码的密钥应该全是字母。第一个表达式将字符串转换为偏移量数组,0
表示 a
,1
表示 b
,等等。97 是 'a'
的 ASCII 码。这样写会更具可读性:
for (int i = 0, n = strlen(key); i < n; i++) {
if (!isalpha((unsigned char)key[i])) {
printf("key '%s' must contain only letters\n", key);
return 1;
}
key[i] = tolower((unsigned char)key[i]);
key[i] = key[i] - 'a';
}
对于第二个表达式,如果字符txt[k]
是小写字母,printf("%c", (((txt[k] - 97) + (key[k % l])) % 26 + 97));
通过添加移位值计算并打印转置字母(key
中的每个字符是一个接一个地用作移位值,a
移位 0
,b
移位 1
等)。以下是步骤:
- 程序计算字母索引
txt[k] - 97
,97
是'a'
, 的ASCII码
- 然后添加移位值
key[k % l]
,以循环方式循环 key
中的值,
- 取模 26 得到 0 到 25 之间的字母索引。
- 它最后添加
97
,'a'
的 ASCII 值,将索引转换回小写字母。
这样写会减少冗余并提高可读性:
for (int i = 0, j = 0; txt[i] != '[=11=]'; i++) {
int c = (unsigned char)txt[i];
if (isupper(c)) {
c = (c - 'A' + key[j++ % l]) % 26 + 'A';
} else
if (islower(c)) {
c = (c - 'a' + key[j++ % l]) % 26 + 'a';
}
putchar(c);
}
另请注意,在检查是否已在命令行上传递了足够的参数之前,不应将 argv[1]
传递给 strlen()
。
这是程序的修改版本:
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, string argv[]) {
if (argc != 2) {
printf("missing key argument\n");
return 1;
}
string key = argv[1];
int klen = strlen(key);
if (klen == 0) {
printf("key cannot be empty\n");
return 1;
}
for (int i = 0; i < klen; i++) {
if (!isalpha((unsigned char)key[i])) {
printf("key '%s' must contain only letters\n", key);
return 1;
}
key[i] = tolower((unsigned char)key[i]) - 'a';
}
string txt = GetString();
for (int i = 0, j = 0; txt[i] != '[=12=]'; i++) {
int c = (unsigned char)txt[i];
if (isupper(c)) {
c = (c - 'A' + key[j++ % klen]) % 26 + 'A';
} else
if (islower(c)) {
c = (c - 'a' + key[j++ % klen]) % 26 + 'a';
}
putchar(c);
}
putchar('\n');
return 0;
}
首先没有人可以问这种问题所以请原谅我
#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main(int argc, string argv[]) {
string key = argv[1];
int l = strlen(argv[1]);
if (argc != 2) {
return 0;
}
for (int i = 0, n = strlen(key); i < n; i++) {
if (!isalpha(key[i])) {
return 0;
}
key[i] = tolower(key[i]);
key[i] = key[i] - 97;
}
string txt = GetString();
for (int k = 0, p = strlen(txt); k < p; k++) {
if (isalpha(txt[k])) {
if (isupper(txt[k])) {
printf("%c", (((txt[k] - 65) + (key[k % l])) % 26 + 65));
}
if (islower(txt[k])) {
printf("%c", (((txt[k] - 97) + (key[k % l])) % 26 + 97));
}
} else
if (!isalpha(txt[k])) {
printf("%c", txt[k]);
}
}
printf("\n");
return 0;
}
我不太明白这两行代码
key[i] = key[i] - 97;
printf("%c", (((txt[k] - 97) + (key[k % l])) % 26 + 97));
是否有关于我们为什么使用第一个以及第二个如何工作的简单解释?
key[i] = key[i] - 97;
该行的用途是给出键[i],该值表示 ascii 字符的值,它是我们字母表中的索引。然后,'a' 将被赋予值 0,'b' 将被赋予值 1 ....,而 'z' 将被赋予值 25.
至于第二行,
printf("%c", (((txt[k] - 97) + (key[k % l])) % 26 + 97))
它打印 ascii 值为
的字符(((txt[k] - 97) + (key[k % l])) % 26 + 97))
97的减法与上面解释的目的相同。
%26是模数,即((txt[k] - 97) + (key[k % l]))除以26(整数除法)的余数。然后,再次加上97,将结果的顺序或索引转换为相应的ascii值。 此页面可能会让您更深入地了解 C 中的字符表示。
关于k,i,l的含义,我让你自己去掌握密码的内部功能,但是整个加密发生在你要解释的第二行。
PS : '65' 的部分是一样的,但是用大写字母,因为 'A' ascii 中的值是 65.
用于 Vigenere 密码的密钥应该全是字母。第一个表达式将字符串转换为偏移量数组,0
表示 a
,1
表示 b
,等等。97 是 'a'
的 ASCII 码。这样写会更具可读性:
for (int i = 0, n = strlen(key); i < n; i++) {
if (!isalpha((unsigned char)key[i])) {
printf("key '%s' must contain only letters\n", key);
return 1;
}
key[i] = tolower((unsigned char)key[i]);
key[i] = key[i] - 'a';
}
对于第二个表达式,如果字符txt[k]
是小写字母,printf("%c", (((txt[k] - 97) + (key[k % l])) % 26 + 97));
通过添加移位值计算并打印转置字母(key
中的每个字符是一个接一个地用作移位值,a
移位 0
,b
移位 1
等)。以下是步骤:
- 程序计算字母索引
txt[k] - 97
,97
是'a'
, 的ASCII码
- 然后添加移位值
key[k % l]
,以循环方式循环key
中的值, - 取模 26 得到 0 到 25 之间的字母索引。
- 它最后添加
97
,'a'
的 ASCII 值,将索引转换回小写字母。
这样写会减少冗余并提高可读性:
for (int i = 0, j = 0; txt[i] != '[=11=]'; i++) {
int c = (unsigned char)txt[i];
if (isupper(c)) {
c = (c - 'A' + key[j++ % l]) % 26 + 'A';
} else
if (islower(c)) {
c = (c - 'a' + key[j++ % l]) % 26 + 'a';
}
putchar(c);
}
另请注意,在检查是否已在命令行上传递了足够的参数之前,不应将 argv[1]
传递给 strlen()
。
这是程序的修改版本:
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, string argv[]) {
if (argc != 2) {
printf("missing key argument\n");
return 1;
}
string key = argv[1];
int klen = strlen(key);
if (klen == 0) {
printf("key cannot be empty\n");
return 1;
}
for (int i = 0; i < klen; i++) {
if (!isalpha((unsigned char)key[i])) {
printf("key '%s' must contain only letters\n", key);
return 1;
}
key[i] = tolower((unsigned char)key[i]) - 'a';
}
string txt = GetString();
for (int i = 0, j = 0; txt[i] != '[=12=]'; i++) {
int c = (unsigned char)txt[i];
if (isupper(c)) {
c = (c - 'A' + key[j++ % klen]) % 26 + 'A';
} else
if (islower(c)) {
c = (c - 'a' + key[j++ % klen]) % 26 + 'a';
}
putchar(c);
}
putchar('\n');
return 0;
}