【问题标题】:我在 C 中的结构链表有问题
【发布时间】:2022-01-23 12:20:36
【问题描述】:

我必须创建一个结构书的链接列表,我的问题是当我创建一个新节点并在其中输入新书的属性时,我以前节点中的所有以前的书都将它们的名称更改为最后一个我进入了,尽管出版年份仍然是原始的。有人可以解释这是如何工作的,以及我必须做些什么才能使其正常工作?

这是我的代码

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

#define N 255

struct Book {
    char *title;
    int year;
};

struct Node {
    struct Book book;
    struct Node *next;
};

struct Book createBook(char *title, int year) {
    struct Book book = {title, year};
    return book;
}

void print(struct Node *head) {
    struct Node *curr_node = head;

    while (curr_node != NULL) {
        printf("%s(%d)\n", curr_node->book.title, curr_node->book.year);
        curr_node = curr_node->next;
    }
}

void add(struct Node **head, struct Book book) {
    struct Node *new_node;
    struct Book *new_book;
    new_node = (struct Node*) malloc(sizeof( struct Node ));

    new_book = &new_node->book;

    new_book->title = book.title;
    new_book->year = book.year;

    new_node->next = (*head);
    *head = new_node;
}

void pop(struct Node **head) {
    struct Node *next_node = NULL;

    if (*head == NULL) {
        printf("List is empty!");
        return;
    }

    next_node = (*head)->next;
    free(*head);
    *head = next_node;
}

void reverse(struct Node **head) {
    struct Node *prev_node = NULL;
    struct Node *curr_node = *head;
    struct Node *next_node = NULL;

    while (curr_node != NULL) {
        next_node = curr_node->next;
        curr_node->next = prev_node;
        prev_node = curr_node;
        curr_node = next_node;
    }

    *head = prev_node;
}

void clear(struct Node **head) {

    struct Node *curr_node = *head;
    struct Node *temp_node = NULL;

    while (curr_node != NULL) {
        temp_node = curr_node->next;
        free(curr_node);
        curr_node = temp_node;
    }

    *head = NULL;
}

int main() {

    struct Node *head = NULL;

    short process = 1; // 1 for True 0 for False
    int option = 0;
    char title[N];
    int year = 0;

    while (process) {

        printf("List of actions:\n");
        printf("1:\tAdd element\n");
        printf("2:\tRemove element\n");
        printf("3:\tReverse list\n");
        printf("4:\tPrint list\n");
        printf("5:\tClear list\n");
        printf("0:\tExit\n");

        scanf("%d", &option);

        switch (option) {

            case 1:
                printf("Enter book\'s title: ");
                scanf("%s", title);
                printf("Enter book\'s year of publishing: ");
                scanf("%d", &year);
                add(&head, createBook(title, year));
                printf("\n");
                break;
            case 2:
                pop(&head);
                break;
            case 3:
                reverse(&head);
                break;
            case 4:
                print(head);
                break;
            case 5:
                clear(&head);
                break;
            case 0:
                process = 0;
                break;
            default:
                printf("\n");
                printf("**************************\n");
                printf("Enter numbers from 1 to 5!\n");
                printf("**************************\n");
                printf("\n");
                continue;
        }
    }
    return 0;
}

【问题讨论】:

  • 下次C题不要加C++标签。

标签: c pointers struct linked-list singly-linked-list


【解决方案1】:

您总是将指针传递给 main 中声明的同一个本地数组 title

 char title[N];

到函数createBook

add(&head, createBook(title, year));

所以所有节点的数据成员title

struct Book {
    char *title;
    int year;
};

由于函数内的初始化,指向在main 中声明的同一个本地数组title

struct Book book = {title, year};

即在main 中声明的局部数组title 用作函数createBook 的参数表达式,被隐式转换为指向其第一个元素的指针。并且所有函数调用都处理数组第一个元素的相同地址。

您需要为每个节点动态分配引用数组title 的副本。

另一种方法是将结构Book 的数据成员title 声明为具有字符数组类型而不是指针类型。

【讨论】:

    【解决方案2】:

    谢谢,现在一切正常!

    在 switch 语句之前,我在 main 函数的 while 循环中为我的 char 指针分配了内存:

    char *title = (char *) calloc(N, sizeof(char));

    所以现在工作代码如下所示:

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    
    #define N 255
    
    struct Book {
        char *title;
        int year;
    };
    
    struct Node {
        struct Book book;
        struct Node *next;
    };
    
    struct Book createBook(char *title, int year) {
        struct Book book = {title, year};
        return book;
    }
    
    void print(struct Node *head) {
        struct Node *curr_node = head;
    
        while (curr_node != NULL) {
            printf("%s(%d)\n", curr_node->book.title, curr_node->book.year);
            curr_node = curr_node->next;
        }
    }
    
    void add(struct Node **head, struct Book book) {
        struct Node *new_node;
        struct Book *new_book;
        new_node = (struct Node*) malloc(sizeof( struct Node ));
    
        new_book = &new_node->book;
    
        new_book->title = book.title;
        new_book->year = book.year;
    
        new_node->next = (*head);
        *head = new_node;
    }
    
    void pop(struct Node **head) {
        struct Node *next_node = NULL;
    
        if (*head == NULL) {
            printf("List is empty!");
            return;
        }
    
        next_node = (*head)->next;
        free(*head);
        *head = next_node;
    }
    
    void reverse(struct Node **head) {
        struct Node *prev_node = NULL;
        struct Node *curr_node = *head;
        struct Node *next_node = NULL;
    
        while (curr_node != NULL) {
            next_node = curr_node->next;
            curr_node->next = prev_node;
            prev_node = curr_node;
            curr_node = next_node;
        }
    
        *head = prev_node;
    }
    
    void clear(struct Node **head) {
    
        struct Node *curr_node = *head;
        struct Node *temp_node = NULL;
    
        while (curr_node != NULL) {
            temp_node = curr_node->next;
            free(curr_node);
            curr_node = temp_node;
        }
    
        *head = NULL;
    }
    
    int main() {
    
        struct Node *head = NULL;
    
        short process = 1; // 1 for True 0 for False
        int option = 0;
    
        int year = 0;
    
        while (process) {
    
            printf("List of actions:\n");
            printf("1:\tAdd element\n");
            printf("2:\tRemove element\n");
            printf("3:\tReverse list\n");
            printf("4:\tPrint list\n");
            printf("5:\tClear list\n");
            printf("0:\tExit\n");
    
            scanf("%d", &option);
            char *title = (char *) calloc(N, sizeof(char));
            switch (option) {
    
                case 1:
    
                    printf("Enter book\'s title: ");
                    scanf("%s", title);
                    printf("Enter book\'s year of publishing: ");
                    scanf("%d", &year);
                    add(&head, createBook(title, year));
                    printf("\n");
                    break;
                case 2:
                    pop(&head);
                    break;
                case 3:
                    reverse(&head);
                    break;
                case 4:
                    print(head);
                    break;
                case 5:
                    clear(&head);
                    break;
                case 0:
                    process = 0;
                    break;
                default:
                    printf("\n");
                    printf("**************************\n");
                    printf("Enter numbers from 1 to 5!\n");
                    printf("**************************\n");
                    printf("\n");
                    continue;
            }
        }
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2011-05-30
      • 2017-06-14
      • 2023-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多