C中哈希表程序中的指针问题

Posted

技术标签:

【中文标题】C中哈希表程序中的指针问题【英文标题】:Problem With Pointers in Hash Table program in C 【发布时间】:2021-12-01 12:37:12 【问题描述】:

所以我正在制作一个列表数组,其中列表存储在由哈希函数定义的索引中,并且列表存储一个结构项目,该项目存储来自 csv 文件的数据,但我真的不知道如何将结构项目存储在名单。我尝试为它制作一个程序,但它没有输出任何东西。

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

#define MAX_BUFFER 20 // Maximum string length this program can handle
#define MAX_NB_POKEMON 22 // Maximum number of Pokemons
#define ARRAY_SIZE 59


typedef struct Pokemon Pokemon;
struct Pokemon 
    int id, age;
    char surname[MAX_BUFFER], depid[MAX_BUFFER],forename[MAX_BUFFER], type[MAX_BUFFER], gender[MAX_BUFFER],nationality[MAX_BUFFER],rel[MAX_BUFFER],occ[MAX_BUFFER];
;

// The CSV parser
int next_field( FILE *f, char *buf, int max ) 
    int i=0, end=0, quoted=0;
    
    for(;;) 
        // fetch the next character from file       
        buf[i] = fgetc(f);
        // if we encounter quotes then flip our state and immediately fetch next char
        if(buf[i]=='"')  quoted=!quoted; buf[i] = fgetc(f); 
        // end of field on comma if we're not inside quotes
        if(buf[i]==',' && !quoted)  break; 
        // end record on newline or end of file
        if(feof(f) || buf[i]=='\n')  end=1; break;  
        // truncate fields that would overflow the buffer
        if( i<max-1 )  ++i;  
    

    buf[i] = 0; // null terminate the string
    return end; // flag stating whether or not this is end of the line


// Stuff to make life a bit neater in main
void fetch_pokemon (  FILE *csv, struct Pokemon *p) 
    char buf[MAX_BUFFER];

    next_field( csv, buf, MAX_BUFFER );      // load id into buffer as string
    p->id = atoi(buf);                       // then parse to integer

    next_field( csv, p->depid, MAX_BUFFER );  // name and type are just strings so read
    next_field( csv, p->surname, MAX_BUFFER ); // those directly into the struct
    next_field( csv, p->forename, MAX_BUFFER );

    // Load all the pokemon's stats from the file using buffer as intermediary
    next_field( csv, buf, MAX_BUFFER );
    p->age = atoi(buf);          // atoi stands for ASCII to Integer
    
    next_field( csv, p->type, MAX_BUFFER ); 
    next_field( csv, p->gender, MAX_BUFFER ); 
    next_field( csv, p->nationality, MAX_BUFFER ); 
    next_field( csv, p->rel, MAX_BUFFER ); 
    next_field( csv, p->occ, MAX_BUFFER ); 


int hash_function(char* s)
    int hash = 0;
    while(*s)
        hash = (hash + *s)%ARRAY_SIZE;
        s++;
    
    return hash;


void print_pokemon( struct Pokemon *p ) 
    printf("%d\t%s\t%s\t%s\t%d\t%s\t%s\t%s\t%s\t%s\t\n", p->id,p->depid,p->surname,p->forename,p->age,p->type,p->gender,p->nationality,p->rel,p->occ);


typedef struct LinkedList LinkedList;
 
// Define the Linkedlist here
struct LinkedList 
    Pokemon* item; 
    LinkedList* next;
;
 
LinkedList* allocate_list () 
    // Allocates memory for a Linkedlist pointer
    LinkedList* list = (LinkedList*) malloc (sizeof(LinkedList));
    return list;

 
LinkedList* linkedlist_insert(LinkedList* list, Pokemon* item) 
    // Inserts the item onto the Linked List
    if (!list) 
        LinkedList* head = allocate_list();
        head->item = item;
        head->next = NULL;
        list = head;
        return list;
     
     
    else if (list->next == NULL) 
        LinkedList* node = allocate_list();
        node->item = item;
        node->next = NULL;
        list->next = node;
        return list;
    
 
    LinkedList* temp = list;
    while (temp->next->next) 
        temp = temp->next;
    
     
    LinkedList* node = allocate_list();
    node->item = item;
    node->next = NULL;
    temp->next = node;
     
    return list;


