【问题标题】:storing and printing string in void pointer在 void 指针中存储和打印字符串
【发布时间】:2017-04-22 10:38:23
【问题描述】:

我编写了一个链表程序,它将数据成员存储为 void *。 在尝试使用 scanf/printf 函数存储和打印时,我遇到了分段错误。

节点定义 -->

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

主要功能 -->

                head=(node *)malloc(sizeof(node));
                if (head==NULL){
                        printf("error in allocation of memory\n");
                        exit(EXIT_FAILURE);
                }
                tail=(node*)create(head);

创建函数 -->

void *create(node *current)
{
        int user_choice;
        while(current){
                printf("\nEnter the data:");
                scanf("%s",current->data);
                printf("stored at %p\n",(void*)current->data);
                printf("%s",(char*)current->data);
                printf("\nType '1' to continue, '0' to exit:\n");
                scanf("%d",&user_choice);

                if(user_choice == 1){
                        current->next=(node*)malloc(sizeof(node));
                        current=current->next;
                }
                else{
                        current->next=NULL;
                }
        }
        return current;
}

谁能说出 scanf 和 prinf 的正确参数应该是什么?


合并答案中给出的点后的工作代码...

void *create(node *current)
{
        node *temp;
        int user_choice;
        while(current){
                printf("\nEnter the data:");
                current->data=(char*)malloc(10*sizeof(char));
                scanf("%s",current->data);
                printf("stored at %p\n",(void*)current->data);
                printf("%s",(char*)current->data);
                printf("\nType '1' to continue, '0' to exit:\n");
                scanf("%d",&user_choice);

                if(user_choice == 1){
                        current->next=(node*)malloc(sizeof(node));
                }
                else{
                        current->next=NULL;
                        temp=current;
                }
                current=current->next;
        }
        return temp;
}

【问题讨论】:

  • 当用户按0时,函数将返回NULL。有很多错误。请阅读一本书,重新思考你的代码,如果有问题再回来。
  • head 为空,并且您打印错误消息(应该转到stderr,而不是stdout)时,您应该做一些事情,而不是继续下一行,要求head 是非-空值。您的程序有未定义的行为。
  • @PaulOgilvie 感谢您的敏锐观察,我已修改代码以纠正此问题和其他错误。你能再看看是否还有其他问题..?发布在答案中。
  • 我没有看到任何改进。还是有很多错误。
  • @PaulOgilvie,我已经添加了答案,更新了问题......

标签: c pointers linked-list void-pointers


【解决方案1】:

在您的代码中,

 scanf("%s",current->data);

尝试使用未初始化的指针,它调用undefined behavior

您需要遵循以下任一方法,

  • 使指针指向有效的内存块(例如,使用malloc() 和family 进行动态分配)
  • 使用数组。

【讨论】:

  • 我在 main 函数中为 head 分配了内存,在 create 函数中作为 current 传递...
  • @HimanshuSourav 确切地说,你分配给了head,而不是head->data。从这个角度思考。
【解决方案2】:

你应该首先初始化结构的数据成员,因为

current->data  = malloc("passes size here");

要放置数据,您必须首先对该数据进行类型转换,因为 void 不是存储类型。 void 指针可用于指向任何数据类型。

喜欢

*(char *)(current->data) = 1;

