CS50 下面的替换是大写我的 A 字符

问题描述 投票:0回答:1

正在做CS50的第2周。它应该是一个加密算法。我已经到了它对我的代码进行加密的地步,但由于某种原因,当我尝试测试我的代码并使用我的名字时,它不会使我的第二个 A 字符成为小写的 a。

密钥:NQXPOMAFTRHLZGECYJIUWSKDVB 输入:阿曼多

我得到的-->密文:NjzNgpe 我想要的-->密文:Njzngpe

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

char alpha[] = {'A','B','C','D','E','F','G','H','I','J','K','L','M',
                'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
int cypher[] = {};
char new[] = {};

void cypher_s(string k);
void scramble(string s, int l);

int main(int argc, string argv[])
{
    if (argc == 2)
    {
        string key = argv[1];
        cypher_s(key);
        string text = get_string("plaintext: ");
        scramble(text, strlen(key));
    }
    else
    {
        printf("You suck, you need a command line argument or typed too many\n");
        return 1;
    }
}

void cypher_s(string k)
{
    for (int i = 0; i < strlen(k); i++)
    {
        cypher[i] = k[i];
    }
}

void scramble(string s, int l)
{
    for (int i = 0; i < strlen(s); i++)
    {
        int position = 0;
        for (int k = 0; k < l; k++)
        {
            if (s[i] == alpha[position])
            {
                printf("Capital %c\n", s[i]);
                new[i] = cypher[position];
                position++;
            }
            else if (s[i] == tolower(alpha[position]))
            {
                printf("Lower %c\n", s[i]);
                new[i] = tolower(cypher[position]);
                position++;
            }
            else
            {
                position++;
            }
        }
    }
    printf("ciphertext: ");
    for (int j = 0; j < strlen(new); j++)
    {
        printf("%c", new[j]);
    }
    printf("\n");
}
c cs50
1个回答
0
投票

尝试您的代码,首先注意到的是尝试编译代码时返回的编译器警告,表示可能超出字符数组的边界。

/home/craig/C_Programs/Console/Crypto/main.c||In function ‘cypher_s’:|
/home/craig/C_Programs/Console/Crypto/main.c|36|warning: array subscript i is outside array bounds of ‘int[0]’ [-Warray-bounds]|
/home/craig/C_Programs/Console/Crypto/main.c|7|note: while referencing ‘cypher’|
/home/craig/C_Programs/Console/Crypto/main.c||In function ‘scramble’:|
/home/craig/C_Programs/Console/Crypto/main.c|68|warning: array subscript j is outside array bounds of ‘char[0]’ [-Warray-bounds]|
/home/craig/C_Programs/Console/Crypto/main.c|8|note: while referencing ‘new’|
/home/craig/C_Programs/Console/Crypto/main.c|56|warning: array subscript i is outside array bounds of ‘char[0]’ [-Warray-bounds]|
/home/craig/C_Programs/Console/Crypto/main.c|8|note: while referencing ‘new’|
/home/craig/C_Programs/Console/Crypto/main.c|50|warning: array subscript position is outside array bounds of ‘int[0]’ [-Warray-bounds]|
/home/craig/C_Programs/Console/Crypto/main.c|7|note: while referencing ‘cypher’|
/home/craig/C_Programs/Console/Crypto/main.c|50|warning: array subscript i is outside array bounds of ‘char[0]’ [-Warray-bounds]|
/home/craig/C_Programs/Console/Crypto/main.c|8|note: while referencing ‘new’|
||=== Build finished: 0 error(s), 6 warning(s) (0 minute(s), 0 second(s)) ===|

此外,即使全局变量是绝对允许的,但通常和习惯上使用每个函数的本地变量以避免变量引用的范围问题。

考虑到这一点并查看简化代码的建议,以下是代码的重构版本。

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

#define SIZE 100

void scramble(char * s, char * x, char * c);

int main(int argc, char * argv[])
{
    if (argc == 2)
    {
        char * key = argv[1];
        char text[SIZE], cypher[SIZE];  /* Define strings with a specific size in lieu of a zero length */
        //cypher_s(key);
        printf("plaintext: ");  /* Do not have CS50 - using usual and customary printf/prompt method    */
        scanf("%s", text);
        //string text = get_string("plaintext: ");
        scramble(text, key, cypher);
        printf("The scrambled text is: %s\n", cypher);  /* Placed the output of the encrypted text in the main function */
    }
    else
    {
        printf("Please enter the encryption key as a parameter\n");
        return 1;
    }
}

void scramble(char * s, char * x, char * c)
{
    char alpha[] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};

    int l = strlen(s);  /* Length of the text to be encrypted   */
    int m = strlen(x);  /* Length of the key                    */

    strcpy(c, s);       /* Set the target string to the text    */

    for (int i = 0; i < l; i++)
    {
        for (int k = 0; k < m; k++)     /* Scan through the encryption key for match    */
        {
            if (s[i] == alpha[k])       /* No need for a separate index counter         */
            {
                //printf("Capital %c\n", s[i]);
                c[i] = x[k];
                break;
            }
            else if (s[i] == tolower(alpha[k]))
            {
                //printf("Lower %c\n", s[i]);
                c[i] = tolower(x[k]);
                break;
            }
            else
            {
                /* Not a character that needs to be encrypted   */
            }
        }
    }
}

以下是一些要点。

  • 由于我没有安装 CS50 软件包,因此我选择恢复为字符串和字符串提示的等效定义;但是,如果您愿意,请随意使用这些功能。
  • 重新定位全局变量以匹配其范围和用法,从而消除了对全局变量的需要。
  • 在评估“cypher”函数时,它的唯一目的是将字符数组存储到整数数组中,因此为了简化而将其删除。
  • 字符串长度在加扰/加密功能中确定并存储在工作变量中,这再次简化了匹配和文本加密的使用。

以下是使用此重构代码在终端进行的一些测试。

craig@Vera:~/C_Programs/Console/Crypto/bin/Release$ ./Crypto NQXPOMAFTRHLZGECYJIUWSKDVB
plaintext: Armando
The scrambled text is: Njzngpe
craig@Vera:~/C_Programs/Console/Crypto/bin/Release$ ./Crypto NQXPOMAFTRHLZGECYJIUWSKDVB
plaintext: Armando$%6__x
The scrambled text is: Njzngpe$%6__d
craig@Vera:~/C_Programs/Console/Crypto/bin/Release$ 

这些重构只是您遇到的问题的众多可能解决方案之一,但此代码重构的关键要点是:

  • 注意所有编译器警告,因为它们可能指出可能的未定义行为,例如零长度字符数组。
  • 如果可能,选择局部变量而不是全局变量。
© www.soinside.com 2019 - 2024. All rights reserved.