23.3.15 文件实训2 数据库文件读取

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;
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值