【问题标题】:Problem With Pointers in Hash Table program in CC中哈希表程序中的指针问题
【发布时间】: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

标签: c struct hash linked-list


【解决方案1】:

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

    if (list) list->next = NULL;

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

free_linkedlist 中有两个错误。

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

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

void free_linkedlist(LinkedList *list)
{
    for (LinkedList *temp; list; list = temp) temp = list->next, free(list);
}

【讨论】:

    猜你喜欢
    • 2021-06-18
    • 2014-05-22
    • 2011-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-10
    • 1970-01-01
    相关资源
    最近更新 更多