【问题标题】:Hackerrank: C - Querying the DocumentHackerrank: C - 查询文档
【发布时间】:2020-06-06 01:53:24
【问题描述】:

我遇到了一个无法识别的分段错误。

我的错误函数接收到一个字符串text。它应该将其转换为 document 并返回。 documentparagraphs(由 '\n' 分隔)组成,sentences(由 '.' 分隔)由words(由 ' ' 分隔)。您可以参考完整的问题陈述here

这是我的代码的相关部分:

char**** get_document(char* text) {
    int p = 0, s = 0, w = 0, c = 0;
    char**** document;
    document = malloc(sizeof(char***));
    document[0] = malloc(sizeof(char**));
    document[0][0] = malloc(sizeof(char*));
    document[0][0][0] = malloc(sizeof(char));
    while (*text)
    {
        if (*text == ' ')
        {
            c = 0;
            ++w;
            document[p][s] = realloc(document[p][s], sizeof(char*) * (w + 1));
        }          
        else if (*text == '.')
        {
            c = 0;
            w = 0;
            ++s;
            document[p] = realloc(document[p], sizeof(char**) * (s + 1));
        } 
        else if (*text == '\n')
        {
            c = 0;
            w = 0;
            s = 0;
            ++p;
            document = realloc(document, sizeof(char***) * (p + 1));
        }
        else
        {
            ++c;
            document[p][s][w] = realloc(document[p][s][w], sizeof(char) * (c + 1));
            document[p][s][w][c - 1] = *text;
            document[p][s][w][c] = '\0';
        }
        ++text;
    }
    return document;
}

调试后才知道程序崩溃的时候

w = 1document[p][s][w][c - 1] = *text;

我不知道为什么会这样。我在执行该语句之前检查了 p、s、w 和 c 的值,以及 realloc 语句是否正确执行。

但徒劳无功!

我的代码可能出了什么问题?

【问题讨论】:

  • 有很多星号。您确定问题需要这种程度的指针间接吗?此外,sizeof(char*)sizeof(char**)sizeof(char***) 的大小应该相同。
  • @RobertHarvey 输出必须是 char**** 才能完成任务
  • 好吧,this 说 realloc “重新分配给定的内存区域。它必须先前由 malloc()、calloc() 或 realloc() 分配,并且尚未使用调用 free 或 realloc。否则,结果未定义。"
  • 好吧,根据this,您的方法应该有效。 “如果 ptr 是空指针,该函数的行为类似于 malloc,分配一个新的 size 字节块并返回一个指向其开头的指针。”
  • 尝试通过 valgrind 运行您的代码。如果你的内存管理不善,它会告诉你在哪里。

标签: c pointers debugging segmentation-fault


【解决方案1】:

您需要为新的段落、句子和单词分配内存。通过重新分配,您增加了实际尺寸大小,但新元素是导致段错误的空指针。

char**** get_document(char* text) {
    int p = 0, s = 0, w = 0, c = 0;
    char**** document;
    document = malloc(sizeof(char***));
    document[0] = malloc(sizeof(char**));
    document[0][0] = malloc(sizeof(char*));
    document[0][0][0] = malloc(sizeof(char));
    while (*text)
    {
        if (*text == ' ')
        {
            c = 0;
            ++w;
            document[p][s] = realloc(document[p][s], sizeof(char**) * (w + 1));
            document[p][s][w] = malloc(sizeof(char*));
        }          
        else if (*text == '.')
        {
            c = 0;
            w = 0;
            ++s;
            document[p] = realloc(document[p], sizeof(char**) * (s + 1));
            document[p][s] = malloc(sizeof(char**));
            document[p][s][w] = malloc(sizeof(char*));
        } 
        else if (*text == '\n')
        {
            c = 0;
            w = 0;
            s = 0;
            ++p;
            document = realloc(document, sizeof(char****) * (p + 1));
            document[p] = malloc(sizeof(char***));
            document[p][s] = malloc(sizeof(char**));
            document[p][s][w] = malloc(sizeof(char*));
        }
        else
        {
            ++c;
            document[p][s][w] = realloc(document[p][s][w], sizeof(char) * (c + 1));
            document[p][s][w][c - 1] = *text;
            document[p][s][w][c] = '\0';
        }
        ++text;
    }
    return document;
}

此外,您的主要打印方法不起作用,因为您没有保存空格(无论如何您都不需要)。所以,我修复了它:

int main()
{
    char* text = "New word.No space before a sentence.\nThis is a new paragraph.";
    char**** doc = get_document(text);
    int p = 0, s = 0, w = 0, c = 0;
    char ch;
    while (ch = *text)
    {
        if (ch == ' ')
        {
            putchar(' ');
            c = 0;
            ++w;
        }
        else if (ch == '.')
        {
            putchar('.');
            c = 0;
            w = 0;
            ++s;
        }
        else if (ch == '\n')
        {
            putchar('\n');
            c = 0;
            w = 0;
            s = 0;
            ++p;
        }
        else putchar(doc[p][s][w][c++]);;
        text++;
    }

    return 0;
}

输出似乎正确:

新词。句子前没有空格。
这是一个新段落。

我认为你不必释放doc,因为你会在它之后从主服务器返回,Hackerrank 会在需要时处理它。但请注意,否则您应该照顾好它。

【讨论】:

  • @ArdentCoder 欢迎您。我也需要一些时间来意识到这一点。你说得对,我编辑它。
  • @ArdentCoder 谢谢。我也花了一些时间来解决这个问题并进行一些调试。
  • 我还有一个问题...错误是在 malloc 之前使用 realloc,对吧?但这不应该根据标准造成这个问题(链接在我的问题的评论中)。能详细解释一下吗?
  • 您可以在这里使用 reallocs 而不是 mallocs,但这毫无意义。问题是,当下一句出现时,s = 1pwc0。您将在 document[p][s][w] = realloc(document[p][s][w], sizeof(char) * (c + 1)); 处取消引用 NULL 指针,因为此时 document[p][s] 为空。
  • 哦,我明白了,所以问题是 取消引用空指针! 但是编译器只知道抱怨 Segmentation Fault 哈哈。
猜你喜欢
  • 1970-01-01
  • 2015-02-10
  • 1970-01-01
  • 2016-10-02
  • 2012-10-31
  • 1970-01-01
  • 1970-01-01
  • 2017-09-13
  • 2017-11-18
相关资源
最近更新 更多