CS50的pset2“替换”输出带来的问题

时间:2020-08-28 16:40:25

标签: c encryption cs50

我似乎无法理解我的程序出了什么问题。作业是CS50在第2周的问题集中的“替代”。目标是创建一个程序,该程序在用户键入26个字符的键作为argv [2]后,将用户键入的文本转换为。用键切换常规字母。我的代码几乎可以正常工作,但是对于要加密的每个文本,使用一个或两个字母(每次都会更改),输出是错误的。

例如 ./substitution YUKFRNLBAVMWZteogxhcipjsqd

纯文本:这是CS50

密文:Cbah ah DH50

(其中字母C应该是K,而不是D)

甚至:

./ substitution NQXPOMAFTRHLZGECYJIUWSKDVB

纯文本:这是CS50

密文:Kfki ki DI50

(由于我的原因,我不知道字母T和字母i都是'k',而且都是错误的)

几个小时以来,我一直在拼命地寻找导致此错误的原因,但似乎找不到它。如果您能帮助我找到我,我将不胜感激。 预先感谢。

((如果您需要对输出进行进一步的说明,这是“ Check50”工具的消息:

:)替代存在。

:)替换。c编译

:(使用ZYXWVUTSRQPONMLKJIHGFEDCBA作为密钥,将“ A”加密为“ Z” 预期的“密文:Z ...”,而不是“密文:A ...”

:(使用ZYXWVUTSRQPONMLKJIHGFEDCBA作为密钥将“ a”加密为“ z” 预期的“密文:z ...”,而不是“密文:a ...”

:(使用NJQSUYBRXMOPFTHZVAWCGILKED作为密钥将“ ABC”加密为“ NJQ” 预期的“密文:NJ ...”,而不是“密文:CF ...”

:((使用NJQSUYBRXMOPFTHZVAWCGILKED作为密钥将“ XyZ”加密为“ KeD” 预期的“密文:Ke ...”,而不是“密文:Ke ...”

:(使用YUKFRNLBAVMWZTEOGXHCIPJSQD作为密钥,将“ This is CS50”加密为“ Cbah ah KH50” 预期的“密文:Cb ...”,而不是“密文:Cb ...”

:((使用yukfrnlbavmwzteogxhcipjsqd作为密钥,将“ This is CS50”加密为“ Cbah ah KH50” 预期的“密文:Cb ...”,而不是“密文:Cb ...”

:((使用YUKFRNLBAVMWZteogxhcipjsqd作为密钥将“ This is CS50”加密为“ Cbah ah KH50” 预期的“密文:Cb ...”,而不是“密文:Cb ...”

:(使用DWUSXNPQKEGCZFJBTLYROHIAVM作为密钥加密所有字母字符 预期的“密文:Rq ...”,而不是“密文:Rr ...”

:)处理缺少密钥的情况

:)处理无效的密钥长度

:)处理密钥中的无效字符

:)处理密钥中的重复字符

:)处理密钥中的多个重复字符)

#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>

// create the stirng variable alphabet for the key substitution
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

int main(int argc, string argv[])
{
    // get the key for the alphabet substitution as the second argument
    string key = argv[1];
    // if the user enters no key, instructions are given
    if (argc == 1)
    {
        printf("Usage: ./substitution key\n");
        return 1;
    }
    // loop to go through all the key chars and check them
    for (int i = 0; i < 26; i++)
    {
        // if at least one of the chars is not a letter, print an error and return 1
        if (!isalpha(key[i]))
        {
            printf("Key can contain only alphabetic characters.\n");
            return 1;
            break;
        }
        // adds another loop to confront a char with all the other 25 to see if there aare duplicates
        for (int j = i + 1; j < 26; j++)
        {
            // if there is a repeated char, print an error and return 1
            if (key[i] == key[j] || key[i] == ' ')
            {
                printf("Key doesn't allow repeating characters.\n");
                return 1;
                break;
            }
        }
    }
    // print an error and return 1 from main if the key is not 26 chats
    if (strlen(key) != 26)
    {
        printf("Key must contain 26 characters.\n");
        return 1;
    }
    else
    {
        // print 'plaintext: ', prompting the user for the string he wants to encrypt, using get_string
        string pltxt = get_string("plaintext: ");
        string cytxt = pltxt;
        // get the lenght of the plaintext variable
        int lentxt = strlen(pltxt);
        // loop that goes through all the chars of the plaintext
        for (int n = 0; n < lentxt; n++ )
        {
            // check if the char is a letter
            if (isalpha(pltxt[n]))
            {
                // loop that goes through all the alphabet letters to see which one the current letter is and to change it with the keys one
                for (int m = 0; m < 26; m++)
                {
                    if (toupper(pltxt[n]) == alphabet[m])
                    {
                        // conditions that keep the cases of the substituted chars
                        if (islower(pltxt[n]))
                        {
                            pltxt[n] = tolower(key[m]);
                        }
                        else if (isupper(pltxt[n]))
                        {
                            pltxt[n] = toupper(key[m]);
                        }
                    }
                }
            }
            // if char is not letter, let it as it is
            else
            {
                cytxt[n] = pltxt[n];
            }
        }
        // output 'cyphertext: ', followed by the encrypted string and a newline
        printf("cyphertext: %s\n", cytxt);
        // exit the program by returning 0 from main
        return 0;
    }
}

1 个答案:

答案 0 :(得分:0)

循环中

                for (int m = 0; m < 26; m++)
                {
                    if (toupper(pltxt[n]) == alphabet[m])
                    {
                        // conditions that keep the cases of the substituted chars
                        if (islower(pltxt[n]))
                        {
                            pltxt[n] = tolower(key[m]);
                        }
                        else if (isupper(pltxt[n]))
                        {
                            pltxt[n] = toupper(key[m]);
                        }
                    }
                }

可能会发生多次替换。

例如,在第一个示例中

./substitution YUKFRNLBAVMWZteogxhcipjsqd

plaintext: This is CS50
  1. C替换为K
  2. K替换为M
  3. M替换为Z
  4. Z替换为D

结果是C被替换为D

为防止这种情况,您应该在第一次命中后退出循环,并且每个字符最多只能进行一次替换。

                for (int m = 0; m < 26; m++)
                {
                    if (toupper(pltxt[n]) == alphabet[m])
                    {
                        // conditions that keep the cases of the substituted chars
                        if (islower(pltxt[n]))
                        {
                            pltxt[n] = tolower(key[m]);
                        }
                        else if (isupper(pltxt[n]))
                        {
                            pltxt[n] = toupper(key[m]);
                        }
                        break; // add this
                    }
                }