473,396 Members | 2,050 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Linked-list's different insertions, help

friends,
I wanted to learn the various ways of inserting a single list. so:
Method 1:

#include<stdlib.h>
#include<stdio.h>
struct node
{
unsigned int data;
struct node *next;
};
void init(void)
{
unsigned int data;
struct node *p;
p= malloc(sizeof *p);
if(p == NULL)
exit(EXIT_FAILURE);
for(data =0;data <10;data++)
{

p->data = data;
p->next = NULL;
printf("%d\n",p->data);
p=p->next;
}
free(&p);
printf("after del =%d\n",p->data);
}

int main(void)
{
init();
return 0;

}

In this method the value is getting printed up to the last printf
statement and throws a runtime error at the end. This method looks
ugly and also wrong.

Method 2:

#include<stdio.h>
#include<stdlib.h>
struct node
{
unsigned int data;
struct node *next;
};

struct node *insert(unsigned int data,struct node **p) /*C's functions
are pass-by-value*/
{
struct node *temp;
temp = malloc(sizeof *p);
if(temp == NULL)
printf("MEM ERROR\n");
temp = *p;
temp->data = data;
temp = temp->next;
temp->next = NULL;
return temp;

}

void disp(struct node **temp) /*C's functions are pass-by-value*/
{
struct node *p;
p=*temp;
while(p->next != NULL)
{
printf("%d\n",p->data);
p=p->next;
}
}

int main(void)
{
struct node *p,*q;
unsigned int data;
p = malloc(sizeof *p);
q= malloc(sizeof *q);
for(data = 0;data<10;data++)
{
p=insert(data,&q);
if(p != NULL)
disp(&p);
else
printf("(ERROR)\n");
}
return 0;
}

In the above method I am not getting any output at all. I am sure the
mistake is with the argument passing but I am unable to sort it out.
Can any body answre the following question:

1)Is there any correct way of insertion in a ls or is it depend on the
situation?
2)Can any one tell me the error I made in the above simple programs?
Nov 13 '05 #1
7 2137
da***********@yahoo.com wrote:
friends,
I wanted to learn the various ways of inserting a single list. so:
Method 1:

#include<stdlib.h>
#include<stdio.h>
struct node
{
unsigned int data;
struct node *next;
};
void init(void)
{
unsigned int data;
struct node *p;
p= malloc(sizeof *p);
if(p == NULL)
exit(EXIT_FAILURE);
You want to put the memory allocation inside the loop to get this
working. for(data =0;data <10;data++)
{

p->data = data;
p->next = NULL;
printf("%d\n",p->data);
p=p->next; The value of p->next is NULL at this point, you invoke undefined
behaviour.
}
free(&p);
printf("after del =%d\n",p->data);
}

int main(void)
{
init();
return 0;

}

In this method the value is getting printed up to the last printf
statement and throws a runtime error at the end. This method looks
ugly and also wrong. Indeed. :-)

Method 2:

#include<stdio.h>
#include<stdlib.h>
struct node
{
unsigned int data;
struct node *next;
};

struct node *insert(unsigned int data,struct node **p) /*C's functions
are pass-by-value*/
{
struct node *temp;
temp = malloc(sizeof *p); You allocated space to hold a pointer to struct node.
if(temp == NULL)
printf("MEM ERROR\n"); You want to bail out here, not only print an error message.
temp = *p; You dropped your reference to the memory you just allocated! temp->data = data; You successfully invoked UB here. temp = temp->next; And again. temp->next = NULL; You successfully invoked UB here. Change this whole section to:

temp = malloc( sizeof **p );
if ( temp == NULL )
{
printf("MEM ERROR\n");
exit( EXIT_FAILURE );
}
temp->data = data;
temp->next = *p;
(*p) = temp;
return temp;
}

void disp(struct node **temp) /*C's functions are pass-by-value*/
{
struct node *p;
p=*temp;
while(p->next != NULL)
{
printf("%d\n",p->data);
p=p->next;
}
} Change this function to:

