c-链表问题



嘿,我正在尝试创建一个链表。下面的代码段打开文件进行读取,然后将其传递到一个函数中,将字符串分解并放置到一个节点中,该节点假定放置在列表中的适当位置。

    void print_list(struct vm_node  *root);
    int addNodeBottom(char *val, struct vm_node *head);
    struct stock_item* setupNode(char *line);
    int main(int argc, char * argv[]) {
        struct vm vm;
        struct menu_item menu_items[NUM_MENU_ITEMS];
        struct vm_node *vmNode;
        vmNode = malloc(sizeof(struct vm_node));
        /* The UNUSED() function is designed to prevent warnings while your
         * code is only partially complete. Delete these 4 function calls once
         * you are using the data structures declared above in your own code */
        UNUSED(argc);
        UNUSED(argv);
        UNUSED(vm);
        UNUSED(menu_items);
        if (argc != 3) {
            printf("insuffcient arguments n");
            return EXIT_SUCCESS;
        }
        /*open stock file*/
        char* fileName = argv[1];
        FILE *file;
        file = fopen(fileName, "r+");
        char buf[256];
        vmNode->next = NULL;
        while (fgets(buf, sizeof buf, file) != NULL) {
            addNodeBottom(buf,vmNode);
        }
        print_list(vmNode);
        /* Test reason for reaching NULL. */
        if (feof(file)) /* if failure caused by end-of-file condition */
            puts("End of file reached");
        else if (ferror(file)) /* if failure caused by some other error      */
        {
            perror("fgets()");
            fprintf(stderr, "fgets() failed in file %s at line # %dn", __FILE__,
                    __LINE__ - 9);
            exit(EXIT_FAILURE);
        }
        fclose(file);
        return EXIT_SUCCESS;
    }

下面的函数是我如何描述setupNode函数的。

    struct stock_item* setupNode(char *line) {
        struct stock_item *root;
        root = malloc(sizeof(struct stock_item));
        char *ptr;
        const char del[2] = "|";
        const char delm[2] = ".";
        char *prices;
        strcpy(root->id, strtok_r(line, del, &ptr)); // returns the ID and stores in in the root node.
        strcpy(root->name, strtok_r(NULL, del, &ptr)); // returns the description and stores it in the root node.
        strcpy(root->description, strtok_r(NULL, del, &ptr)); // returns the description and stores it in the root node.
        prices = strtok_r(NULL, del, &ptr); // returns a string of the price for vm_item.
        int dol = atoi(strtok(prices, delm));
        int cent = atoi(strtok(NULL, delm));
        root->price.dollars = dol;
        root->price.cents = cent;
        int quantity = atoi(strtok_r(NULL, del, &ptr)); // returns how many items are in stock.
        root->on_hand = quantity;
        return root;
    }

这是addNode函数

    int addNodeBottom(char *val, struct vm_node *head){
        //create new node
        struct vm_node *newNode = malloc(sizeof(struct vm_node));
        if(newNode == NULL){
            printf("%s", "Unable to allocate memory for new noden");
            exit(-1);
        }
        newNode->data = setupNode(val);
        newNode->next = NULL;  // Change 1
        //check for first insertion
        if(head->next == NULL){
            head->data = newNode->data;
            head->next = newNode;
        }
        else
        {
            //else loop through the list and find the last
            //node, insert next to it
            struct vm_node *current = head;
            while (TRUE) { // Change 2
                if(current->next == NULL)
                {
                    current->next = newNode;
                    break; // Change 3
                }
                current = current->next;
            };
        }
        free(newNode);
        return 0;
    }

和printList功能

    void print_list(struct vm_node  *root) {
        while (root) {
            printf("%s ", root->data->id);
            root = root->next;
        }
        printf("n");
    }

