【问题标题】:Hash table didn't return correct value by it's Index哈希表没有通过它的索引返回正确的值
【发布时间】:2021-07-05 07:12:01
【问题描述】:

我有这个 csv 文件包含联系人:

NAME, NUMBER, ADDRESS, EMAIL
Kevin Mahendra, +62 812-XXXX-XXXX, Jln.Anggrek Merah 3, kevinitsnovember@gmail.com
Adwi Lanang, +62 821-XXXX-XXXX, Jln.Ruhui Rahayu, adwilanang@gmail.com
Wasis Sirutama, +62 813-XXXX-XXXX, Jln.Pramuka 6 25, wasisnaruto@gmail.com
Alief Dean, +62 811-XXXX-XXXX, Jln.Padat Karya, aliefdean@gmail.com
Baharudin Nuri, +62 813-XXXX-XXXX, Jln.Ruhui Rahayu 1, baharudin008@yahoo.com
Yonggi Wijaya, +62 853-XXXX-XXXX, Jln.PM Noor Pondok S, yonggiwijaya@gmail.com
Artha Yoga, +62 822-XXXX-XXXX, Jln.A.Yani Gg.1, arthayoga97@gmail.com
Rusydi Nashier, +62 858-XXXX-XXXX, Jln.Perjuangan No.90, rusydinashier@gmail.com
Andre Pieters, +62 822-XXXX-XXXX, Jln.Villa Tamara No.1, azzahz@gmail.com
Paco Corleone, +62 816-XXXX-XXXX, Jln.Anggrek Merah 3, pacocorleone@gmail.com

这是我的 C 代码:

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

// Number of buckets for TABLE
#define N 26

#define MAX 50

typedef struct Contact
{
    char name[MAX];
    char number[MAX];
    char address[MAX];
    char email[MAX];
    struct Contact* next;
} 
Contact;

void searching_contact(FILE *file);
void load_hash_table(FILE **file);
unsigned int hash(const char *name);

// Hash table
Contact *table[N];

int main(void)
{  
    // OPEN CSV FILE AS append and read mode
    FILE *file = fopen("contacts.csv", "r");
    if (file == NULL)
    {
        printf("Error open file!\n");
        return 1;
    }

    searching_contact(file);

    fclose(file);
    return 0;
}    

void searching_contact(FILE *file)
{

    char name[MAX];

    printf("Search Name: ");
    scanf("%[^\n]%*c", name);
    fflush(stdin);

    // Load csv file into hash table first    
    load_hash_table(&file);

    // Get index number by calling hash function
    int hashIndex = hash(name);
    printf("\n\nIndex number we get from searching: %i\n", hashIndex);
    
    // Point to table that may contain the person
    Contact *cursor = table[hashIndex];
    
    // This will always print the last person
    printf("The name on the table: %s\n", cursor->name);

    // Keep traversing linked list in table
    while (cursor != NULL)
    {
        // If the person found, print the contact information
        if (strcmp(name, cursor->name) == 0)
        {
            printf("%s %s %s %s", cursor->name, cursor->number, cursor->address, cursor->email);
        }
        else
        {
            // If not the person, but in the same table, go to the next linked list
            cursor = cursor->next;
        }
    }
    printf("Not found!\n");
}

// FUNCTION TO LOAD CSV FILE INTO HASH TABLE
void load_hash_table(FILE **file)
{
    Contact *new = malloc(sizeof(Contact));
    if (new == NULL)
        exit(1);

    /*
        "%[^,], "
        Empty space or space after above sign will remove spaces or newline (\n) on each string
        Just because, when we try to use hash function, the spaces or newline will also include
        And we want to remove them so when user searching by name it will produce same hash index
    */
    while(fscanf(*file, "%[^,], %[^,], %[^,], %[^\n] ", new->name, new->number, new->address, new->email) == 4)
    {   
        // Skip header from CSV file   
        if (strcmp("NAME", new->name) == 0)
            continue;    
    
        // Get index number from hash function with People name as input
        int index = hash(new->name);

        // Try to print name and it's index in csv file for debugging
        printf("%s\n", new->name);
        printf("%i\n", index);
        
        /* 
            Create linked list point to WHAT inside Table[index]
            For very first struct, it points to NULL, then store it in Table
            Next struct, with the same Index number, it will point the first one
        */   
        new->next = table[index];
        table[index] = new;

        // Malloc for next fscanf
        Contact *new = malloc(sizeof(Contact));
        if (new == NULL)
            exit(1);
    }
}

// Hash function that will return index number from Table
unsigned int hash(const char *name)
{
    // TODO
    unsigned long hash = 5381;
    int c;

    while ((c = toupper(*name++)))
    {
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
    }
    return hash % N;
}

所以,我正在尝试制作一个程序,用户可以通过姓名搜索联系人。如您所见,我还想使用哈希表/哈希函数来锻炼。所以在搜索之前,它会将所有 csv 文件加载到哈希表中(参见load_hash_table())。但最终,即使用户已经输入了正确的姓名,它也总是找不到人。

我尝试仅使用 printf 进行调试。

首先,在load_hash_table() 函数中,我打印每个名称及其索引。它工作正常。它打印 csv 文件中的所有名称以及由hash 函数生成的正确索引。

其次,这是问题所在。当我尝试在 searching() 函数内打印时。它产生了正确且相同的 index 数字。但是当我打印名字时,它总是打印 csv 文件上的最后一个人,即 Paco Corleone。无论我们在 Table[] 中放入什么索引号,它总是会打印最后一个人的姓名。

我不明白。当 load_hash_table() 函数内的 while 循环 结束时,哈希表似乎丢失了之前已加载的所有数据。当你运行我给出的代码时,也许你会看到问题。请帮助我,我是 C 语言的新手,谢谢!

【问题讨论】:

标签: c file hash hashmap


【解决方案1】:

几个问题:

  1. 主要问题是有两条Contact *new = malloc(sizeof(Contact)); 行。一个在循环内,一个在循环外。它们是两个不同变量。 while 循环条件使用循环外的条件。因此fscanf 为每个循环写入相同的内存。解决此问题的一种方法是将第二个实例设为new = malloc(sizeof(Contact));。请注意,由于最后分配的节点丢失,此循环存在内存泄漏 - 留给您作为练习来修复。

  2. searching_contact 有一个无限循环,因为if (strcmp(name, cursor-&gt;name) == 0) 块缺少break

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    相关资源
    最近更新 更多