CS50 pset2 替换

CS50 pset2 substitution

挑战在于创建一个程序,您可以在其中输入一个 26 个字符长的字符串,基本上可以替换字母表。因此,例如,如果您将密钥设置为“qwertyuiopasdfghjklzxcvbnm”,它将使用 q 表示 a,w 表示 b,e 表示 c,r 表示 d,等等。然后您输入一个字符串作为您的消息,它将明文转换为密文。

到目前为止,在课程中我们还没有涉及指针,所以我想人们应该能够在不使用 * 或 & 来引用指针的情况下完成这一挑战。相反,我们被告知使用允许我们使用“字符串”的库,而库则处理在后台为我们使用指针的技术性工作。不过我对此有点困惑,因为我最初尝试的代码是这样的:

    {
        if(isupper(plainText[i]))
        {
            cypherText[i] = key[plainText[i] - 'A'];
        }
        else if (islower(plainText[i]))
        {
            cypherText[i] = key[plainText[i] - 'a'];
        }
    }
    printf("%s\n", cypherText);

但我收到以下错误:

error: incompatible integer to pointer conversion assigning to 'string' (aka 'char *') from 'char'; take the address with & [-Werror,-Wint-conversion]
            cypherText[i] = key[plainText[i] - 'A'];
                          ^ ~~~~~~~~~~~~~~~~~~~~~~~
                            &
error: incompatible integer to pointer conversion assigning to 'string' (aka 'char *') from 'char'; take the address with & [-Werror,-Wint-conversion]
            cypherText[i] = key[plainText[i] - 'a'];
                          ^ ~~~~~~~~~~~~~~~~~~~~~~~
                            &
error: format specifies type 'char *' but the argument has type 'string *' (aka 'char **') [-Werror,-Wformat]
    printf("%s\n", cypherText);

所以我把代码改成了下面的

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

int main(void)
{
    string key;
    do
    {
        key = get_string("Key:");
    }
    while(strlen(key) != 26);

    string plainText = get_string("Text:");
    string cypherText[strlen(plainText)];

    for (int i = 0; plainText[i] != '[=12=]'; i++)
    {
        if(isupper(plainText[i]))
        {
            cypherText[i] = &key[plainText[i] - 'A'];
        }
        else if (islower(plainText[i]))
        {
            cypherText[i] = &key[plainText[i] - 'a'];
        }
    }
    printf("%s\n", *cypherText);
}

现在它编译了但没有按预期工作,而且这个错误不是我通过调试能够识别的。基本上当我 运行 使用键“bcdefghijklmnopqrstuvwxyza”(字母表左移一个字母)然后我使用像“hello”这样的消息时,我将得到输出“ijklmnopqrstuvwxyza”,它以正确的字母开头,但随后只是继续对我莫名其妙地解析字母表。即使我只写一个字母长的消息,密文也会打印为多个字符。

所以我的问题是:

我的假设是否正确,是否有一种方法可以不使用指针来完成这个挑战?如果是这样,我如何在不使用 & 或 * 的情况下更正这些错误消息?

当我使用 & 和 * 时,是什么导致了这种奇怪的尾随字母表行为?

谢谢。

您在 string cypherText[strlen(plainText)]; 中定义了一个字符串数组,因此最初的错误是由于试图将一个字符串(也称为 char*)分配给一个字符串数组(也称为 char**),因此:

error: format specifies type 'char *' but the argument has type 'string *' (aka 'char **') [-Werror,-Wformat]
    printf("%s\n", cypherText);

你什么时候做的

        if(isupper(plainText[i]))
        {
            cypherText[i] = &key[plainText[i] - 'A'];
        }
        else if (islower(plainText[i]))
        {
            cypherText[i] = &key[plainText[i] - 'a'];
        }

您正在操纵指针 cypherText 指向的位置,您实际上是在分配 cypherText[0][0] 从 &key[plainText[i] - 'a'] 开始,在您的测试用例中是字母 'i'。 i 的每个增量都会更改 cypherText 数组的行,因此 cypherText[1][0] 将指向字母 'f'、,但重要的是它与分配给 [=] 的内存相同14=].

当你 printf("%s\n", *cypherText); 时,你要求打印一个字符串,而 *cypherText 是你的字符串数组的开始,所以程序很乐意打印出你之前的第一个字符串分配与 key 相同,但从字母 'i' 开始。它读取此字符串,直到到达“\0”并愉快地结束它。