I have tested both the addNode function and the printf loop with different lists and they work fine. But something is wrong with this one because when I print the list it rints the head and then all the other words are the same with the last given from the user.
This is the addnode(the word is given from the user-I checked it, it works fine)
struct list* addNode(struct list* head, char *word){
struct list *curr,*help,*Nhead;
curr=(struct list *)malloc(sizeof(struct list));
curr->sorted=head->sorted;
if(curr->sorted==false){
Nhead=head;
while(head->next!=NULL){
head=head->next;
}
curr->data.word=word;
curr->prev=head;
curr->next=NULL;
head->next=curr;
}
else{
Nhead=head;
for(help=head; help!=NULL; help=help->next){
if(strcmp(word,help->data.word)<0){
break;
}
}
if(help==NULL){
for(help=head; help->next!=NULL; help=help->next){}
curr->next=NULL;
curr->data.word=word;
curr->prev=help;
help->next=curr;
}
else{
curr->next=help;
curr->prev=help->prev;
curr->data.word=word;
help->prev=curr;
if(help!=head){
help=curr->prev;
help->next=curr;
}
else{
Nhead=curr;
}
}
}
return Nhead;
}
and this is how i print
for(curr=pathWordsH; curr!=NULL; curr=curr->next){
printf("%s",curr->data.word);
if(curr->next!=NULL){
printf("-->");
}
}
You don't show how you read in the words, but I guess this is what happens:
When you take input from the user, you probably use the same char buffer. You assign that char buffer to your list node's word and it holds the current word while you're constructing the list. After you are done, all nodes reference the same char buffer, whose contents are the last word the user provided.
You should therefore copy the contents instead of assigning pointers. There are basically two ways of doing this: Either allocate memory to list->word for each node or make the word entry a fixed-size buffer.
The (non-standard, but widely available) function strdup duplicates a string on the heap. So instead of assigning the pointer
curr->data.word = word;
assign a copy of the contents:
curr->data.word = strdup(word);
Because you have allocated extra memory, you should free the memory in word when you destroy a list node.
Related
I have a code that sorts a list, I can get it to sort when the list is hardcoded. I am now attempting to implement getting the list from an input file and running it the same way through the code then printing it to an output file. I am trying to get a scanned list from an input file to go through what I have (that is working) for sorting and for the result to be printed to an output file.
You have assigned *tmp to head. But I can see that head had always been NULL. So the loop is never entered, and nothing is being inserted to the list.
So what we'd need to do it first initialize head to a node instance
typdef struct node
{
char* data;
struct node *prev;
struct node *next;
}node;
head = malloc(sizeof(node));
then we assign it data.
head->attribute = value;
finally we set this pointer location value to our tmp pointer as well.
tmp = head;
no we can proceed with our loop
strings in C are represented as an array of chars, whose stored location points to the first element of the char array. the array must also end with a NULL chat '\0'. note that strlen(str) will return length of string without the NULL char so you must add 1 while mallocing to take this into sconsideration. i would advise not messing with strings unless absolutely necessary. by that I mean trying to manually manipulate them. this will introduce another set of problems not related to what we're working on in general. we should just use strncar(), strncpy() methods until c style strings become completely intuitive.
I hope I understood right your question. I tried to fix the program like it will read a file and make a list of the data in the file.
I fixed some issues;
For the transverse function, i added a for loop and printed the data using %c.
while (temp != NULL) {
for(i=0; temp->data[i]!='\0'; i++) {
printf("%c\n", temp->data[i]);
}
temp = temp->next;
}
I changed the insertAtEnd function like this;
void insertAtEnd(FILE* f, char* data)
And naturally, in main function, calling this function changed like;
insertAtEnd(ifp, result[i]);
By the way for the following statement, my complier wanted me to express the temp as char, it said it was the first use of this. It also seems like you entered a space after &.
insertAtEnd(ofp, &temp);
I added the following statements to the main function;
argc -= optind;
argv += optind;
I also changed this ifp= fopen(ifilename, "r"); statement with this ifp= fopen("ifilename.txt", "r");statement. I opened a text file named ifilename.txt and wrote some data there.
EDIT:
Ok so if you want to print the strings to an output file and you want to print the words in the lines individually, you will change the code doing the following things:
I changed the struct's data with an array, gave it an expected maximum line length with a sharp defined MAX_LEN;
struct node
{
char* data[MAX_LEN];
struct node *prev;
struct node *next;
};
I changed the insertAtEnd function again because I scanned the file in main function, made an array of the strings, sent it to this function and added it to the end of the list. I used this piece of code in main fuction:
char* result[count];
char* temp = (char*)malloc(sizeof(char));
while (fgets(temp, sizeof(temp), ifp))
{
result[count] = (char*)malloc(sizeof(char)*20);
strcpy(result[count], temp);
insertAtEnd(result, count);
count++;
}
count is the number of strings in the file. I also sent this number to insertAtEnd function;
void insertAtEnd(char* data[], int size)
{
//Create a new node
struct node *newnode = (struct node*)malloc(sizeof(struct node));
newnode->data[size] = data[size];
if (newnode->data[size] != NULL) {
...
I wanted to use the output file you opened in the main function, so I sent this file and sent the count -number of strings- to the printing function transverse like this;
void traverse(FILE *of, int size)
{
int i;
// List is empty
if (head == NULL) {
printf("\nList is empty\n");
return;
};
// Else print the Data
struct node* temp;
temp = head;
while (temp != NULL) {
for(i=0; i<size; i++) {
fputs(temp->data[i], of);
temp = temp->next;
}
fprintf(of, "\n");
}
}
Also in main function, calling this function will be changing like;
traverse(ofp, count);
I am having problem storing all the values into the Generic LinkedList, my linkedlist works totally works on a normal user Keyboard input but when I try to store values(strings) from a file, there is something weird happening, it only store the last value of the file.
I have checked my addToList() function but theres nothing wrong with it.
P.s But I am feeling its either I am printing wrong or my reading from the file into the linkedlist is wrong.
Thank you.
#include<stdio.h>
#include <stdlib.h>
#include<string.h>
#include "LinkedListItems.h"
#define MAX 10000
int main()
{
printf("Testing MissileFIle.txt");
void* secondStr;
//Had to malloc the thing
secondStr = (void*)malloc(1*sizeof(char));
FILE* missileFile;
missileFile = fopen("missiles.txt", "r");
if(missileFile == NULL)
{
printf("The file is empty");
}
number_list_t* missileList = calloc(1, sizeof(number_list_t));
void* input;
//Have to allocate the input
input = malloc(1*sizeof(void*));
//this is to read the data into the second Str
while(fgets(secondStr,MAX,missileFile) != NULL)
{
//Let just print out first just to test my memory
printf("%s\n",secondStr);
//Right now its only reading one string so far which is really weird AFFFFF
addTolist(missileList,secondStr);
}
//Gotta declare another list just to print out the list
number_node_t* current = missileList->head;
while(current != NULL)
{
//There is something wrong with this line
printf("%s\n",current-> number);
current = current-> next;
}
fclose(missileFile);
}
OUTPUT:
Testing MissileFile.txt
splash
single
V-line
h-line
Single
Single
Single
Single
Single
Single
typedef struct NumberNode
{
//It can store any data type
void* number;
struct NumberNode* next;
}number_node_t;
//List of Nodes
typedef struct NumberList
{
number_node_t* head;
int count; //This is not nesssary but it can be useful for counting how many variables
}number_list_t;
void addTolist(number_list_t* list, void* newNumber)
{
//tem[ = newNode]
number_node_t* newNode = calloc(1,sizeof(number_node_t));
newNode->number = newNumber;
newNode->next = list->head;
list->head = newNode;
}
INPUT DATA:
single
splash
single
V-Line
h-line
Single
The way you have implemented this, it cannot work.
The main problem, among many, is related to the void* pointers which cannot be dereferenced.
The size of elements should be given, either on creating the list in which case all elements are of the same type, or separately for each individual element. You can check out this question for an example of something that could work.
As far as the buffer thing is concerned, addToList should allocate new memory for each newNumber. What you are currently doing results in all data of the list pointing to a specific space in memory (the one allocated to secondStr). Each time you change the content of that memory space, all elements in the list are affected. This is why you print the same value for all elements and more specifically the last value in your file.
The way you allocate memory is also not really ok, same goes for the way you open your file, there is memory leaking etc. I am not going into details.
At least this issue:
Copy the string
OP's goal includes the need to copy the string from the read buffer to the list, not just copy the buffer pointer.
// void addTolist(number_list_t* list, void* newNumber) {
void addStringTolist(number_list_t* list, const char *s) {
// number_node_t* newNode = calloc(1,sizeof(number_node_t));
number_node_t* newNode = calloc(1, sizeof *newNode); // todo: add error check
size_t sz = strlen(s) + 1;
newNode->number = malloc(sz); // todo: add error check
strpy(newNode->number, s);
newNode->next = list->head;
list->head = newNode;
}
Note: When freeing the list, newNode->number also needs to be free'd.
regarding:
while(fgets(secondStr,MAX,missileFile) != NULL)
MAX is defined as 10000 but secondStr is defined as pointer to one byte. so when this is executed, a buffer overflow occurs.
This is undefined behavior and probably the root of the problem with reading from a file
So I'm trying to understand how a linked list works with storing string type pieces of data. As far as I know, a linked list uses a data structure to store data in a somewhat fashionable way so you can easily enter new pieces of data inside, remove them, and rearrange them as you please. My problem is, I need to take a string in from the user, assign it a spot in the linked list and move on to the next node in the list and do the same thing again. At this point however, I'm simply trying to take one string from the user, store it in the new_node value, (or (*new_node).value for those of you thinking in terms of pointers and not linked lists) and print it out. The main just asks the user for a string input, the add_to_list func takes the input and adds it to the beginning of the linked list, and the print func simply prints what ever is in the linked list. Where the problem lies in my understanding (at least what I think is the problem) is the point at which I assign the data structure the value of the input, new_node->value=*n should just make the value contain the input string as it would just giving another array the value of whatever the pointer *n is containing, unfortunately that's not the case and I'm not sure why that is. Here's the code for simplicity's sake.
EDIT: Thanks everyone for the responses and the explanation behind why strcpy is necessary when dealing with assigning the value of an array of characters to another array ie: strings!
#include <stdio.h>
#include <stdlib.h>
#define LARGE 10
struct node *add_to_list(struct node *list, char *n);
struct node{
char value[LARGE+1];
struct node *next;
};
struct node *first = NULL;
void print(void);
int main(void) {
char job[LARGE],*p;
printf("Please enter printing jobs\n");
scanf ("%s", job);
p=&job[0];
first = add_to_list(first, p);
print();
return 0;
}
struct node *add_to_list(struct node *list, char *n)
{
struct node *new_node;
new_node = malloc(sizeof(struct node));
if (new_node == NULL) {
printf("Error: malloc failed in add_to_list\n");
exit(EXIT_FAILURE);
}
new_node->value = *n;
new_node->next = list;
return new_node;
}
void print(void){
struct node *new_node;
for(new_node=first;new_node!= NULL; new_node=new_node->next){
printf("%s\n",new_node->value);
}
}
Use strcpy instead of assigning a char to an array, which doesn't compile. Arrays are not lvalues, and cannot be assigned to without subscripting, so any assignment with an array name by itself on the left will not compile. Change
new_node->value = *n;
to
#include <string.h>
...
strcpy(new_node->value, n);
you cannot assign string as normal integer assignment.
whenever you want to copy a array you have to use library functions like memcpy or strcpy. In your case its array of characters i.e string you have to use strcpy.
usage char *strcpy(char *dest, const char *src);
so in your code it has to be like strcpy(new_node->value,n); instead of new_node->value=*n;
Reason for using strcpy is mentioned in the link below
why strcpy function
I have numbers in a linked list which i am supposed to convert to char* and return .
Here is is the function where the problem probably exists.
char* int_str(struct Node** head,char* result) //head is pointer to singly linked list
{
struct Node* temp = *head;
char* string1="";
char* str;
while(temp != NULL)
{
string1=myitoa(temp->data,string1); // myitoa() works fine
str=(char*)malloc(1+strlen(string1));
strcpy(str,string1);
strcat(result,str);
temp=temp->next;
}
return result;
}
The last call to temp->data always ends up having unknown garbage values . (The linked list is built correctly as printing the linked list works properly.)
Example : the linked list is 1->2->3
The last call to temp->data in the function gives 50(some garbage value)
ie 1->2->50
while in the main function the list correctly gives 1->2->3
The last variable ends up as garbage in this function but shows correctly in main function why ?
char* string1;
This declares a pointer but does not allocate a buffer for the string. It's a bit confusing that this uninitialized pointer is passed to myitoa, because myitoa can not do anything with it without causing undefined behaviour.
This line always allocates 5 bytes on 32 bit systems:
str=(char*)malloc(1+sizeof(string1));
sizeof(string1) is the size of the pointer, not of the string. Use
str=(char*)malloc(1+strlen(string1));
instead, or, even better, use
str=malloc(1+strlen(string1));
because the result of malloc should not be casted.
This piece of code will most probably do the job. There is no need to malloc. str is defined as an array of 20 chars. This is where the number in ASCII is stored.
char* int_str(struct Node** head,char* result) //head is pointer to singly linked list
{
struct Node* temp = *head;
char str[20];
while(temp != NULL)
{
strcat(result, myitoa(temp->data, str));
temp=temp->next;
}
return result;
}
I don't think that the problem lies in string manipulations. Most probably it is related to the creation of linked list. Try this:
First of all, try printing the value of temp->data in the loop. Possibly it should be garbage (in which case the list creation contains problem). If the printed value is correct, then check if the "result" string which is being returned, holds the same value or not. If not, then the problem is in myitoa function.
Here I am assuming that myitoa is allocating memory to string1.(if not, then you have to allocate some memory to it either before passing it to function or inside myitoa.
Disclaimer: This is a homework problem. As should be evident, I am trying to solve it myself. I seem to have hit a problem I am unable to figure out, so some help would be appreciated.
I am required to hash a set of words, and insert it into an array of linked lists. So, if 3 different words have the hash 38, at array[38], I need to have a linked list with the 3 words.
I am using this struct
struct Word {
char* word;
struct Word* next;
};
After I hash, I insert it into the array like this:
struct Word* table[1000]; // array of linked-lists
char word[128];
while(fgets(word, sizeof(word), dict) != NULL) {
hashValue = hashWord(word, strlen(word));
struct Word *newWord = malloc(sizeof(struct Word));
newWord->word = word;
if (table[hashValue] == NULL) {
table[hashValue] = newWord;
} else { // at index hashValue, table already contains at least one element
// insert new word as first element of linked-list
newWord->next = table[hashValue];
table[hashValue] = newWord;
}
}
I know there are about 5 words that have a hash of 38, but when I print them, I get the same word 5 times:
struct Word* foo = table[38];
while (foo->next != NULL) {
printf("%s", foo->word); // prints the same word every time
foo = foo->next;
}
It seems I am overwriting my linked list at some point, but I cannot figure out where.
while(fgets(word, sizeof(word), dict) != NULL) {
...
newWord->word = word;
The problem is that you're replacing the contents of word, which is the same pointer stored in every newWord.
You're allocating a new Word structure on the heap each time with this line:
struct Word *newWord = malloc(sizeof(struct Word));
But this only allocates memory for the Word structure itself; the Word structure includes a char *word—i.e. a pointer to a character (or NUL-terminated string, in this case), but it doesn't actually include any space for the string itself.
You need to explicitly allocate memory for the string, now. Try this:
newWord->word = strdup(word);
This will put a copy of word into each Word structure. This copy won't be overwritten when fgets() next gets called in your while loop. Remember that the stack-allocated character array:
char word[128];
is only valid while this function is executing; you must allocate something on the heap (with malloc(), or something that uses it, like strdup()) if you want it to live beyond the function call.
When you're finished, don't forget to free() the char *words before freeing each Word*.
You're overwriting the word array. You are only storing pointers to the array, but the array gets overwritten with each new word. You need separate memory to hold each word.