【问题标题】:Segmentation fault in C code using `string` from cs.50.h使用 cs.50.h 中的“字符串”在 C 代码中出现分段错误
【发布时间】:2016-05-24 07:37:39
【问题描述】:

我在这里有一个程序,我正在尝试使用凯撒密码来解码一串字母;本质上,我将字符串中的每个字符“向下”移动一个字母(“a”->“b”、“f”->“g”、“z”->“a”)。

我向下移动一个字母的数量取决于我给它的键。

在这个特定的程序中,我在 main() 函数中硬编码了一个秘密编码消息,以及一个遍历每个可能键的 for 循环。

这个想法是,如果这个秘密信息简单地向下移动 x 个字母,吐出 25 个版本的密码将揭示一个可理解的答案。

不幸的是,我在一个程序中使用了一些新概念 - argc、argv 和多个函数。我对此很陌生。

有人可以帮助解释我遇到的分段错误吗?我认为我不会导致任何参数溢出。

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

string decode(int key, string message);

int main(void)
{
    string secret_message = "ueuag rKJ AGIQ GIAR FEgN";

    for (int i = 0; i < 25; i++)
    {
        decode(i, secret_message);
        printf("%s", secret_message);
    }

    return 0;
}

string decode(int key, string message)
{
    int i;

    for (i = 0; i < strlen(message); i++)
    {
        if (message[i] >= 'a' && message[i] <= 'z')
        {
            message[i] = ((message[i] - 97 + key) % 26) + 97;
        }
        else if (message[i] >= 'A' && message[i] <= 'Z')
        {
            message[i] = ((message[i] - 65 + key) % 26) + 65;
        }
    }

    return message;
}

【问题讨论】:

  • 不知道它的定义,我猜直接把string传给printf不好。
  • 什么是string???它在哪里声明?并且为了避免与std::string 发生不必要的混淆,我会从中删除 [C++] 标记。这不是 C++..
  • 看起来string 是来自cs50.hchar* 的typedef,这是计算机科学课程的流行 库。
  • 哇.. 尝试教人 C 时,这真是个坏主意。
  • @rodrigo:在那种情况下,[C++] 标签在这里没有任何业务。

标签: c segmentation-fault cs50 caesar-cipher


【解决方案1】:

为什么string 对于 中的类型不是一个好主意?,在这里你可以看到一个例子。您正在修改字符串文字,您不应该这样做。这样做会调用未定义的行为。而不是 string 类型,您应该将字符串视为它们在 中的内容。

改成这样

char secret_message[] = "ueuag rKJ AGIQ GIAR FEgN";

还有解码功能

char *decode(int key, char *message)
{
    int i;

    for (i = 0; message[i] != '\0'; i++)
    {
        if (message[i] >= 'a' && message[i] <= 'z')
        {
            message[i] = ((message[i] - 97 + key) % 26) + 97;
        }
        else if (message[i] >= 'A' && message[i] <= 'Z')
        {
            message[i] = ((message[i] - 65 + key) % 26) + 65;
        }
    }

    return message;
}

如您所见,我将字符串视为一个数组,因为它就是一个字节数组,末尾带有 '\0'。如果您知道这一点,您将永远不会做类似typedef char * string 的事情,因为它非常具有误导性。

cs50.hstring是一个typedef代表一个char指针,而指针不是字符串,字符串是字节序列和char *指针可以指向char 的数组,如果你定义它并正确初始化它,它可能是一个字符串。但是 char * 指针可以指向字符串文字,并且您无法更改它们,如果将其定义为则不清楚

string string_literal = "Do not attempt to modify me, it's undefined behavior";

在声明指向字符串文字的指针时,您应该使用const char * 以避免意外尝试修改它。

另外,在我看来,typedefing 指针根本没有任何好处,并且会引起很多混乱,指针是指针,并且在声明时必须在其标识符附近有一个 *,如果你不需要*你很容易忽略代码中的指针而感到困惑。

【讨论】:

  • 感谢您提供丰富的评论。我已将所有 更改为 并遇到同样的问题
  • @DavidManess 请在我更新答案时继续阅读,请参阅我的建议 -> “您不能覆盖字符串文字”。
  • @DavidManess 将string 更改为char* 将无济于事,因为string 已经是char* 的typedef。您需要将您的secret_message 声明为char[],而不是char*(或string),然后程序才能运行。
  • @Paul 并添加到您的评论中,您可以使用字符串文字初始化数组,它会创建您可以实际修改的字符串文字的副本。
  • @Paul 谢谢,那行得通。 iharob 感谢您的时间和解释。
猜你喜欢
  • 2020-01-19
  • 1970-01-01
  • 2018-11-26
  • 1970-01-01
  • 2015-06-22
  • 1970-01-01
  • 1970-01-01
  • 2020-11-27
  • 1970-01-01
相关资源
最近更新 更多