首页 > 解决方案 > CS50 pset2 替换

问题描述

挑战在于创建一个程序,您可以在其中输入一个 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] != '\0'; 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”,然后继续解析字母对我来说莫名其妙。即使我只写一个长字母的消息,密文也会打印为多个字符。

所以我的问题是:

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

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

谢谢你。

标签: arrayscpointerscs50c-strings

解决方案


您在 中定义了一个字符串数组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”,但至关重要的是,它与分配给key.

当 you 时printf("%s\n", *cypherText);,您要求打印一个字符串,并且*cypherText是字符串数组的开头,因此程序会愉快地打印出第一个字符串,您之前将其分配为与 相同key,但从字母 'i' 开始. 它读取这个字符串,直到到达 '\0' 并愉快地称之为一天。


推荐阅读