这是Defs 类型

    #ifndef VM_TYPE
    #define VM_TYPE
    #define IDLEN 5
    #define NAMELEN 40
    #define DESCLEN 255
    #define NUMDENOMS 8
    #define UNUSED(var) (void)var
    #define COIN_COUNT 20
    #define DEFAULT_ONHAND 20
    /* Type definition for our boolean type */
    typedef enum truefalse
    {
        FALSE, TRUE
    } BOOLEAN;
    /* Each price will have a dollars and a cents component */
    struct price
    {
        unsigned dollars,cents;
    };
    /* The different denominations of coins available */
    enum denomination
    {
        FIVE_CENTS, TEN_CENTS, TWENTY_CENTS, FIFTY_CENTS, ONE_DOLLAR, 
        TWO_DOLLARS, FIVE_DOLLARS, TEN_DOLLARS
    };
    /* Each coin in the coins array will have a denomination (20 cents, 
     * 50 cents, etc) and a count - how many of that coin do we have on hand
     */
    struct coin
    {
        enum denomination denom;
        unsigned count;
    };
    /* The data structure that holds the data for each item of stock
     */
    struct stock_item
    {
        char id[IDLEN+1];
        char name[NAMELEN+1];
        char description[DESCLEN+1];
        struct price price;
        unsigned on_hand;
    };
    /* The data structure that holds a pointer to the stock_item data and a
     * pointer to the next node in the list
     */
    struct vm_node
    {
        struct stock_item * data;
        struct vm_node * next;
    };
    /* The head of the list - has a pointer to the rest of the list and a 
     * stores the length of the list 
     */
    struct vm_list
    {
        struct vm_node * head;
        unsigned length;
    };
    /* This is the head of our overall data structure. We have a pointer to 
     * the vending machine list as well as an array of coins. 
     */
    struct vm
    {
        struct vm_list * item_list;
        struct coin coins[NUMDENOMS];
        char * foodfile;
        char * coinsfile;
    };
    #endif

以及正在被读入以进行解析的文本文件的格式。

 I0001|Coke            |375 ml Can of coke                                         |3.50|50
 I0002|Pepsi           |375 ml Can of pepsi                                        |3.00|20
 I0003|Lemon Cheesecake|A delicious, 1/8 size slice of cheesecake                  |4.00|10
 I0004|Mars Bar        |A delicious 50 g Mars Bar chilled just the way you like it.|3.00|20
 I0005|Lemon Tart      |A delicious lemon butter tart with a pastry based          |3.75|12

尝试打印列表时的输出完全是垃圾,有什么想法吗?

您有未定义的行为,因为在addNodeBottom中,您使例如current->next指向您分配的新节点,然后释放新节点,因此current->next中的指针现在指向未分配的内存。

此外,当设置第一个节点时(当head->nextNULL时),则不设置headnext指针,使其为NULL。相反,要区分是否为空列表,请检查非空data字段:

if (head->data == NULL)
{
    // List is empty
}
else
{
    // List is not empty
}

其他提示:在将新节点实际添加到列表之前,无需分配新节点。找到列表中最后一个节点的循环可以简化为:

vm_node *current;
for (current = head; current->next != NULL; current = current->next)
{
    // Empty loop body
}

在上述循环之后,current将是列表中的最后一个节点,您现在可以分配一个新节点。


如果我重写addNodeBottom函数(不修改函数签名),它看起来像这样(没有任何错误处理):

int addNodeBottom(char *val, struct vm_node *head){
    //create new node
    stock_item *data = setupNode(val);
    if (head->data == NULL)
        head->data = data;
    else
    {
        vm_node *current;
        for (current = head; current->next != NULL; current = current->next)
            ;
        current->next = malloc(sizeof(*current->next));
        current->next->data = data;
        current->next->next = NULL;
    }
    return 0;
}

注意:第一次调用上述函数之前,必须设置vmNode->data = NULL,而不仅仅是vmNode->next

主要问题是因为您要创建一个新节点,在其中存储数据,然后使用free删除新节点。我理解你的逻辑,因为它现在在列表中,所以你不再需要它了。但这不是问题所在。在列表中,您只需放置一个指针,指向您创建的新节点。您不会复制列表中的新节点。您只放置一个指针,该指针指向为您创建的节点分配的内存。如果您释放了内存的这一部分,那么它就不存在了,任何其他应用程序或您的应用程序都可以覆盖这一部分。所以它最终变成了垃圾。

相关内容

  • 没有找到相关文章

最新更新