Thread: 0 being inserted at start of linked-list

  1. #1
    Registered User
    Join Date
    Dec 2012
    Posts
    34

    0 being inserted at start of linked-list

    Hi all -

    I'm poking around with doing a few Haskell-like functions for linked-lists. Take, drop and so on.

    I've done the code below. The problem is that it mysteriously inserts a 0 at the start of the list, and I have no idea why. So - hopefully someone can help out here.
    Code:
      
    
    #include <stdio.h>
    #include <stdlib.h> 
    #include <stddef.h> 
    #include <string.h>
    #include <ctype.h> 
    #include <malloc.h> 
    
    
    /*  List functions.  */  
    
    struct node { 
        int data;    
        struct node *next;   
    } ;
    
    
    /* Function to add data to end of a list  */ 
    struct node *list_append(struct node *n, int data)
    {  
       
       /* A pointer to iterate along the list */ 
       struct node *ptr = NULL; 
       
       /* Now, create a new node using the data. */ 
       struct node *newnode = NULL; 
       newnode = malloc(sizeof(struct node));  
       
       newnode->data = data; 
       newnode->next = NULL;   
      
      /* Is our existing list null? */ 
      /* If so, our "list" is just the newly-created node. */ 
       if(n == NULL) 
         {  
            n = newnode;         
         }             
               
       else 
         {         
             for( ptr = n; ptr->next != NULL; ptr = ptr->next ) 
               { 
                 /* Iterate through the list until we find the last node */   
               }         
          
           /* Add the new node to the end of the list. */ 
           /* In other words: the last ptr->next WAS null, but it is */ 
           /* now pointing to newnode. */  
           ptr->next = newnode;       
         }     
           
      return n;                 
           
    }  /* End of list_append  */  
    
        
        
    /* Free the list memory. */ 
    void free_list(struct node *n) 
    { 
      /* We create TWO pointers. */ 
      /* ptr is used to iterate through the list. */ 
      /* tmp (which points to the same place) is used to */ 
      /* actually free the memory. */    
       struct node *ptr, *tmp = NULL;        
              
      /* Check that the list is non-null. */   
       if(n != NULL) 
         {  
                              
             for( ptr = n; ptr->next != NULL; ptr = ptr->next ) 
               { 
                 /* Iterate through the list */   
                  printf( "Freeing %d\n",  (ptr->data) );  
                  tmp = ptr;              
                  free(tmp);                   
               }         
          
           /* Free the last element of the list */ 
           /* (where ptr->next IS null). */        
            printf( "Freeing %d\n",  (ptr->data) ); 
            free(ptr);      
         }         
    }     
                   
    
    void print_list(struct node *n)
    { 
       /* A pointer for iterating. */ 
       struct node *ptr = NULL;  
        
       /* Iterate along the list.  */ 
        for( ptr = n; ptr->next != NULL; ptr = ptr->next )    
           { 
              printf( "mylist->data = %d\n",  (ptr->data) );               
           }         
        
        /* For the last nore (where ->next IS NULL), we need to print */ 
        /* it outside the loop. */ 
        printf( "mylist->data = %d\n",  (ptr->data) ); 
      
    }
    
    
    struct node *take(struct node *n, int i)
    { 
       struct node *ret = NULL;   
       ret = malloc(sizeof(struct node));    
       
        /* A pointer for iterating. */ 
       struct node *ptr = NULL;  
           
       int j=0;      
            
       for( ptr = n; ( ptr->next != NULL && j < i ); ptr = ptr->next )         
       {                
          list_append(ret, ptr->data) ;   
          /* memcpy( (int *)ret->data, (int *)ptr->data, sizeof( (int *)ptr->data) );  */ 
          j++;
       }
        
     return ret;
    
    } 
     
    
    int main() 
    {
    
    struct node *mynode = NULL; 
    
    mynode = list_append(mynode, 23) ; 
    mynode = list_append(mynode, 45) ; 
    mynode = list_append(mynode, 71) ; 
    mynode = list_append(mynode, 248) ; 
    mynode = list_append(mynode, 18) ; 
    
    struct node *mynode2 = NULL; 
    mynode2 = take(mynode, 3); 
    
    print_list(mynode); 
    
    puts("Now the new list \n");  
    print_list(mynode2);  
     
    free_list(mynode);     
    free_list(mynode2);         
    
    return 0; 
    
    }
    Many thanks in advance for your help!
    Bye for now -
    - latte123

  2. #2
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    The free function has at least one logical error.
    However, this is not why you got a zero.

    Imagine a list with 3 nodes.

    n pointer is set to the first node. Same for ptr. Then tmp also points to the first node. You free tmp. Where tmp, n and ptr point now? To garbage! Then you want to set ptr, where the next field of where ptr already points to. This can result in segmentation fault. You should move at least the pointer ptr, before freeing tmp!
    After deleting the whole list, I suggest you to have the n pointer set to NULL.

    What take function is supposed to do? I do not know Haskel and the names of the functions and variables you have do not seem to help at all!
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  3. #3
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Ok, now about the 0 thing.

    Let's say I modify your take function
    Code:
    struct node *take(struct node *n, int i)
    {
       struct node *ret = NULL;  
       ret = malloc(sizeof(struct node));  /* Why you do this? That's the problem! */
       ret->data = 666; /* I added this! */
       ...
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  4. #4
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    stdlib.h provides malloc, realloc, calloc, and free. You ought to use that instead of malloc.h.

    Note that, in take, you're list_append()ing to a null pointer. You'd be better off (from a performance point of view) implementing cons and either building the list backward and reversing it or building it recursively.

    edit: s/null pointer/uninitialised data.

    edit#2: Actually, take is just a one-liner if you implement cons:
    struct node *take(const struct node *lst, int n)
    {
    return n <= 0 ? 0 : cons(lst->data, take(lst->next, n - 1));
    }

    And drop is even easier since you don't need to make a copy of the list. There isn't any need to use append at all, since you can build your initial list in the same manner:

    lst = cons(23, cons(45, cons(71, cons(248, cons(18, 0)))));
    Last edited by Barney McGrew; 02-14-2013 at 03:23 PM.

  5. #5
    Registered User
    Join Date
    Dec 2012
    Posts
    34
    Quote Originally Posted by Barney McGrew View Post
    stdlib.h provides malloc, realloc, calloc, and free. You ought to use that instead of malloc.h.

    Note that, in take, you're list_append()ing to a null pointer. You'd be better off (from a performance point of view) implementing cons and either building the list backward and reversing it or building it recursively.

    edit: s/null pointer/uninitialised data.

    edit#2: Actually, take is just a one-liner if you implement cons:
    Code:
    struct node *take(const struct node *lst, int n)
    {
            return n <= 0 ? 0 : cons(lst->data, take(lst->next, n - 1));
    }
    And drop is even easier since you don't need to make a copy of the list. There isn't any need to use append at all, since you can build your initial list in the same manner:
    Code:
    lst = cons(23, cons(45, cons(71, cons(248, cons(18, 0)))));
    Hi Barney!

    Thanks very much for that - that's great!
    A very elegant way to do things!
    Thanks too to all others who have helped out here - your comments have been very helpful!
    - latte123
    Last edited by latte123; 02-14-2013 at 04:03 PM.

  6. #6
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    If you were truly doing this like Haskell, which is a functional programming language, then there would be no list. Instead it operates entirely by lazy evaluation.
    The results don't even exist, in a list or otherwise, and are instead pulled through from the functions that ultimately generate the data, on demand. The closest thing in a procedural programming language is the IEnumerable interface in C#.

    Whilst that's great that you are learning more than one kind of programming language, you're better off not trying to mix the concepts of one into the other. Learn each language, and how it works, and when they are appropriate to use. Learn their strengths and weaknesses and learn to use the right tool for the job. They are not merely different syntaxes.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Declaring linked list inside linked list
    By blueboyz in forum C Programming
    Replies: 33
    Last Post: 04-20-2012, 10:13 AM
  2. Start program when USB-memory is inserted?
    By Marcux in forum C Programming
    Replies: 3
    Last Post: 04-18-2008, 11:32 PM
  3. Replies: 6
    Last Post: 03-02-2005, 02:45 AM
  4. How to start this linked list?
    By Daniel in forum C++ Programming
    Replies: 4
    Last Post: 01-31-2003, 09:47 AM
  5. Traverse a linked list from end to start
    By pjodk in forum C Programming
    Replies: 4
    Last Post: 04-07-2002, 06:09 PM

Tags for this Thread