C PSET 2:维格纳密码部分工作?

C PSET 2:维格纳密码部分工作?,c,cs50,vigenere,C,Cs50,Vigenere,我创建了以下代码作为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

我创建了以下代码作为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),这会导致代码跳到下一行,并遗漏看似随机的序列。字符串的第一个字漏掉了第三个字符,第二个字漏掉了第三个和第四个,第三个字漏掉了第一个。我就是不明白发生了什么

我使用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'; 
        }      
    }    
}
#包括
#包括
#包括
#包括
#包括
int Validate1(int argc);
int Validate2(字符串argv);
无效密码(字符串x);
void KeyCalc(字符串argv);
字符串消息;
整数长度;
int*键;
int计数器=0;
int main(int argc,字符串argv[])
{
//检查是否提供了正确数量的参数
int Val1=Validate1(argc);
if(Val1==0)
{
//检查参数是否为字符字符串
int Val2=Validate2(argv[1]);
if(Val2==0)
{
//获取字符串长度
长度=strlen(argv[1]);
//动态更新密钥数组长度
KEY=(int*)malloc(LENGTH*sizeof(*KEY));
if(KEY==NULL)
{
fprintf(stderr,“malloc失败\n”);
}
//计算密钥
KeyCalc(argv[1]);
//从要加密的用户处获取消息
MESSAGE=get_字符串(“明文:”);
printf(“密文:”);
//加密来自用户的消息
Cypher(argv[1]);
免费(钥匙);
返回0;
}
其他的
{
//验证失败
printf(“用法:./vigenere关键字\n”);
返回1;
}
}
其他的
{
//验证失败
printf(“用法:./vigenere关键字\n”);
返回1;
}
}
//验证提供的参数数
int Validate1(int argc)
{
如果(argc!=2)
{
返回1;
}
其他的
{
返回0;
}
}
//验证参数是否为字符串
int Validate2(字符串argv)
{
int k=0;
//循环遍历参数行字符串中的所有字符,并检查是否按字母顺序排列
for(int i=0;i0)
{
返回1;
}
其他的
{
返回0;
}
}
无效密码(字符串x)
{
//确定要编码的消息的长度
int mllength=strlen(消息);
//确定钥匙的长度
int Slen=strlen(x);
//循环浏览用户提供的消息中的所有字符
对于(int i=0;iSlen-1)
{
计数器=0;
}
//检查字符是否按字母顺序排列
if(isalpha(消息[i]))
{
//将字符转换为ASCII int值
charl=消息[i];
//将键值添加到消息值并环绕ascii映射
if(isupper(消息[i]))
{
l=l+键[计数器];
如果(l>'Z')
{
l=l-26;
}
}
其他的
{
l=l+键[计数器];
如果(l>'z')
{
l=l-26;
}    
}
//将值转换回字符并存储在数组中
消息[i]=(字符)l;
//打印字符
printf(“%c”,消息[i]);
计数器++;
}
其他的
{
//字符是“数字”或“符号”或“空格”,只需显示即可
printf(“%c”,消息[i]);
}
}
printf(“\n”);
}
void KeyCalc(字符串argv)
{
//将键条目转换为A/A=0到Z/Z=26的值
for(int i=0;i
  • 使用“baz”作为关键字将“barfoo”加密为“caqgon”
  • 使用“BaZ”作为关键字将“BaRFoo”加密为“CaQGon”
  • 使用“baz”作为关键字将“world!$?”加密为“xoqmd!$?”
  • 使用“baz”作为关键字将“hello,world!”加密为“iekmo,vprke!”
  • 拒绝将“Hax0r2”作为关键字

来自凯撒pset规范:

…凯撒算法(即密码)通过 通过k个位置“旋转”每个字母。更正式地说,如果p是 明文(即未加密的消息),pi是 p、 k是一个密钥(即非负整数),然后 密文c中的字母ci计算为

ci=(pi+k)%26

此算法(在任何一种“情况”下)都不会:

 l = l + KEY[COUNTER];
                if (l > 'Z')
                {
                    l = l - 26;    
                }
从9:30开始是如何实施“轮班”的良好入门


该代码中出现问题的直接原因是该
l=l+键[计数器]可以在外部生成结果。在CS50实现中,
char
默认为有符号字符。因此,例如,'r'+'z'(如“barfoo”中用“baz”加密)将产生-117

来自凯撒pset规范:

…凯撒算法(即密码)通过 通过k个位置“旋转”每个字母。更正式地说,如果p是 纯文本(即