473,395 Members | 1,701 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,395 software developers and data experts.

Linked List Issue

Hello all again,

Sorry for troubling you with my problems. I've tried to implement
simple double linked lists, here's my structure:
struct DResult {
double val;
char* title;
struct DResult* next;
struct DResult* prev;
};

I also have a typedef for struct DResult to DResult.

Then I've written a function to append an element to the list with the
following declation:
int dresult_append(DResult* list, DResult* element);
Then I used a debugger to trace down the issue with the function, so
the this code fragment inside the function:
if(list == NULL) // empty list
{
list = element;

return 1;
}

The problem is that list is updated after the assignment but after the
function returns, it goes back to NULL. I'm quite puzzled. Do I have to
use a double pointer for the list like DResult** list and then update
*list ( which a pointer to a DResult)?

Regards

Feb 15 '06 #1
9 1480
gamehack <ga******@gmail.com> wrote:
int dresult_append(DResult* list, DResult* element);
Then I used a debugger to trace down the issue with the function, so
the this code fragment inside the function:
if(list == NULL) // empty list
{
list = element;

return 1;
}

The problem is that list is updated after the assignment but after the
function returns, it goes back to NULL. I'm quite puzzled.
C is pass by value. If you assign to a formal parameter, that
assignment has no effect outside of the function where it happens. For
this reason, it's generally considered poor form to assign to a formal
parameter in the first place.
Do I have to
use a double pointer for the list like DResult** list and then update
*list ( which a pointer to a DResult)?


Yes, that would certainly solve your problem.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
Feb 15 '06 #2
[snip]
this reason, it's generally considered poor form to assign to a formal
parameter in the first place.


What is the proper design for this kind of function? Should I use
another proper approach?

Thanks

Feb 15 '06 #3
gamehack <ga******@gmail.com> wrote:
[snip]
this reason, it's generally considered poor form to assign to a formal
parameter in the first place.


What is the proper design for this kind of function? Should I use
another proper approach?


Because C is so widely used, there aren't a lot of guidelines that are
used throughout all of the C language. Passing a pointer-to-pointer
would be okay, as would returning the new list pointer. I would
intuitively prefer to return the new list pointer, but I've also seen a
reasonable case made for non-idempotent functions to use the return
value only for success/failure notification.

The reason not to assign directly to a formal parameter is just that it
doesn't work, for your definition of "work". Assigning to the thing
that a formal parameter points to, on the other hand, is fine and
actually very common.

--
Chris Smith
Feb 15 '06 #4
gamehack wrote:

Sorry for troubling you with my problems. I've tried to implement
simple double linked lists, here's my structure:
struct DResult {
double val;
char* title;
struct DResult* next;
struct DResult* prev;
};

I also have a typedef for struct DResult to DResult.

Then I've written a function to append an element to the list with the
following declation:
int dresult_append(DResult* list, DResult* element);


There's your trouble. C passes by value, so to change a list you
have to alter something. You want:

struct DResult *appendto(struct DResult *list,
struct DResult *element);

called by something like

thelist = appendto(thelist, newelement);

and you better have some rules about the initial state, i.e. the
empty list.

--
"The power of the Executive to cast a man into prison without
formulating any charge known to the law, and particularly to
deny him the judgement of his peers, is in the highest degree
odious and is the foundation of all totalitarian government
whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
Feb 16 '06 #5
On Wed, 15 Feb 2006 14:41:04 -0800, gamehack wrote:
[snip]
this reason, it's generally considered poor form to assign to a formal
parameter in the first place.

What is the proper design for this kind of function? Should I use another
proper approach?


I'd suggest that there are two common solutions to this problem. The
fundamental issue is that the list is not properly represented by the
structure that hold a node's data. A list can be empty so the real
repsenetation of the list is a *pointer* to one of those structs (a
pointer which might then be NULL).

Option 1: Every list modifying function takes a list (i.e. a struct ptr)
as an arguments and returns a list as a result. Every call of the
function must then look something like this:

struct DResult *my_list;
....
my_list = list_append(my_list, 1.2);

Option 2: Define a new struct that holds (at least) the pointer to the
start of the list. You can do more with this method, because the
structure can hold extra information such as a pointer to last element
(for appending) or a count of the number of elements or whatever else
might help your design:

struct DResultList {
struct DResult *start;
struct DResult *end;
int n_elements;
};

All your list functions now take a pointer to a struct DResultList and
operate on it.

Option 1 makes it very simple to write short recusive list functions.
Option 2 is much more flexible but requires more complexity.

--
Ben.

Feb 16 '06 #6

Ben Bacarisse wrote:
On Wed, 15 Feb 2006 14:41:04 -0800, gamehack wrote:
[snip]
this reason, it's generally considered poor form to assign to a formal
parameter in the first place.

What is the proper design for this kind of function? Should I use another
proper approach?


I'd suggest that there are two common solutions to this problem. The
fundamental issue is that the list is not properly represented by the
structure that hold a node's data. A list can be empty so the real
repsenetation of the list is a *pointer* to one of those structs (a
pointer which might then be NULL).