void disp( struct node *head )
{
for ( ; head != NULL; head = head->next )
printf( "%d\n", head->data );
}

int main(void)
{
struct node *p,*q; You need only one pointer; drop q.
unsigned int data;
You do the memory allocation in insert(), so drop the following two
lines (not to mention you forgot to check the return value of malloc()): p = malloc(sizeof *p);
q= malloc(sizeof *q);
Instead, initialize p to NULL:

p = NULL;
for(data = 0;data<10;data++)
{
p=insert(data,&q);
if(p != NULL)
disp(&p);
else
printf("(ERROR)\n");
}
Insert will change the value of p, so all you have to do is:

for ( data = 0; data < 10; data++ )
insert( data, &p );
disp( p );
return 0;
}

In the above method I am not getting any output at all. I am sure the
mistake is with the argument passing but I am unable to sort it out.
Can any body answre the following question:

1)Is there any correct way of insertion in a ls or is it depend on the
situation? You can insert at the beginning, at the end or at another position,
dending on what you want to do with the list. You can do it like in
the (corrected!) second example, where the insert function changes the
pointer to the first element of the list, or you can do this in the
calling funtion; it's merely a question of style and personal
preference.
2)Can any one tell me the error I made in the above simple programs?

See above.

In C sometimes things are much simpler as one might think. ;-)

Regards

Irrwahn
--
My other computer is a abacus.
Nov 13 '05 #2
On 21 Sep 2003 10:05:28 -0700, da***********@yahoo.com wrote:
friends,
I wanted to learn the various ways of inserting a single list. so:
Method 1:
Unfortunately, this does not build a linked list at all. At no time
does the member next of a struct node point to any other struct node.

#include<stdlib.h>
#include<stdio.h>
struct node
{
unsigned int data;
struct node *next;
};
void init(void)
{
unsigned int data;
struct node *p;
p= malloc(sizeof *p);
if(p == NULL)
exit(EXIT_FAILURE);
for(data =0;data <10;data++)
{

p->data = data;
When data is 0, p contains the value returned by malloc. Storing into
p->data is OK.

As noted below, when data > 0, p contains NULL. Any attempt to
dereference p invokes undefined behavior. On my system, the code
failed after printing 0.
p->next = NULL;
printf("%d\n",p->data);
p=p->next;
Since p->next is NULL, p is also.
}
free(&p);
I don't believe it is ever proper to use the & operator on the
argument to free. By definition, free expects to receive a value
previously returned by malloc (or a related function). p is a defined
variable whose storage is not allocated by malloc. &p is the address
of this storage and is therefore not a malloc generated value.

What you probably want is to store the address of allocated memory in
p and later free this allocation with
free (p);
printf("after del =%d\n",p->data);
After you free p, you are not allowed to dereference it. You cannot
print the value of data after the memory has been freed because the
object no longer exists.
}

int main(void)
{
init();
return 0;

}

In this method the value is getting printed up to the last printf
statement and throws a runtime error at the end. This method looks
As noted above, it should have failed after the first printf. In any
case, you have at least three examples of undefined behavior (one
inside a loop)
Dereferencing a NULL pointer.
Passing an invalid value to free.
Dereferencing a freed pointer.

Any one of them could cause the symptoms you are seeing.
ugly and also wrong.

Method 2:

#include<stdio.h>
#include<stdlib.h>
struct node
{
unsigned int data;
struct node *next;
};

