You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hackerrank文档查询C语言题:realloc无效大小报错求助

解决Hackerrank《Querying the Document》的四级指针内存错误问题

我正在解决Hackerrank平台的C语言题目《Querying the Document》,需要通过四级指针构建文档结构,但程序运行时出现「aborted, realloc invalid size」错误,已调试两天仍未找到问题。以下是我的实现代码、测试输入及预期输出,请求帮忙指出问题所在:

实现代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#define MAX_CHARACTERS 1005
#define MAX_PARAGRAPHS 5

char *kth_word_in_mth_sentence_of_nth_paragraph(char ****document, int k, int m, int n) {
    return *(*(*(document + n - 1) + m - 1) + k - 1);
}

char **kth_sentence_in_mth_paragraph(char ****document, int k, int m) { 
    return (*(*(document + m - 1) + k - 1));
}

char ***kth_paragraph(char ****document, int k) {
    return *(document + k - 1);
}

char ****get_document(char *text) {
    /* allocating memory */
    int len = strlen(text);
    /* allocate memory for each component first */
    char ****document = malloc(sizeof(char ***));
    char ***paragraph = malloc(sizeof(char **));
    char **sentence = malloc(sizeof(char *));
    char *word = malloc(sizeof(char) * 1024);
    /* connect all the components to point in the sequence that is required */
    *document = paragraph;
    *paragraph = sentence;
    *sentence = word;
    /* declare some numbers as iterators for the words, sentences,etc. */
    int parano = 0;
    int sentno = 0;
    int wordno = 0;
    int charno = 0;
    /* now iterate over the text filling and expanding the document at the same time */
    /*----------------------------------------------------------------------------------------------------*/
    /* feeding data in those spaces */
    for (int i = 0; i < len; i++) {
        if (text[i] == ' ') {
            /* wrapping the current word, that is, resizing to len + 1 */
            char *current_word = *(*(*(document + parano) + sentno) + wordno);
            current_word = realloc(current_word, strlen(current_word) + 1);
            /*  resizing the current sentence to add another word*/
            char **current_sentence = (*(*(document + parano) + sentno));
            current_sentence = realloc(current_sentence, sizeof(char *) * (wordno + 2));
            
            wordno++;
            charno = 0;
            /* allocating space to that new char * / word that has been created in the same sentence */
            *(*(*(document + parano) + sentno) + wordno) = malloc(sizeof(char) * 1000);
        }
        else if (text[i] == '.') {
            /* wrapping of the current word has to be done anyways */
            char *current_word1 = *(*(*(document + parano) + sentno) + wordno);
            current_word1 = realloc(current_word1, strlen(current_word1) + 1);
            charno = 0;
            
            if (text[i + 1] != '\n') {
                /* the paragraph does not change, and the sentence ends */
                /* resize that paragraph for adding another sentence */
                char ***current_para = *(document + parano);
                current_para = realloc(current_para, sizeof(char **) * (sentno + 2));
                sentno++;
                wordno = 0;
                /* allocating word to that sentence */
                *(*(document + parano) + sentno) = malloc(sizeof(char *));
                /* allocating space for that word */
                *(*(*(document + parano) + sentno) + wordno) = malloc(sizeof(char) * 1000);
            } else {
                /*  if this is the last sentence of this paragraph*/
                wordno = 0;
                charno = 0;
                sentno = 0;
            }
        }
        else if (text[i] == '\n') {
            /* paragraph has changed */
            /* add another paragraph to the document */
            document = realloc(document, sizeof(char ***) * (parano + 2));
            parano++;
            /* add sentence to that paragraph */
            (*(document + parano) ) = malloc(sizeof(char **));
            /* add a word to that paragrapgh */
            (*(*(document + parano) + sentno)) = malloc(sizeof(char *));
            /* allocate space for that word */
            *(*(*(document + parano) + sentno) + wordno) = malloc(sizeof(char) * 1000);
        } else {
            scanf("%c", *(*(*(document + parano) + sentno) + wordno) + charno);
            printf("%c\n", **(*(*(document + parano) + sentno) + wordno) + charno);
            charno++;
        }
    }
    return document;
}

