花算子 2024-08-12 22:00 采纳率: 83.3%
浏览 12
已结题

C primer plus编程练习的bug:无法malloc()

《C primer plus》第十七章编程练习倒数第二题:
本程序想要实现的功能是:
让用户输入一个文件名,程序识别文件里的所有单词,并让用户选择想要进行的操作:
1、列出所有单词和它出现的次数。
2、用户输入一个单词,程序打印它出现的次数,如果没有就打印:

No that word!

3、退出。
但是:每次到addItem()时,总是会无法malloc()

main.c

#include <stdio.h>
#include <string.h>
#include "tree.h"

void printItem(Item item)
{

    printf("%-20s:    %d", item.name, item.number);

}

char show()
{

    char choice;

    printf("Pleas choice what you want to do:\nl)ist all the words    c)hoose a word\nq)uit this program\n:");
    scanf("%c", &choice);

    return choice;

}

void find(Tree * tree)
{

    char   word[20];
    Item   item;
    Item * point;

    printf("Please enter a word:");
    scanf("%s", word);

    if(isTreeEmpty(tree))
    {

        printf("No words!\n");

        return;

    }

    strcpy(item.name, word);

    if(!findItem(&item, tree))
    {

        printf("No that word!\n");

        return;

    }

    while(getchar() != '\n')
        continue;

    point = whereIsItem(&item, tree);

    printf("There is %d of that.\n", point->number);

}

void list(Tree * tree)
{

    everyone(tree, printItem);

}

int main()
{

    Tree   words;
    FILE * file;
    char   filename[40];
    char   word[20];
    char   choice;
    Item   temp;

    makeTree(&words);

    printf("Enter a file name:");
    scanf("%s", filename);

    file = fopen(filename, "r");

    if(file == NULL)
    {

        printf("Can't open file.\n");

        return 1;

    }

    makeTree(&words);

    while(getchar() != '\n')
    continue;

    while(fscanf(file, "%s", word) == 1)
    {

        strcpy(temp.name, word);

        addItem(&temp, &words);

    }

    choice = show();

    for(int i = 0; i > -1; i++)
    {

        switch(choice)
        {

            case 'l':

                list(&words);
                break;
    
            case 'c':

                find(&words);
                break;

            case 'q':

                break;

            default:

                printf("Pleas enter l, c or q.\n");

        }

    }
    emptyTree(&words);

    fclose(file);

    printf("Bye-bye~~~\n");

    return 0;

}

implement_tree.c

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

typedef struct pair
{

    Node * parent;

    Node * child;

} Pair;

static bool ToLeft(const Item *, const Item *);

static bool ToRight(const Item *, const Item *);

static void inOrder(const Node * node, void (*func)(Item item))
{

    if(node != NULL)
    {

        inOrder(node->left,  func);

        (*func)(node->item);

        inOrder(node->right, func);

    }

}

static void deletAllNodes(Node * root)
{

    Node * right;

    if(root != NULL)
    {

        right = root->right;

        deletAllNodes(root->left);

        free(root);

        deletAllNodes(right);

    }

}

static void addNode(Node * new_node, Node * root)
{

    if(ToLeft(&new_node->item, &root->item))
    {

        if(root->left == NULL)
        {

            root->left = new_node;

        }
        else
        {

            addNode(new_node, root->left);

        }

    }
    else if(ToRight(&new_node->item, &root->item))
    {

        if(root->right == NULL)
        {

            root->right = new_node;

        }
        else{

            addNode(new_node, root->right);

        }

    }
    else
    {

        fprintf(stderr, "ERROR!!!!!!");

        exit(1);

    }

}

static bool ToLeft(const Item * item1, const Item * item2)
{

    int comp1;

    if((comp1 = strcmp(item1->name, item2->name)) < 0)
    {

        return true;

    }
    else if(comp1 == 0 && item1->number < item2->number)
    {

        return true;

    }
    else
    {

        return false;

    }

}

static bool ToRight(const Item * item1, const Item * item2)
{

    int comp1;

    if((comp1 = strcmp(item1->name, item2->name)) > 0)
    {

        return true;

    }
    else if(comp1 == 0 && item1->number > item2->number)
    {

        return true;

    }
    else
    {

        return false;

    }

}

static Node * makeNode(const Item * item)
{

    Node * node;

    node = (Node *)malloc(sizeof(Node));

    if(node != NULL)
    {

        node->item  = *item;
        node->left  = NULL;
        node->right = NULL;

    }

    return node;

}
static Pair seekItem(const Item * item, const Tree * tree)
{

    Pair look;

    look.parent = NULL;

    look.child  = tree->root;

    if(look.child == NULL)
    {

        return look;

    }

    while(look.child != NULL)
    {

        if(ToLeft(item, &(look.child->item)))
        {

            look.parent = look.child;

            look.child  = look.child->right;

        }else if(ToRight(item, &(look.child->item)))
        {

            look.parent = look.child;

            look.child  = look.child->right;

        }else
        {

            break;

        }

    }

    return look;

}

static void deletNode(Node ** node)
{

    Node * temp;

    if((*node)->left == NULL)
    {

        temp = *node;

        *node = (*node)->right;

        free(temp);

    }
    else if((*node) ->right == NULL)
    {

        temp = *node;

        *node = (*node)->left;

        free(temp);

    }
    else
    {

        for(temp = (*node)->left; temp->right != NULL; temp = temp->right)

            continue;

        temp->right = (*node)->right;

        temp = *node;

        *node = (*node)->left;

        free(temp);

    }

}

/*----主要接口----*/

