【问题标题】:C- Linked List with *charsC- 带 *chars 的链表
【发布时间】:2021-08-12 21:03:21
【问题描述】:

我正在尝试构建一个简单的链表。

我已经成功地建立了一个只有 int 变量的链表,但是当我添加 *char 变量时,输出是错误的。

int 值似乎正确,但 *char 类型错误。

*char 类型似乎总是最后插入的。

示例输入

Number: 5
Character: a

Number: 4
Character: b

样本输出

5
b

**************

4
b


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

typedef struct BOOKS
{
    int value;
    char *char_value;
    struct BOOKS *next;
} BOOKS;

BOOKS *insert_value(BOOKS *node, int n, char *char_value);

BOOKS *read_list(BOOKS *head);

int main()
{
    int aux = 0;
    int menu = 0;
    int option;
    BOOKS *head = NULL;
    BOOKS *tail = NULL;

    while (menu != -2)
    {

        int choices;
        printf("1. Insert Book\n");
        printf("2. Print Books\n");
        printf("3. Exit\n");

        scanf("%d", &choices);
        switch (choices)
        {
        case 1:
        {
            int n;
            char char_value[2000] = "";
            printf("Number:");
            scanf("%d", &n);
            printf("Character: ");
            scanf("%s", &char_value);

            if (aux == 0)
            {
                /*FIRST INTERACTION*/
                head = malloc(sizeof(BOOKS));
                tail = malloc(sizeof(BOOKS));
                head = tail = insert_value(tail, n, char_value);
                aux = 1;
            }
            else
            {

                tail->next = malloc(sizeof(BOOKS));
                /*FORMING TAIL->NEXT*/
                tail->next = insert_value(tail->next, n, char_value);
                /*ASSIGNING TAIL->NEXT AS THE NEW TAIL */
                tail = tail->next;
            }
            break;
        }
        case 2:
        { /*READ THE LIST*/
            read_list(head);
            break;
        }
        case 3:
        {

            menu = -2;
            break;
        }

        default:
            printf("Invalid choice\n");
            break;
        }
    }
}

BOOKS *insert_value(BOOKS *node, int n, char *char_value)
{
    node->value = n;
    node->char_value = char_value;
    node->next = NULL;
    return node;
}

BOOKS *read_list(BOOKS *head)
{
    BOOKS *a = head;
    while (a != NULL)
    {

        printf("%d\n", a->value);
        printf("%s\n", a->char_value);
        printf("\n********************\n");
        a = a->next;
    }
}

【问题讨论】:

  • node-&gt;char_value = char_value; ... 但您实际上并没有 malloc 和 copy.the 字符串。您让node-&gt;char_value 指向外部的char_value,这与您用于所有插入的char_value 相同。
  • 在 Ted 的评论中添加 insert_value,将 node-&gt;char_value = char_value; 更改为 node-&gt;char_value = strdup(char_value);
  • node-&gt;char_value = char_value 不复制字符串,它只复制指针。如果您希望每个节点都有自己的字符串副本,那么您必须以某种方式为每个节点中的字符串分配足够的空间。一种方法是使用函数malloc。您还可以让每个节点包含固定数量的字节,但这可能会浪费大量内存。
  • 谢谢大家真的很有帮助!!!!
  • @CraigEstey POSIX 只是添加了 C 标准对 libc 的要求,例如 ISO/IEC 9899:2018。因此,您可以在没有 strdup 的情况下拥有完全兼容的 C 实现。

标签: c linked-list


【解决方案1】:

您将char_valuemain 传递给insert_books 函数,然后将此指针保存在新创建的node 中。 char_valuemain 的地址不会改变,因此您将相同的地址保存到您创建的每个 node。由于所有这些指针都指向同一个地方,它们都会读回最后写入的任何值。如果要在每个node 中复制字符串,可以使用(非标准)strdupmalloc 更多内存并使用strcpy。但是,无论如何您都使用字符数组来接受一个字符,这是一个奇怪的设计选择。我建议将mainstruct BOOKS 中的char_value 更改为char char_value;,然后您可以像value 一样简单地使用等于分配来保存字符的副本。请务必scanf a char the correct way

其他几件事:

如前所述,您可以将scanf("%s", &amp;char_value); 更改为scanf("%s", char_value);char_value是一个字符数组,在这种情况下衰减为char*,不需要指定char_value的地址。

head = malloc(sizeof(BOOKS));
tail = malloc(sizeof(BOOKS));
head = tail = insert_value(tail, n, char_value);

这是内存泄漏。您正在为headtail 分配单独的内存,但随后将两个指针设置为等于为tail 分配的内存(insert_value 的返回值)。为head 分配的内存从未被freed 使用过。

【讨论】:

    【解决方案2】:

    这将有助于解决错误:-

    #include <stdio.h>
    #include<string.h>
    #include <stdlib.h>
    
    typedef struct BOOKS
    {
        int value;
        char char_value[2000];
        struct BOOKS *next;
    } BOOKS;
    
    BOOKS *insert_value(BOOKS *node, int n, char *char_value);
    
    BOOKS *read_list(BOOKS *head);
    
    int main()
    {
        int aux = 0;
        int menu = 0;
        int option;
        BOOKS *head = NULL;
        BOOKS *tail = NULL;
    
        while (menu != -2)
        {
    
            int choices;
            printf("1. Insert Book\n");
            printf("2. Print Books\n");
            printf("3. Exit\n");
    
            scanf("%d", &choices);
            switch (choices)
            {
            case 1:
            {
                int n;
                char char_value[2000];
                printf("Number:");
                scanf("%d", &n);
                printf("Character: ");
                scanf("%s", char_value);
    
                if (aux == 0)
                {
                    /*FIRST INTERACTION*/
                    head = malloc(sizeof(BOOKS));
                    tail = malloc(sizeof(BOOKS));
                    head = tail = insert_value(tail, n, char_value);
                    aux = 1;
                }
                else
                {
    
                    tail->next = malloc(sizeof(BOOKS));
                    /*FORMING TAIL->NEXT*/
                    tail->next = insert_value(tail->next, n, char_value);
                    /*ASSIGNING TAIL->NEXT AS THE NEW TAIL */
                    tail = tail->next;
                }
                break;
            }
            case 2:
            { /*READ THE LIST*/
                read_list(head);
                break;
            }
            case 3:
            {
    
                menu = -2;
                break;
            }
    
            default:
                printf("Invalid choice\n");
                break;
            }
        }
    }
    
    BOOKS *insert_value(BOOKS *node, int n, char *char_value)
    {
        node->value = n;
        int size = sizeof(char_value)/sizeof(char);
        strncpy(node->char_value, char_value, size);
        node->next = NULL;
        return node;
    }
    
    BOOKS *read_list(BOOKS *head)
    {
        BOOKS *a = head;
        while (a != NULL)
        {
    
            printf("%d\n", a->value);
            printf("%s\n", a->char_value);
            printf("\n********************\n");
            a = a->next;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-26
      • 2010-12-19
      • 1970-01-01
      • 1970-01-01
      • 2012-05-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多