I am trying to build an array of structures with a string and starting address of a linked list of another structure. Several strings from each line of a file is to be filled into this data structure. But whenever I am coming back to the next line, all the variables of the array and LL that I have filled up so far is being changed to the variables in the current line. As a result all the elements of the array as well as the corresponding linked lists are giving the same result in each element of the array. Here is the code.
struct node
{
char* nodedata;
struct node* link;
};
struct motief
{
char* motiefname;
struct node* link;
};
void add_unique_nodes(struct motief*,int,char *);
int unique_motief(struct motief*,char*);
void add_unique_nodes(struct motief* motiefs,int motief_no,char * token)
{
struct node *temp,*r;
r = malloc(sizeof(struct node));
r->nodedata = token;
//for the first node
if(motiefs[motief_no].link == NULL)
{
motiefs[motief_no].link = r;
}
else
{
temp = motiefs[motief_no].link;
while(temp->link != NULL && token != temp->nodedata)
temp = temp->link;
if(token != temp->nodedata)
temp->link = r;
}
r->link = NULL;
}
void main()
{
struct motief motiefs[100];
FILE *fp, *ft;
fp = fopen("dump.txt","r");
ft = fopen("motief_nodes","w");
char line[100] ={0};
char seps[] = ",";
char* token;
int motief_no = 0;
int i,j;//loop variable
//read the database
while(!feof(fp))
{
if( fgets(line, sizeof(line), fp ))
{
if(motief_no == 1)
printf("for start of 2nd step %s\t",motiefs[0].motiefname);//????
printf("for line %d\t",motief_no);
//get the motief from each input line as a token
token = strtok (line, seps);
//store it in motief array
motiefs[motief_no].motiefname = token;
printf("%s\n",motiefs[motief_no].motiefname);
if(motief_no == 1)
printf("for zero %s\n",motiefs[0].motiefname);
motiefs[motief_no].link = NULL;
//get and store all the nodes
while (token != NULL)
{
//get the node
token = strtok (NULL, seps);
if(token != NULL)
add_unique_nodes(motiefs,motief_no,token);
}
if(motief_no == 0)
printf("for end of 1st step %s\n",motiefs[0].motiefname);
motief_no++;
if(motief_no == 2)//break at 2nd loop, at 1
break;
}
I am new to C programming. I cannot find why it is happening. Please help me to find where I am going wrong and why the file is read into the array besides the specified variable for that purpose in my code. Thanks in advance. Here are few lines from the file to be read.
000100110,1,95,89
000100111,1,95,87
000100110,1,95,74
000100110,1,95,51
I am displaying the structure with the following code
struct node* temp;
for(j=0;j<2;j++)
{
printf("turn %d\t",j);
printf("%s\t",motiefs[j].motiefname);
temp = motiefs[j].link;
printf("%s\t",temp->nodedata);
do
{
temp = temp->link;
printf("%s\t",temp->nodedata);
}while(temp->link != NULL);
printf("\n");
}
And the it shows the following overall result
for line 0 000100110
for end of 1st step 000100110
for start of 2nd step 000100111,1,95,87
for line 1 000100111
for zero 000100111
turn 0 000100111 1 95 87
turn 1 000100111 1 95 87
You keep changing the same memory space when you read into 'line'. you need to allocate new memory space each time you want a different array.
Picture 'line' as pointing to a specific chunk of 100 bytes in a row. You keep telling the fgets function to write to that location, and you also keep copying the address of that location into your structs when you assign the 'token' to moteifname.
Then when you change what's at that address of course it's overwriting what the struct points to as well!
You need to choose to allocate the space in each struct instead of having an internal pointer OR you need to dynamically allocate space each iteration using malloc and then free() all the pointers at the end.
https://www.codingunit.com/c-tutorial-the-functions-malloc-and-free
Related
Objective
To create an array of an array of structs, the dimensions based on a file. Then store that into a Linked List.
I am reading from a file formatted like this:
Read a file that is in the form:
name (string) country (string) age (int)
john USA 54
Sam Aus 18
ect
I dont know how many rows and columns the file will have , nor do I know what varible type each column will be
So in theory the first array of struct will contain [NUMBER OF COLUMNS] strucs that will store each variable (using a void pointer and typecasting) along the line( so strucArrayCol[0] = john , structArrayCol[1] = USA ect).
Each of these array of strucs will be stored into another array of strucs which will have [NUMBER OF ROWS] elements so strucArray2Row[0] = strucArrayCol (which contains john , USA and 54) and strucArrayRow[1] will contain another strucArrayCol which contains (sam Aus 18).
So right now I can read the file, and find the number or rows, columns and the variable type of each column.
This is where i start having trouble as im not sure how to go about
1. How to create this array within array ( I know i need to use Malloc)
2.How I would store the variables in the first array of struc, if I
wanted to store age could I just do
void *data = malloc(sizeof(int));
*((int*)data) = TEMP_AGE;
void data being a struc in StrucArrayCol ( in the case of the example if I wanted to store the age of John void* data would be in StrucArrayCol[3] which is inside StucArrayRow[0], as its the 3rd col in the first line)
Sorry if this dosent make sense
Thanks
You can create a linked-list within a linked-list, assuming there is aversion to anything which is not a linked-list! Declare two linked-list node structures, one for rows in the file, and one for columns within each row:
struct column
{
char *buf;
struct column *next;
};
struct row
{
struct column *head;
struct row *next;
};
Read the file one line at a time, add one row node for each line. Each row will have its own link-lists, it will parse the line in to columns.
struct column* column_create(struct column* cursor, char *line)
{
struct column *node = malloc(sizeof(struct column));
node->next = 0;
node->buf = malloc(strlen(line) + 1);
strcpy(node->buf, line);
if (cursor)
cursor->next = node;
return node;
}
struct row* row_create(struct row* cursor, char *line)
{
struct row *node = malloc(sizeof(struct row));
node->next = 0;
node->head = 0;
//parse the line in to columns
struct column *col = 0;
char *token = strtok(line, " \n");
while (token)
{
col = column_create(col, token);
if (!node->head)
node->head = col;
token = strtok(NULL, " \n");
}
if (cursor)
cursor->next = node;
return node;
}
Or you can do this with a 2-dimensional array of text (which would be 3-dimensional array of characters). Or use an array of strings to hold all the lines in the file, then parse each line in to column. From there, you can test each column to see if it is integer or not.
If you don't know the number of lines in the file, use realloc to allocate as much memory is needed during run time. This example reads all the lines in file, and copies it to an array of lines:
int main()
{
FILE *f = fopen("test.txt", "r");
char **lines = 0;
int lines_size = 0;
int lines_capacity = 0;
char buf[1024];
while (fgets(buf, sizeof(buf), f))
{
int len = strlen(buf);
if (!len) continue;
if (lines_size == lines_capacity)
{
lines_capacity += 16;
lines = realloc(lines, lines_capacity * sizeof(char*));
}
lines[lines_size] = malloc(len + 1);
strcpy(lines[lines_size], buf);
lines_size++;
}
int i;
for (i = 0; i < lines_size; i++)
printf("%s", lines[i]);
printf("\n");
for (i = 0; i < lines_size; i++)
free(lines[i]);
free(lines);
return 0;
}
This will work as long as line length in the file never exceeds 1024. Separately, you can parse each line using strtok
void parseline(char *line)
{
char copy[1024];
strcpy(copy, line);
char *token = strtok(copy, " \n");
while (token)
{
printf("[%s], ", token);
token = strtok(NULL, " \n");
}
printf("\n");
}
You need a linked list in a linked list.
Barmak wrote how to get the data. So here is how to get the linked list.
struct sString{
char* str;
void* next_hor;
void* next_ver;
};
struct sInt{
char* Int;
void* next_hor;
void* next_ver;
};
in first column
if ( check type of column)
{for each row
{
generate corresponding struct and link it to previous element (add-function)
}
}
for other columns
{
( check type of column)
{for each row
{
generate corresponding struct and link it to previous element (add-function)
also iterate though linked list and insert the horizontal link
}
}
}
Its very clustered, has tons of overhead and is hard to manage but it should work.
The vertical pointer could also be of the right type as the types don't change in a column.
I'm trying to build a string that will go into a logfile with this format: "Executable: Time:... Error: ...". However, I am having trouble allocating for my time variable in my data structure. I have been able to code it so that the time can go before the string later but I cannot figure out how to have the time be between the executable and the error message. If anyone could tell me what I'm doing wrong I'd appreciate it.
Code:
log.h
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include <time.h>
typedef struct data_struct
{
time_t time;
char *string;
} data_t;
int addmsg(data_t data, char *arg0);
void clearlog(void);
char *getlog(void);
int savelog(char *filename);
loglib.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include "log.h"
//Basic template from Excercise 2.13
typedef struct list_struct
{
data_t item;
struct list_struct *next;
} log_t;
static log_t *headPtr = NULL;
static log_t *tailPtr = NULL;
//Like book example with add on for executable name
int addmsg(data_t data, char *arg0)
{
log_t *newnode;
int nodesize;
char timeString[] = ": Time: ";
char errorString[] = " Error: ";
//Allocate size for "Executable: time: Error: "
nodesize = sizeof(log_t) + strlen(data.string) + strlen(arg0) + sizeof(time_t) + strlen(timeString) + strlen(errorString) + 1;
if((newnode = (log_t *)(malloc(nodesize))) == NULL)
{
perror("Malloc failed: ");
return -1;
}
//Makes string "Executable: time: Error: "
newnode->item.time = data.time;
char *timeCode = ctime(&newnode->item.time);
newnode->item.string = (char *)newnode + sizeof(log_t);
strcpy(newnode->item.string, arg0);
newnode->item.string = strcat(newnode->item.string, timeString);
newnode->item.string = strcat(newnode->item.string, timeCode);
newnode->item.string = strcat(newnode->item.string, errorString);
newnode->item.string = strcat(newnode->item.string, data.string);
newnode->next = NULL;
//Puts string as EOF
if(headPtr == NULL)
{
headPtr = newnode;
}
else
{
tailPtr->next = newnode;
}
tailPtr = newnode;
return 0;
}
//Clears log
void clearlog(void)
{
log_t *nextPtr = headPtr;
//Loop through and clear the log
while(nextPtr != NULL)
{
nextPtr = headPtr->next;
free(headPtr);
headPtr = nextPtr;
}
}
char *getlog(void)
{
int size = 1;//Set to 1 because of null terminator
int entryNum = 0; //Number of error logs
log_t *node = headPtr; //Start at beggining
char *wholeLog = NULL; //Used to return the entire log
char *entryString = NULL;
//Get size
while(node != NULL)
{
entryNum++;
size += strlen(node->item.string);
node = node->next;
}
//Memory allocation
wholeLog = malloc(sizeof(char)*(size + 1 + (entryNum * 2)));
if(wholeLog == NULL)
{
perror("Malloc failed: ");
return NULL;
}
//Reset node to beggining
node = headPtr;
//Builds the entire log to return
while(node != NULL)
{
entryString = strcat(entryString, node->item.string);
wholeLog = strcat(wholeLog, entryString);
wholeLog = strcat(wholeLog, "\n"); //New line
node = node->next;
}
//Make space
wholeLog += (strlen(wholeLog) - size - (entryNum-1));
return wholeLog;
}
int savelog(char *filename)
{
FILE *f;
char *logPrinter;
f = fopen(filename, "a");
if(!f)
{
perror("Error opening file: ");
return -1;
}
//Get the log to print
logPrinter = getlog();
if(logPrinter == NULL)
{
printf("Empty Log\n");
return 0;
}
fprintf(f, "%s\n", logPrinter);
fclose(f);
return 0;
}
Your code seems bent on calculating the size of a memory buffer that would hold both the log_t node structure and the concatenated message parts, having the string pointer within the data_t member of the linked list node point within the single memory block, just passed the linked list node content, where the message is stored. In short, a single allocation holding both the node and the message.
That said, exploit the fact that there are standard library API's, notably snprintf that can calculate formatted message buffer length requirements for you, and you can then skip most of the string management malaise in favor of the real purpose of this, managing the linked list structure and the dynamic message content with a single invoke to malloc (and by circumstance, a single invoke to free() when this fiasco needs to be undone):
Determine the length of the formatted string data
Allocate a buffer large enough to hold that data, and the structure that will precede it.
Position the string pointer in the structure to the first char just passed the structure layout.
Perform the formatted message dump into the memory pointed to by that string pointer.
The result is a single allocation of dynamic length, depending on the content of the message being formatted.
Using snprintf Instead
int addmsg(data_t data, const char *arg0)
{
static const char fmt[] = "%s: Time: %s Error: %s";
char stime[32] = ""; // per ctime docs, must be at least 26 chars
int res = -1;
// get time string, trim newline
ctime_r(&data.time, stime);
if (*stime)
stime[strlen(stime)-1] = 0;
// find needed message size
int req = snprintf(NULL, 0, fmt, data.string, stime, arg0);
if (req > 0)
{
// include size of log record, formatted message, and terminator
log_t *node = malloc(sizeof (log_t) + req + 1);
if (node != NULL)
{
node->item.string = (char*)(node+1); // NOTE: see below
node->item.time = data.time;
node->next = NULL;
snprintf(node->item.string, req+1, fmt, data.string, stime, arg0);
// link into list
if (!headPtr)
headPtr = node;
else
tailPtr->next = node;
tailPtr = node;
// good return value
res = 0;
}
else
{
perror("Failed to allocate memory for log mesage: ");
}
}
else
{
perror("Failed to perform message formatting: ");
}
return res;
}
Everything above is fairly straight forward, save for possible NOTE, which I'll explain now. It uses pointer arithmetic. Given a pointer node of some type log_t* the expression:
(node + 1)
calculates the next position in memory where a subsequent log_t object could reside, or the "one-past" memory position in the case of the end of a sequence. When we allocated our memory, we did so to a layout that looks like this:
node ---> |=== log_t ===|===== message text =====|
the expression (node+1), using typed pointer arithmetic, give us:
node ---> |=== log_t ===|===== message text =====|
(node+1)-----------------^
which is then cast to char*, saved in node->data.string and used as the target for the final message formatting using snprintf. Short version: node->item.string points to the extra memory we allocated following the log_t structure pointed to by node.
That's it. The result is a single allocation to a linked list node that contains both the node management data, and also contains a pointer to the dynamic message string stored in the suffix memory of the single allocation past the log_t core data.
If you replaced the log_t construction piece of addmsg with something perhaps like this you would get better results. Your calculation of required memory size is a little off. Might want to also avoid assuming things about memory with your malloc (i.e. Allocating extra memory to store both a structure and the contents of a pointer member of that structure could easily get you into trouble)
...
log_t *newnode = NULL;
void *vp = NULL;
if (NULL == (vp = malloc(sizeof(log_t)))) {
perror("malloc failed (sizeof(log_t))");
return -1;
}
newnode = (log_t *)vp;
newnode->item.time = data.time;
char *timeCode = ctime(&newnode->item.time);
int msgsize = strlen(": Time: Error: ")
+ strlen(arg0)
+ strlen(timeCode)
+ strlen(data.string)
+ 1;
if (NULL == (vp = malloc(msgsize))) {
perror("malloc failed (msgsize)");
free(newnode);
return -1;
}
newnode->item.string = (char *)vp;
sprintf(newnode->item.string, "%s: Time: %s Error: %s", arg0, timeCode, data.string);
...
I don't know why I can read the Linked list without problems in LABEL : 1 ; but the program just crashes and print grabage in the LABEL : 0 ;
In other terms, why the linked list works fine inside the lecture function , but not outside it ?
Here is my code :
/* including libraries */
#define V 20
typedef struct DATA{
char* NomP;char* NomA;
struct DATA *Next;
}DATA;
// Prototypes .
int main(void)
{
char FileName[V];
puts("Data file ? : ");gets(FileName);
FILE* fs = fopen(FileName,"r"); // Check if fs is NULL
DATA *HEAD = MALLOC(sizeof (DATA)); int len = lecture_data(fs,HEAD);
print_data(HEAD,len); //LABEL : 0
return 0;
}
int lecture_data(FILE *fs,DATA *ROOT)
{
char cNom[V],cArticle[V];
int eofs=0;int i=0;
while(!eofs)
{
DATA *Data = MALLOC(sizeof (DATA));
fscanf(fs,"%s %s",cNom,cArticle);
Data->NomA = MALLOC(strlen(cArticle)+1);
Data->NomP = MALLOC(strlen(cNom)+1);
strcpy(Data->NomA,cArticle);
strcpy(Data->NomP,cNom);
if( i==0 )
{
Data -> Next = NULL ;
ROOT = Data ;
}
else
{
DATA* Ptr = ROOT ;
while( (Ptr->Next) != NULL )
{
Ptr = (Ptr -> Next);
}
Data -> Next = NULL ;
Ptr -> Next = Data ;
}
i++;
eofs = feof(fs) ;
// check ferror(fs) here
}
puts("Start of reading :");
print_data(ROOT,len); // LABEL : 1
puts("End Of Reading ");
fclose(fs);
return i;
}
Here is the printing function :
void print_data(DATA *L_ROOT,int len)
{
int i = 0 ;
DATA* LINK;
LINK = L_ROOT;
while( LINK != NULL )
{
printf("%d : DATA->NomA : %s\n",i,LINK->NomA);
printf("%d : DATA->NomP : %s\n",i,LINK->NomP);
LINK = LINK -> Next ;
i++;
}
}
You're allocating data for the root of the list in the main function, and pass that to the function so that it may populate the list, but the first time you allocate an element you overwrite the ROOT pointer value.
this makes you lose the only connection between the function and the outside world (since the return value is just a number), so the HEAD value in main() is left pointing at nothing meaningful (because your function never uses it), while the list remains allocated in some memory location that no one outside is pointing to, which means it's lost. Running valgrind would have been able to identify this.
You can fix that by changing the (i==0) case from -
ROOT = Data ;
into
ROOT->next = Data ;
but make sure you're ignoring the data of the root node later on.
p.s. - using capitalized variables and types is not considered a good idea (it's mostly reserved for macros). It also makes your code look like you're shouting :)
The (main) problem is that lecture_data doesn't use it's input parameter (ROOT) for storage of the linked list, nor does it return the internal generated list. The correct way to handle this is to have ROOT reference the calling scope's parameter so that it can update it's reference as necessary.
int main(void)
{
char FileName[V];
puts("Data file ? : ");gets(FileName);
FILE* fs = fopen(FileName,"r"); // Check if fs is NULL
DATA *HEAD = NULL;
int len = lecture_data(fs, &HEAD);
print_data(HEAD); //LABEL : 0
return 0;
}
int lecture_data(FILE *fs,DATA **ROOT)
{
char cNom[V],cArticle[V];
int i=0;
DATA *current = *ROOT; // grab the passed in reference
while(!feof(fs))
{
if(fscanf(fs,"%s %s",cNom,cArticle) <= 0) // This call is only successful if the return value is > 0
{
// check ferror(fs) here
continue; // Can also "break;" here, essentially, it's eof already
}
DATA *Data = MALLOC(sizeof (DATA));
Data->NomA = MALLOC(strlen(cArticle)+1);
Data->NomP = MALLOC(strlen(cNom)+1);
strcpy(Data->NomA,cArticle);
strcpy(Data->NomP,cNom);
if(NULL == current) // ROOT was uninitialized before the call
{
Data -> Next = NULL;
*ROOT = Data;
}
else
{ // We don't need to iterate the list in every step.
Data->Next = current->Next; // This part allows the function to insert nodes in the middle / end of an existing list
current->Next = Data;
current = Data;
}
i++;
}
puts("Start of reading :");
print_data(ROOT); // LABEL : 1
puts("End Of Reading ");
fclose(fs);
return i;
}
Note: print_data didn't do anything with the len parameter, so no need passing it in at all.
This solution is not wasteful in terms of "empty" nodes in the list (as opposed to having an empty head to ignore), and is suitable both for initializing the list from scratch AND for cases where you need to append / insert into an existing list.
I'm having some troubles passing the information of a .csv file to a struct using linked lists...
The file is like:
1,3.234,hello,f
3,4.2432,worldkind,o
.
.
.
My C Program:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 50
typedef struct TP
{
int key;
//data
int atomnum;
float massnum;
char nome[MAX+1];
char sym[MAX+1];
struct tableper *nseg;
struct tableper *nant;
}tp;
tp* putmemory(tp *dbase1) //function to put data to struct
{
FILE *fp1;
char *token,ch,temp[MAX];
int *tokenint,i,aux[MAX],in=-1,flag=0;
char BUFFER[MAX],*aux2;
tp *nv;
if ((fp1 = fopen("TabelaPeriodica.csv","r")) == NULL)
printf("File could not be opened \n");
while(!feof(fp1))
{
while((ch=fgetc(fp1)) != '\r')
{
temp[++in]=ch;
if(ch == ',')
{
nv->key = ++i;
token = strtok(temp[++i],",");
nv->atomnum = token;
token = strtok(NULL,",");
nv->massnum = atof(token);
token = strtok(NULL,",");
strcpy(nv->nome,token);
token = strtok(NULL,",");
strcpy(nv->sym,token);
free(nv);
}
}
}
}
int main()
{
tp *dbase1;
putmemory(dbase1);
return 0;
}
My problems are:
pass a vector of chars to a vector of string
read each line and save in struct
each iteration save nv(new_node) to struct using linked list
one of the many issues I spot is that you never allocate memory for nv...
Also I would use fgets to read a whole line and then use strtok on it
again, you have to allocate nv, and then set dbase1 to it, so you build up a linked list
You need to allocate memory for nv.
In your current code, nv is an uninitialized pointer. You can't use it just like that.
Also you have a free(nv) in your code and no corresponding nv = malloc(sizeof *nv); or similar
This is a lot of code but I'm at ends here trying to figure out why its not working.
This is the code I'm running:
struct dict {
struct word **tbl;
int (*hash_fcn)(struct word*);
void (*add_fcn)(struct word*);
void (*remove_fcn)(struct word*);
void (*toString_fcn)(struct word*);
};
struct word {
char *s;
struct word *next;
};
this is part of the main function:
hashtbl=malloc(sizeof(struct dict));
//hashtbl->tbl=malloc(sizeof(struct word*)*256);
int i;
for(i=0;i<256;i++)
{
hashtbl->tbl[i] = malloc(sizeof(struct word));
hashtbl->tbl[i] = NULL;
//hashtbl->tbl[i]=NULL;
}
hashtbl->add_fcn=&add_word;
hashtbl->remove_fcn=&remove_word;
hashtbl->hash_fcn=&hash_function;
hashtbl->toString_fcn=&toString;
FILE *p;
p = fopen("a.txt", "r");
if(p == NULL) { printf("ERROR!\n"); return 0; }
char line[MAXBYTES];
while(fgets(line, MAXBYTES, p))
{
char *token = strtok(line, " ");
while(token != NULL)
{
struct word *words = malloc(sizeof(struct word));
words->s = token;
words->next=NULL;
trim(words);
hashtbl->add_fcn(words);
token = strtok(NULL, " ");
printf("....\n");
hashtbl->toString_fcn(NULL);
printf("....\n\n");
}
free(token);
}
Here are two functions used (to String just prints it out)
void add_word(struct word *insert)
{
if(strcmp(insert->s, "\n") == 0) {return;}
int hash = hashtbl->hash_fcn(insert);
if(hash==0) { return; }
struct word *word = hashtbl->tbl[hash];
if(word==NULL)
{
struct word *newword = malloc(sizeof(struct word));
newword->s=insert->s;
newword->next=NULL;
hashtbl->tbl[hash]=newword;
printf("() %d %s \n", hash, hashtbl->tbl[hash]->s);
}
else
{
struct word *tp = word;
while(word->next != NULL)
word=word->next;
struct word *newword = malloc(sizeof(struct word));
newword->s=insert->s;
newword->next=NULL;
word->next=newword;
hashtbl->tbl[hash]=tp;
}
}
int hash_function(struct word *string)
{
char *firstletter = string->s;
char c = *firstletter;
int ascii = (int)c;
return ascii;
}
a.txt is
cat
dog
mouse
and it prints out the following:
() 99 cat
....
99 : cat
....
() 100 dog
....
99 : dog
100 : dog
....
() 109 mouse
....
99 : mouse
100 : mouse
109 : mouse
....
it should be printing out
99:cat
100:dog
109:mouse
thanks
You have many problems here.
First:
hashtbl=malloc(sizeof(struct dict));
//hashtbl->tbl=malloc(sizeof(struct word*)*256);
You need to uncomment that line, since without it you don't allocate the array of struct pointers in hashtbl->tbl, and leave it uninitialized. It'll probably cause a segfault as is.
Next:
for(i=0;i<256;i++)
{
hashtbl->tbl[i] = malloc(sizeof(struct word));
hashtbl->tbl[i] = NULL;
//hashtbl->tbl[i]=NULL;
}
This is leaking memory. You're allocating a struct word to each element of hashtbl->tbl, but then overwriting the pointer with NULL. So you leak all the memory you allocated, and leave each array element set to NULL. Get rid of the malloc() and just set them to NULL, since you'll allocate the structs later when you actually add a word.
In this part:
hashtbl->add_fcn=&add_word;
hashtbl->remove_fcn=&remove_word;
hashtbl->hash_fcn=&hash_function;
hashtbl->toString_fcn=&toString;
...the & are not needed -- the function names without parentheses are good enough. As long as the parentheses are omitted, it will be interpreted as the address of the function and not a function call.
And then here:
char *token = strtok(line, " ");
while(token != NULL)
{
struct word *words = malloc(sizeof(struct word));
words->s = token;
...the char * returned by strtok() typically points within the string you're processing, i.e. within the buffer you read lines into. It will not remain intact while you continue processing the file. You need to make a copy of the string, not just save the pointer.
free(token);
...are you sure you should free this?