CS50 凯撒密码漏洞

CS50 Caesar Cipher Bug

好吧,我完全被难住了。我不明白为什么这个程序输出每次都好像有一个随机密钥。

这个节目:

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

int main(int argc, string argv[])
{
    string sKey = argv[1];
// Make sure program was run with just one command-line argument
    if (argc != 2 || atoi(argv[1]) < 0)
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }

//Counts length of string and checks if all chars are digits
    int counter = 0;
    for (int i = 0; i < strlen(sKey); i++)
    {
        if isdigit(sKey[i])
        {
            counter++;
        }
    }

//Checks if the key is a number
    if (counter != strlen(sKey))
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }

// Convert argv[1] from a `string` to an `int`
    int key = (int)sKey;

// Prompt user for plaintext
    string plaintext = get_string("Plaintext:  ");
    printf("Ciphertext: ");
    for (int i = 0; i < strlen(plaintext); i++)
    {
        if (isalpha(plaintext[i]) && isupper(plaintext[i]))
        {
            printf("%c", (((plaintext[i] - 'A') + key) % 26) + 'A');
        }
        else if (isalpha(plaintext[i]) && islower(plaintext[i]))
        {
            printf("%c", (((plaintext[i] - 'a') + key) % 26) + 'a');
        }
        else
        {
            printf("%c", plaintext[i]);
        }
    }
    printf("\n");
}

将输出:

caesar/ $ ./caesar 1
Plaintext:  Hello, I'm Justin.
Ciphertext: Fcjjm, G'k Hsqrgl.
caesar/ $ ./caesar 1
Plaintext:  Hello, I'm Justin.
Ciphertext: Pmttw, Q'u Rcabqv.

这似乎是模运算符的问题,因为当我隔离它时我可以重现问题。它是我包含的库之一吗?我自己解决了这个问题,最后在 youtube 上查找了一个解决方案,结果发现我的解决方案执行了与正确解决方案相同的操作。我一定是遗漏了什么。

谢谢

这是因为 int key = (int)sKey; 不会将字符串转换为整数...至少不是您认为的那样。它将字符串指针 sKey(内存地址)指向一个整数。因为每次你 运行 程序都可以是不同的地址,这就是它看起来随机的原因。将数字字符串转换为值的正确方法是使用 atoistrtol。你的程序的第一部分应该是这样的:

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

int main(int argc, string argv[])
{
    string sKey = argv[1];
    int i;

    // Make sure program was run with just one command-line argument
    if (argc != 2)
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }

    // Checks if all chars are digits
    for (int i = 0; sKey[i]; i++)
        if (!isdigit(sKey[i]) break;

    // If the key contains any non-digits, error
    if (sKey[i])
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }

    // Convert argv[1] from a `string` to an `int`
    int key = atoi(sKey);

// The rest should be fine