Thread: Using a linked list globally and File I/O

  1. #16
    Registered User
    Join Date
    Dec 2007
    Posts
    53
    I've got it to compile past the incompatible pointer warnings (I use -Wall) by the following:

    Code:
    void printone (struct node** head, int i)
    
    ...
    
    void printall (struct node** head)
    {
          ...
          printone(&*head, i)
          ...
    }
    Is that form correct?

  2. #17
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I would have thought that you do the loop through the linked list in printall, and printone is responsible for printing a particular node. Your model appears to imply that it's printing the "nth" element in the linked list, and presumably traverses the list every time.

    "Pointer to incomplete type" would indicate that you don't have a "struct node" declared - perhaps it's called something else?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #18
    Registered User
    Join Date
    Dec 2007
    Posts
    53
    I saw that too, and I've changed the code. printall has the loop to go to the next node before handing "current" over to printone so that printtone can actually print the data in "current", the Nth node.

    Another quick question though.

    Code:
    current->soldier = soldiers
    works, while...
    Code:
    soldiers = current->soldier
    doesn't. Why?

    EDIT: Full code.

    Code:
    void printall(struct node** head)
    {
    	struct node* current = *head;
    	
    	printf("\n");
    	
    	while (current->next != NULL)
    	{
    		printone(&current);
    		current = current->next;
    	}
    }
    
    void printone(struct node** current)
    {
    	soldiers = current->soldier;
    	printf("\n\n");
    	printf("ASM: %ld", soldiers.aa);
    	printf("Onomatepwnymo: %s", soldiers.firstname);
    }
    Last edited by Leftos; 01-04-2008 at 09:39 AM.

  4. #19
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Leftos View Post
    I saw that too, and I've changed the code. printall has the loop to go to the next node before handing "current" over to printone so that printtone can actually print the data in "current", the Nth node.

    Another quick question though.

    Code:
    current->soldier = soldiers
    works, while...
    Code:
    soldiers = current->soldier
    doesn't. Why?

    EDIT: Full code.

    Code:
    void printall(struct node** head)
    {
    	struct node* current = *head;
    	
    	printf("\n");
    	
    	while (current->next != NULL)
    	{
    		printone(&current);
    		current = current->next;
    	}
    }
    Are you sure this is correct - I expect this to not print the final node.
    
    void printone(struct node** current)
    {
    	soldiers = current->soldier;
    	printf("\n\n");
    	printf("ASM: %ld", soldiers.aa);
    	printf("Onomatepwnymo: %s", soldiers.firstname);
    }
    What is soldiers - is it a global variable?

    See also red comment above.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #20
    Registered User
    Join Date
    Dec 2007
    Posts
    53
    Let's go again.

    Code:
    /* Initialize record structure for each soldier */
    struct record {
    	long int aa;
    	char firstname[20];
    	char lastname[30];
    	char datein[11];
    	char dateout[11];
    	int freedays;
    	int servicedays;
    } soldiers;
    
    /* Initialize nodes for linked list */
    struct node {
    	struct record	soldier;
    	struct node*	next;
    };
    
    void printall(struct node** head)
    {
    	struct node* current = *head;
    	
    	printf("\n");
    	
    	while (current != NULL)
    	{
    		printone(&current);
    		current = current->next;
    	}
    }
    
    void printone(struct node** current)
    {
    	soldiers = current->soldier;
    	printf("\n\n");
    	printf("ASM: %ld", soldiers.aa);
    	printf("Onomatepwnymo: %s", soldiers.firstname);
    }
    Both node and record are globals. The "record" type "soldiers" structure is also global, and contains the data we want to insert into a new element or the data we want to print each time, while the linked list holding all the "soldiers" element travels by reference from function to function.

  6. #21
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    In printone, current isn't a pointer to node, it's a pointer to a pointer to node, so you'll have to dereference once: try (*current)->soldier.

  7. #22
    Registered User
    Join Date
    Dec 2007
    Posts
    53
    Thanks, that worked. I hope everything goes well from here on now. And thanks to everyone who bothered to show up and reply.
    Last edited by Leftos; 01-04-2008 at 10:08 AM.

  8. #23
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    Why do you use ** in those functions? Why not just one *?

  9. #24
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Leftos View Post
    So now I know that I need to do this...
    Code:
    void printall (struct node** head)
    ...in order for the printall function to have access to the list. However, if I call printone from within printall and I want printone to have access to the same list as well, how do I declare printone, and how do I pass on head?
    No you don't.
    You only need ** if a function is going to modify a *. So in essence, taking a struct node** head means it's going to reassign the head * pointer, which it shouldn't.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #25
    Registered User
    Join Date
    Dec 2007
    Posts
    53
    Okay, well, the double asterisk is only needed when the called function is going to modify the linked list.

    Any ways to delete an element from a single linked list? I'm confused as to how I'll set the previous element's pointer to point to the next element from the one deleted.

    I tried the following but I get segmentation fault.

    Code:
    void delrec(struct node** head, int acount)
    {
    	int i;
    	struct node* current = *head;
    	struct node* todel;
    	
    	for (i=0;i<=acount-1;i++)
    	{
    		current = current->next;
    	}
    	
    	todel = current->next;
    	current->next = current->next->next;
    	free(todel);
    }
    Last edited by Leftos; 01-04-2008 at 12:34 PM.

  11. #26
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    No it's not. It's already referencing the node, not a copy of it.

    To delete, you would be able to delete the next, or pass a pointer to the node and the head, and delete it.

    This is one of the places that a doubly linked list is useful.

  12. #27
    Registered User
    Join Date
    Dec 2007
    Posts
    53
    robwhit, I based my code on the tutorials I found in this e-book. Pages 12 to 14 are what I based the double asterisk on. If they're wrong or I'm still wrong, please do tell.

    Could this work?

    Code:
    void delrec(struct node** head, int acount)
    {
    	int i;
    	struct node* current = *head;
    	
    	for (i=0;i<=acount-1;i++)
    	{
    		current = current->next;
    	}
    	
    	current->soldier = current->next->soldier;
    	current->next = current->next->next;
    	free(current->next);
    }
    Nope. Segmentation fault. I obviously can't access current->next->soldier.

    EDIT: SOLVED! Took a look here, and changed it only slightly for it to work with my code.

    Code:
    void delrec(struct node** head, int acount)
    {
    	int i;
    	struct node* current = *head;
    	struct node* previous = NULL;
    	
    	for (i=1;i<=acount-1;i++)
    	{
    		previous = current;
    		current = current->next;
    	}
    	
    	if (previous == NULL) *head = current->next;
    	else previous->next = current->next;
    	free(current);
    }
    Last edited by Leftos; 01-04-2008 at 01:01 PM.

  13. #28
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    The double asterisk is only needed if you want to be able to modify the head variable that you have in the calling code. It will still point to the same linked list.

    You could do it that way, but gaining the extra level of indirection just to dereference it again is extraneous.

    Singly linked lists don't have a previous member. edit: haha never mind that.

    Suppose that you delete more than one node at a time. How many times would you have called malloc? How many times would you have called free? edit2: nevermind to that too...
    Last edited by robwhit; 01-04-2008 at 02:38 PM.

  14. #29
    Registered User
    Join Date
    Dec 2007
    Posts
    53
    I sense from what you're saying that there's something obviously wrong with my code, but could you elaborate?

  15. #30
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    nevermind, brain fart.

    there are still a few things though:

    for (i=0;i<=acount-1;i++)

    this can be written as:

    for (i=0;i<acount;i++)

    and what is acount used for?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. linked list versus array
    By FoodDude in forum C++ Programming
    Replies: 18
    Last Post: 08-22-2005, 10:57 AM