struct node *insert(unsigned int data,struct node **p) /*C's functions
are pass-by-value*/
{
struct node *temp;
temp = malloc(sizeof *p);
temp is a pointer to struct. Therefore you must allocate enough space
to hold this struct. p is a pointer to pointer to struct so *p is
simply a pointer to struct. It is guaranteed that sizeof *p is too
small. You need either sizeof **p or better sizeof *temp.
if(temp == NULL)
printf("MEM ERROR\n");
temp = *p;
You have now thrown away the value that malloc just returned. temp
now points to the struct allocated to q in main.
temp->data = data;
temp = temp->next;
That struct was never initialized in main so any attempt to evaluate
temp->next leads to undefined behavior. If you code survives this,
temp now contains an indeterminate value.
temp->next = NULL;
You have just stepped on some unknown part of memory that temp happens
to point to. More undefined behavior.
return temp;
You pass back the address of some unknown and possibly non-existent
part of memory.

}

void disp(struct node **temp) /*C's functions are pass-by-value*/
{
struct node *p;
p=*temp;
while(p->next != NULL)
{
printf("%d\n",p->data);
p=p->next;
Nowhere is the member next on any struct node ever initialized.
}
}

int main(void)
{
struct node *p,*q;
unsigned int data;
p = malloc(sizeof *p);
q= malloc(sizeof *q);
for(data = 0;data<10;data++)
{
p=insert(data,&q);
if(p != NULL)
disp(&p);
else
printf("(ERROR)\n");
}
return 0;
}

In the above method I am not getting any output at all. I am sure the
mistake is with the argument passing but I am unable to sort it out.
You have many more problems than just the arguments. Before
attempting linked lists, you need a really firm understanding of
pointers
dynamic allocation
passing/returning values to/from called functions
avoiding undefined behavior
Can any body answre the following question:

1)Is there any correct way of insertion in a ls or is it depend on the
situation?
Yes there is at least one (preferred) correct method (algorithm) to
insert items into a linked list. If you have access to Knuth's books
(in most school libraries), that is probably the definitive source.
Most programming books also discuss it since it is a very common
topic. google probably has several on-line references.

On the other hand, how you implement the algorithm may indeed depend
on the situation. That is why program development should start with
design and not with coding.
2)Can any one tell me the error I made in the above simple programs?


I have identified some. You have coding errors, logic errors, and
design errors. I recommend you put the list project on hold for a
while and study the suggested topics first.
<<Remove the del for email>>
Nov 13 '05 #3
Changed code: (not fully)

#include<stdio.h>
#include<stdlib.h>
struct node
{
unsigned int data;
struct node *next;
};

struct node *insert(unsigned int data,struct node **p)
{
struct node *temp;
temp = malloc(sizeof **p);
if(temp == NULL)
{
printf("MEM ERROR\n");
exit(EXIT_FAILURE);
}
else
{

temp->data = data;
temp->next = *p;
temp->next = NULL;
*p = temp;
return *p;
}
return NULL;

}

void disp(struct node *head)
{
for(;head !=NULL;head=head->next)
printf("%d\n",head->data);

}

int main(void)
{
struct node *p=NULL,*q;
unsigned int data;
for(data = 0;data<10;data++)
{
q=insert(data,&p);
if(q != NULL)
disp(q);
else
printf("(ERROR in program)\n");
}
return 0;
}

By making the changes I have some doubts.

1)when I took off the and temp->next = NULL along with your suggested
changes in insert() function I am getting output like this:
0
1
0
2
1
0
3
2
1
0
4
3
2
1
0
5
4
3
2
1
0
6
5
4
3
2
1
0
7
6
5
4
3
2
1
0
8
7
6
5
4
3
2
1
0
9
8
7
6
5
4
3
2
1
0

Is node->next = NULL is updating the current node? I coded with out
the node->next = NULL is got the above output. But when I added the
node->next=NULL (pls look the full code above) I got the answer as 0
to 9.

2)node = node->next is moving the list. I made the list traversal in
the function disp().By
avoiding the line temp=temp->next in the function insert() is that
mean that we should no move the list again?

3)What is the difference between

*p = temp;
(*p) = temp;
Since both works fine

