PSET 2:Vigenere Cipher 部分工作?
PSET 2: Vigenere Cipher partially working?
我创建了以下代码作为对 CS50x PSET2 的回答:Vigenere 并且它在某种程度上起作用但是当 运行 通过 check50 时我得到下面列出的一些错误:
:) vigenere.c exists.
:) vigenere.c compiles.
:) encrypts "a" as "a" using "a" as keyword
:( encrypts "barfoo" as "caqgon" using "baz" as keyword - output not valid ASCII text
:( encrypts "BaRFoo" as "CaQGon" using "BaZ" as keyword - output not valid ASCII text
:) encrypts "BARFOO" as "CAQGON" using "BAZ" as keyword
:( encrypts "world!$?" as "xoqmd!$?" using "baz" as keyword- output not valid ASCII text
:( encrypts "hello, world!" as "iekmo, vprke!" using "baz" as keyword- output not valid ASCII text
:) handles lack of argv[1]
:) handles argc > 2
:( rejects "Hax0r2" as keyword - timed out while waiting for program to exit
似乎发生的情况是密钥包含高值(即 z/Z),它导致代码跳到下一行并错过看似随机序列的内容。例如。在字符串的第一个单词中,它错过了第 3 个字符,然后是第二个单词,它错过了第 3 个和第 4 个字符,然后是第 3 个单词第 1 个。我只是不明白发生了什么。
我已经使用 printf 来确保设置和传递给函数的所有变量在运行时都是正确的。函数本身返回正确的响应(Hax0r2 的验证除外)。我尝试通过将结果与在线 vigenere 密码工具进行比较来进行调试。
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int Validate1(int argc);
int Validate2(string argv);
void Cypher(string x);
void KeyCalc(string argv);
string MESSAGE;
int LENGTH;
int *KEY;
int COUNTER = 0;
int main(int argc, string argv[])
{
//Check if right amount of arguments are supplied
int Val1 = Validate1(argc);
if (Val1 == 0)
{
//Check if argument is a string of chars
int Val2 = Validate2(argv[1]);
if (Val2 == 0)
{
//get the string length
LENGTH = strlen(argv[1]);
//Dynamically update KEY array length
KEY = (int *)malloc(LENGTH * sizeof(*KEY));
if (KEY == NULL)
{
fprintf(stderr, "malloc failed\n");
}
//calculate the key
KeyCalc(argv[1]);
//get the message from the user to be encrypted
MESSAGE = get_string("plaintext: ");
printf("ciphertext: ");
//encrypt message from user
Cypher(argv[1]);
free(KEY);
return 0;
}
else
{
//validation failed
printf("Usage: ./vigenere keyword\n");
return 1;
}
}
else
{
//validation failed
printf("Usage: ./vigenere keyword\n");
return 1;
}
}
//Validate the number of arguments supplied
int Validate1(int argc)
{
if (argc != 2)
{
return 1;
}
else
{
return 0;
}
}
//Validate the argument is a string
int Validate2(string argv)
{
int k = 0;
//loop through all characters in argument line string and check if alphabetic
for (int i = 0; i < LENGTH; i++)
{
if isalpha(argv[i])
{
//Do Nothing
}
else
{
k++;
}
}
//k counts the number of non-alphabetic characters, so if > 0 then invalid input
if (k > 0)
{
return 1;
}
else
{
return 0;
}
}
void Cypher(string x)
{
//identify the length of the message to be coded
int Mlength = strlen(MESSAGE);
//identify the length of the key
int Slen = strlen(x);
//cycle through all characters in message supplied by user
for (int i = 0; i < Mlength; i++)
{
// loop through key
if (COUNTER > Slen - 1)
{
COUNTER = 0;
}
//check if the character is alphabetic
if (isalpha(MESSAGE[i]))
{
//convert the character to ASCII int value
char l = MESSAGE[i];
//add key value to message value and wrap around ascii mapping
if (isupper(MESSAGE[i]))
{
l = l + KEY[COUNTER];
if (l > 'Z')
{
l = l - 26;
}
}
else
{
l = l + KEY[COUNTER];
if (l > 'z')
{
l = l - 26;
}
}
//convert value back into character and store in array
MESSAGE[i] = (char) l;
// print character
printf("%c", MESSAGE[i]);
COUNTER++;
}
else
{
//character is 'numeric' or 'symbol' or 'space' just display it
printf("%c", MESSAGE[i]);
}
}
printf("\n");
}
void KeyCalc(string argv)
{
//convert key entry to values A/a = 0 to Z/z = 26
for (int i = 0; i < LENGTH; i++)
{
char k = argv[i];
if (islower(argv[i]))
{
KEY[i] = k - 'a';
}
else
{
KEY[i] = k - 'A';
}
}
}
- 使用 "baz" 作为关键字将 "barfoo" 加密为 "caqgon"
- 使用 "BaZ" 作为关键字
将 "BaRFoo" 加密为 "CaQGon"
- 使用"baz"作为关键字
将"world!$?"加密为"xoqmd!$?"
- 使用"baz"作为关键字
将"hello, world!"加密为"iekmo, vprke!"
- 拒绝 "Hax0r2" 作为关键字
来自 caesar pset 的规范:
...Caesar’s algorithm (i.e., cipher) encrypts messages by
“rotating” each letter by k positions. More formally, if p is some
plaintext (i.e., an unencrypted message), pi is the ith character in
p, and k is a secret key (i.e., a non-negative integer), then each
letter, ci, in the ciphertext, c, is computed as
ci = (pi + k) % 26
此算法(在任一 "case" 中)不这样做:
l = l + KEY[COUNTER];
if (l > 'Z')
{
l = l - 26;
}
从 9:30 开始的 This walkthrough 是关于如何实施 "shift" 的很好的入门读物。
此代码中问题的近因是此 l = l + KEY[COUNTER];
可以产生 ascii range 之外的结果。在 CS50 实现中,char
默认为 signed 字符。因此,例如,'r' + 'z'(如 "barfoo" 用 "baz" 加密)将产生 -117。
我创建了以下代码作为对 CS50x PSET2 的回答:Vigenere 并且它在某种程度上起作用但是当 运行 通过 check50 时我得到下面列出的一些错误:
:) vigenere.c exists.
:) vigenere.c compiles.
:) encrypts "a" as "a" using "a" as keyword
:( encrypts "barfoo" as "caqgon" using "baz" as keyword - output not valid ASCII text
:( encrypts "BaRFoo" as "CaQGon" using "BaZ" as keyword - output not valid ASCII text
:) encrypts "BARFOO" as "CAQGON" using "BAZ" as keyword
:( encrypts "world!$?" as "xoqmd!$?" using "baz" as keyword- output not valid ASCII text
:( encrypts "hello, world!" as "iekmo, vprke!" using "baz" as keyword- output not valid ASCII text
:) handles lack of argv[1]
:) handles argc > 2
:( rejects "Hax0r2" as keyword - timed out while waiting for program to exit
似乎发生的情况是密钥包含高值(即 z/Z),它导致代码跳到下一行并错过看似随机序列的内容。例如。在字符串的第一个单词中,它错过了第 3 个字符,然后是第二个单词,它错过了第 3 个和第 4 个字符,然后是第 3 个单词第 1 个。我只是不明白发生了什么。
我已经使用 printf 来确保设置和传递给函数的所有变量在运行时都是正确的。函数本身返回正确的响应(Hax0r2 的验证除外)。我尝试通过将结果与在线 vigenere 密码工具进行比较来进行调试。
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int Validate1(int argc);
int Validate2(string argv);
void Cypher(string x);
void KeyCalc(string argv);
string MESSAGE;
int LENGTH;
int *KEY;
int COUNTER = 0;
int main(int argc, string argv[])
{
//Check if right amount of arguments are supplied
int Val1 = Validate1(argc);
if (Val1 == 0)
{
//Check if argument is a string of chars
int Val2 = Validate2(argv[1]);
if (Val2 == 0)
{
//get the string length
LENGTH = strlen(argv[1]);
//Dynamically update KEY array length
KEY = (int *)malloc(LENGTH * sizeof(*KEY));
if (KEY == NULL)
{
fprintf(stderr, "malloc failed\n");
}
//calculate the key
KeyCalc(argv[1]);
//get the message from the user to be encrypted
MESSAGE = get_string("plaintext: ");
printf("ciphertext: ");
//encrypt message from user
Cypher(argv[1]);
free(KEY);
return 0;
}
else
{
//validation failed
printf("Usage: ./vigenere keyword\n");
return 1;
}
}
else
{
//validation failed
printf("Usage: ./vigenere keyword\n");
return 1;
}
}
//Validate the number of arguments supplied
int Validate1(int argc)
{
if (argc != 2)
{
return 1;
}
else
{
return 0;
}
}
//Validate the argument is a string
int Validate2(string argv)
{
int k = 0;
//loop through all characters in argument line string and check if alphabetic
for (int i = 0; i < LENGTH; i++)
{
if isalpha(argv[i])
{
//Do Nothing
}
else
{
k++;
}
}
//k counts the number of non-alphabetic characters, so if > 0 then invalid input
if (k > 0)
{
return 1;
}
else
{
return 0;
}
}
void Cypher(string x)
{
//identify the length of the message to be coded
int Mlength = strlen(MESSAGE);
//identify the length of the key
int Slen = strlen(x);
//cycle through all characters in message supplied by user
for (int i = 0; i < Mlength; i++)
{
// loop through key
if (COUNTER > Slen - 1)
{
COUNTER = 0;
}
//check if the character is alphabetic
if (isalpha(MESSAGE[i]))
{
//convert the character to ASCII int value
char l = MESSAGE[i];
//add key value to message value and wrap around ascii mapping
if (isupper(MESSAGE[i]))
{
l = l + KEY[COUNTER];
if (l > 'Z')
{
l = l - 26;
}
}
else
{
l = l + KEY[COUNTER];
if (l > 'z')
{
l = l - 26;
}
}
//convert value back into character and store in array
MESSAGE[i] = (char) l;
// print character
printf("%c", MESSAGE[i]);
COUNTER++;
}
else
{
//character is 'numeric' or 'symbol' or 'space' just display it
printf("%c", MESSAGE[i]);
}
}
printf("\n");
}
void KeyCalc(string argv)
{
//convert key entry to values A/a = 0 to Z/z = 26
for (int i = 0; i < LENGTH; i++)
{
char k = argv[i];
if (islower(argv[i]))
{
KEY[i] = k - 'a';
}
else
{
KEY[i] = k - 'A';
}
}
}
- 使用 "baz" 作为关键字将 "barfoo" 加密为 "caqgon"
- 使用 "BaZ" 作为关键字 将 "BaRFoo" 加密为 "CaQGon"
- 使用"baz"作为关键字 将"world!$?"加密为"xoqmd!$?"
- 使用"baz"作为关键字 将"hello, world!"加密为"iekmo, vprke!"
- 拒绝 "Hax0r2" 作为关键字
来自 caesar pset 的规范:
...Caesar’s algorithm (i.e., cipher) encrypts messages by “rotating” each letter by k positions. More formally, if p is some plaintext (i.e., an unencrypted message), pi is the ith character in p, and k is a secret key (i.e., a non-negative integer), then each letter, ci, in the ciphertext, c, is computed as
ci = (pi + k) % 26
此算法(在任一 "case" 中)不这样做:
l = l + KEY[COUNTER];
if (l > 'Z')
{
l = l - 26;
}
从 9:30 开始的 This walkthrough 是关于如何实施 "shift" 的很好的入门读物。
此代码中问题的近因是此 l = l + KEY[COUNTER];
可以产生 ascii range 之外的结果。在 CS50 实现中,char
默认为 signed 字符。因此,例如,'r' + 'z'(如 "barfoo" 用 "baz" 加密)将产生 -117。