哈希表单元格读取返回问号?技术问题排查求助
核心问题
你看到的问号是因为所有哈希表节点的symbol指针都指向同一个临时缓冲区,且该缓冲区最终被写入了非打印字符(EOF)。具体原因如下:
缓冲区复用导致指针指向失效:
在readFile函数中,你只分配了一个char* current缓冲区,每次读取字符时都会覆盖它的内容。当你调用insertion_hashTable时,如果只是直接将node->symbol指向current,那么所有节点的symbol都会指向这个共享缓冲区。循环结束时,缓冲区最后存储的是fgetc返回的EOF(通常是-1,对应非打印字符),因此打印时会显示问号。未正确处理EOF:
while (!feof(p))的循环逻辑会导致最后一次读取EOF并将其作为有效字符插入哈希表,这会额外添加一个无效的节点。fgetc的类型匹配问题:fgetc返回int类型(包含EOF的标识),直接存入char可能因符号扩展导致非预期值(比如无符号char会把-1转为255,也是非打印字符)。
修复步骤
1. 修正文件读取循环
修改循环逻辑,提前检测EOF,避免处理无效字符:
hashTable readFile(char* fileName){ FILE* p = fopen(fileName, "r"); assert(p); hashTable h = creation_hashTable(fileLength(fileName)); // 无需malloc哈希表结构 char* current = malloc(2); assert(current != NULL); current[1] = '\0'; int c; // 用int存储fgetc的返回值,正确识别EOF while ((c = fgetc(p)) != EOF){ current[0] = (char)c; if (!presence_test_hashTable(h, current)){ insertion_hashTable(h, current); } increment_hashTable(h, current); } free(current); // 释放临时缓冲区 fclose(p); return h; }
2. 为每个节点的symbol分配独立内存
在insertion_hashTable中,必须为每个节点的symbol复制一份独立的字符串,而不是直接复用current的指针。可以用strdup(POSIX标准)或手动分配复制:
void insertion_hashTable(hashTable h, char* s){ int index = hashFunction(s, h.capacity); node* new_node = malloc(sizeof(node)); assert(new_node != NULL); // 复制字符串到独立内存 new_node->symbol = malloc(2); assert(new_node->symbol != NULL); new_node->symbol[0] = s[0]; new_node->symbol[1] = '\0'; new_node->weight = 1; new_node->succ = NULL; insertion_linkedList(&h.cells[index], *new_node); free(new_node); // 如果insertion_linkedList会复制节点内容,需调整此处逻辑 }
注意:如果你的
insertion_linkedList函数会自行分配节点内存,只需确保传入的node.symbol是独立复制的字符串即可。
3. 验证字符串有效性
确保所有symbol都是以\0结尾的合法字符串(你已经在current[1] = 0中处理了这一点,保持即可)。
关键原理
每个哈希表节点需要持有自己独立的字符字符串副本,而不是共享同一个临时缓冲区的指针。这样即使临时缓冲区被覆盖,节点的symbol值也不会改变。同时,正确处理EOF可以避免插入无效字符节点。
内容的提问来源于stack exchange,提问作者M K