4)In the main() I have used two node pointers p,q and assigned the
return value of function insert() to q. You have suggested that one
node pointer is enough. Is it because of optimization?
Irrwahn Grausewitz <ir*****************@freenet.de> wrote in message news:<hm********************************@4ax.com>. ..
da***********@yahoo.com wrote:
friends,
I wanted to learn the various ways of inserting a single list. so:
Method 1:

#include<stdlib.h>
#include<stdio.h>
struct node
{
unsigned int data;
struct node *next;
};
void init(void)
{
unsigned int data;
struct node *p;
p= malloc(sizeof *p);
if(p == NULL)
exit(EXIT_FAILURE);


You want to put the memory allocation inside the loop to get this
working.
for(data =0;data <10;data++)
{

p->data = data;
p->next = NULL;
printf("%d\n",p->data);
p=p->next;

The value of p->next is NULL at this point, you invoke undefined
behaviour.
}
free(&p);
printf("after del =%d\n",p->data);
}

int main(void)
{
init();
return 0;

}

In this method the value is getting printed up to the last printf
statement and throws a runtime error at the end. This method looks
ugly and also wrong.

Indeed. :-)

Method 2:

#include<stdio.h>
#include<stdlib.h>
struct node
{
unsigned int data;
struct node *next;
};

struct node *insert(unsigned int data,struct node **p) /*C's functions
are pass-by-value*/
{
struct node *temp;
temp = malloc(sizeof *p);

You allocated space to hold a pointer to struct node.
if(temp == NULL)
printf("MEM ERROR\n");

You want to bail out here, not only print an error message.

temp = *p;

You dropped your reference to the memory you just allocated!
temp->data = data;

You successfully invoked UB here.
temp = temp->next;

And again.
temp->next = NULL;

You successfully invoked UB here. Change this whole section to:

temp = malloc( sizeof **p );
if ( temp == NULL )
{
printf("MEM ERROR\n");
exit( EXIT_FAILURE );
}
temp->data = data;
temp->next = *p;
(*p) = temp;
return temp;
}

void disp(struct node **temp) /*C's functions are pass-by-value*/
{
struct node *p;
p=*temp;
while(p->next != NULL)
{
printf("%d\n",p->data);
p=p->next;
}
}

Change this function to:

void disp( struct node *head )
{
for ( ; head != NULL; head = head->next )
printf( "%d\n", head->data );
}

int main(void)
{
struct node *p,*q;

You need only one pointer; drop q.
unsigned int data;


You do the memory allocation in insert(), so drop the following two
lines (not to mention you forgot to check the return value of malloc()):
p = malloc(sizeof *p);
q= malloc(sizeof *q);


Instead, initialize p to NULL:

p = NULL;
for(data = 0;data<10;data++)
{
p=insert(data,&q);
if(p != NULL)
disp(&p);
else
printf("(ERROR)\n");
}


Insert will change the value of p, so all you have to do is:

for ( data = 0; data < 10; data++ )
insert( data, &p );
disp( p );
return 0;
}

In the above method I am not getting any output at all. I am sure the
mistake is with the argument passing but I am unable to sort it out.
Can any body answre the following question:

1)Is there any correct way of insertion in a ls or is it depend on the
situation?

You can insert at the beginning, at the end or at another position,
dending on what you want to do with the list. You can do it like in
the (corrected!) second example, where the insert function changes the
pointer to the first element of the list, or you can do this in the
calling funtion; it's merely a question of style and personal
preference.
2)Can any one tell me the error I made in the above simple programs?

See above.

In C sometimes things are much simpler as one might think. ;-)

Regards

Irrwahn

Nov 13 '05 #4
da***********@yahoo.com wrote:
Changed code: (not fully)

#include<stdio.h>
#include<stdlib.h>
struct node
{
unsigned int data;
struct node *next;
};

struct node *insert(unsigned int data,struct node **p)
{
struct node *temp;
temp = malloc(sizeof **p);
if(temp == NULL)
{
printf("MEM ERROR\n");
exit(EXIT_FAILURE);
}
else
{

temp->data = data;
temp->next = *p;
temp->next = NULL;
You just broke your list: you created a new node and then failed to link
it to the rest of the list by assigning NULL to temp->next.
*p = temp;
return *p;
}
return NULL;
This return statement will never be executed.

}

