【问题标题】:Singly linked list C, printing单链表 C、打印
【发布时间】:2016-06-15 12:52:05
【问题描述】:

我是开发的初学者,所以我的老师给了我一个任务来完成,我需要在链表中输入几个字符串,在我输入 print 后,它们需要以正确的顺序打印,从第一个到最后。

这是我得到的:

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

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

char createlist(node *pointer, char data[100]) {
    while (pointer->next != NULL) {
        pointer = pointer->next;
    }

    pointer->next = (node*) malloc(sizeof(node));
    pointer = pointer-> next;
    pointer->data = *data;
    pointer->next = NULL;
}

int main() {
    node *first, *temp;
    first = (node*) malloc(sizeof(node));
    temp = first;
    temp->next = NULL;

    printf("Enter the lines\n");
    while (1) {
        char data[100];
        gets(data);
        createlist(first, data);
        if (strcmp(data, "print") == 0)
            printf("%s\n", first->data);
        else if (strcmp(data, "quit") == 0)
            return (0);

    };

}

当我运行它时,我得到: 输入以下行: asdfsdf 打印 (空)

任何帮助将不胜感激,因为这是我第一次使用链表。

【问题讨论】:

  • 请注意,他们说的是you shouldn't cast the result of malloc() in C
  • 你不应该使用gets(),它有不可避免的缓冲区溢出风险。
  • 您应该在第一次使用调试器时进行。
  • 将错误类型的数据传递给%s for printf() 调用未定义的行为
  • 没有那个就不行。我正在使用 Kdevelop。

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


【解决方案1】:
  • 您应该正确地格式化您的代码。
  • first-&gt;data 是通过malloc() 分配的并且没有被初始化,所以使用它的值会调用未定义的行为
  • 为了不特别处理第一个元素,你应该使用指针指针让createlist()修改first
  • 由于createlist() 不会返回任何内容,其返回值的类型应为void
  • 我猜你想复制字符串而不是分配每个字符串的第一个字符。
  • 要打印您输入的所有内容,必须编写执行此操作的代码。
  • 您不应该使用gets(),它有不可避免的缓冲区溢出风险。
  • 您应该free() 分配您通过malloc() 分配的任何内容。

改进的代码:

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

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

void createlist(node **pointer, char data[100])
{
    while (*pointer != NULL)
    {
        pointer = &(*pointer)->next;
    }

    *pointer = malloc(sizeof(node));
    if (*pointer == NULL)
    {
        perror("malloc 1");
        exit(1);
    }
    (*pointer)->data = malloc(strlen(data) + 1);
    if ((*pointer)->data == NULL)
    {
        perror("malloc 2");
        exit(1);
    }
    strcpy((*pointer)->data, data);
    (*pointer)->next = NULL;
}

int main(void)
{
    node *first = NULL;

    printf("Enter the lines\n");
    while (1)
    { 
        char data[100], *lf;
        if (fgets(data, sizeof(data), stdin) == NULL) strcpy(data, "quit");
        if ((lf = strchr(data, '\n')) != NULL) *lf = '\0'; /* remove newline character */
        createlist(&first, data);
        if (strcmp(data, "print") == 0)
        {
            node *elem = first;
            while (elem != NULL)
            {
                printf("%s\n", elem -> data);
                elem = elem->next;
            }
        }
        else if (strcmp(data, "quit") == 0)
        {
            while (first != NULL)
            {
                node *next = first->next;
                free(first->data);
                free(first);
                first = next;
            }
            return(0);
        }

    }

}

【讨论】:

  • 感谢您的帮助。我收到以下错误: main.cpp:18:35: error: invalid conversion from ‘void*’ to ‘node* {aka Node*}’ [-fpermissive] pointer = malloc(sizeof(node)); main.cpp:24:47: 错误:从 'void' 到 'char*' 的无效转换 [-fpermissive] (*pointer)->data = malloc(strlen(data) + 1);
  • @Mirakurun 使用 C 编译器,而不是 C++ 编译器。这个问题在标题和标签中都标记为C,代码是C。你到底为什么把这段代码编译成C++?
  • 是的,那是我的错,甚至没有看到我的扩展名是 cpp。我刚刚在 Kdevelop 上配置了 C,它完美无缺。再次感谢您。
【解决方案2】:

createlist() 中,您正在迭代到列表的末尾。在那里,您正在添加一个新节点并设置输入的新文本。通过这样做,您会错过已经拥有第一个节点的信息。因为您在每次调用 createlist() 时都在迭代到最后,所以您每次都跳过您的第一个节点,所以它仍然没有文本并传递 NULL

为了不跳过第一个初始节点,您可以像这样更改createlist()

char createlist(node *pointer, char data[100])
{
   while (pointer->data != NULL && pointer->next != NULL)
   {
     pointer = pointer->next;
   }
   ...
   ... 
}

或者您可以不创建第一个节点,而是仅在输入第一行文本之后创建。


编辑:这里有两个额外的样式提示:

  • 如果有人输入 120 个字符会怎样?文本将超出您的 char[100] 数组,并将填满其他使用的 RAM。这是缓冲区溢出。您可以尝试仅获取前 100 个字符,获取 substring。或者,使用 fgets()

  • 的长度参数
  • 为 100 创建一个常量,例如 #define MAX_BUFFER_LENGTH 100,并每次都使用它。

【讨论】:

  • 谢谢!你们两个都帮了我很多。
  • 很高兴帮助 :-) 玩得开心。
猜你喜欢
  • 2016-01-21
  • 1970-01-01
  • 1970-01-01
  • 2014-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多