/* * hash-table.c * create a hash-table and play around with it * Nael Abu-Ghazaleh */ #include #include #include int hash(char *key, int size); #define SHELVES 2 #define MAX_NAME_LENGTH 30 typedef struct book { char *name; int isbn; struct book *next; } BookNode; /* Shelf is now a data type */ void printHashtable(BookNode **table); void printList(BookNode *head); void freeHashtable(BookNode **table); void freeList(BookNode *hd); void fatalError(char *msg); /*void append(BookNode **hd, BookNode *newBook); void delete(BookNode **hd, char *name); void deleteRecur(BookNode **hd, char *name); */ int main(int argc, char *argv[]) { FILE *inFile; BookNode **shelves=NULL; BookNode *tmp = NULL; int hash_value; /* temp variables to read data from file */ char name[MAX_NAME_LENGTH]; int isbn; if (!(inFile = fopen("books.txt", "r"))) fatalError("Can't open books.txt"); /*create the shelves hash table*/ if((shelves= (BookNode **) malloc(sizeof(BookNode*)*SHELVES))==NULL) fatalError("malloc of shelves failed"); /* Read the books from the file */ while(fscanf(inFile,"%s %d",name,&isbn) == 2) { if ((tmp = (BookNode *)malloc(sizeof(BookNode))) == NULL) fatalError("malloc of tmp failed"); if ((tmp->name = (char *)malloc((strlen(name) + 1) * sizeof(char))) == NULL) fatalError("malloc of tmp->name failed"); strcpy(tmp->name,name); tmp->isbn = isbn; /* Place the new node in the hash table */ hash_value = hash(name,SHELVES); tmp->next = shelves[hash_value]; shelves[hash_value]=tmp; printf("Added %s book to shelf %d\n",name,hash_value); } fclose(inFile); printf("printing the hashtable contents:\n"); printHashtable(shelves); freeHashtable(shelves); return 0; } int hash (char *key, int size) { int i=0; int result=0; if(key==NULL) return -1; while(key[i]) { result+=key[i]*(i+1); i++; } return result % size; } /* Notice we use our incoming head pointer as an iterator! * We are not corrupting the real head in main - this is just a copy * Some folks like this style, some would rather use an explicit temp ptr */ void printHashtable(BookNode **table) { int i; if(table==NULL) { fprintf(stderr,"printHashtable with an NULL table pointer!\n"); return; } for (i=0 ; i < SHELVES; i++) { printf("Shelf %d: ",i); if(table[i]==NULL) { printf("Empty!\n"); } else { printList(table[i]); } } return; } void printList(BookNode *hd) { for ( ; hd != NULL; hd = hd->next) { printf("[%s,%d]", hd->name, hd->isbn); if (hd->next) printf(" -> "); } printf("\n"); } void freeHashtable(BookNode **table) { /*what goes here?*/ } /* use recursion to free string and struct on the way back up the list. * Doing this going forward would be cutting our bridge off in front of us */ void freeList(BookNode *hd) { if (hd == NULL) return; freeList(hd->next); /* recurse to the end of list */ free(hd->name); /* free the string */ free(hd); /* then the struct */ } /* a convenient function to print a fatal error msg and exit the program * Note we don't bother cleaning up memory. It will be done for us * when our program exits. */ void fatalError(char *msg) { fprintf(stderr,"\nFATAL ERROR: %s!!\n\n", msg); exit(EXIT_FAILURE); }