为什么访问我的哈希表的单元格会返回问号?

Why does accessing the cells of my hashtable return question marks?

提问人:M K 提问时间:10/30/2023 更新时间:10/31/2023 访问量:82

问:

我想用从用户输入文件中读取的字符填充一个哈希表,作为字符数组(即第一个元素是字符,第二个元素是 NULL 字符的字符数组——比如“a”或“b”......你明白了)。

为此,我创建了一个哈希表结构以及基本操作(见下文)

// hashtable structure
struct hashTable{
    linkedList* cells;
    int capacity;
};
typedef struct hashTable hashTable;

// hashtable function prototypes

int hashFunction(char* s, int capacity);

hashTable creation_hashTable(int capacity);

bool presence_test_hashTable(hashTable h, char* s);

void insertion_hashTable(hashTable h, char* s);

void increment_hashTable(hashTable h, char* s);

基于链表结构(见下文)。

// linked list node 
struct node{
    char* symbol;
    int weight;
    struct node* succ;
};
typedef struct node node;

// linked list structure
struct linkedList{
    node* head;
};
typedef struct linkedList linkedList;

// linked list function prototypes

linkedList creation_linkedList();

bool search_linkedList(linkedList l, char* s);

void insertion_linkedList(linkedList *l, node n);

与 hashTable 和 linkedList 结构关联的所有函数似乎都可以正常工作。这是我创建的用于填充哈希表的函数:

hashTable readFile(char* fileName){
    FILE* p = fopen(fileName, "r");
    assert(p); 
    hashTable* h = malloc(sizeof(hashTable));
    *h = creation_hashTable(fileLength(fileName));
    char* current = malloc(2);
    current[1] = 0;
   
    while (!feof(p)){
        current[0] = fgetc(p);
        if (!presence_test_hashTable(*h,current))
            insertion_hashTable(*h,current);
        increment_hashTable(*h,current);
    }

    fclose(p);
    return *h;
}

该函数似乎工作正常:当我打印出非 NULL 单元格的权重值时,我会得到相应的权重。

但是,在终端中编译并运行以下内容:

int main(){
    hashTable h = readFile("li_def.txt"); // lorem ipsum filler text file
    for (int i = 0; i < h.capacity; ++i){
        if (h.cells[i].head){ 
            printf("%s\n", h.cells[i].head->symbol);
        }
    }

    exit(0);
}

返回问号行,如

?
?
...

坦率地说,我根本不确定这里发生了什么。如上所述,我能够毫无问题地访问单元格的权重值,因此在基本层面上,该函数正在执行应有的操作。

我不确定如何处理这个问题,因为我无法访问非 NULL 单元格的符号值。问题出在哪里?是否正在填充符号值?如果是这样,为什么它们被打印出来作为问号?

任何帮助将不胜感激。提前致谢。

数组 C 链接列表 哈希表 文件处理

评论

0赞 UnholySheep 10/30/2023
除非执行某种类似的内存分配,否则您可能将相同的内存分配给哈希表中的所有节点insertion_hashTablestrdupchar*
0赞 pmacfarlane 10/30/2023
旁白:在每个节点中存储一个以零结尾的单字符字符串似乎很奇怪。为什么不直接存储角色呢?
0赞 Some programmer dude 10/30/2023
使用该函数,您可以按值传递结构。这意味着该函数获取哈希表结构的副本。当它修改结构时,它只修改其结构的本地副本,而不修改调用中使用的原始副本。您需要传递指向结构的指针void insertion_hashTable(hashTable h, char* s);hashTable
0赞 n. m. could be an AI 10/30/2023
while (!feof(p)){总是的。
0赞 n. m. could be an AI 10/30/2023
hashTable* h = malloc(...); *h = ...; ,.,,; return *h;创建内存泄漏。没有内存泄漏的相同结果可以通过以下方式实现:但这不一定正确。你最想要的总是传递指向 的指针,永远不要重视它自己。hashTable h = creation_hashTable(...); ...; return h;hashTablehashTable

答:

1赞 Lorelius Hogglefart 10/31/2023 #1

“symbol” 是一个 char*(指针),它指向长度为 2(1 个字符 + null 个字符)的字符数组。您得到“?”作为输出,因为您使用的是“%s”,但“%s”需要以 null 结尾的字符串,因此内容未正确格式化为字符串。此外,函数中的变量是指向长度为 2 的字符数组的指针,并在循环的每次迭代中被覆盖。这基本上意味着你将一堆指针存储在同一个内存位置,所以当你打印它们时,“%s”找不到一个空字符,它只会给你一个问号。这意味着您需要为每个“符号”单独分配内存。另外,请记住,当您不再使用该函数时,请使用该函数清除已分配的内存。printf("%s\n", h.cells[i].head->symbol);currentreadFile()free();

hashTable readFile(char* fileName) {
FILE* p = fopen(fileName, "r");
assert(p);
hashTable* h = malloc(sizeof(hashTable));
*h = creation_hashTable(fileLength(fileName));
char* current = malloc(2);
current[1] = '\0'; 

while (!feof(p)) {
    current[0] = fgetc(p);
    if (!presence_test_hashTable(*h, current)) {
        char* new_symbol = malloc(2); 
        new_symbol[0] = current[0]; 
        new_symbol[1] = '\0'; 
        insertion_hashTable(*h, new_symbol);
    }
    increment_hashTable(*h, current);
}

free(current);
fclose(p);
return *h;

}