找错,无书时能入库,但一借书程序就停止了

higurasikagome 2013-12-22 09:28:34
求找错,图书借还,存在就借出(Del),不存在入库(插入),用文件操作
typedef struct BiTNode
{
char data[30];
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
#define EQ(a,b) (!strcmp((a),(b)))
#define LT(a,b) (strcmp((a),(b))<0)
#define LQ(a,b) (strcmp((a),(b))<=0)

int Filempty(char *ch)//文件判空,不空返回1,空0
{
FILE *fp;
char b;
fp=fopen(ch,"r");
if(fp==NULL)
{
printf("文件不存在!\n");
return 0;
}
b=fgetc(fp);
if(b==EOF) //文件存在但为空
{
printf("当前文件没有记录!\n");
fclose(fp);
return 0;
}
else
{
printf("文件不为空\n");
fclose(fp);
return 1;
}
}
void Del(BiTree &T,BiTree p)
{ /* 从二叉排序树中删除结点p,并重接它的左或右子树。 */
BiTree q,s;
char ch[30]={'\0'};
if(!p->rchild) /* 右子树空则只需重接它的左子树(待删结点是叶子也走此分支) */
{
q=p;
p=p->lchild;
free(q);
}
else if(!p->lchild) /* 只需重接它的右子树 */
{
q=p;
p=p->rchild;
free(q);
}
else /* 左右子树均不空 */
{
q=p;
s=p->lchild;
while(s->rchild) /* 转左,然后向右到尽头(找待删结点的前驱) */
{
q=s;
s=s->rchild;
}
strcpy(p->data,s->data); /* s指向被删结点的"前驱"(将被删结点前驱的值取代被删结点的值) */
if(q!=p)
q->rchild=s->lchild; /* 重接*q的右子树 */
else
q->lchild=s->lchild; /* 重接*q的左子树 */
free(s);
}
}




int SearchBST(BiTree &T,char *e,BiTree f,BiTree &p) // 算法9.5(b)
{ // 在根指针T所指二叉排序树中递归地查找其关键字等于key的数据元素,若查找
// 成功,则指针p指向该数据元素结点,并返回TRUE,否则指针p指向查找路径上
// 访问的最后一个结点并返回FALSE,指针f指向T的双亲,其初始调用值为NULL
if(!T) // 查找不成功
{
p=f;
return 0;
}
else if EQ(e,T->data) // 查找成功
{
p=T;
return 1;
}
else if LT(e,T->data)
return SearchBST(T->lchild,e,T,p); // 在左子树中继续查找
else
return SearchBST(T->rchild,e,T,p); // 在右子树中继续查找
}

int InsDelBST(BiTree &T, char *e)
{ // 当二叉排序树T中不存在关键字等于e.key的元素时,插入e并返回TRUE,否则返回FALSE。算法9.6
BiTree p,s;

if(!SearchBST(T,e,NULL,p)) // 查找不成功
{
s=(BiTree)malloc(sizeof(BiTNode));
strcpy(s->data,e);
s->lchild=s->rchild=NULL;
if(!p)
T=s; // 被插结点*s为新的根结点
else if LT(e,p->data)
p->lchild=s; // 被插结点*s为左孩子
else
p->rchild=s; // 被插结点*s为右孩子
return 0;
}
else
{
Del(T,p);
return 1;//返回给Find
}
}










void FindFore(BiTree &T,char *ch)//传参时为空树
{
FILE *fp;
char str[20];//文件行读取写入str
fp=fopen(ch,"r");//只读打开
if(fp==NULL)//不存在文件,新建
{
printf("文件不存在将新建!\n");
fp=fopen(ch,"w");
fclose(fp);
}
if(Filempty(ch)!=0)//文件不空,读取文件内容到二叉树
{
while(!feof(fp))
{
fgets(str,20,fp);//行读取,如遇换行符,结束读取
puts(str);
InsDelBST(T,str);
}
fclose(fp);
}

}







void InitBiTree(BiTree &T)
{
T=NULL;
}

/*1.被FindFore调用,从文件读字符串插入二叉树,
2.Find调用,存在删除,不存在插入
*/



void Find(BiTree &T)
{

char d[40];
int flag;
printf("请输入您要查询的图书:\n");
gets(d);
flag=InsDelBST(T,d);
if(flag==0)
printf("书库里没有您要的书,该书将稍后入库!\n");
else
printf("《%s》查阅到,您将借出!\n",d);

}

void BtoF(BiTree T,char *ch)//中序遍历二叉树,写入文件
{
FILE *fp;
BiTree cur=T, prev=NULL;
fp=fopen(ch,"w");
while (cur != NULL)
{
if (cur->lchild == NULL) // 1.
{
fputs(cur->data,fp);
cur = cur->rchild;
}
else
{

prev = cur->lchild;
while (prev->lchild!= NULL && prev->rchild != cur)
prev = prev->rchild;

if (prev->rchild == NULL) // 2.a)
{
prev->rchild = cur;
cur = cur->lchild;
}
else // 2.b)
{
prev->rchild = NULL;
fputs(cur->data,fp);
cur = cur->rchild;
}
}
}

fclose(fp);
}






int main()
{
BiTree T;
char ch[40];
InitBiTree(T);
printf("输入要打开的文件名:\n");
gets(ch);
FindFore(T,ch);
Find(T);
BtoF(T,ch);
return 0;
}





...全文
83 点赞 收藏 6
写回复
6 条回复
higurasikagome 2013年12月22日
引用 4 楼 KenZhang1031 的回复:
引用
终于有大神理我啦,文件操作很生疏的,现看现写,很谢谢你!这道题将文件内容读入到二叉排序树,修改二叉排序树后,用BtoF( 即Binary to File),将文件清空后把改动后的二叉树再写入文件。
罪过,请勿亵渎神! 如果是想把借出的书从树中删除对应的节点,那你的Del函数是错误的,你自己理清一下思路就知道。
这个,我都盯着看两天啦!找不出错啊
回复 点赞
Mr. Code 2013年12月22日
引用
终于有大神理我啦,文件操作很生疏的,现看现写,很谢谢你!这道题将文件内容读入到二叉排序树,修改二叉排序树后,用BtoF( 即Binary to File),将文件清空后把改动后的二叉树再写入文件。
罪过,请勿亵渎神! 如果是想把借出的书从树中删除对应的节点,那你的Del函数是错误的,你自己理清一下思路就知道。
回复 点赞
higurasikagome 2013年12月22日
引用 2 楼 KenZhang1031 的回复:
三个问题: 1、fgets函数用得不对,会把换行符也读进来,实际上书名是不包含换行符的。 2、feof函数用得不对,指针到达文件结尾后,需再读一次才会判断是结尾,因此:你的下面一段代码:
while(!feof(fp))
        {
            fgets(str,20,fp);//行读取,如遇换行符,结束读取
            puts(str);
            InsDelBST(T,str);
        }
改为:
while(fgets(str,20,fp))
		{
			//fgets(str,20,fp);//行读取,如遇换行符,结束读取
			if(str[strlen(str) - 1] == '\n')
				str[strlen(str) - 1] = 0;
			puts(str);
			InsDelBST(T,str);
		}
可以解决你查找图书的问题。让你能找到书库里有的书。 3、最后的函数BtoF不知道你想实现什么功能,这个你得好好根据你想实现的功能整整。你用fp=fopen(ch,"w")打开文件写,书库的记录都被你清除了。到底要实现什么?
,终于有大神理我啦,文件操作很生疏的,现看现写,很谢谢你!这道题将文件内容读入到二叉排序树,修改二叉排序树后,用BtoF( 即Binary to File),将文件清空后把改动后的二叉树再写入文件。
回复 点赞
Mr. Code 2013年12月22日
三个问题: 1、fgets函数用得不对,会把换行符也读进来,实际上书名是不包含换行符的。 2、feof函数用得不对,指针到达文件结尾后,需再读一次才会判断是结尾,因此:你的下面一段代码:
while(!feof(fp))
        {
            fgets(str,20,fp);//行读取,如遇换行符,结束读取
            puts(str);
            InsDelBST(T,str);
        }
改为:
while(fgets(str,20,fp))
		{
			//fgets(str,20,fp);//行读取,如遇换行符,结束读取
			if(str[strlen(str) - 1] == '\n')
				str[strlen(str) - 1] = 0;
			puts(str);
			InsDelBST(T,str);
		}
可以解决你查找图书的问题。让你能找到书库里有的书。 3、最后的函数BtoF不知道你想实现什么功能,这个你得好好根据你想实现的功能整整。你用fp=fopen(ch,"w")打开文件写,书库的记录都被你清除了。到底要实现什么?
回复 点赞
higurasikagome 2013年12月22日
文件如图
回复 点赞
Mr. Code 2013年12月22日
引用
这个,我都盯着看两天啦!找不出错啊
你要调试代码,光看不行,单步跟踪。
回复 点赞
发动态
发帖子
C语言
创建于2007-09-28

3.2w+

社区成员

24.0w+

社区内容

C语言相关问题讨论
社区公告
暂无公告