Vigenere Cipher 仅在处理 C 中的 space(" ") 之前有效 - 为什么?
Vigenere Cipher only works up until dealing with a space(" ") in C - why?
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, string argv[])
{
string k = argv[1];
string s = GetString();
int l = strlen(k);
for(int i = 0, n = strlen(s); i < n; i++)
{
if(s[i] >= 65 && s[i] <= 90)
{
int i2 = ((s[i]-65) + (k[i%l]-97)) % 26;
printf("%c", i2+65);
} else if(s[i] >= 97 && s[i] <= 122)
{
int i2 = ((s[i]-97) + (k[i%l]-97)) % 26;
printf("%c", i2+97);
} else
{
printf("%c", s[i]);
}
}
printf("\n");
return 0;
}
为了使代码与问题更相关,我已经删除了尽可能多的部分。基本上为什么当 "s" 中没有任何 space(" ") 而当 "s" 由 space(" ") 组成时这段代码不起作用?
正如你们大多数人可能知道的那样,在 argv[1] 中输入的参数是密码的 "keyword"。然后用户输入 "plain-text" 来加密 (s)。如果它不包含任何 space、" ",当我尝试使用各种单词或句子时它会起作用。我只是不明白这背后的逻辑。如果 s[i]
不是前两个条件之一,为什么循环会中断 - 我本以为 "else" 条件会起作用。
如果有人能对此有所说明,我将不胜感激 - 非常感谢!
ps:我知道顶部有一些额外的库,argv[1]
的用户输入未通过 isalpha()
验证。我现在只想更好地了解循环过程,我已经在另一个文件中准备好了这些检查。
这是实现我所做的 'separate counters for string and key' 评论的代码。它还使用字母代码 'a'
和 'A'
(并避免需要使用 'z'
或 'Z'
)而不是使用数字。它确实假设您正在处理 single-byte 代码集(除非您在 ASCII 范围内工作,否则不是 UTF-8)其中 lower-case 和 upper-case 字母每个都在连续的范围(因此它不能可靠地与 EBCDIC 一起工作,但可以与大多数其他代码集一起工作),并且它还会忽略重音字符。 (它必须做 setlocale("")
才能得到 locale-specific 对哪些字符是字母的解释。)
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(int argc, string argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s key\n", argv[0]);
return 1;
}
string k = argv[1];
int l = strlen(k);
for (int i = 0; i < l; i++)
{
int c = k[i];
if (!isalpha(c))
{
fprintf(stderr, "%s: non-alpha character %c in key string\n", argv[0], c);
return 1;
}
k[i] = tolower(c);
}
printf("Enter a string to be encrypted:\n");
string s = GetString();
int n = strlen(s);
for (int i = 0, j = 0; i < n; i++)
{
int c = (unsigned char)s[i];
if (isupper(c))
c = ((c - 'A') + (k[j++ % l] - 'a')) % 26 + 'A';
else if (islower(c))
c = ((c - 'a') + (k[j++ % l] - 'a')) % 26 + 'a';
putchar(c);
}
putchar('\n');
return 0;
}
这里是一个示例 运行,它演示了使用 'a' 作为此维吉尼亚密码密钥中的字母之一的弱点:
./vc caesArandAbrAcaDabRa
Enter a string to be encrypted:
It is reported that Caesar said "Veni, vidi, vici" when he conquered Britain.
Kt mk rvpbutfu tjaw Cbvscr wsiu "Vrqi, wzdk, vlcj" nhgn lw cfndxesvd Drltbzn.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, string argv[])
{
string k = argv[1];
string s = GetString();
int l = strlen(k);
for(int i = 0, n = strlen(s); i < n; i++)
{
if(s[i] >= 65 && s[i] <= 90)
{
int i2 = ((s[i]-65) + (k[i%l]-97)) % 26;
printf("%c", i2+65);
} else if(s[i] >= 97 && s[i] <= 122)
{
int i2 = ((s[i]-97) + (k[i%l]-97)) % 26;
printf("%c", i2+97);
} else
{
printf("%c", s[i]);
}
}
printf("\n");
return 0;
}
为了使代码与问题更相关,我已经删除了尽可能多的部分。基本上为什么当 "s" 中没有任何 space(" ") 而当 "s" 由 space(" ") 组成时这段代码不起作用?
正如你们大多数人可能知道的那样,在 argv[1] 中输入的参数是密码的 "keyword"。然后用户输入 "plain-text" 来加密 (s)。如果它不包含任何 space、" ",当我尝试使用各种单词或句子时它会起作用。我只是不明白这背后的逻辑。如果 s[i]
不是前两个条件之一,为什么循环会中断 - 我本以为 "else" 条件会起作用。
如果有人能对此有所说明,我将不胜感激 - 非常感谢!
ps:我知道顶部有一些额外的库,argv[1]
的用户输入未通过 isalpha()
验证。我现在只想更好地了解循环过程,我已经在另一个文件中准备好了这些检查。
这是实现我所做的 'separate counters for string and key' 评论的代码。它还使用字母代码 'a'
和 'A'
(并避免需要使用 'z'
或 'Z'
)而不是使用数字。它确实假设您正在处理 single-byte 代码集(除非您在 ASCII 范围内工作,否则不是 UTF-8)其中 lower-case 和 upper-case 字母每个都在连续的范围(因此它不能可靠地与 EBCDIC 一起工作,但可以与大多数其他代码集一起工作),并且它还会忽略重音字符。 (它必须做 setlocale("")
才能得到 locale-specific 对哪些字符是字母的解释。)
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(int argc, string argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s key\n", argv[0]);
return 1;
}
string k = argv[1];
int l = strlen(k);
for (int i = 0; i < l; i++)
{
int c = k[i];
if (!isalpha(c))
{
fprintf(stderr, "%s: non-alpha character %c in key string\n", argv[0], c);
return 1;
}
k[i] = tolower(c);
}
printf("Enter a string to be encrypted:\n");
string s = GetString();
int n = strlen(s);
for (int i = 0, j = 0; i < n; i++)
{
int c = (unsigned char)s[i];
if (isupper(c))
c = ((c - 'A') + (k[j++ % l] - 'a')) % 26 + 'A';
else if (islower(c))
c = ((c - 'a') + (k[j++ % l] - 'a')) % 26 + 'a';
putchar(c);
}
putchar('\n');
return 0;
}
这里是一个示例 运行,它演示了使用 'a' 作为此维吉尼亚密码密钥中的字母之一的弱点:
./vc caesArandAbrAcaDabRa
Enter a string to be encrypted:
It is reported that Caesar said "Veni, vidi, vici" when he conquered Britain.
Kt mk rvpbutfu tjaw Cbvscr wsiu "Vrqi, wzdk, vlcj" nhgn lw cfndxesvd Drltbzn.