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 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
[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
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
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
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.
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
"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.
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
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. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
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...
|
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...
|
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...
|
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...
|
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;
};
...
|
by: Xarky |
last post by:
Hi,
I am writing a linked list in the following way.
struct list
{
struct list *next;
char *mybuff;
};
|
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;
...
|
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...
|
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...
|
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...
|
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...
|
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...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
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...
|
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...
|
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...
|
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...
|
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...
| |