📄 file.h
字号:
#define false 0
#define true 1
#include "stdio.h"
#include <string.h>
typedef struct
{
char name[3]; /*文件或目录名*/
char type[2]; /*文件类型名*/
char attribute; /*属性*/
char address; /*文件或目录的起始盘块号*/
char length; /*文件长度,以盘块为单位*/
}content; /*目录结构*/
typedef struct
{
int dnum; /*磁盘盘块号*/
int bnum; /*磁盘盘块内第几个字节*/
}pointer;
/*已打开文件表中读写指针的结构*/
typedef struct
{
char name[20]; /*文件绝对路径名*/
char attribute;
int number,flag; /*文件的属性,用1个字节表示,char类型*/
int length; /*文件长度,文件占用的字节数int flag;*/
/*操作类型,用"0"表示以读操作方式开文件的,用"1"表写操作方式打开文件的*/
pointer read; /*读文件的位置,文件刚打开时dnum为文件起始盘*/
pointer write; /*写文件的位置,文件刚建立时dnum为文件起始盘块号,bnum为"0",文件打开时为文件的末尾*/
}OFILE; /*已打开文件表项类型定义*/
#define fn 5 /*模拟实验中系统允许打开文件的最大数量*/
struct
{
OFILE file[fn]; /*已打开文件表*/
int length; /*已打开文件表中登记的文件数量*/
}openfile; /*已打开文件表定义*/
char buffer1[64]; /*模拟缓冲1*/
content buffer2[8]; /*模拟缓冲2*/
FILE *fc; /*模拟磁盘的文件的指针*/
copen(OFILE *x1,OFILE *x2)
{
strcpy(x1->name, x2->name);
x1->attribute=x2->attribute;
x1->number=x2->number;
x1->length=x2->length;
x1->flag=x2->flag;
x1->read.dnum=x2->read.dnum;
x1->read.bnum=x2->read.bnum;
x1->write.dnum=x2->write.dnum;
x1->write.bnum=x2->write.bnum;
}
sopen(char *name) /*在已打开文件表中查找文件name*/
{
int i;
i=0;
/*依次查找已打开文件表*/
while(i<openfile.length&&strcmp(openfile.file[i].name, name)!=0)i++;
if (i>=openfile.length)
return(-1);
return(i);
} /*查找函数sopen结束*/
dopen(char *name)
/*在已打开文件表中删除文件name*/
{
int i;
i=sopen(name);
if(i==-1)
printf("文件未打开\n");
else
{
copen(&openfile.file[i], &openfile.file[openfile.length-1]);
openfile.length--;
}
} /*删除函数dopen结束*/
iopen(OFILE *x)
/*在已打开文件表中插入n文件x->name*/
{
int i;
i=sopen(x->name);
if(i!=-1)
{
printf("文件已经打开\n");
return(false);
}
else
if(openfile.length==fn)
{
printf("已打开文件表已满\n");
return(false);
}
else
{
copen(&openfile.file[openfile.length],x);
openfile.length++;
return(true);
}
}/* 填写已打开文件表函数结束 */
allocate()
/* 分配一个磁盘块,返回块号 */
{
int i;
fseek(fc,0,SEEK_SET); /*将模拟磁盘的文件指针移至模拟磁盘FAT表*/
fread(buffer1,64L,1,fc); /*将FAT表中第一个盘块读入模拟缓冲buffer1中*/
for(i=3;i<63;i++)
if(buffer1[i]==0) /*FATk中的第i项为0,分配第i块磁盘块,修改FAT表,并且写回磁盘*/
{
buffer1[i]=255;
fseek(fc,0,SEEK_SET);
fwrite(buffer1,64L,1,fc);
return(i); /*返回磁盘号*/
}
fread(buffer1,64l,1,fc); /*将FAT表中第二个盘块读入模拟缓冲buffer1中*/
for(i=0;i<63;i++)
if(buffer1[i]==0) /*FAT中的第i项为0,分配第i+64块磁盘块,修改FAT表,并且写回磁盘*/
{
buffer1[i]=255;
fseek(fc,-64L,SEEK_CUR);
fwrite(buffer1,64L,1,fc);
return(i+64); /*返回磁盘号*/
}
printf("已经没有磁盘空间\n");
return(false);
}/* 分配磁盘块函数结束 */
read_file(char *name,int length)
/*读文件函数,文件路径名name,读取长度length*/
{
int I, t;
char ch;
if((I=sopen(name))==-1)
{
printf("文件没有打开或不存在\n");
return(false);
}
if(openfile.file[I].flag==-1)
{
printf("文件以写方式打开,不能读\n");
return(false);
}
t=0;
fseek(fc, openfile.file[I].read.dnum*64L, SEEK_SET);
fread(buffer1, 64,1,fc);
while(t<length&&buffer1[openfile.file[I].read.bnum]!='#')
{
putchar(buffer1[openfile.file[I].read.bnum]);
/*读出一个字符(这里在屏幕上显示*/
if((t+1)%64==0)putchar('\n');
/*修改读指针*/
openfile.file[I].read.bnum++;
if(openfile.file[I].read.bnum>=64) /*一块读完,读取下一个盘块*/
{
fseek(fc,openfile.file[I].read.dnum/64*64,SEEK_SET);
fread(buffer1,64,1,fc);
openfile.file[I].read.dnum=buffer1[openfile.file[I].read.dnum%64];/*修改读指针*/
openfile.file[I].read.bnum=0;
fseek(fc,openfile.file[I].read.dnum*64L,SEEK_SET);
fread(buffer1,64,1,fc); /*读取下一个*/
}
t++;
}
}/*读函数结束*/
/*写文件函数
char *name 文件路径名
char *buff 存放准备写入磁盘的内容
int length 写入内容的长度*/
write_file(char *name,char *buff,int length)
{
int I, t,dd;
if ((I=sopen(name))==-1) /*文件不存在,无法写*/
{
printf("文件没有打开或不存在\n");
return(false);
}
if(openfile.file[I].flag==0)
{
printf("文件以读方式打开,不能写\n");
return(false);
}
t=0;
fseek(fc,openfile.file[I].write.dnum*64L,SEEK_SET);
fread(buffer1,64,1,fc);
while(t<length)
{
buffer1[openfile.file[I].write.bnum]=buff[t];
openfile.file[I].write.bnum++;
openfile.file[I].length++;
if(openfile.file[I].write.bnum>=64)
{
fseek(fc,openfile.file[I].write.dnum*64L,SEEK_SET);
fwrite(buffer1,64,1,fc); /*一块写完,写回磁盘*/
if((dd = allocate()) == false)
{
openfile.file[I].write.bnum--;
printf("无磁盘空间,部分信息丢失,写失败\n");
return(false);
}
fseek(fc,openfile.file[I].write.dnum/64*64L,SEEK_SET);
fread(buffer1,64,1,fc);
buffer1[openfile.file[I].write.dnum%64]=dd;
fseek(fc,openfile.file[I].write.dnum/64*64L,SEEK_SET);
fwrite(buffer1,64,1,fc);
openfile.file[I].write.dnum=dd;
openfile.file[I].write.bnum =0;
}
t++;
}
fseek(fc,openfile.file[I].write.dnum*64L,SEEK_SET);
fwrite(buffer1,64,1,fc);
printf("写文件完成.");
}
/*查找路径名为name的文件或目录,返回该目录的起始盘块号
char *name;
int flag; /*flag=8表示查找目录,否则为文件
int * dnum,*bnum ; /*返回文件或目录的目录项登记位置,盘块dnum中第bnum项*/
search(char *name,int flag,int *dnum,int *bnum)
{
int k,I,s,t,j,last=0;
char pna[3],type[2];
if((strcmp(name,"")==0)||(strcmp(name,"/")==0)) /*根目录*/
return(2);
k=0;
if(name[0]=='/')k=1;
I=2; /*i=根目录的起始盘块号*/
while(last!=1)
{/* pna=从name 分离出"/"后一个目录名(或文件名) */
for(s=0;name[k]!='.'&&name[k]!='/'&&s<3&&name[k]!='\0';s++,k++)
pna[s]=name[k];
for(;s<3;s++) /*用空格补全名长度*/
pna[s]=' ';
while(name[k]!='.'&&name[k]!='\0'&&name[k]!='/') /*除去余字符*/
k++;
type[0]=type[1]='\0';
if(name[k]=='.') /*取文件类型名type*/
if(flag==8)
{
printf("目录不应该有有类型名,查找失败\n");
return(false);
}
else
{ /*文件遇到类型名认为结束,后面的字符作废*/
k++;
if(name[k]!='\0')
type[0]=name[k];
k++;
if(name[k]!='\0')
type[1]=name[k];
if(name[k]!='\0'&&name[k+1]!='\0')
{
printf("文件名错误\n");
return(false);
}
last=1;
}
else
if(name[k]!='\0')
k++;
if(name[k]!='\0')
last=1;
/*查找名字等于pna的目录项*/
fseek(fc,I*64L,SEEK_SET);
fread(buffer2,64L,1,fc);
j=0;
if(last==1&&flag!=8) /*查找名字pna,类型名type的文件目录项*/
while(j<8&&!(buffer2[j].attribute!=8&&buffer2[j].name[0]==pna[0]&&buffer2[j].name[1]==pna[1]&&buffer2[j].name[2]==pna[2]&&buffer2[j].type[0]==type[0]&&buffer2[j].type[1]==type[1]))
j++;
else /*查找名字等于pna的目录项*/
while(j<8&&!(buffer2[j].attribute==8&&buffer2[j].name[0]==pna[0]&&buffer2[j].name[1]==pna[1]&&buffer2[j].name[2]==pna[2]))
j++;
if(j<8) /*找到该目录或文件*/
if(last==1) /*查找结束*/
{
*dnum=I;
*bnum=j;
return(buffer2[j].address);
}
else /*查找还未结束*/
I=buffer2[j].address; /*读取下一个盘块*/
else
{
printf("路径错误\n");
return(false);
}
}/* while查找结束 */
}/* search()结束 */
/*建立文件函数,路径名name,文件属性attribute*/
create_file(char *name,int attribute)
{
int dnum,bnum,I,j,last,k,s,d,t,tt,b,dd,flag,dn,bn;
char dname[3],tname[2],pathname[20];
OFILE x;
if(attribute%2==1)
{
printf("只读文件,无法写,不能建立\n");
return(false);
}
if(openfile.length==fn)
{
printf("已打开表已满,不能建立\n");
return(false);
}
/*将name分成两部分,目录路径pathname和目录名dname*/
for(j=0;name[j]!='\0';j++) /*查找最后一个'/'*/
if(name[j]=='\/')
s=j;
/*分离文件名*/
for(j=0;j<=s;j++)
pathname[j]=name[j];
pathname[j]='\0';
for(k=0,j=s+1;name[j]!='\0'&&k<3&&name[j]!='.';j++,k++)
dname[k]=name[j];
if(k==0)
{
printf("错误文件名或目录名\n");
return(false);
}
for(;k<3;k++)
dname[k]=' ';
k=0;
if(name[j++]=='.') /*分离类型名*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -