c包含struct的打印树

时间:2014-05-17 08:29:00

标签: c printing struct tree

我正在尝试编写二叉树程序,其中树的节点包含“库存”结构。 程序应该从txt文件中读取并将信息插入树中(按部件号排序)。

我遇到的问题是我无法弄清楚为什么print_inorder函数会导致我的程序崩溃。

这是我的代码:

#include "stdafx.h"
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>



typedef struct inventory
{
    char invName[36];
    int  invPartNo;
    int  invQOH;
    float invUnitCost;
    float invPrice;
}stock;

typedef struct btree {
    void *data;
    int key_value;
    struct btree *left;
    struct btree *right;
} tree_t;

//function definitions
struct btree *initTree();
void print_inventory(struct inventory *stuff);
void print_inorder(tree_t *tree);
struct inventory * ReadData(FILE *fptr);
struct btree *search(int key, struct btree *leaf);
struct btree *insert(struct btree *root, int x);
void readFromTxt(FILE *fp, struct btree *head);

int _tmain(int argc, _TCHAR* argv[])
{
    //currently in initTree, the first node is empty (doesn't contain an inventory item) and has key_value 1
    //need to set key_value to equal product code

    struct btree *root;
    root = initTree();
    FILE *fp = fopen("input.txt", "r");

    readFromTxt(fp, root);
    print_inorder(root);

    return 0;
}

//initialize tree
struct btree *initTree()
{
    struct btree *temp = (struct btree*)malloc(sizeof btree);
    temp->left = NULL;
    temp->right = NULL;
    temp->key_value = 1;
    return temp;
}

//print inventory
void print_inventory(struct inventory *stuff)
{
    printf("Name: %s\n", stuff->invName);
    printf("Part Number: %.5d\n", stuff->invPartNo);//printf(“ %.9d”, x)
    printf("Quantity on hand: %d\n", stuff->invQOH);
    printf("Unit Cost: %0.2f\n", stuff->invUnitCost);
    printf("Price %0.2f\n\n", stuff->invPrice);
}

//recursively print tree
void print_inorder(tree_t *tree)
{
    if (tree != NULL) { //problem likely here
        print_inorder(tree->left);

        //printf("%d\n", tree->data);
        //printf inventory values
        if(tree->key_value != 1) //don''t print root
            print_inventory((struct inventory *)tree->data);

        print_inorder(tree->right);
    }
}

//read user input to produce new leaf with inventory struct
struct inventory * ReadData(FILE *fptr)
{
    struct inventory *temp = (struct inventory *)malloc(sizeof inventory);

    if(fptr==stdin)
        printf("Enter item name: ");
    fscanf_s(fptr, "%s", temp->invName);
    if(fptr==stdin)
        printf("Enter item part number: ");
    fscanf_s(fptr, "%d", &temp->invPartNo);
    if(fptr==stdin)
        printf("Enter item quantity on hand: ");
    fscanf_s(fptr, "%d", &temp->invQOH);
    if(fptr==stdin)
        printf("Enter item unit cost: ");
    fscanf_s(fptr, "%f", &temp->invUnitCost);
    if(fptr==stdin)
        printf("Enter item price: ");
    fscanf_s(fptr, "%f", &temp->invPrice);

    return temp;
}

//search tree
struct btree *search(int key, struct btree *leaf)
{
    if(leaf != 0)
    {
        if(key == leaf->key_value)
            return leaf;

        else if(key < leaf->key_value)
            return search(key, leaf->left);

        else
            return search(key, leaf->right);
    }
}

//add to tree
struct btree *insert(struct btree *root, int x)
{
 if(!root)
  {
    root=(struct btree*)malloc(sizeof(struct btree));
    root->key_value = x;
    root->left = NULL;
    root->right = NULL;
    return(root);
  }
  if(root->key_value > x)
     root->left = insert(root->left,x);
  else
   {
     if(root->key_value < x)
    root->right = insert(root->right,x);
   }
   return(root);
 }


void readFromTxt(FILE *fp, struct btree *head)
{
    if( fp != NULL)
    {
        while(!feof(fp))
        {
            struct btree *tNode = (struct btree*)malloc(sizeof btree);
            struct inventory *newNode =  (struct inventory*)malloc(sizeof inventory);
            fgets(newNode->invName, 100, fp);
            fscanf(fp, " %d %d %f %f ", &newNode->invPartNo,&newNode->invQOH,&newNode->invUnitCost,&newNode->invPrice);
            tNode->data = newNode;
            tNode->key_value = newNode->invPartNo;
            head->key_value++;
            insert( head, tNode->key_value );
        }
    }
}

这是我试图读取的txt文件:

1/4 drive socket set
19343
6
38.55
43.25
Claw Hammer
13448
14
3.27
4.89
#2 Flat Blade Screwdriver
12488
24
.70
1.85
#2 Phillips Screwdriver
12455
17
0.81
2.00
#1 Phillips Screwdriver
12456
27
0.67
1.80
#1 Flat Blade Screwdriver
12489
36
.65
1.75

1 个答案:

答案 0 :(得分:0)

您的代码中存在许多设计缺陷。

  • 使用1的特殊键将虚拟节点保存为根(或头)。但稍后,您可以增加头部的键以跟踪项目计数。最后,在打印iventory数据时检查1的特殊键。由于密钥不再为1且虚拟头节点的库存数据为NULL,因此您访问非法内存 - seg错误!

  • 插入新节点时,实际上并未传递节点,只是键值。然后,您使用该ID和在没有库存数据的情况下在现场创建新节点。实际上,data指针未初始化,甚至不保证为NULL

  • 我知道虚拟节点意味着您永远不必更新头部,但这不是一个好的设计。相反,您应该从NULL头开始,并在插入新节点时更新它。这通常通过将指针传递给指向节点的指针来完成。

  • 请保持您的命名一致。当您旁边有一个新节点(名为newNode)时,您不应该调用新的广告资源数据tNode。另外,typedefs是什么?您只能使用tree_t一次。最好坚持使用struct btree

  • 您阅读数据的方式也容易出错。例如,您读取最多100个字符到newNode->invName的缓冲区,它只能容纳36个字符。灾难食谱。混合fscanffgets通常不是一个好主意,请不要使用feof - 检查其他f函数的返回值,看看你是否已经到了文件的末尾。

  • C中的内存不是垃圾回收。这意味着对于每个malloc,应该有一个相应的free。轻松分配 - 实际上分配太多 - 并在使用后尝试清理树。