void disp(struct node *head)
{
for(;head !=NULL;head=head->next)
printf("%d\n",head->data);

}

int main(void)
{
struct node *p=NULL,*q;
You don't need q;
unsigned int data;
for(data = 0;data<10;data++)
{
q=insert(data,&p);
insert(data,&p);

And, if you /really/ want to print the list you have so far after each
insert operation:

disp( p );
if(q != NULL)
disp(q);
else
printf("(ERROR in program)\n");
The else part will never get executed (insert will never return NULL).
}
return 0;
}

By making the changes I have some doubts.

1)when I took off the and temp->next = NULL along with your suggested
changes in insert() function I am getting output like this: <output SNIPPED>
Is node->next = NULL is updating the current node? I coded with out
the node->next = NULL is got the above output. But when I added the
node->next=NULL (pls look the full code above) I got the answer as 0
to 9.
Yes, but this just indicates you broke your list, as explained above;
you should get something like (newlines stripped):
0
1 0
2 1 0
3 2 1 0
....
9 8 7 6 5 4 3 2 1 0

2)node = node->next is moving the list.
No, it's traversing the list.
I made the list traversal in
the function disp().By
avoiding the line temp=temp->next in the function insert() is that
mean that we should no move the list again?
No, it means you produce no list at all, because you fail to link the
nodes together to form a list.

3)What is the difference between

*p = temp;
(*p) = temp;
Since both works fine
There is no difference.

4)In the main() I have used two node pointers p,q and assigned the
return value of function insert() to q. You have suggested that one
node pointer is enough. Is it because of optimization?


No, it's because your insert() function changes p, so you don't gain
anything by letting two pointers, p and q, point to exactely the same
object (the most recently inserted node).

<SNIP>

Below is the complete corrected program, for your convenience; the
output looks like I mentioned above, also note that there is no more
blank shortage nowadays ... ;-)
#include <stdio.h>
#include <stdlib.h>

struct node
{
unsigned int data;
struct node *next;
};

struct node *insert( unsigned int data, struct node **p )
{
struct node *temp;
temp = malloc( sizeof **p );
if ( temp == NULL )
{
printf( "MEM ERROR\n" );
exit( EXIT_FAILURE );
}

temp->data = data;
temp->next = *p;
*p = temp;
return *p;
}

void disp( struct node *head )
{
for( ; head !=NULL; head=head->next )
printf( "%d\n", head->data );
}

int main( void )
{
struct node *p = NULL;
unsigned int data;

for( data = 0; data<10; data++ )
{
insert( data, &p );
disp( p );
}
return EXIT_SUCCESS;
}

Regards

Irrwahn
--
My other computer is a abacus.
Nov 13 '05 #5
Barry Schwarz <sc******@deloz.net> wrote in message news:<bk**********@216.39.134.131>...
On 21 Sep 2003 10:05:28 -0700, da***********@yahoo.com wrote:
friends,
I wanted to learn the various ways of inserting a single list. so:
Method 1:
Unfortunately, this does not build a linked list at all. At no time
does the member next of a struct node point to any other struct node.