【讨论】:

    【解决方案3】:

    请试试这个

    void *create(node *current)
    {
            int user_choice;
            while(true){
                    if(current == NULL) {
                       current = (node *)malloc(sizeof(node));
                       current->data = NULL;
                       current->next = NULL;
                    }
                    printf("\nEnter the data:");
                    scanf("%s",current->data);
                    printf("stored at %p\n", (void *)current->data);
                    printf("%s",current->data);
                    //printf("%s",(char*)current->data);
                    printf("\nType '1' to continue, '0' to exit:\n");
                    scanf("%d",&user_choice);
    
                    if(user_choice == 1){
                            current->next=(node*)malloc(sizeof(node));
                            current=current->next;
                    }
                    else{
                            current->next=NULL;
                            tail = current;
                            current=current->next;
                            break;
                    }
            }
            return current;
    }
    

    注意:在我们尝试使用该元素之前,必须先初始化该元素(即,必须为其分配一些内存)。

    【讨论】:

    • 您在任何时候都没有显示您已经为current->data 分配了任何内存。您也不总是初始化新分配节点的所有元素。在 C 语言中,你总是要考虑“我的指针指向哪里”。
    • current = (node *)malloc(sizeof(node)); 分配节点内存为其元素分配内存,如current->datacurrent->next
    • 但是current->data会持有一个void*指针,使用前需要分配。
    • 我的意思是新节点的数据元素不指向任何东西(它甚至不一定是空指针),而是能够将数据读入指向的空间通过数据元素,您必须首先为其分配空间以指向。
    【解决方案4】:

    正如其他人所说:

    scanf("%s",current->data);
    

    在 C 中未定义。current->data 需要指向某个地方才能在其中存储任何内容。

    你应该改为:

    1. 接受来自scanf的输入。
    2. 存储在临时缓冲区中。
    3. 插入链表
    4. 最后打印出整个链表
    5. free() 链表末尾。

    我也觉得你现在的void *create函数做的太多了,把你的代码拆分成不同的函数会更容易,只是为了更容易处理所有的指针操作,插入等。

    为了演示这些要点,我不久前编写了一些代码来执行这些操作,并且已经过修改以帮助您编写代码。它不是最好的代码,但它确实使用了这些点来帮助您编写代码。

    这里是:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define MAXSTRLEN 100
    
    typedef struct node {
        void *data;
        struct node *next;
    } node_t;
    
    typedef struct {
        node_t *head;
        node_t *foot;
    } list_t;
    
    list_t *create_list(void);
    node_t *generate_node(void);
    list_t *insert_node(list_t *list, char *data);
    void print_list(list_t *list);
    void free_list(list_t *list);
    
    int
    main(int argc, char *argv[]) {
        list_t *list;
        char data[MAXSTRLEN];
        int user_choice;
    
        list = create_list();
    
        while (1) {
            printf("Enter the data: ");
            scanf("%s", data);
    
            printf("\nType '1' to continue, '0' to exit:\n");
            if (scanf("%d",&user_choice) != 1) {
                printf("Invalid input\n");
                exit(EXIT_FAILURE);
            }
    
            if (user_choice == 1) {
                list = insert_node(list, data);
            } else {
                list = insert_node(list, data);
                break;
            }
        }
    
        print_list(list);
    
        free_list(list);
        list = NULL;
    
        return 0;
    }
    
    /* inserting at foot, you can insert at the head if you wish. */
    list_t
    *insert_node(list_t *list, char *data) {
        node_t *newnode = generate_node();
    
        newnode->data = malloc(strlen(data)+1);
        strcpy(newnode->data, data);
    
        newnode->next = NULL;
        if (list->foot == NULL) {
            list->head = newnode;
            list->foot = newnode;
        } else {
            list->foot->next = newnode;
            list->foot = newnode;
        }
        return list;
    
    }
    
    node_t
    *generate_node(void) {
        node_t *new = malloc(sizeof(*new));
        new->data = NULL;
        return new;
    }
    
    void
    print_list(list_t *list) {
        node_t *curr = list->head;
    
        printf("\nlinked list data:\n");
        while(curr != NULL) {
            printf("%s\n", (char*)curr->data);
            curr = curr->next;
        }
    }
    
    list_t
    *create_list(void) {
        list_t *list = malloc(sizeof(*list));
    
        if (list == NULL) {
            fprintf(stderr, "%s\n", "Error allocating memory");
            exit(EXIT_FAILURE);
        }
    
        list->head = NULL;
        list->foot = NULL;
        return list;
    }
    
    void
    free_list(list_t *list) {
        node_t *curr, *prev;
        curr = list->head;
        while (curr) {
            prev = curr;
            curr = curr->next;
            free(prev);
        }
        free(list);
    }
    

    更新:

    还要注意我是如何为newnode-&gt;data 分配内存的?

    像这样:

    newnode->data = malloc(strlen(data)+1); //using buffer from scanf
    

    这意味着我可以在这个指针中存储数据,你的current-&gt;data 需要做类似的事情。

    【讨论】:

      【解决方案5】:

      工作代码-->

      void *create(node *current)
      {
              node *temp;
              int user_choice;
              while(current){
                      printf("\nEnter the data:");
                      current->data=(char*)malloc(10*sizeof(char));
                      scanf("%s",current->data);
                      printf("stored at %p\n",(void*)current->data);
                      printf("%s",(char*)current->data);
                      printf("\nType '1' to continue, '0' to exit:\n");
                      scanf("%d",&user_choice);
      
                      if(user_choice == 1){
                              current->next=(node*)malloc(sizeof(node));
                      }
                      else{
                              current->next=NULL;
                              temp=current;
                      }
                      current=current->next;
              }
              return temp;
      }
      

      【讨论】:

      • @RoadRunner 确实如此:)
      猜你喜欢
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 2021-06-08
      • 2011-09-17
      • 2019-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多