I have a linked list I implemented that works fine for various file inputs (it reads them line by line and inserts them.)
void insert_words(FILE* file, node_type* list)
{
char buffer[12];
int length = 0;
while (!feof(file)){
fscanf(file, "%s", buffer);//buffer contains the string/name
length = strlen(buffer);
if (length != 0) {
insert_sorted(list, buffer);
}
} //while
}
Given this code, I'm seeing issues which when fscanf is executed with the given sample input after reading in 'fff', things seem to go sour.
one
two
three ee
fff
ee
As ee is being parsed:
list = 0x009dfac0 {name=0x009dfac0 "one" next=0x00c98c08 {name=0x00c98c08 "three" next=0x00c98ba0 {name=0x00c98ba0 "two" ...} } }
After the next token:
list = 0x009dfac0 {name=0x009dfac0 "ee" next=0x009df068 {name=0x009df068 "È”ü\xf\x1" next=0x0ff7caa0 {msvcr110d.dll!_except_handler4(_EXCEPTION_RECORD *, _EXCEPTION_REGISTRATION_RECORD *, _CONTEXT *, void *)} {...} }
When examining my list, the 'next' pointer is corrupted immediately after fscanf is fired off. What are the potential causes?
Inserted sort upon request:
void insert_sorted(node_type* list, char* value)
{
// Copy our pointer so we can move around
node_type *n = (node_type*) malloc(sizeof *n);
node_type *loc = NULL;
node_type *tmp;
node_type dat;
node_type* prev = list;
node_type* head = list;
n->next = NULL;
strcpy(n->name, value);
// First element, assign immediately
if( strcmp(list->name, "") == 0 )
{
*list = *n;
return;
}
while(head != NULL)
{
// We should do a comparison to see if one is greater than another
int cmp_result = strcmp(value, head->name);
// If the value is bigger, this means the value needs to be inserted after
if(cmp_result > 0)
{
loc = head;
}
else if (cmp_result < 0) // this needs to be ahead
{
if(prev == head)
{
dat = *head;
*head = *n;
head->next = &dat;
return;
}
prev->next = n;
n->next = head;
return;
}
else if(cmp_result == 0)
{
free(n);
return; // duplicate, die
}
// Advance to the next pointer
prev = head;
head = head->next;
}
// You've reached the end, that must mean you've succesfully reached the point to insert
tmp = loc->next; // get the value we're going to end up detaching
n->next = tmp; // link the two together
loc->next = n;
}
Modify the loop into
while (fscanf(file, "%s", buffer) == 1) {
length = strlen(buffer);
// ...
}
Because feof(file) still returns 0 after the last successful fscanf(). It returns non-0 after the first failed fscanf().
Regarding insert_sorted(), look at the following lines:
head->next = &dat;
return;
Since dat is a local object, saving its address leads to invalid address once the function returns.
You're not testing for end of file correctly. In general, it's not correct to use feof, but instead to test the return value of the function with which you read from the file.
fscanf returns the number of entities that it was able to read. So in your case you would test that it returned 1, which would indicate a successful read. And to avoid buffer overflow, you can put a limit on the number of characters to read with a number between the % and the s.
And there's no reason to be so stingy with your buffer size.
So:
void insert_words(FILE* file, node_type* list)
{
char buffer[128];
while (fscanf(file, "%127s", buffer) == 1) {
insert_sorted(list, buffer);
}
}
BTW, you're not reading "line by line" but "space-delimited string by space-delimited string". To read the file line-by-line you could use fgets.
And before you say "that's not the problem", try it first. These are the only problems that could come from this function.
Related
You should be able to enter any movie title and genre into this program as long as they are smaller then 30 characters. Then insert a rating between 1-5. The insert function takes those three inputs and stores them into a doubly linked list. After Two entries into this list the program creates an unexpected breakpoint on this line newBlock = (movieInfo*)malloc(sizeof(movieInfo)); The problems is in the insert function.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct movieInfo {
char* title;
char* genre;
int rating;
struct movieInfo* prev;
struct movieInfo* next;
}movieInfo;
//prototypes
int getNum(void);
movieInfo insert(char* title, char *genre,int rating, movieInfo** head, movienfo** tail);
void showList(movieInfo* head);
void eliminateEndOfLine(char* buffer);
void eliminateEndOfLine(char* buffer);
#define kWhileLoopCounter 1
#define kBuffer 30
int main() {
char title[kBuffer];
char genre[kBuffer];
int rating = 0;
movieInfo* head = NULL;
movieInfo* tail = NULL;
movieInfo* node = NULL;
while (kWhileLoopCounter) {
printf("Please enter a title or exit the loop by entering ""."" and enter \n");
fgets(title, kBuffer, stdin);
if (strcmp(title, ".\n") == 0) {
break;
}
eliminateEndOfLine(title);
printf("Please enter a genre or exit the loop by entering ""."" and enter \n");
fgets(genre, kBuffer, stdin);
if (strcmp(genre, ".\n") == 0) {
break;
}
eliminateEndOfLine(genre);
for (;;) { //jut to check and make sure the user does not enter a value greater then one
printf("Please enter a rating between 1-5\n");
rating = getNum();
if (rating < 1) {
printf("The number you have entered in less then 1,\n\n");
}
else if (rating > 5) {
printf("The number you have entered is greater than 5\n\n");
}
else {
insert(title, genre, rating, &head, &tail);
break;
}
}
}
showList(head);
freeAll(head);
return 0;}
This function seems to be the problem!!!
movieInfo insert(char title[],char genre[],int rating, movieInfo** head, movieInfo** tail) {
movieInfo* newBlock = NULL;
movieInfo* beforeElement = NULL;
movieInfo* afterElement = NULL;
newBlock = (movieInfo*)malloc(sizeof(movieInfo));
newBlock->title = (char*)malloc((strlen(title) + 1));
newBlock->genre = (char*)malloc((strlen(genre) + 1));
/*newBlock->rating = (int*)malloc(1);*/
if (newBlock == NULL) {
printf("No memory was allocated \n");
return **head;
}
strncpy(newBlock->title, title,30);
strncpy(newBlock->genre, genre,30);
newBlock->prev = newBlock->next = NULL;
if (*head == NULL) {
*head = *tail = newBlock;
return**head;
}
else if (strcmp((*head)->title, title) >= 0) {
newBlock->next = *head;
(*head)->prev = newBlock;
*head = newBlock;
}
else {
beforeElement = *head;
afterElement = (*head)->next;
while (afterElement != NULL) {
if (strcmp(afterElement->title, title) >= 0) {
break;
}
beforeElement = afterElement;
afterElement = afterElement->next;
}
newBlock->prev = beforeElement;
newBlock->next = afterElement;
beforeElement->next = newBlock;
if (afterElement == NULL)
{
*tail = newBlock;
}
else
{
afterElement->prev = newBlock;
}
}
return **head;
}
This contains the smaller functions.
void showList(movieInfo* head)
{
movieInfo* item = NULL;
item = head;
char titleHeader[] = "Title";
char genreHeader[] = "Genre";
char ratingHeader[] = "Rating";
printf("\n\n%-30s %-30s %-30s\n",titleHeader,genreHeader,ratingHeader);
while (item != NULL)
{
printf("%-30s %-30s %-30d\n", item->title,item->genre, item->rating);
item = item->next;
}
}
int getNum(void)
{/* the array is 121 bytes in size; we'll see in a later lecture how we can improve this code */
char record[121] = { 0 }; /* record stores the string */
int number = 0;
/* NOTE to student: indent and brace this function consistent with your others */
/* use fgets() to get a string from the keyboard */
fgets(record, 121, stdin);
/* extract the number from the string; sscanf() returns a number
* corresponding with the number of items it found in the string */
if (sscanf(record, "%d", &number) != 1)
{
/* if the user did not enter a number recognizable by
* the system, set number to -1 */
number = -1;
}
return number;
}
void eliminateEndOfLine(char* buffer)
{
char* target = strchr(buffer, '\n');
if (target != NULL)
{
*target = '\0';
}
}
void freeAll(movieInfo* head)//This function frees the head
{
movieInfo* curr = NULL, * next = NULL;
curr = head;
// traverse the list, being careful to not access freed blocks
while (curr != NULL)
{
// keep a pointer to the next block so we can go there after it's freed
next = curr->next;
free(curr);
curr = next;
}
}
Read carefully what strncpy does, e.g. at https://en.cppreference.com/w/c/string/byte/strncpy.
If, after copying the terminating null character from src, count is not reached, additional null characters are written to dest until the total of count characters have been written.
So if for instance title is 12 characters long, then 13 bytes will be allocated for newBlock->title, but strncpy(newBlock->title, title, 30) will write a full 30 bytes into that 13-byte array, thus overflowing it.
There is a separate bug if title is more than 30 characters long. Say it's 50. In this case you have allocated a full 51 bytes, but strncpy will only copy 30, and moreover:
If count is reached before the entire array src was copied, the resulting character array is not null-terminated.
As such, later attempts to call strcmp on the created string are likely to crash and/or give incorrect results.
Since you have allocated enough space to hold the entire string, there is no reason to cut it off at 30 characters. It is safe to just do strcpy(newBlock->title, title); which will fix both bugs and avoid unnecessary truncation to boot. If you really want to limit the title to 30 characters, then check its length when it is first input.
This recent answer has some good advice on using strncpy, i.e. "don't". Avoiding buffer overflows is important but strncpy isn't a very good solution.
One more bug is that you've forgotten to fill in newBlock->rating.
I need to create a circular doubly linked list with a sentinel node which is supposed to read data from a file and insert it in the list, than perform some operations with it. For now I'm stuck on a simple print function which won't print from a list for some reason. The data in the file is in the form of strings,
example: "Popular Sorting Algorithms,
Bubble Sort, Merge Sort, "empty line", etc
Here is my code so far:
Header file contains:
typedef struct NODE {
struct NODE *prev;
char *value;
struct NODE *next;
} NODE;
typedef struct LIST {
int count;
struct NODE *next;
struct NODE *prev;
} LIST;
int InsertEnd(NODE *head, char * value, int *lineCount);
void printLines(int *lineCount);
void Traverse(NODE *head);
Main contains:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "header.h"
int main()
{
int lineCount = 0;
NODE *head;
head = (NODE *)malloc(sizeof(NODE)); /* creates head node dynamically */
head->next = NULL; /* points to first element */
head->prev = NULL; /* points to last element */
head->value = "HEAD"; /* not needed, but it was pretty useful when debugging */
//*********BEGIN OF OPEN FILE FUNCTION
FILE* fp;
char *fname = NULL;
fname = (char *)malloc(200); <<<<<===== I would prefer to set the size dynamically adjusting but I dont know how
printf("Reading file input.txt\n");
//Checks if the file us unable to be opened, then it shows the error message
if ( !(fp = fopen("input.txt", "r")))
{
printf("\nError, Unable to open the file for reading \n");
exit(100);
}
//*********BEGIN OF READ FROM FILE FUNCTION
while (!feof(fp))
{
fgets(fname, 150, fp); //reads the file and stores in buffer
fname[strlen(fname) - 1] = '\0'; // reduces empty strings for input
if (fname != '\0')
{
InsertEnd(head, fname, &lineCount);
//printf("%s\n", head->next->value); <<<<==== If uncomment this print function would work properly but only in this context
}
else
{
printf("Error'\n"); // For debugging
}
}
Traverse(head); // Print Function Should Be Working in Here
printf("Debugging print\n");
printLines(&lineCount); // Shows Line Count
return 0;
}
// Function inserts a new node at the end of the LIST
int InsertEnd(NODE *head, char * value, int* lineCount)
{
int lineCounter = *lineCount;
/* create new node */
NODE *newnode;
newnode = (struct NODE *)malloc(sizeof( struct NODE));
newnode->value = value;
/* placing new node in LIST */
if (head->next == NULL) /* LIST was empty */
{
newnode->next = head;
newnode->prev = head;
head->next = newnode;
head->prev = newnode;
lineCounter++; // Increment line counter
}
else /* LIST wasn't empty */
{
newnode->next = head;
newnode->prev = head->prev;
head->prev->next = newnode; /* adjust node that was previously last */
head->prev = newnode; /* adjust head node */
lineCounter++; // Increment line counter
}
*lineCount = lineCounter;
return lineCount;
}
// This function prints how many lines there are in the LIST, but I need to get rid of the empty spaces
void printLines(int *lineCount)
{
printf("Line counter is %d", *lineCount); // Shows the number of lines, but doesn't skip empty ones.
}
void Traverse(NODE *head)
{
NODE *current = head;
printf("Forward:");
while (current!= head->prev)
{
printf("%s \n", current->value);
current = current->next;
}
printf("\n");
}
Therefore, I have several problems so far:
1) I need to get rid of empty strings in my list most likely. What would be a better approach, to get rid of them while reading or just not displaying when printing? How would I do this exactly?
2) How can I fix my print(traverse) function and whats wrong there?
3) Additionally all of this should be going on through the menu manager which would prompt for a command ( I got this right I think). But there are some functions that I don't know how to implement. For example when used hits "I" it should call Insert functions and prompt the user to enter two more values and , and later insert at the appropriate . How would I do that? Example "I 1 8"
4) Similarly to the previous one, there should be List function which should print lines between specific values. User input format should be "L to " list inclusively. Example "L 2 5"
5) Similarly to previous there should be a delete function with the format "D " inclusively. Example "D 3 7"
6) And the very last is the Save function in the format "S " Example "S output.txt"
Thank You for the help!
I see at least these issues in your code,
In main()
if (fname != '\0')
this should be
if (fname[0] != '\0')
In InsertEnd()
newnode->value = value;
should be
newnode->value = strdup(value);
In you code there should be some correctness which is very help full first as per your request you need to allocate buffer dynamically but not know file length so it can be achived by this one
int sz;
printf("Reading file input.txt\n");
//Checks if the file us unable to be opened, then it shows the error message
if ( !(fp = fopen("sample.txt", "r")))
{
printf("\nError, Unable to open the file for reading \n");
exit(100);
}
fseek(fp, 0L, SEEK_END);
sz = ftell(fp);
printf("size of file %d\n",sz);
fname = (char *)malloc(sz);
rewind(fp);
Now for reading content from file you checked fname to \0 which is not correct i corrected your while..loop.
while (!feof(fp))
{
if(fgets(fname,256, fp) != 0)
{
fname[strlen(fname) - 1] = '\0'; // reduces empty strings for input
InsertEnd(head, fname, &lineCount);
}
else
{
printf("Error'\n"); // For debugging
}
}
I am working on a problem in the K&R book (#6.3) where the user inputs a sequence of words, and you have to create a list of these words along with the lines that each one appears on. It's supposed to involve structures so these are the ones I have right now:
struct entry {
int line;
int count;
struct entry *next;
};
struct word {
char *str;
struct entry *lines;
struct word *next;
};
static struct word *wordlist = NULL; // GLOBAL WORDLIST
However when I input something and the program tries to add a new entry to the structure (which is somewhat like a linked list), there is a problem and the program terminates with no error message. Code for that:
void add_entry(char *word, int line)
{
if (word == NULL || line <= 0 || is_blocked_word(word))
return;
struct word *w;
for (w = wordlist; w != NULL && w->next != NULL && !strcmp(w->str, word); w = w->next);
// If word is found in the wordlist, then update the entry
if (w != NULL) {
struct entry *v;
for (v = w->lines; v != NULL && v->next != NULL && v->line != line; v = v->next);
if (v == NULL) {
struct entry *new = (struct entry*) malloc(sizeof(struct entry));
new->line = line;
new->count = 1;
new->next = NULL;
if (w->lines == NULL)
w->lines = new;
else
v->next = new;
}
else v->count++;
}
// If word is not found in the word list, then create a new entry for it
else {
struct word *new = (struct word*) malloc(sizeof(struct word));
new->lines = (struct entry*) malloc(sizeof(struct entry));
new->next = NULL;
new->str = (char*) malloc(sizeof(char) * strlen(word));
new->lines->line = line;
new->lines->count = 1;
new->lines->next = NULL;
strcpy(new->str, word);
// If the word list is empty, then populate head first before populating the "next" entry
if (wordlist == NULL)
wordlist = new;
else
w->next = new;
}
}
The program terminates even after adding just the first word to wordlist. This is on the line that says if (wordlist == NULL) wordlist = new; where new contains the pointer to a valid structure that I malloc'ed. How can this be possible?
As far as I know it's a problem with my pointer usage but I'm not sure where exactly it lies. Can someone help?
Some fairly evident, and some not-so-evident things.
The for-loop limit for w stops one short
for (w = wordlist; w != NULL && w->next != NULL && !strcmp(w->str, word); w = w->next);
This will start with the first and continue until
We have run out of nodes
We have almost (one short) run out of nodes.
The word in the current node does NOT match
Almost the same problem, different for-loop
for (v = w->lines; v != NULL && v->next != NULL && v->line != line; v = v->next);
As above, this has similar attributes (but not the third option, as this correctly continues so long as the line numbers do not match. The prior loop broke as soon as any word did not match.
And that is in the first ten lines of this function.
String allocation size fails to account for the nulchar terminator
This falls short by one char of the allocation size needed for a zero-terminated string:
malloc(sizeof(char) * strlen(word))
You always need space for the terminator. The easiest way to remember that is to consider how many chars are needed for a zero-length C string? Answer: one, because the terminator needs to go somewhere. After that is simply length+1
One possible way to do this is via a pointer-to-pointer approach, shown below:
void add_entry(const char *word, int line)
{
if (word == NULL || line <= 0 || is_blocked_word(word))
return;
struct word **pp = &wordlist;
for (; *pp && strcmp((*pp)->str, word); pp = &(*pp)->next);
if (*pp)
{
// search for matching line number
struct entry **vv = &(*pp)->lines;
for (; *vv && (*vv)->line != line; vv = &(*vv)->next);
if (!*vv)
{
*vv = malloc(sizeof(**vv));
if (!*vv)
{
perror("Failed to allocate line entry.");
exit(EXIT_FAILURE);
}
(*vv)->count = 1;
(*vv)->line = line;
(*vv)->next = NULL;
}
else
{ // found an entry. increment count.
(*vv)->count++;
}
}
else
{ // no matching word. create a new word with a new line entry
size_t len = strlen(word);
*pp = malloc(sizeof(**pp));
if (!*pp)
{
perror("Failed to allocate word entry.");
exit(EXIT_FAILURE);
}
(*pp)->lines = malloc(sizeof(*(*pp)->lines));
if (!(*pp)->lines)
{
perror("Failed to allocate line count entry.");
exit(EXIT_FAILURE);
}
(*pp)->str = malloc(len + 1);
if (!(*pp)->str)
{
perror("Failed to allocate word string entry.");
exit(EXIT_FAILURE);
}
(*pp)->lines->count = 1;
(*pp)->lines->line = line;
(*pp)->lines->next = NULL;
(*pp)->next = NULL;
memcpy((*pp)->str, word, len+1);
}
}
How It Works
In both cases, we use a pointer-to-pointer. They are a most-hand construct when the desire is to perform tail-end insertion on a linked list without having to keep a "one-back" or "previous" pointer. Just like any pointer, they hold an address. Unlike a regular pointer-to-something, a pointer-to-pointer-to-something holds the address of another pointer. With it we can "loop" by initially setting it to the address of the head pointer, the entering the search.
struct word **pp = &wordlist;
for (; *pp && strcmp((*pp)->str, word); pp = &(*pp)->next);
Here we start with the address of our head pointer. the loop will terminate if the pointer at the address held in pp is NULL, or if the word actually matches. Otherwise it sets the address of (not the address in) the next pointer of the current node.If we run out of words and never find a match the loop will break, but with a most-handy consequence: pp contains the address of the pointer that we need to set to the new allocation. If the list were initially empty, it contains the address of the head pointer.
With that, we can then do this:
if (*pp)
{
// search for matching line number
struct entry **vv = &(*pp)->lines;
for (; *vv && (*vv)->line != line; vv = &(*vv)->next);
Notice we use the same idea on the line-entry list. Either we're going to find an entry, or the loop will exit with *vv being NULL, and vv contains the address of the next pointer we want to set to our new allocation.
I strongly urge you to step through this code in a debugger line-by-line, and understand how it works. utilizing this technique has many redeeming qualities, among them the incredibly brief method of populating a forward-linked list in O(n) complexity without having to check for a head pointer or walking the list for each insertion and retaining the original order (as opposed to reversing the order as a stack-like solution would result):
struct node *head = NULL;
struct node **pp = &head;
while (get-data-for-our-list)
{
*pp = malloc(sizeof(**pp));
// TODO: populate (*pp)->members here
pp = &(*pp)->next;
}
*pp = NULL;
I have this function "load" where I read words from a dictionary and put them in an hashtable of linked lists. When I try to read a line and save it in my new_node->text the compiler returns SEGMENTATION FAULT and I don't know why. The error apperars when I use strncpy.
#define HASHTABLE_SIZE 76801
typedef struct node
{
char text[LENGTH+1];
//char* text;
//link to the next word
struct node* next_word;
}
node;
node* hashtable[HASHTABLE_SIZE];
bool load(const char* dictionary)
{
FILE* file = fopen(dictionary,"r");
unsigned long index = 0;
char str[LENGTH+1];
if(file == NULL)
{
printf("Error opening file!");
return false;
}
while(! feof(file))
{
node * new_node = malloc(sizeof(node)+1000);
while( fscanf(file,"%s",str) > 0)
{
printf("The word is %s",str);
strncpy(new_node->text,str,LENGTH+1);
//strcpy(new_node->text,str);
new_node->next_word = NULL;
index = hash( (unsigned char*)new_node->text);
if(hashtable[index] == NULL)
{
hashtable[index] = new_node;
}
else
{
new_node->next_word = hashtable[index];
hashtable[index] = new_node;
}
n_words++;
}
//free(new_node);
}
fclose(file);
loaded = true;
return true;
}
Let's look at your code line by line, shall we?
while(! feof(file))
{
This is not the right way to use feof - check out the post Why is “while ( !feof (file) )” always wrong? right here on StackOverflow.
node * new_node = malloc(sizeof(node)+1000);
Hmm, ok. We allocate space for one node and 1000 bytes. That's a bit weird, but hey... RAM is cheap.
while( fscanf(file,"%s",str) > 0)
{
Uhm... another loop? OK...
printf("The word is %s",str);
strncpy(new_node->text,str,LENGTH+1);
//strcpy(new_node->text,str);
new_node->next_word = NULL;
index = hash( (unsigned char*)new_node->text);
Hey! Wait a second... in this second loop we keep overwriting new_node repeatedly...
if(hashtable[index] == NULL)
{
hashtable[index] = new_node;
}
else
{
new_node->next_word = hashtable[index];
hashtable[index] = new_node;
}
Assume for a second that both words hash to the same bucket:
OK, so the first time through the loop, hashtable[index] will point to NULL and be set to point to new_node.
The second time through the loop, hashtable[index] isn't NULL so new_node will be made to point to whatever hashtable[index] points to (hint: new_node) and hashtable[index] will be made to point to new_node).
Do you know what an ouroboros is?
Now assume they don't hash to the same bucket:
One of the buckets now contains the wrong information. If you add "hello" in bucket 1 first and "goodbye" in bucket 2 first, when you try to traverse bucket 1 you may (only because the linking code is broken) find "goodbye" which doesn't belong in bucket 1 at all.
You should allocate a new node for every word you are adding. Don't reuse the same node.
Here, I am trying to read the contents of a file line by line and create a struct for each line. The problem is when I print the list of words, every single one of them is the last word of the file (which is } in this sample). I believe since line changes frequently and I pass a pointer to a char, value of every struct changes as well. I've been trying to fix this problem for nearly a day without any luck. What's a good way to read every word into a struct and link each struct to the linked list?
Note that there are some helper methods used below. I've tested them multiple times and they are working.
Token struct
typedef struct token
{
char* value;
struct token* next;
}TOKEN;
File content
target1:
dependency1
{
command1,
command2
}
Main
TOKEN *head = NULL;
// represents each formatted line from the script file
char* line = malloc(161*sizeof(char));
FILE* fileRead = openFile("RawRules.txt", "r");
while((line = readLine(line, fileRead)) != NULL)
{
head = add(head, line);
}
displaylist(head);
freeNodes(head);
fclose(fileRead);
Add function Modified from http://cprogramminglanguage.net/singly-linked-list-c-source-code.aspx
TOKEN* add(TOKEN *head, char* value){
TOKEN *tmp;
if(head == NULL){
head=(TOKEN *)malloc(sizeof(TOKEN));
if(head == NULL){
printf("Error! memory is not available\n");
exit(0);
}
head-> value = value;
head-> next = head;
}else{
tmp = head;
while (tmp-> next != head)
tmp = tmp-> next;
tmp-> next = (TOKEN *)malloc(sizeof(TOKEN));
if(tmp -> next == NULL)
{
printf("Error! memory is not available\n");
exit(0);
}
tmp = tmp-> next;
tmp-> value = value;
tmp-> next = head;
}
return head;
}
readline function
// reads a line of a file into buffer
char* readLine(char* buffer, FILE* file) {
buffer = fgets(buffer, 161, file);
return buffer;
}
This did not fix the problem either
while(true)
{
char* ll = malloc(161*sizeof(char));
ll = readLine(ll, fileRead);
f(ll != NULL)
head = add(head, ll);
else
break;
}
Sorry, I progammed in C like billion years ago, so call me a noob!
In the add() function, you're simply assigning a char *, rather than allocating any new memory (and then copying) for each string. So each TOKEN ends up pointing at the original buffer. As you're using a single buffer at the top-level, you're overwriting it over and over again.
In short: You need a separate buffer for each line. One way (not necessarily the best way) is to do the following inside add():
int len = strlen(value);
...
tmp->value = malloc(len+1); /* +1 for null terminator */
strncpy(tmp->value, value, len+1);
Remember that at some point, you'll need to free() all of these extra buffers.