【问题标题】:Problems with Linked List of String in CC中字符串链表的问题
【发布时间】:2021-01-10 02:21:55
【问题描述】:

我正在尝试制作一个 minishell 并存储用户键入的所有命令,当用户输入 history 它应该显示用户迄今为止输入的所有命令,当用户输入 history -c 然后它应该清除链表。

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>

typedef struct node
{
    char* data;
    struct node *next;
} node;

node *create_node(char* data)
{
    node *ptr = malloc(sizeof(node));
    if (ptr == NULL)
    {
        fprintf(stderr, "Error: Out of memory in create_node()\n");
        exit(1);
    }
    
    ptr->data = data;
    ptr->next = NULL;
    return ptr;
}

node *insert_node(node *head, char* data)
{
    node *temp;
    if (head == NULL)
        return create_node(data);
    temp = head;
    while (temp->next != NULL)
    {     
        temp = temp->next;
    }
    // 'temp' is pointing to the last node in the list now.
    temp->next = create_node(data);
    return head;
}

void print_list(node *head)
{
    node *temp;
    if (head == NULL)
    {
        printf("(empty list)\n");
        return;
    }

    for (temp = head; temp != NULL; temp = temp->next)
        printf("%s%c", (char*)temp->data, '\n');
}

int main (int argc, char ** argv)
{
    char buf[1024];
    char * args[MAX_ARGS];
    char ** arg;
    node *head = NULL;
    while (1)
    {
        printf("#");
        if (fgets (buf, 1024, stdin ))
        {
            head = insert_node(head, buf);
            arg = args;
            *arg++ = strtok(buf, SEPARATORS);  // tokenize input
            while ((*arg++ = strtok(NULL, SEPARATORS)));
            if (args[0])
            {
                //#byebye command, exist the while loop.
                if (!strcmp(args[0], "byebye")) {
                    break;
                }      
  
                if (!strcmp(args[0], "history"))
                {
                    // command history with flag c

                    if (args[1] && !strcmp(args[1], "-c"))
                    {
                        // clear the linked list
                    } 
                    else
                    {
                        print_list(head);
                        printf("\n");
                    }
                    continue;
                }
                arg = args;
                while (*arg) fprintf(stdout, "%s ", *arg++);
                fputs ("\n", stdout);
            }
        }
    }
    return 0;
}

但这是我的输出:

#你好 你好 #添加 添加 #列出 列出 #历史 历史 历史 历史 历史

所以,不是打印出所有命令,而是打印出history,我不知道我做错了什么。请帮忙,我已经有一段时间没有接触 C 和指针了。

【问题讨论】:

  • ptr-&gt;data = malloc(sizeof(char*)); ptr-&gt;data = (char*)data; 有点奇怪。这是一个非常小的分配,而且,如果你试图复制一个字符串,那只会覆盖指向刚刚分配的内存的指针。虽然代码很难阅读:太多的空格。
  • 您是否尝试单步执行代码?
  • 您所做的只是移动指针。你没有复制任何东西。在 create_node 中,您只需将 *data 分配给 node-&gt;data。你没有复制
  • create_node。您分配一个新节点,但您将传入的数据指针分配给节点中的数据指针。没有字符副本。看看@Remy Lebeau 是如何做到的
  • 是的,我做了@Quimby,它似乎工作正常,因为我使用 print 语句来查看正在存储的字符串,它似乎工作正常,直到我输入历史并且突然所有链接列表都有历史作为数据而不是原始数据

标签: c string linked-list


【解决方案1】:

您的create_node() 实现错误。

您正在为node::data 成员泄漏malloc() 的内存,因为您立即重新分配node::data 以指向输入char* 参数指向的同一内存,从而丢失malloc'ed 内存。

因此,您创建的所有节点最终都指向main() 中的同一个char[] 缓冲区,用户输入的每个字符串都会重复使用该缓冲区。

create_node() 需要制作char 数据的副本,这可能是您打算做的,但没有正确地做。试试这个:

node *create_node(char* data)
{
    node *ptr = malloc(sizeof(node));
    if (ptr == NULL)
    {
        fprintf(stderr, "Error: Out of memory in create_node()\n");
        exit(1);
    }

    ptr->data = strdup(data);
    ptr->next = NULL;

    if (ptr->data == NULL)
    {
        fprintf(stderr, "Error: Out of memory in create_node()\n");
        free(ptr);
        exit(1);
    }

    return ptr;
}

然后你需要添加一个新函数来释放每个节点及其data,当你完成使用它时,例如:

node* free_node(node* n)
{
    node *next = n->next;
    free(n->data);
    free(n);
    return next;
}

...

int main (int argc, char ** argv)
{
    node *head = NULL;
    ...

    while (head != NULL) {
        head = free_node(head);
    }

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-13
    • 2010-12-07
    • 2016-07-23
    • 2021-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多