void makeTree(Tree * tree)
{

    tree->root = NULL;

    tree->size = 0;

}

bool isTreeEmpty(const Tree * tree)
{

    if(tree->root == NULL)

        return true;

    else

        return false;

}

bool isTreeFull(const Tree * tree)
{

    if(tree->size == MAXITEM)

        return true;

    else

        return false;

}

int howMany(const Tree * tree)
{

    return tree->size;

}

bool addItem(const Item * item, Tree * tree)
{

    Node * new_node;

    if(isTreeFull(tree))
    {

        fprintf(stderr, "Tree is full");

        return false;

    }

    if(seekItem(item, tree).child != NULL)
    {

        seekItem(item, tree).child->item.number++;

        return false;

    }

    new_node = makeNode(item);

    if(new_node == NULL)
    {

        fprintf(stderr, "ERROR!!!!!!!!!");

        return false;

    }

    tree->size++;

    if(tree->root == NULL)

        tree->root = new_node;

    else

        addNode(new_node, tree->root);

    return true;

}

bool  findItem(const Item * item, const Tree * tree)
{

    return (seekItem(item, tree).child == NULL) ? true : false;

}

Item * whereIsItem(const Item * item, const Tree * tree)
{

    Node * node;

    node = seekItem(item, tree).child;
    if(node != NULL)
        return &(node->item);
    else
        return NULL;

}

bool deletItem(const Item * item, Tree * tree)
{

    Pair look;

    look = seekItem(item, tree);

    if(look.child == NULL)
    {

        return false;

    }
    if(look.parent == NULL)
    {

        deletNode(&tree->root);

    }
    else if(look.parent->left == look.child)
    {

        deletNode(&look.parent->left);

    }
    else
    {

        deletNode(&look.parent->right);

    }

    tree->size--;

    return true;

}

void everyone(const Tree * tree, void (*pfun)(Item item))
{

    if(tree != NULL)
    {

        inOrder(tree->root,pfun);

    }

}

void emptyTree(Tree * tree)
{

    if(tree != NULL)
    {

        deletAllNodes(tree->root);

    }

    tree->root = NULL;

    tree->size = 0;

}

tree.h

#ifndef _TREE_H_
#define _TREE_H_

#include <stdbool.h>

#define SLEN    20
#define MAXITEM    10

typedef struct item
{

    char name[SLEN];

    int number;

} Item;
typedef struct node
{

    Item item;

    struct node * left;

    struct node * right;

} Node;
typedef struct tree
{

    Node * root;
    
    int size;

} Tree;

void    makeTree(Tree * tree);
bool    isTreeEmpty(const Tree * tree);
bool    isTreeFull(const Tree * tree);
int    howMany(const Tree * tree);
bool    addItem(const Item * item, Tree * tree);
bool    findItem(const Item * item, const Tree * tree);
Item *  whereIsItem(const Item * item, const Tree * tree);
bool    deletItem(const Item * item, Tree * tree);
void    everyone(const Tree * tree, void (*pfun)(Item item));
void    emptyTree(Tree * tree);

#endif
  • 写回答

10条回答 默认 最新

  • bug菌¹ 优质创作者: Java、算法与数据结构技术领域 2024-08-12 22:39
    关注

    该回答引用ChatGPT,望对题主有所帮助/启发;若有帮助,还望采纳🤝🤝🤝


    在你的代码中,addItem() 函数里调用 seekItem() 来查找元素时存在一个问题,导致内存分配失败。这个问题通常出现在查找函数的实现上,即在函数 seekItem() 中,有可能会导致程序访问错误的节点或递归时方向判断不正确。

    以下是修复问题的建议:

    修复 seekItem 函数

    seekItem() 函数中,你在进行递归查找时,使用了 look.child = look.child->right;,这可能是个逻辑错误。对于向左查找的情况,应该是 look.child = look.child->left;

    修复后的代码

    static Pair seekItem(const Item * item, const Tree * tree)
    {
        Pair look;
        look.parent = NULL;
        look.child  = tree->root;
    
        while(look.child != NULL)
        {
            if(ToLeft(item, &(look.child->item)))
            {
                look.parent = look.child;
                look.child  = look.child->left;  // 修正了这个地方
            }
            else if(ToRight(item, &(look.child->item)))
            {
                look.parent = look.child;
                look.child  = look.child->right;
            }
            else
            {
                break;  // 找到了元素,退出循环
            }
        }
        return look;
    }
    

    调试 malloc 的使用

    如果 seekItem() 的逻辑修复后仍然存在 malloc() 失败的问题,可以考虑以下步骤:

    1. 检查内存是否不足:虽然这通常不是问题,但可以通过检查分配的内存大小和可用内存来确认。

    2. 使用调试工具:使用诸如 valgrind 等工具来检测内存泄漏或非法内存访问。

    3. 确保malloc()前后没有对内存的破坏:确保在调用 malloc() 前,内存没有被其他地方的代码破坏(例如数组越界、非法指针操作等)。

    其他潜在问题

    • 确保每次调用 seekItem() 的输入参数都是正确的 Item 指针和有效的 Tree 指针。
    • addItem() 函数中,如果 seekItem() 找到了现有节点,则应该增加其计数,而不需要尝试重新分配内存。

    在修复这些问题后,你的代码应该能够正确地执行 malloc() 并分配新的节点。如果问题仍然存在,请继续详细检查内存的使用,特别是在 makeNode()addNode() 函数中。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(9条)

报告相同问题?

问题事件

  • 系统已结题 8月21日
  • 已采纳回答 8月13日
  • 创建了问题 8月12日