【问题标题】:Return a pointer from a function, then free the pointer从函数返回一个指针,然后释放指针
【发布时间】:2022-01-07 14:15:45
【问题描述】:

我尝试从命令行argv[] 处理多个名称,然后添加或删除以“+”或“-”开头的名称。 IE +bill +ted -ted 将添加 bill 和 ted 然后删除 ted。我可以毫无问题地将名称添加到此列表中,但我的 removeNode() 函数调用会导致分段错误。在我的 main() 中,当我转到要删除的进程名称时,我将 char * name 设置为等于 removeNode() 的返回指针,它应该是来自被释放节点的字符串。返回此指针的正确方法是什么,以便我可以从命令行中删除我引用的名称?我还包括了我的插入功能。

int insert(struct node ** head, char * name) {
    struct node * newNode = (struct node * ) malloc(sizeof(struct node));
    newNode -> data = name;
    newNode -> next = NULL;
    struct node * current = * head;
    if ( * head == NULL) {
        * head = newNode;
        return 1;
    }
    while (current -> next != NULL) {
        current = current -> next;
    }
    current -> next = newNode;
    return 1;
}

char * removeNode(struct node ** head, char * name) {
    struct node * current = * head;
    struct node * previous;

    if (current == NULL) {
        return "error0";
    }

    if (strcmp(current -> data, name) == 0) {
        char * data = current -> data;
        * head = current -> next;
        free(current);
        printf("Removed %s \n", name);
        return data;
    }
    while (current != NULL) {
        previous = current;
        current = current -> next;
        if (strcmp(current -> data, name) == 0) {
            char * data = current -> data;
            previous -> next = current -> next;
            free(current);
            printf("Removed %s \n", name);
            return data;
        }
    }
    return "error0";
}

int main(int argc, char * argv[]) {
    printf("Author : Torin Costales \n");
    struct node * head = NULL;
    for (int x = 1; x < argc; x++) {
        if (argv[x][0] == '+') {
            char * name = malloc((strlen(argv[x] + 1) + 1));
            if (name == NULL) return EXIT_FAILURE;
            strcpy(name, argv[x]);
            printf("adding %s \n", name);
            insert( & head, name);
            printf("List: ");
            printList( & head);
        } else if (argv[x][0] == '-') {
            printf("removing %s \n", argv[x] + 1);
            char * name = removeNode( & head, argv[x] + 1);
            free(name);
            printList( & head);

        }
    }
}

【问题讨论】:

  • removeNode 释放返回值会导致很大的问题,因为返回值有时是"error0"。另外,不用两行代码分配空间并将argv[x]复制到name,只需使用char *name = strdup(argv[x]);
  • 样式指南:点. 和箭头-&gt; 运算符绑定非常紧密,因为它们是postfix operators。它们的周围不应有空格。写current -&gt; data 不是惯用的C 语言,表示编码器是一个tyro(新手)。使用current-&gt;data

标签: c linked-list argv


【解决方案1】:

导致错误的问题是您正在使用

strcpy(name, argv[x]);

你应该使用的地方

strcpy(name, argv[x] + 1);

这导致在尝试删除 ted 时返回由 "error0" 生成的字符串,因为列表包含 +bill+ted


已修复和清理:

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

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

void printList(struct node *node) {  // Don't need a pointer to a pointer.
    printf("List:");
    for (; node; node = node->next)
        printf(" %s", node->data);
        
    printf("\n");
}

// Returns 0 on success.
// Returns -1 and sets errno on error.
int append(struct node **node_pp, char *name) {  // Better name
   while (*node_pp)
      node_pp = &( (*node_pp)->next );

    struct node *newNode = malloc(sizeof(struct node));
    if (!newNode)
        return -1;

    newNode->data = name;
    newNode->next = NULL;

    *node_pp = newNode;
    return 0;
}

// Returns NULL if not found.
char *removeNode(struct node **node_pp, const char *name) {  // Added `const`
    for (; *node_pp; next_p = &( (*node_pp)->next )) {
        if (strcmp((*node_pp) -> data, name) == 0) {
            struct node * oldNode = *next_p;
            *node_pp = oldNode->next;

            char *data = oldNode->data;
            free(oldNode);
            return data;
        }
    }

    return NULL;  // NULL is a far better value to return on error.
}

int main(int argc, char * argv[]) {
    struct node *head = NULL;
    for (int x = 1; x < argc; x++) {
        if (argv[x][0] == '+') {
            char *name = strdup(argv[x] + 1);  // Simpler
            if (name == NULL) {
                perror("Can't allocate memory");  // Error message is good
                exit(EXIT_FAILURE);
            }

            printf("Appending %s.\n", name);
            if (append(&head, name) < 0) {
                perror("Can't append node to list");
                exit(EXIT_FAILURE);
            }
        } else if (argv[x][0] == '-') {
            const char *name_to_find = argv[x] + 1;
            printf("Removing %s.\n", name_to_find);
            char *name = removeNode(&head, name_to_find);
            if (name) { // Do check if it was found!
               free(name);
            } else {
                printf("%s not found\n", name_to_find);
            }
        }

        printList(head);
        printf("\n");
    }
}

+foo +bar -baz -foo 的输出:

Appending foo.
List: foo

Appending bar.
List: foo bar

Removing baz.
baz not found
List: foo bar

Removing foo.
List: bar

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-07
    • 1970-01-01
    • 2013-10-20
    • 1970-01-01
    • 2021-11-04
    • 2013-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多