简体   繁体   中英

Printing the nodes of a linked list through a recursive function

I've been asked to make a couple of programs using C. In one of these programs, I need to create a linked list so I can do some stuff with it. But, I am not allowed to use global variables nor loops (While, For, etc.) in any of these programs. So here is a small program I wrote just to fresh up linked lists:

#include <stdio.h>
#include <stdlib.h>

struct node {

    int number;
    struct node *next;

};

void create (struct node *, struct node *);
void insert (struct node *, struct node *);
void display (struct node *);

int main(void) {

    struct node *head;
    struct node *current;
    struct node *temp;

    create ( head, current );

    insert ( head, current );

    temp = head;

    display ( temp );

}

void create ( struct node *head, struct node *current ) {

    int a;

    printf("Insert: ");
    scanf("%d", &a);
    current = malloc(sizeof(struct node));
    current -> number = a;
    current -> next = NULL;
    head = current;

}

void insert ( struct node *head, struct node *current ) {

    int b;

    printf("insert: ");
    scanf("%d", &b);

    if ( b == -1 ) return;
    else {

        current = malloc(sizeof(struct node));
        current -> number = b;
        current -> next = NULL;

    }

    insert ( head, current );

}

void display ( struct node *temp ) {

    if ( temp != NULL ) {

        printf("%d \t", temp -> number); //Error: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
        temp = temp -> next;

        display ( temp );

    }
    else return;

}

It's more or less the standard code that every book has, but instead of loops I use recursive functions. If you look closely, I have a problem with the display() function. I get this error: EXC_BAD_ACCESS (code=EXC_I386_GPFLT) inside the function, at the printf() line. So I can't print my list on screen. I've been debugging it for like 4 hours now and I can't find what's wrong, any help will be appreciated!

Two major faults:

  1. You have not initialiased the list pointers in main() so their values are effectively random .

  2. You are passing copies of these variables to the create() and insert() functions. These functions have no effect, because the copies are thrown away when the functions return.

The result is when you try to display() the list, you get a crash, as you are passing the still uninitialised pointers.

UPDATE

Here is a revision to your program. The insertion, display and freeing are recursive. Rather than pass a double pointer for the insert() function to modify, it returns the new head of the list. Note that creating the empty list needs no more than setting its pointer to NULL . Also, please see that display() is simpler.

#include <stdio.h>
#include <stdlib.h>

struct node {
    int number;
    struct node *next;
};

struct node *insert (struct node *head) {
   // return new list pointer
    int b = 0;
    struct node *current;
    printf("Insert: ");
    if (1 != scanf("%d", &b) || b == -1)
        return head;
    current = malloc(sizeof(struct node));
    if (current == NULL) {
        printf("Bad malloc!\n");
        exit (1);
        }
    current->number = b;
    current->next = head;
    return insert(current);
}

void display (struct node *list) {
    if (list) {
        printf("%d \t", list->number);
        display(list->next);
    }
}

void free_list (struct node *list) {
    if (list) {
        free_list(list->next);
        free(list);
    }
}

int main(void) {
    struct node *head = NULL;
    head = insert (head);

    printf("List is: ");
    display(head);
    printf("\n");

    free_list (head);
    return 0;
}

Program output:

Insert: 1
Insert: 2
Insert: 3
Insert: 4
Insert: -1
List is: 4      3       2       1

Some minor problems dealt with: not checking the return value from scanf() or from malloc() . It might seem a bore to do this, but in time you will value the routine of checking everything that you do, since most of the language checking in C happens at compiler time, not at run time. At runtime, there is very little protection.

A third problem on top of the one posted by weather vane :

your insert is very weird. You ask for input and then recursively call insert again. Asking for input, ... But you never hook in the current in the chain of the linked list.

Your code contains two problems. Firstly, the functions insert and create should take struct node ** arguments instead of struct node * arguments. Then you need to call them in this way:

  create ( &head, &current );
  insert ( &head, &current );

because otherwise the changes made to head and current do not get reflected in the values of head and current because C has call by value semantics (and call by reference is emulated by using pointers). So, the current = malloc(...); and head = current; lines don't actually change the current and head pointers in the main function, just the local variables.

Then, you need to access them in this style:

  *current = malloc(sizeof(struct node));
  (*current) -> number = a;
  (*current) -> next = NULL;
  *head = *current;

which would be part of the code of the create function.

You're also not actually updating the next link of current node in insert. So, instead of:

    current = malloc(sizeof(struct node));
    current -> number = b;
    current -> next = NULL;

Try this:

    (*current)->next = malloc(sizeof(struct node));
    *current = (*current)->next;
    (*current) -> number = b;
    (*current) -> next = NULL;

I also see a problem in your code that you don't check the return value of malloc. You should never assume that memory allocation is always successful. Handle the NULL return from malloc by printing a descriptive error message and exiting your program.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM