linked list built but not working properly - c

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.

Related

Traversing C pointer list: weird printf behaviour

I declared a linked list implemented in C as follows:
struct node_List {
int i;
char * name;
struct node_List* next;
};
typedef struct node_List nodeList;
Then I declared the list head globally as:
nodeList list; // head of the list - does not contain relevant data
Finally, I have a function id(char * s) with a string s as th only argument.
nodeType id(char *s)
{
nodeType *p; // another List type
if ((p = malloc(sizeof(nodeType))) == NULL) {
// error: out of memory;
}
nodeList * node = &list;
// printf(" ");
while (node->next != NULL){
node = node->next;
if (strcmp(node->name, s) == 0){
// printf(" ");
// assign node to an attribute in p
return p;
}
}
// error: not found;
}
The problem is, when i run this program and call foo("somestring") the program executes the error: not found part and aborts execution, despite the string somestring being in the list.
I tried executing the very same program by inserting some printf() for debugging purposes, and it works perfectly, except it prints additional characters along with the output.
This happens each time I add some print lines, e.g. if I uncomment the two printf()s which I wrote in the example above (one of them or both, i get the same successful result). It doesn't work though if the printf is called with no arguments or with an empty string "".
I can't figure out what's happening, I double-checked the list creation and population functions and I am totally sure they work correctly. I tried changing the while break condition, but that didn't work, too. I have observed a similar behaviour on both Linux (with gcc) and Windows (using CodeBlocks editor's integrated compiler)
How could a printf directive affect a program so much?
EDIT: This code is part of a syntax analyzer written in Yacc. The whole code can be found below. It's a long read, and it is not completed, but the code above was tested and used to work as explained.
lexer: http://pastebin.com/1TEzzHie
parser: http://pastebin.com/vwCtMhX4
When looking in the provided source code, the algorithm to explore the linked list has two ways to miss node in the while-loop comparison.
Way 1 - starting only from the second node of the list.
Placing node = node->next; before the comparison will force the first comparison to be &(list)->next instead of &(list).
To start from the first node, simply place node = node->next; after
the comparison.
Way 2 - never ending to the last node of the list.
Using (node->next != NULL) in the while condition will force to exit from the loop before comparing the last node => node->next = NULL;.
To end by the last node, simply change the while condition to (node != NULL).
Solution:
while (node != NULL){ // end from the last node
if (strcmp(node->name, s) == 0){
// printf(" ");
// assign node to an attribute in p
return p;
}
node = node->next; // explore link after comparison
}
The actual error is a wrong type declaration of a variable returned by the function:
nodeType* createPoint(char* l){
nodeList* p;
if((p=malloc(sizeof(nodeList))) == NULL){
yyerror("out of memory");
} else {
// do stuff with p
}
return p;
}
The function return value was a nodeType* and p was instantiated as nodeList*.
The declaration of those two types was pretty simple, that's why the program could work.
the working code can be found here.
The strange behaviour with printf() was probably caused by the heap space needed for printf's arguments: since this function accepts an arbitrary number of parameters, it saves them in a list. This list is instantiated in the heap, there overwriting the old data left there from the wrong implementation of createPoint.

How do you store string type data in a linked list in C?

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

Correct AddNode function but somehing happens when I printf

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.

Same pointer address but different fields

