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", ¶graph_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
相关产品推荐
相关产品推荐

