【问题标题】:Caesar cipher program written in C has a bug用C编写的凯撒密码程序有一个错误
【发布时间】:2022-09-30 21:20:55
【问题描述】:

我为 cs50 编写了一个程序,它应该接收(整数)key(在运行时)并输出plaintext 的提示,然后根据凯撒密码函数输出明文的加密版本。 当我在 cs50 IDE 中运行该程序时,它会在终端 (make caesar) 中编译,当我在运行时输入 \'key\'​​ 时(例如./caesar 2),我会收到提示 [Plaintext: ] 和例如我输入Hello。输出将是[Ciphertext: 99102109109112],而不是预期的[Ciphertext: JGOOQ]

这是我的代码:


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

// Get the \'key\' value at run-time (./ceasar \'key\').
// key_value must be a digit/number).
// String argv[1] must be converted to int.
// Prompt user for plaintext.
// plaintext must be converted by casaer cipher to ciphertext.
// Print ciphertext.

// Declaring variables.
string plaintext;
string ciphertext;
int key_value;

// declaring the caesar cipher function (takes in an array of characters (aka string) and an int).
void caesar_cipher(char str[], int shift_value);

int main(int argc, string argv[])
{
    // check if there are two arguments at run-time and the second argument (argv[1]) is a digit.
    if (argc == 2 && isdigit(*argv[1]))
    {
        // convert string argv[s] to an int.
        key_value = atoi(argv[1]);
        // Prompt user for plaintext.
        plaintext = get_string(\"Plaintext: \");

        printf(\"Ciphertext: \");

        caesar_cipher(plaintext, key_value);

        // new line
        printf(\"\\n\");
        return 0;
    }
    else
    {
        printf(\"Usage: ./caesar \'key\'\\n\");
        return 1;
    }
}

// char str[] will take in \'plaintext\' and int shift_value will take in \'key\'
void caesar_cipher(char str[], int shift_value)
{
    int s = 0;
    char c = str[s];

    if (c != \'\\0\')
    {
        // iterate through every character, letter-by-letter.
        for (int i = 0, n = strlen(plaintext); i < n; i++)
        {
            // case for uppercase letters.
            if (isupper(c))
            {
                 printf(\"%i\", (((plaintext[i] - \'A\') + shift_value) % 
                        26) + \'Z\');
            }
            // case for lowercase letters.
            else if (islower(c))
            {
                printf(\"%i\", (((plaintext[i] - \'a\') + shift_value) % 26) 
                       + \'z\');
            }
            else
            {
                printf(\"%c\", c);
            }
        }
    }
}
  • 你为什么要循环调用caesar_cipher
  • else if (str[i] &gt;= \'a\' &amp;&amp; str[i] &lt;= \'a\') ---> else if (str[i] &gt;= \'a\' &amp;&amp; str[i] &lt;= \'z\')z!不是
  • @CGi03 islower() 更好...

标签: c pointers debugging cs50 caesar-cipher


【解决方案1】:

有多个问题:

  • 您将转换后的字符输出为带有%i 的整数,而不是带有%c 的字符。

  • 测试if (c != '\0') 是多余的:如果字符串为空,循环将立即退出。

  • 您必须将每个字符存储到循环内的c 中才能正常运行。

  • 您必须将 'A' 而不是 'Z' 添加到移位索引中。小写也有同样的问题。

  • 该函数应该将加密执行到另一个字符串cyphertext,而不是打印它。

这是修改后的版本:

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

// Get the 'key' value at run-time (./ceasar 'key').
//     key value must be a number.
//     string argv[1] must be converted to int.
// Prompt user for plaintext.
// plaintext must be converted by caesar_cipher to ciphertext.
// Print ciphertext.

char *caesar_cipher(const char *str, int shift_value);

int main(int argc, string argv[]) {
    string plaintext;
    string ciphertext;
    int key_value;

    // check if there are two arguments at run-time and the second argument (argv[1]) is a digit.
    if (argc == 2 && isdigit((unsigned char)*argv[1])) {
        // convert key string argv[1] to an int.
        key_value = atoi(argv[1]);
        // prompt user for plaintext.
        plaintext = get_string("Plaintext: ");
        cyphertext = caesar_cipher(plaintext, key_value);
        printf("Ciphertext: %s\n", cyphertext);
        return 0;
    } else {
        printf("Usage: ./caesar 'key'\n");
        return 1;
    }
}

// The caesar_cipher function:
// takes in a string and a shift value,
// allocate a new string and perform the Caesar transformation in place
// returns the new string.
char *caesar_cipher(const char *str, int shift_value) {
    char *dest = strdup(str);

    // iterate through every character, letter-by-letter.
    for (int i = 0; dest[i] != '\0'; i++) {
        unsigned char c = dest[i];
        // case for uppercase letters.
        if (isupper(c)) {
            c = 'A' + (c - 'A' + shift_value) % 26;
        } else
        if (islower(c)) {
            c = 'a' + (c - 'a' + shift_value) % 26;
        }
        dest[i] = c;
    }
    return dest;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    • 2015-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多