📄 4-linkfileautowr.cpp
字号:
fread(&iHead,IH,1,ifp);
preAddr=iHead.headNext; //存放刚刚读入的头文件的值
if(preAddr==-1 || preAddr<0) //假如索引文件中无任何数据则直接把原来的索引数据写入到索引文件中,结束任务
{
writeIndexFileHead(ifp,IH); //写索引文件的头,直接写下一个单元的地址IH
writeIndexFile(ifp,&i,phyNum); //写索引文件,第phyNum个索引
return 1;
}
//如果索引文件中存在至少一条数据,把头文件中所指的下一条数据都存放在pre和curr中
fseek(ifp,preAddr,SEEK_SET);
fread(&pre,IN,1,ifp);
fseek(ifp,preAddr,SEEK_SET);
fread(&curr,IN,1,ifp);
//如果新数据比当前数据curr还要小,则修改索引的头,并修改索引本身,最后把这条新的索引项写入索引文件
if(i.primaryKey<curr.primaryKey)
{
iHead.headNext=phyNum*IN+IH; //新插入结点的地址赋值给索引文件头
writeIndexFileHead(ifp,iHead.headNext); //写入索引头文件
i.next=preAddr; //给新索引数据的next赋值
writeIndexFile(ifp,&i,phyNum);
return 1;
}
else // //插入到中间
{
do
{
if(curr.primaryKey==i.primaryKey || pre.primaryKey==i.primaryKey) //如果插入相同值不插入并返回0
{
printf("\a");
return 0;
}
if(pre.next==-1) //比最末尾的还大,就插入到最末尾,针对pre=curr的情况
{
pre.next=phyNum*IN+IH;
fseek(ifp,preAddr,SEEK_SET);
fwrite(&pre,IN,1,ifp);
writeIndexFile(ifp,&i,phyNum); //最后插入新的索引数据
return 1;
}
if(curr.next==-1) //针对pre!=curr的情况
{
preAddr=pre.next;
curr.next=phyNum*IN+IH;
fseek(ifp,preAddr,SEEK_SET);
fwrite(&curr,IN,1,ifp);
writeIndexFile(ifp,&i,phyNum); //最后插入新的索引数据
return 1;
}
if(curr.primaryKey==pre.primaryKey)
{
fseek(ifp,pre.next,SEEK_SET); //curr指针下移动一位
fread(&curr,IN,1,ifp);
}
else
{
preAddr=pre.next; //获得pre的地址,以便后面要写入pre的值
pre=curr;
fseek(ifp,pre.next,SEEK_SET); //curr指针下移动一位
fread(&curr,IN,1,ifp);
}
}while(i.primaryKey>=curr.primaryKey);
i.next=pre.next;
pre.next=phyNum*IN+IH;
fseek(ifp,preAddr,SEEK_SET); //把修改以后的pre写回去
fwrite(&pre,IN,1,ifp);
writeIndexFile(ifp,&i,phyNum); //最后插入新的索引数据
return 1;
}
}
else
{
printf("调节链表时打开索引文件失败! (error 8.) \a\n");
return 0;
}
}
//--------------------------------------------------------------------------------9 读物理数据
/*
不管索引,在数据文件f中一直往下读数据,直到文件末尾末尾
*/
void readAllDataFile(FILE *f)
{
int i; //循环变量
dataNode d;
if(f!=NULL)
{
for(i=0;!feof(f);i++)
{
fseek(f,i*DN+DH,SEEK_SET);
fread(&d,DN,1,f);
if(d.account>0)
{
printf("No.%3d\t帐号:%-5d\t姓名:%-10s\t余额:%-7.2lf\t其它:%-s\n",i+1,d.account,d.name,d.balance,d.other);
d.account=0;
}
}
printf("\n");
}
else
printf("读数据文件时文件打开失败! (error 9.) \a\n");
}
//--------------------------------------------------------------------------------10 读物理索引文件
void readAllIndexFile(FILE *ifp) //读取有效的索引
{
int i; //循环变量
indexHead head;
indexNode node;
if(ifp!=NULL)
{
rewind(ifp);
fread(&head,IH,1,ifp); //获得索引文件头
printf("文件头:%d\n",head.headNext);
for(i=0;i<phyNum;i++) //总共num个有效值
{
fseek(ifp,i*IN+IH,SEEK_SET);
fread(&node,IN,1,ifp);
printf("No.%d:\t索引地址:%d\t帐号:%-5d\t数据地址:%-5d\tnext地址:%-5d\n",i+1,i*IN+IH,node.primaryKey,node.addr,node.next);
}
}
else
printf("读索引文件是文件打开失败! (error 10.) \a\n");
}
//--------------------------------------------------------------------------------11 按索引读取数据
void readDataByIndex(FILE *daf,FILE *inf)
{
indexHead ih;
indexNode in;
dataNode dn;
double sum=0;
if(daf!=NULL && inf!=NULL)
{
int i;
rewind(inf);
fread(&ih,IH,1,inf);
for(i=0;i<num;i++)
{
if(i==0) //读取第一条索引
{
fseek(inf,ih.headNext,SEEK_SET);
fread(&in,IN,1,inf);
}
else
{
fseek(inf,in.next,SEEK_SET);
fread(&in,IN,1,inf);
}
fseek(daf,in.addr,SEEK_SET);
fread(&dn,DN,1,daf);
printf("No.%-3d\t帐号:%-5d\t姓名:%-8s\t余额:%-7.2lf\t其它:%-s\n",i+1,dn.account,dn.name,dn.balance,dn.other);
sum+=dn.balance;
}
if(num<1)
printf("数据文件中无数据! (error 11.) \a\n");
printf("总金额=%lf\n",sum);
}
}
//--------------------------------------------------------------------------------12 删除数据
void deleteData(FILE *inf,FILE *daf,int n)
{
indexHead ih;
indexNode firstNode; //专门存放第一个索引数据
indexNode in;
indexNode pre;
indexNode prepre; //prepre的next就是pre的地址
int preAddr; //存储索引结点pre的地址,pre就是要删除节点的前面的一个节点,到时候要修改pre的next
if(inf!=NULL)
{
rewind(inf);
fread(&ih,IH,1,inf); //读取索引文件的头,存放在ih中
fseek(inf,ih.headNext,SEEK_SET);
fread(&firstNode,IN,1,inf); //读取第一条索引数据,由firstNode来保存
pre=in=firstNode;
prepre.next=ih.headNext;
while(in.primaryKey<n && in.next!=-1) //如果in的值小于并且in的next!=-1则循环,直到遇到...
{
if(in.primaryKey==pre.primaryKey) //如果是刚开始读取数据,in和pre都指向第一条索引数据
{
}
else if(firstNode.primaryKey==pre.primaryKey) //读第2条索引数据
{
preAddr=prepre.next;
fseek(inf,preAddr,SEEK_SET); //读完之后向下移动一个单元
fread(&prepre,IN,1,inf);
}
else //其它数据
{
fseek(inf,preAddr,SEEK_SET); //
fread(&prepre,IN,1,inf);
preAddr=prepre.next;
}
pre=in; //in向下移动一位,pre总是在in后面或者相同,存入in中
fseek(inf,pre.next,SEEK_SET);
fread(&in,IN,1,inf);
} //结束while
if(in.primaryKey==n) //如果找到了这条数据...
{
if(pre.primaryKey==in.primaryKey) //如果要删除的就是最小的那个索引,只用修改所有文件的头文件
{
writeIndexFileHead(inf,pre.next); //直接修改并写回索引文件头
num--;
writeDataFileHead(daf,num,phyNum); //写回数据文件数据总数num
printf("帐号:%-5d\t地址:%-5d 成功删除! \n",in.primaryKey ,in.addr);
}
else //如果删除的不是当前最小的索引
{
pre.next=in.next; //in就是当前要删除的节点,in.next是唯一有用的信息
fseek(inf,preAddr,SEEK_SET); //写回要删除结点前一个节点
fread(&prepre,IN,1,inf);
fseek(inf,prepre.next,SEEK_SET);
fwrite(&pre,IN,1,inf);
num--;
writeDataFileHead(daf,num,phyNum); //写回数据文件
printf("帐号:%-5d\t地址:%-5d 成功删除! \n",in.primaryKey ,in.addr);
}
}
else
printf("未找到要删帐号! (error 12.) \a\n");
}
}
//--------------------------------------------------------------------------------13 清除数据,第二次打开文件
/*
具体说明:
*/
void clear(FILE *dp,FILE *ip)
{
dp=fopen("dataFile.dat","w"); //以w方式打开文件将清除文件中所有数据
ip=fopen("indexFile.dat","w");
fclose(dp);
fclose(ip);
dp=fopen("dataFile.dat","rb+"); //打开数据文件
ip=fopen("indexFile.dat","rb+"); //打开索引文件
phyNum=0; //物理数据数
num=0; //有效数据数
writeDataFileHead(dp,0,0); //写数据文件头
writeIndexFileHead(ip,-1); //写索引文件头
}
//--------------------------------------------------------------------------------14 插入单条数据
/*
具体说明:
首先对数据分析,然后调整索引文件并生成要生成的索引数据项,如果顺利就插入,假如有重复值不进行插入并给予提示
*/
int insert(FILE *dp,FILE *ip,dataNode dn) //向数据文件dp,索引文件ip中写入数据结点dn
{
indexNode newIndex; //定义索引节点newIndex
newIndex.primaryKey=dn.account; //搜集索引文件信息primaryKey
newIndex.addr=phyNum*DN+DH; //搜集索引文件信息addr
newIndex.next=-1; //搜集索引文件信息next
if(adjust(ip,newIndex)) //如果有效插入一条数据,同时在adjust中把索引也写入索引文件
{
writeDataFile(dp,&dn,phyNum); // 14 现在可以将数据写入数据文件,注意:位置是在物理数据后面而不是有效数后面
num++; //全局变量num增加,说明已经写入了一条数据
phyNum++; //全局变量phyNum也增加,说明已经写入了一条数据
writeDataFileHead(dp,num,phyNum);
return 1;
}
else
{
printf("要插入的帐号为%d的节点在数据文件中已经存在. 插入失败! (error 14.) \a",dn.account);
return 0;
}
}
//--------------------------------------------------------------------------------15 自动生成链表文件
void aotoWork(FILE *daf,FILE *ipf,FILE *sf,int autoNum)
{
dataNode sn;
int i;
int sNum;
int count=0;
int by,cy;
srand(time(NULL)); //产生随机数因子
if(daf==NULL || ipf==NULL || sf==NULL)
{
printf("在自动生成链表文件时候文件打开失败! (error 15.) \a\n");
}
else
{
by=MAXDATA/32767;
cy=MAXDATA-(by*32767);
for(i=0;i<autoNum;i++)
{
sNum=rand()*(rand()%by)+rand()%cy; //产生数据源文件中的定位随机数sNum,因为实现生成的数据文件中有,最大rand()=32767
fseek(sf,sNum*sizeof(dataNode),SEEK_SET);
fread(&sn,sizeof(dataNode),1,sf);
if(!insert(daf,ipf,sn)) //插入数据
{
printf("第(%d)条数据\n",i);
i--;
}
count++;
if(count%100==0)
printf("\n第%d条\n",count);
} //结束for
printf("总共输入了%d次的数据!\n",count);
}
}
//--------------------------------------------------------------------------------16 查询
void searchN(FILE *ifp,FILE *daf,int acct) //返回的是找到的节点的在数据文件中的地址
{
indexHead ih;
indexNode in;
dataNode sn;
int sAddr=-1;
rewind(ifp);
fread(&ih,IH,1,ifp); //获取索引文件的头
in.next=ih.headNext;
in.primaryKey=-1;
in.addr=0;
while(in.next!=-1 && acct>in.primaryKey) //查找的数比但前primary大而且没有到最后一个结点就循环
{
fseek(ifp,in.next,SEEK_SET);
fread(&in,IN,1,ifp); //读取下一个节点
printf("%d ->",in.primaryKey);
}
if(in.primaryKey==acct) //找到了
{
printf("\n\n%d",in.primaryKey);
fseek(daf,in.addr,SEEK_SET); //读取查到地址处的数据打印出来
fread(&sn,DN,1,daf);
printf("查询成功: 帐号:%-5d\t姓名:%-10s\t余额:%-7.2lf\t其它:%-s\n",sn.account,sn.name,sn.balance,sn.other);
}
else
printf("\n未找到要查询的帐号. 查询失败! (error 16.)\a\n");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -