Description
键盘输入一个数字以打开相应的数据库文件(1---aaa.dic,2---bbb.dic,3---ccc.dic), 再输入一个学生的名字,从文件中读出该同学的math成绩,若查无其人,则输出No。
有关数据库文件头的结构,请参看3591题目中的描述。文件头之后,是数据部分,数据部分的结构如下:
下面是文件头结构的数据表(3591):
说明:已知数据库文件中肯定有name和math两个字段
名字中有可能有空格,如:zhang san
分数位数不够,左边会有空格,如: 7.5
有些记录已被逻辑删除
Input
输入1或者2或者3,再输入一个学生的名字
Output
用printf("%.3f\n",...)这种格式输出分数(保留3位小数)或No
Sample Input
1
lisi
Sample Output
80.000
Code 1 here:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct{
char biaozhi;
char shijian[3];
int zongshu;
short long1;
short long2;//每条记录的长度
char empty[20];
}HEAD;
typedef struct{
char name[10];
char empty_c;
char leixing;
int weizhi;
char long3;
char weishu;
char empty[14];
}FIELD;
int main()
{
FILE *fp;
int i,a,b,j;
float score;
char name[11]="0",s[11]="0",name1[11]="0",c;
HEAD head;
FIELD field[2];
scanf("%d\n",&b);//注意要取走一个换行符,或者不写'\n',在下一行添getchar();
gets(name1);//学生姓名
if(b==1)
{
if((fp=fopen("aaa.dic","rb"))==NULL)
exit(1);
}
if(b==2)
{
if((fp=fopen("bbb.dic","rb"))==NULL)
exit(1);
}
if(b==3)
{
if((fp=fopen("ccc.dic","rb"))==NULL)
exit(1);
}
fread(&head,32,1,fp);
a=(head.long1-32-1)/32;//字段长度
for(i=1;i<=a;i++)//找name的位置
{
fread(&field[0],32,1,fp);
if(strcmp(field[0].name,"name")==0)
{
break;
}
}
fseek(fp,32,0);
for(i=1;i<=a;i++)//找math的位置
{
fread(&field[1],32,1,fp);
if(strcmp(field[1].name,"math")==0)
{
break;
}
}
for(j=0;j<head.zongshu;j++)//跳记录,怎么结束呢,上面结构体有信息了
{
strcpy(name,"\0");
fseek(fp,head.long1,0);//跳整个文件头
fseek(fp,head.long2*j,1);//跳记录
fseek(fp,field[0].weizhi,1);//跳到name的位置
fread(&name,field[0].long3,1,fp);
for(i=field[0].long3-1;i>=0;i--)//是空格时添0,注意数组是要-1的
{
if(name[i]==32||name[i]=='\0')
name[i]='\0';
else
break;
}
if(strcmp(name,name1)==0)//如果名字一样,输出他的数学成绩
{
fseek(fp,head.long1,0);//跳文件头
fseek(fp,head.long2*j,1);//跳记录
fread(&c,1,1,fp);//看是否逻辑删除
if(c==42){
printf("No");
break;
}
fseek(fp,field[1].weizhi-1,1);//跳到math的位置,往上一个
fread(&s,field[1].long3,1,fp);//读
score=(float)atof(s);
printf("%.3f",score);
break;
}
}
if(j>=head.zongshu)
printf("No");
fclose(fp);
return 0;
}
关于下面的题目,是直接读取了跳过文件头的第一条记录(也可以叫第0条记录),上面的代码是在如下代码的基础上改进的,如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct{
char biaozhi;
char shijian[3];
int zongshu;
short long1;
short long2;
char empty[20];
}HEAD;
typedef struct{
char name[10];
char empty_c;
char leixing;
int weizhi;
char long3;
char weishu;
char empty[14];
}FIELD;
int main()
{
FILE *fp;
int i,a,b;
float score;
char name[11]="0",s[11]="0";//一定初始化
HEAD head;
FIELD field;
scanf("%d",&b);
if(b==1)
{
if((fp=fopen("aaa.dic","r"))==NULL)
exit(1);
}
if(b==2)
{
if((fp=fopen("bbb.dic","r"))==NULL)
exit(1);
}
fread(&head,32,1,fp);
a=(head.long1-32-1)/32;
for(i=1;i<=a;i++)
{
fread(&field,32,1,fp);
if(strcmp(field.name,"name")==0)
{
break;
}
}
fseek(fp,head.long1+field.weizhi,0);
fread(&name,field.long3,1,fp);
for(i=field.long3-1;name[i]==32||name[i]==0;i--)//name里中间可能有空格,需要保留,后面也可能有空格,是不需要保留的,所以从后往前读,遇到空格或'\0'都换成'\0',对于'\0'理解不是很深刻,没有机会尝试是否AC,但上一题使用的方法是可以的
{
name[i]='\0';
}
for(i=0;name[i]!='\0';i++)
printf("%c",name[i]);
printf("\n");
fseek(fp,32,0);
for(i=1;i<=a;i++)
{
fread(&field,32,1,fp);
if(strcmp(field.name,"math")==0)
{
break;
}
}
fseek(fp,head.long1+field.weizhi,0);
fread(s,field.long3,1,fp);//得到的是字符分数,需要转换成实型分数,在这里使用atof()函数实现此功能功能,或者编程序实现。函数自动换成浮点数
score=(float)atof(s);
printf("%.3f",score);
fclose(fp);
return 0;
}