I've been trying to learn C by myself after basic Java knowledge and I'm trying to implement a linked list. I'm running into trouble when making a createList function - a function that's supposed to make an empty list. I'm having a bit of a weird problem with passing pointers though. These are just snippets of the code, and my definitions of the node / list are located in a header file given by a book CD (so that's not the problem)
LList* createList(void){
LList list;
list.first = NULL;
printf("List from mk_list: \nfirst:%d\nlist address:%d\n",list.first,&list);
return &list;
} //This prints 0 and then the address of list
void print_list(LList *list){
printf("\nList from print_List\nFirst%d\nAddress:%d\n", list->first,list);
} //This prints some random non-null address for some reason, but also the
//SAME address as the list from createList. Why does list->first not print as 0?
int main(void)
{
LList*newList = createList();
printf("\nList from main:\nFirst:%d\nAddress:%d\n", newList->first,newList);
print_list(newList);
system("pause");
return 0;
} //Prints same exact thing as the printf in the createList.
return &list;
list resides on stack and its lifetime completes as function returns. So, using a pointer to it invokes undefined behavior.
Create the object on heap.
Here is your problem:
LList* createList(void)
{
LList list;
...
return &list;
}
Variable list is allocated on the stack, whenever you enter the code of function createList.
Whenever this function (or any other function for that matter) is called, the stack is in a different status.
Sometimes it's 75% full, sometimes only 24% (this is just a figure of speech though).
Your local variable is allocated at the next free slot in the stack, so it doesn't have a constant address throughout the lifetime of your program, but only during the execution of the function itself.
Shorty after the function returns, some other local variable might be allocated in the same address.
Hence, there is no point in returning this address, as you are doing in your code.
UPDATE:
One optional solution for you is to declare LList newList in main, and pass &newList to createList instead of returning a value from that function:
void createList(LList* list)
{
list->first = NULL;
printf("List from mk_list: \nfirst:%d\nlist address:0x%X\n",list->first,list);
}
P.S.: You should probably name this function initList instead.

Pointer arithmetic

I created a linked list with ten nodes. I want to get the address of the first node I created in the linked list. I am getting incorrect address value for the first node. This is the code which I wrote :
#include "singlyLinkedList.h"
#include <stddef.h> //for NULL
#include <stdlib.h> //for malloc
#include <stdio.h> //for printf
node *pNode;
void CreateLinkedList()
{
int i;
pNode = (node*)malloc(sizeof(node)); //create space for first node []
for(i=0;i<10;i++)
{
pNode->element = i; //enter value [0]
printf("Value is %d addr is %p\n",pNode->element,pNode);
pNode->nextPtr = (node*)malloc(sizeof(node)); //[0]->[]->NULL
pNode = pNode->nextPtr;
}
pNode->nextPtr=NULL;
}
//Function to get first node address
void GetFirstNodeAddress()
{
pNode = pNode-10*(sizeof(node));
printf("\n *** Value is %p",pNode);
}
int main()
{
CreateLinkedList();
GetFirstNodeAddress();
}
You assume that the 10 malloc's you do will result in 10 consecutive addresses. You handle it as if it is an array, yet the elemenents of the linked list are independent.
The way these linked lists usually work is that you initialise them and keep the first pointer to be returned later. Then grow more elements on the tail. You can not walk backwards in a single linked list.
I gave a code example in an earlier post today
You don't use pointer arithmetic in linked list implementations, at least not trivial ones. And you're populating your list incorrectly. You need to retain the head pointer. This is one such way to do it:
// Note: do NOT invoke on a non-empty pNode list
void CreateLinkedList()
{
node **pp = &pNode;
int i;
for (i=0;i<10;++i)
{
*pp = malloc(sizeof(**pp));
(*pp)->element = i;
pp = &(*pp)->nextPtr;
}
*pp = NULL;
}
How It Works
Just like pNode is a pointer to a node, pp is a pointer to a node *. During the lifetime of the loop pp always holds the address of the next pointer about to be filled with a new node allocation. After the allocation and node setup, pp is filled with the address of the nextPtr pointer of the node just-created. This continues until the end of the fill. At that point the pointer addressed by pp is the tail nextPtr and should be null-terminated (which is what *pp = NULL does). Step through this code in a debugger to see better how it works.
Personally I would pass the address of the head pointer as a parameter, but this is one immediate way to get your code running.
Try printf("\n *** Value is %p",(void *) &pNode);. & is typically the easiest way to get pointer addresses
also from what I know: pNode = pNode-10*(sizeof(node)); is incorrect.
when you are doing pointers, they point to areas in memory that are not necessarily contiguous (following in order in memory). Meaning you could have one pointer pointing to memory blocks 5-10, which also has a pointer to memory blocks 83-88. If you want to get the first node, create a pNode rootNode and assign your first created pNode to that. Then you can traverse it in a while loop as well as printing out the address as listed above or whatever else you please.

Resources