char *get_input_text() {    
    int paragraph_count;
    scanf("%d", &paragraph_count);

    char p[MAX_PARAGRAPHS][MAX_CHARACTERS], doc[MAX_CHARACTERS];
    memset(doc, 0, sizeof(doc));
    getchar();
    for (int i = 0; i < paragraph_count; i++) {
        scanf("%[^\n]%*c", p[i]);
        strcat(doc, p[i]);
        if (i != paragraph_count - 1)
            strcat(doc, "\n");
    }

    char *returnDoc = (char *)malloc((strlen(doc)+1) * (sizeof(char)));
    strcpy(returnDoc, doc);
    return returnDoc;
}

void print_word(char *word) {
    printf("%s", word);
}

void print_sentence(char **sentence) {
    int word_count;
    scanf("%d", &word_count);
    for (int i = 0; i < word_count; i++) {
        printf("%s", sentence[i]);
        if (i != word_count - 1)
            printf(" ");
    }
} 

void print_paragraph(char ***paragraph) {
    int sentence_count;
    scanf("%d", &sentence_count);
    for (int i = 0; i < sentence_count; i++) {
        print_sentence(*(paragraph + i));
        printf(".");
    }
}

int main() {
    char *text = get_input_text();
    char ****document = get_document(text);

    int q;
    scanf("%d", &q);

    while (q--) {
        int type;
        scanf("%d", &type);

        if (type == 3) {
            int k, m, n;
            scanf("%d %d %d", &k, &m, &n);
            char *word = kth_word_in_mth_sentence_of_nth_paragraph(document, k, m, n);
            print_word(word);
        }
        else if (type == 2) {
            int k, m;
            scanf("%d %d", &k, &m);
            char **sentence = kth_sentence_in_mth_paragraph(document, k, m);
            print_sentence(sentence);
        } else {
            int k;
            scanf("%d", &k);
            char ***paragraph = kth_paragraph(document, k);
            print_paragraph(paragraph);
        }
        printf("\n");
    }     
}

测试输入

2
Learning C is fun.
Learning pointers is more fun.It is good to have pointers.
3
1 2
2
5
6
2 1 1
4
3 1 1 1

预期输出

Learning pointers is more fun.It is good to have pointers.
Learning C is fun
Learning

错误分析与修复方案

1. 字符写入逻辑错误

处理普通字符时,错误使用scanf("%c")读取输入,但text已经是完整的输入文本,应该直接从text[i]取字符赋值。同时printf表达式错误,**(...) + charno会把字符的ASCII值加charno,而非读取对应位置的字符:

// 修复后代码
char *current_word = *(*(*(document + parano) + sentno) + wordno);
current_word[charno] = text[i];
printf("%c\n", current_word[charno]);
charno++;

2. Realloc后未更新原指针

realloc返回新内存地址后,未将新地址写回文档结构的对应指针,导致原指针指向已释放的旧内存,触发内存错误:

// 修复单词的realloc
char **word_ptr = &(*(*(document + parano) + sentno))[wordno];
*word_ptr = realloc(*word_ptr, charno + 1); // 用已写入的字符数计算大小,而非strlen
(*word_ptr)[charno] = '\0';

// 修复句子的realloc
char ***sentence_ptr = &(*(document + parano))[sentno];
*sentence_ptr = realloc(*sentence_ptr, sizeof(char *) * (wordno + 2));

// 修复段落的realloc
char ****para_ptr = &document[parano];
*para_ptr = realloc(*para_ptr, sizeof(char **) * (sentno + 2));

3. 单词未添加字符串终止符

realloc单词时必须手动添加'\0',否则strlen会读取未知内存,计算错误长度导致realloc使用无效大小:

// 在处理空格/句号时,给当前单词添加终止符
char *current_word = *(*(*(document + parano) + sentno) + wordno);
current_word = realloc(current_word, charno + 1);
current_word[charno] = '\0';

4. 越界访问风险

处理.时直接访问text[i+1]会在i为最后一个字符时越界,需先判断边界:

if (i + 1 < len && text[i + 1] != '\n') {
    // 原句子切换逻辑
}

5. 初始内存初始化问题

初始分配的word未初始化,可能包含垃圾数据,建议用calloc自动初始化为0:

char *word = calloc(1024, sizeof(char));

内容的提问来源于stack exchange,提问作者Sahil Gautam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 20:41:07