void free_linkedlist(LinkedList* list) 
    LinkedList* temp = list;
    while (list) 
        temp = list;
        free(temp->item);
        free(temp);
    

LinkedList* hashTable[ARRAY_SIZE]=0;


void print_table(void)
    printf("Start\n");
    int i;
    for(i=0;i<ARRAY_SIZE;i++)
        if(hashTable[i] == NULL)
            printf("\t%i\t---\n",i);
        else
        printf("%d\t%s\t%s\t%s\t%d\t%s\t%s\t%s\t%s\t%s\t\n", hashTable[i]->item->id,hashTable[i]->item->depid,hashTable[i]->item->surname,hashTable[i]->item->forename,hashTable[i]->item->age,hashTable[i]->item->type,hashTable[i]->item->gender,hashTable[i]->item->nationality,hashTable[i]->item->rel,hashTable[i]->item->occ);
        
    
    printf("End\n");

int main () 
    FILE *f;
     Pokemon pArray[MAX_NB_POKEMON];        
     Pokemon p;
//   char* a;
     int a;
    // Try to open the input file. If there is a problem, report failure and quit
    f = fopen(".csv", "r");      //the csv file is loaded here 
    if(!f)  
        printf("unable to open file\n"); 
        return EXIT_FAILURE; 
    
    
    fetch_pokemon( f, &p ); // discard the header data in the first line

    // Now read and print pokemon until the end of the file
    int nbPokemons = 0;
    //printf("Person ID  Deposition ID  Surname  Forename Age Person Type Gender\tNationality\tReligion Occupation\n");
    while(!feof(f)) 
        fetch_pokemon( f, &pArray[nbPokemons] );
        a=hash_function(pArray[nbPokemons].surname);
        LinkedList* d=allocate_list();
        d->item=&pArray[nbPokemons];
        hashTable[a]=d;
        free_linkedlist(d);
        printf("%d\n",a);
    //  check(&pArray[nbPokemons]);
    //  strcpy(a,pArray[nbPokemons].surname);
        print_pokemon( &pArray[nbPokemons] );
    //  printf("\n");
        nbPokemons++;
    
//  print_table();
//  print_pokemon(&pArray[5]);

    fclose(f);
    return EXIT_SUCCESS;

'''

【问题讨论】:

if(feof(f) || 为时已晚。使用int ch = fgetc(f); if (ch == EOF) break; buf[i] = ch; ...。也许还有其他问题。 #define MAX_BUFFER 20 // Maximum string length this program can handle, char surname[MAX_BUFFER] 是有问题的。对于 20 的最大 length 字符串,需要 21 的缓冲区 size。但没有发布的意见,不清楚这是否会影响 OP 的案例。 请修剪您的代码,以便更容易找到您的问题。请按照以下指南创建minimal reproducible example。 【参考方案1】:

您忘记在main 中的LinkedList* d=allocate_list(); 之后将d-&gt;next 设置为NULL;最好加一行

    if (list) list->next = NULL;

allocate_list 中,因此您可以将linkedlist_insert 中的所有…-&gt;next = NULL; 删除。

free_linkedlist 中有两个错误。

    你不能free(temp-&gt;item);,因为item不是mallocd,而是设置为&amp;pArray[nbPokemons]。 您忘记将list 推进到next 节点。

更正后的 free_linkedlist 可能是 e。 g.

void free_linkedlist(LinkedList *list)

    for (LinkedList *temp; list; list = temp) temp = list->next, free(list);

【讨论】:

以上是关于C中哈希表程序中的指针问题的主要内容,如果未能解决你的问题,请参考以下文章

在 C 中寻找数组(与链表)哈希表实现

C中的通用哈希表

C语言哈希表

以整数为键并映射到 void 指针的 C 映射/哈希表

WebService 中的静态哈希表

数组链表哈希表