Thread: Linked Lists

  1. #1
    Registered User
    Join Date
    Mar 2010
    Location
    Australia
    Posts
    174

    Linked Lists

    I'm getting a seg fault in this program on linked lists, and frankly, I'm not surprised because this topic has been giving me a hell of a lot of trouble.

    What I have so far is

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct _Node {
        int value;
        struct _Node *next;
    } NodeT;
    
    NodeT *makeNode(int data);
    NodeT *joinList(NodeT *head1, NodeT *head2);
    void printList(NodeT *head);
    void freeList(NodeT *head);
    
    int main(int argc, char *argv[]) {
        NodeT *l = NULL;
        NodeT *head = NULL;
        NodeT *prevl = NULL;
        int data = 0;
        int numScanned = 1;
        int count = -1;
        
        while (numScanned) {
            printf("Enter an integer: ");
            numScanned = scanf("%d", &data);
            if (numScanned) {
                count++;
                l = makeNode(data);
                if (count == 0) {
                    head = l;
                } else {
                    prevl = l;
                }
                l->next = joinList(prevl, l);
                
            }
        }
        for (l = head; l!=NULL; l = l->next) {
            printList(l);
        }
        
        return EXIT_SUCCESS;
    }
    
    NodeT *makeNode(int data) {
        NodeT *new;
        new = malloc(sizeof(NodeT));
        if (new == NULL) {
            fprintf(stderr, "Out of memory\n");
            exit(1);
        }
        new->value = data;
        new->next = NULL;
        return new;
    }
    
    NodeT *joinList(NodeT *head1, NodeT *head2) {
        head1->next = head2;
        return head1->next;
    }
    
    void printList(NodeT *head) {
        NodeT *cur = head;
        while (cur != NULL) {
            printf("%d", cur->value);
            cur=cur->next;
            if (cur != NULL) {
                printf("->");
            }
        }
        printf("\n");
    }
    
    void freeList(NodeT *head) {
        NodeT *cur;
        cur = head;
        while (cur != NULL) {
            NodeT *tmp = cur->next;
            free(cur);
            cur = tmp;
        }
    }
    I'm fairly comfortable with all functions except the joinList one, and I'm unsure about the way my main has been set out either. If someone can be bothered to scrutinize my program, I'd be very thankful.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    What exactly is joinList supposed to do?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Aug 2012
    Posts
    41
    When you are calling joinList(); for first time you are passing head1 as NULL, so there is no point of head1->next. That is where program is terminated.
    Modify your program accordingly.

  4. #4
    Registered User
    Join Date
    Mar 2010
    Location
    Australia
    Posts
    174
    Quote Originally Posted by laserlight View Post
    What exactly is joinList supposed to do?
    It's supposed to return the pointer between one node and the next to create the link.

    Quote Originally Posted by sana.iitkgp View Post
    When you are calling joinList(); for first time you are passing head1 as NULL, so there is no point of head1->next. That is where program is terminated.
    Modify your program accordingly.
    head1 isn't NULL though? I think the problem is that head1 == head2 so that line
    head1->next = head2;
    is wrong.

  5. #5
    Registered User
    Join Date
    Aug 2012
    Posts
    41
    Code:
        NodeT *prevl = NULL;   <<<<<---- prevl is NULL
        int data = 0;
        int numScanned = 1;
        int count = -1;
        
        while (numScanned) {
            printf("Enter an integer: ");
            numScanned = scanf("%d", &data);
            if (numScanned) {
                count++;  <<<--count is '0' now
                l = makeNode(data);
                if (count == 0) {
                    head = l;
                } else {
                    prevl = l;   <<<<---- still prevl is NULL as this not executes at all
                }
                l->next = joinList(prevl, l);   <<<<------ prevl is head1 so head1 is NULL
                
            }
    You got my point?

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Mentallic
    It's supposed to return the pointer between one node and the next to create the link.
    Are you sure it is not supposed to join the two linked lists, returning a pointer to the first node of the resulting linked list?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by Mentallic View Post
    It's supposed to return the pointer between one node and the next to create the link.
    Given how unintelligible that description is, it's no wonder it doesn't do anything useful at present.
    Currently the way you are using it leaves you with l->next pointing at itself.

    I'd advise getting your thoughts straight as to what it is supposed to do, and I agree with laserlight as to what it's probably meant to do.
    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"

  8. #8
    Registered User
    Join Date
    Mar 2010
    Location
    Australia
    Posts
    174
    Quote Originally Posted by sana.iitkgp View Post
    You got my point?
    Ahh yes I see now.

    Quote Originally Posted by laserlight View Post
    Are you sure it is not supposed to join the two linked lists, returning a pointer to the first node of the resulting linked list?
    Yeah sorry that is what I meant but you've said it more clearly.

    Quote Originally Posted by iMalc View Post
    Given how unintelligible that description is, it's no wonder it doesn't do anything useful at present.
    Currently the way you are using it leaves you with l->next pointing at itself.

    I'd advise getting your thoughts straight as to what it is supposed to do, and I agree with laserlight as to what it's probably meant to do.
    That's one of my problems with this topic. I missed the lecture when we were introduced to linked lists and all of a sudden the second lecture makes no sense and I'm now left stranded, twiddling my thumbs as I stare at the code trying to make sense of it all. I definitely need to try and wrap my head around this.

    I've made a few changes thus far, and I've changed some variable names too just for it to make a little more sense for me.

    Code:
    int main(int argc, char *argv[]) {
        NodeT *l = NULL;
        NodeT *cur = NULL;
        NodeT *prevl = NULL;
        int data = 0;
        int numScanned = 1;
        int count = -1;
        
        while (numScanned) {
            printf("Enter an integer: ");
            numScanned = scanf("%d", &data);
            if (numScanned) {
                count++;
                cur = makeNode(data);
                if (count == 0) {
                    l = cur;
                    prevl = cur;
                } else {
                    prevl->next = joinList(prevl, cur);
                    prevl = cur;
                }
            }
        }
        for (l = cur; cur!=NULL; cur = cur->next) {
            printList(cur);
        }
        
        return EXIT_SUCCESS;
    }
    
    NodeT *joinList(NodeT *head1, NodeT *head2) {
        head1->next = head2;
        return head1->next;
    }
    It's actually not compiling. The error is that my node l is declared but unused, even though it's used in my main (the node l stands for list, it's basically the start of the linked list).

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Mentallic
    It's actually not compiling. The error is that my node l is declared but unused, even though it's used in my main (the node l stands for list, it's basically the start of the linked list).
    That should not result in an error, though it might result in a warning. By the way, l is generally a poor choice of variable name because of its close resemblance to I and/or 1 on several fonts.

    Basically, the idea here is: find the last node (tail) of the first linked list and set its next pointer to point to the head of the second linked list.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Code:
        for (l = cur; cur!=NULL; cur = cur->next) {
            printList(cur);
        }
    You get the warning because you only assign values to "l" but never use it.
    The reason is your for-loop for printing the list. "l" is the root node of your list (and should be called head or root because it is just one node and not the whole list) and you should never overwrite it otherwise you will loose the reference to the list.
    You should flip the assignemt inside the for-loop.

    Bye, Andreas

  11. #11
    Registered User
    Join Date
    Mar 2010
    Location
    Australia
    Posts
    174
    Quote Originally Posted by laserlight View Post
    That should not result in an error, though it might result in a warning.
    Oh right, sorry, that's what I was meant to say. Our class requires that we compile all our programs with the flags -Wall -Werror -O.

    Quote Originally Posted by laserlight View Post
    By the way, l is generally a poor choice of variable name because of its close resemblance to I and/or 1 on several fonts.
    I totally agree, I only chose it because one of the class examples used that variable so I've changed it to head.

    Quote Originally Posted by laserlight View Post
    Basically, the idea here is: find the last node (tail) of the first linked list and set its next pointer to point to the head of the second linked list.
    Code:
    NodeT *joinList(NodeT *head1, NodeT *head2) {
        head1->next = head2;
        return head1->next;
    }
    Does just that doesn't it?

    Quote Originally Posted by AndiPersti View Post
    Code:
        for (l = cur; cur!=NULL; cur = cur->next) {
            printList(cur);
        }
    You get the warning because you only assign values to "l" but never use it.
    The reason is your for-loop for printing the list. "l" is the root node of your list (and should be called head or root because it is just one node and not the whole list) and you should never overwrite it otherwise you will loose the reference to the list.
    You should flip the assignemt inside the for-loop.

    Bye, Andreas
    Thanks for spotting that! What a silly mistake...

    Ok so it seems like I've gotten the program working exactly the way I needed it to, and frankly I'm really surprised at how little changes I needed to make. Thanks for all the help guys.

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Mentallic
    Code:
    NodeT *joinList(NodeT *head1, NodeT *head2) {
        head1->next = head2;
        return head1->next;
    }
    Does just that doesn't it?
    No, it doesn't, except for the special case where the first linked list only has exactly one element. Even then, it returns the wrong thing.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by laserlight View Post
    No, it doesn't, except for the special case where the first linked list only has exactly one element. Even then, it returns the wrong thing.
    I think Mentallic has still problems with the right vocabulary for linked lists.
    The last version of the program he has shown us is appending every new node at the end of the list. "prevl" should therefore better be called "tail" and "joinList()" should be called "appendNode()" (there is no second list to join). But this function isn't really necessary because if he changes line 19
    Code:
    prevl->next = joinList(prevl, cur);
    to
    Code:
    prevl->next = cur;
    the result will be the same.

    Bye, Andreas

  14. #14
    Registered User
    Join Date
    Mar 2010
    Location
    Australia
    Posts
    174
    Quote Originally Posted by laserlight View Post
    No, it doesn't, except for the special case where the first linked list only has exactly one element. Even then, it returns the wrong thing.
    What my program is supposed to do is to create a linked list, not to join two linked lists together from head to tail. Each node needs to be connected to the next node in the list such that when I call my print function

    Code:
    void printList(NodeT *head) {
        NodeT *cur = head;
        while (cur != NULL) {
            printf("%d", cur->value);
            cur=cur->next;
            if (cur != NULL) {
                printf("->");
            }
        }
    }
    It will print out each node as expected. The output should be as follows:

    Quote Originally Posted by terminal
    prompt$ ./llbuild
    Enter an integer: 12
    Enter an integer: 34
    Enter an integer: 56
    Enter an integer: a
    Finished: list is 12->34->56
    Quote Originally Posted by AndiPersti View Post
    I think Mentallic has still problems with the right vocabulary for linked lists.
    The last version of the program he has shown us is appending every new node at the end of the list. "prevl" should therefore better be called "tail" and "joinList()" should be called "appendNode()" (there is no second list to join).
    Yes that's what I need to be doing - sorry about all the confusion.

    Quote Originally Posted by AndiPersti View Post
    But this function isn't really necessary because if he changes line 19
    Code:
    prevl->next = joinList(prevl, cur);
    to
    Code:
    prevl->next = cur;
    the result will be the same.

    Bye, Andreas
    Except this is homework and one of the requirements is that I created a function joinList with those parameters given. It may be unnecessary and convoluted on its own, but it's required. Maybe it's possible however to clean up my main somehow? I feel like it could be more succinct.

  15. #15
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by Mentallic View Post
    Except this is homework and one of the requirements is that I created a function joinList with those parameters given. It may be unnecessary and convoluted on its own, but it's required. Maybe it's possible however to clean up my main somehow? I feel like it could be more succinct.
    Ok, then joinList is not the best name for the function but you have to live with it.

    Currently you maintain in main a pointer to the tail of the list (prevl) and so it's pretty easy to add a new node at the end of the list.
    But perhaps the reason for your assingment was to do all the work in the function (with or without a helping tail pointer) and your main should just look like:
    Code:
    int main(void)
    {
    
        NodeT *list = NULL, *new_node;
           
        do 
        {
            // get number
            new_node = makeNode(data);
            list = joinList(new_node);
        } while (breaking condition);
    
        printList(list);
        freeList(list);
        return 0;
    }
    But without knowing the exact assignment that's just my guess.

    Bye, Andreas

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Double Linked Dynamic Lists Vs Unrolled Linked Lists
    By lantzvillian in forum C Programming
    Replies: 6
    Last Post: 02-14-2012, 01:07 PM
  2. Replies: 4
    Last Post: 05-01-2010, 10:19 PM
  3. Question about Linked lists of lists
    By hear_no_evil in forum C Programming
    Replies: 2
    Last Post: 11-08-2004, 02:49 AM
  4. question on linked lists(stack with linked lists)
    By dionys in forum C Programming
    Replies: 1
    Last Post: 06-02-2004, 11:08 AM
  5. Linked List of Linked lists Revisited.
    By Qui in forum C++ Programming
    Replies: 11
    Last Post: 04-11-2004, 09:45 PM