Hello,
I'm currently working on a Hash Table that takes strings as keys and maps them to any sort of object. Here is my Hash Table module:
Code:
// Header file
#define HASHSIZE 101
struct entry { struct entry *next; char* name; void* defn; };
typedef struct hashtable { struct entry* hashtab[HASHSIZE]; } HT;
void newHT(HT* , int );
void* getHT(HT* , char* );
void* putHT(HT* , char* , void* );
unsigned hash(char* );
// implementation
#include "HT.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int size;
void newHT(HT* p, int tableSize) {
size = tableSize;
}
void* getHT(HT* p, char* s) {
struct entry* np;
for (np = p->hashtab[hash(s)]; np != NULL; np = np->next)
if (strcmp(s,np->name) == 0) return np->defn;
return NULL;
}
void* putHT(HT* p, char* name, void* defn) {
struct entry* np;
unsigned hashval;
if ((np = getHT(p,name)) == NULL) {
np = (struct entry *) malloc(sizeof(*np));
if (np == NULL || (np->name = name) == NULL)
return NULL;
hashval = hash(name);
np->next = p->hashtab[hashval];
p->hashtab[hashval] = np;
}
else
free((void*)np->defn);
if ((np->defn = defn) == NULL)
return NULL;
return np;
}
/* hash: form hash value for string s */
unsigned hash(char *s) {
unsigned hashval;
for (hashval = 0; *s != '\0'; s++)
hashval = *s + 31 * hashval;
return hashval % size;
}
What I'm trying to do is insert objects that are another module I created called TeamRecord. Here is the code for that:
Code:
// Header file
typedef struct grecord {
char* team1;
char* team2;
int score1, score2;
} GameRecord;
typedef struct trecord {
char* name;
int totPoints, goalsFor, goalsForInGame, goalsAgainst, goalsAgInGame, gamesPlayed;
GameRecord* games[100];
} TeamRecord;
void newTeamRecord(TeamRecord *,char *);
void totalPoints(TeamRecord *);
void totalGoals(TeamRecord *, int );
void goalsAgainst(TeamRecord *, int );
void gameList(TeamRecord *, GameRecord*);
void output(TeamRecord *);
void newGameRecord(GameRecord*,char *,char *,int ,int );
void outputGame(GameRecord*);
//implementation
#include "TeamRecord.h"
#include <stdio.h>
#include <string.h>
void newTeamRecord(TeamRecord *tr, char* name) {
tr->name = name;
tr->goalsFor = 0;
tr->goalsAgainst = 0;
tr->gamesPlayed = 0;
}
void totalPoints(TeamRecord *tr) {
if (tr->goalsForInGame > tr->goalsAgInGame) tr->totPoints += 2;
else if (tr->goalsForInGame == tr->goalsAgInGame) tr->totPoints++;
}
void totalGoals(TeamRecord *tr, int goals) {
tr->goalsForInGame = 0;
tr->goalsFor += goals;
tr->goalsForInGame += goals;
}
void goalsAgainst(TeamRecord *tr, int goals) {
tr->goalsAgInGame = 0;
tr->goalsAgainst += goals;
tr->goalsAgInGame += goals;
}
void gameList(TeamRecord *tr, GameRecord* game) {
tr->games[tr->gamesPlayed] = game;
tr->gamesPlayed++;
}
void output(TeamRecord *tr) {
int i;
printf("%s %d %d %d %d ",tr->name,tr->totPoints,tr->goalsFor,tr->goalsAgainst,tr->gamesPlayed);
for (i = 0; i < tr->gamesPlayed; i++)
outputGame(tr->games[i]);
putchar('\n');
}
void newGameRecord(GameRecord* gr,char* team1, char* team2, int score1, int score2) {
gr->team1 = team1;
gr->team2 = team2;
gr->score1 = score1;
gr->score2 = score2;
}
void outputGame(GameRecord* gr) {
printf("[ %s %d %s %d ]", gr->team1, gr->score1, gr->team2, gr->score2);
}
I know that both of these work on their own. I created test programs for both and they both appeared to work correctly. However, when I try to insert TeamRecords (created from lines in stdin), I get bizarre output. Here is my code where I'm putting the TeamRecords into the Hash Table.
Code:
#include "HT.h"
#include "TeamRecord.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main() {
char buf[BUFSIZ];
char* team1;
char* team2;
char* keys[100];
int score1, score2,keyNum = 0,i;
HT map;
newHT(&map,101);
while( fgets(buf,BUFSIZ,stdin) ) {
team1 = strtok(buf," ");
score1 = atoi(strtok(NULL," "));
team2 = strtok(NULL," ");
score2 = atoi(strtok(NULL,"\n"));
GameRecord game;
newGameRecord(&game,team1,team2,score1,score2);
TeamRecord temp;
if(getHT(&map,team1) != NULL) {
gameList((TeamRecord*)getHT(&map,team1),&game);
totalGoals((TeamRecord*)getHT(&map,team1),score1);
goalsAgainst((TeamRecord*)getHT(&map,team1),score2);
totalPoints((TeamRecord*)getHT(&map,team1));
}
else {
newTeamRecord(&temp,team1);
gameList(&temp,&game);
totalGoals(&temp,score1);
goalsAgainst(&temp,score2);
totalPoints(&temp);
putHT(&map,team1,&temp);
keys[keyNum] = team1;
keyNum++;
}
if(getHT(&map,team2) != NULL) {
gameList((TeamRecord*)getHT(&map,team2),&game);
totalGoals((TeamRecord*)getHT(&map,team2),score2);
goalsAgainst((TeamRecord*)getHT(&map,team2),score1);
totalPoints((TeamRecord*)getHT(&map,team2));
}
else {
newTeamRecord(&temp,team2);
gameList(&temp,&game);
totalGoals(&temp,score2);
goalsAgainst(&temp,score1);
totalPoints(&temp);
putHT(&map,team2,&temp);
keys[keyNum] = team2;
keyNum++;
}
free(&temp);
free(&game);
}
for (i = 0; i < keyNum; i++) {
output((TeamRecord*)getHT(&map,keys[i]));
}
}
When I run this with input like this:
Dal 4 SMU 2
My output looks like this:
SMU 1936666163 2 4 1 [ Dal 4 SMU 2 ]
SMU 1936666163 2 4 1 [ Dal 4 SMU 2 ]
It should look like this:
Dal 2 4 2 1 [ Dal 4 SMU 2 ]
SMU 0 2 4 1 [ Dal 4 SMU 2]
I think I'm doing something wrong with TeamRecord temp. It seems like only one TeamRecord gets created and is changed with each new team. Also, the total points number (the second number in the output) is messed up for some reason. Can anyone figure out what's wrong with this? I've been working at it for a couple of days and can't figure out what's going on.