#include<stdlib.h>
#include<stdio.h>
struct node
{
unsigned int data;
struct node *next;
};
void init(void)
{
unsigned int data;
struct node *p;
p= malloc(sizeof *p);
if(p == NULL)
exit(EXIT_FAILURE);
for(data =0;data <10;data++)
{

p->data = data;


When data is 0, p contains the value returned by malloc. Storing into
p->data is OK.

As noted below, when data > 0, p contains NULL.


Would you mind explaining a little bit more?
What you probably want is to store the address of allocated memory in
p and later free this allocation with
free (p);
printf("after del =%d\n",p->data);


After you free p, you are not allowed to dereference it. You cannot
print the value of data after the memory has been freed because the
object no longer exists.


printf cannot print the objects which has been freed by free().
Prototype of free is
void free(void *block);
We can check weather the malloc() allocated memmory to the object by
checking it's return value. Then how can we sure that the object
deallocated with free().
Nov 13 '05 #6
da***********@yahoo.com wrote:
Barry Schwarz <sc******@deloz.net> wrote in message news:<bk**********@216.39.134.131>...
On 21 Sep 2003 10:05:28 -0700, da***********@yahoo.com wrote: <SNIP>
>void init(void)
>{
> unsigned int data;
> struct node *p;
> p= malloc(sizeof *p);
> if(p == NULL)
> exit(EXIT_FAILURE);
> for(data =0;data <10;data++)
> {
>
> p->data = data;
When data is 0, p contains the value returned by malloc. Storing into
p->data is OK.

As noted below, when data > 0, p contains NULL.


Would you mind explaining a little bit more?


The first time the loop body gets executed you set p->next = NULL and
then p = p->next; hence p == NULL. The second time the loop body
executes you try to assign data to NULL->data, which invokes dreaded
undefined behaviour.
What you probably want is to store the address of allocated memory in
p and later free this allocation with
free (p);
> printf("after del =%d\n",p->data);


After you free p, you are not allowed to dereference it. You cannot
print the value of data after the memory has been freed because the
object no longer exists.


printf cannot print the objects which has been freed by free().
Prototype of free is
void free(void *block);
We can check weather the malloc() allocated memmory to the object by
checking it's return value. Then how can we sure that the object
deallocated with free().


We cannot; we call free() and hopefully the implementation takes the
appropriate actions, whatever these are alike. However, we invoke
undefined behaviour if we try to access memory that has been free()'d.

In implementors we trust. 8^]

Regards

Irrwahn
--
My other computer is a abacus.
Nov 13 '05 #7
thanks for all the answers
Nov 13 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Robert McGregor | last post by:
Hi all, I've got a Front End / Back End database that was working just fine. One day i opened the FE to find that if I tried to open one of the linked tables from the database window, nothing...
3
by: Michael Plant | last post by:
Hello one and all. I have a stored table in my database and the form I'm using is based on a query that draws data from my stored table and a linked table. The linked table is a *.txt file. ...
4
by: Neil Ginsberg | last post by:
I have ODBC linked tables to a SQL 7 database in an A2K database. The linked tables do not have the password stored in them, so the first time the user accesses them, they need to enter the SQL...
1
by: Phil Abrahamsen | last post by:
Access 2002: Example: Master record: ID#, Name Linked records: ID#, Member year If a member for the last 3 years you have 3 linked records withmember year = 2002, 2003, and 2004. I want to...
3
by: Zlatko Matić | last post by:
Hi! What happens with linked tables if they were linked using File DSN, when I copy the Access file on some other PC without File DSN ? What is the difference between DSN on linked tables and...
8
by: Crazy Cat | last post by:
Hi, When I click on the properties of a linked server, all the General properties are read - only, which means that if I want to edit any general properties I have to delete the linked server...
6
by: Neil | last post by:
After creating a linked server to a remote server, I needed to log in using sp_addlinkedsrvlogin to get my stored procedure to work. However, I noticed that after stopping SQL Server and the DTC...
5
by: Neil | last post by:
I am getting time-out errors when I try to perform a simple delete on a linked server. The command is: Delete From MyTable Where PKID=12345 I have tried executing this command directly from...
9
by: erick-flores | last post by:
If you have access to the database that the linked table is in, modify it there. You can't modify a linked table. Alternatively, you can import the linked table, then it won't be linked any more...
25
by: bubbles | last post by:
Using Access 2003 front-end, with SQL Server 2005 backend. I need to make the front-end application automatically refresh the linked SQL Server tables. New tables will be added dynamically in...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.