That's what I've done.
Option 1: Every list modifying function takes a list (i.e. a struct ptr)
as an arguments and returns a list as a result. Every call of the
function must then look something like this:

struct DResult *my_list;
....
my_list = list_append(my_list, 1.2);
I'm not really a fan of this approach - I think the user(programmer
actually) should not be required to use this construct, it's much more
intuitive to provide just two parameters and don't care about the
result(with respect to the list and element variables).
Option 2: Define a new struct that holds (at least) the pointer to the
start of the list. You can do more with this method, because the
structure can hold extra information such as a pointer to last element
(for appending) or a count of the number of elements or whatever else
might help your design:

struct DResultList {
struct DResult *start;
struct DResult *end;
int n_elements;
};

All your list functions now take a pointer to a struct DResultList and
operate on it.

This is how I resolved my issue:

int dresult_append(DResult** list, DResult** element);

And in main.c I do something like:
DResult* list = NULL;
DResult* element = dresult_new();
where dresult_new() mallocs the structure and initialises all the
structure elements.
Option 1 makes it very simple to write short recusive list functions.
Option 2 is much more flexible but requires more complexity.

--
Ben.


Thanks

Feb 16 '06 #7
"gamehack" <ga******@gmail.com> wrote in message
news:11**********************@g43g2000cwa.googlegr oups.com...
This is how I resolved my issue:

int dresult_append(DResult** list, DResult** element);
Why is the second argument a double pointer? Is any modification necessary
for *element?
And in main.c I do something like:
DResult* list = NULL;
DResult* element = dresult_new();
where dresult_new() mallocs the structure and initialises all the
structure elements.

Feb 16 '06 #8
gamehack wrote:

Then I used a debugger to trace down the issue with the function, so
the this code fragment inside the function:
if(list == NULL) // empty list
{
list = element;

return 1;
}

The problem is that list is updated after the assignment but after the
function returns, it goes back to NULL. I'm quite puzzled. Do I have
to use a double pointer for the list like DResult** list and then
update *list ( which a pointer to a DResult)?

You received the answer already, but I'll also point out that this
issue is covered in the FAQ:

http://c-faq.com/ptrs/passptrinit.html
It's a good idea to run through that with your questions first.

Brian
Feb 16 '06 #9
On Thu, 16 Feb 2006 06:41:27 -0800, gamehack wrote:
Ben Bacarisse wrote:
On Wed, 15 Feb 2006 14:41:04 -0800, gamehack wrote:
> [snip]
>> this reason, it's generally considered poor form to assign to a
>> formal parameter in the first place.
>>
>>
> What is the proper design for this kind of function? Should I use
> another proper approach?
I'd suggest that there are two common solutions to this problem.
<two linked-list options snipped>

This is how I resolved my issue:

int dresult_append(DResult** list, DResult** element);


I should have included this as option 3 (although it follows naturally
from my first paragrah). It is fine, of course, but not my favourite.

Having gone to the effort of passing a pointer to a mutable "thing" I
think it makes sense to make it a struct even if it has only one pointer
in it! At least you get the chance to grow it later if your
implementation requires it -- and you get another name: struct DResultList
which helps to distinguish between the nodes and the list itself.

BTW, it is best not to quote sigs (unless you want to talk about them).

--
Ben.

Feb 16 '06 #10

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

Similar topics

7
by: Chris Ritchey | last post by:
Hmmm I might scare people away from this one just by the title, or draw people in with a chalange :) I'm writting this program in c++, however I'm using char* instead of the string class, I am...
11
by: fighterman19 | last post by:
because in linked list each node contains only one digit like curr->nodevalue_1= 0 curr->nodevalue_2=1 sum->nodevalue = curr->nodevalue_1 + curr->nodevalue_2 so when the number go up to >10...
33
by: junky_fellow | last post by:
Consider a singly-linked list. Each node has a structure, struct node { char c; struct node *next; }; Each of the nodes contain an alphabetic character. Can anybody suggest a way to print...
4
by: dssuresh6 | last post by:
Whether browsing forward or backward can be done using a singly linked list. Is there any specific case where a doubly linked list is needed? For people who say that singly linked list allows...
4
by: JS | last post by:
I have a file called test.c. There I create a pointer to a pcb struct: struct pcb {   void *(*start_routine) (void *);   void *arg;   jmp_buf state;   int    stack; }; ...
57
by: Xarky | last post by:
Hi, I am writing a linked list in the following way. struct list { struct list *next; char *mybuff; };
17
by: darrell.blake | last post by:
I've just written a doubly linked list but when I tell the iterator to move forward in the list it removes all the previous elements in the list. i.e. If I were to do: List list; ...
17
by: 2005 | last post by:
Hi In C++, are the following considered best practices or not? - passing aguments to functions (ie functions do not take any arguments ) - returning values using return statement Anything...
6
by: mattmao | last post by:
Okay, this is just my exercise in order to prepare for the coming assignment regarding the damned Linked List issue... The task is simple and I am about to finish it. However, I couldn't go around...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
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?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
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
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
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
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...

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.