第1关:使用FILE结构操作文本文件
任务描述
本关要求编写函数ext\fractDigit
,该函数从已有的当前目录下的文件a.txt
中读取并解析出其中的数值,并将结果写到当前目录下的文件b.txt
中。
其中:文件a.txt
中包含各种字符,但只有数字字符是有效的,提取其中的数字字符,将每3
个数字组成一个整数,写到文件b.txt
中,每个整数之间用一个空格分开。读取过程中,如果a.txt
中最后剩下不到3
个数字字符,则将剩下的1
个或者2
个数字字符组成一个整数。
例如:
a.txt
中的内容是1j3j5sd0msd454ss3msd563
,则抽取出来写入文件b.txt
的内容应该是135 45 435 63
(第二个整数是由045
三个数字组成,所以是45
)。
相关知识(略)
编程要求
本关的编程任务是补全step1/fileTxt.c
文件中ext\fractDigit
函数,以实现使用FILE
结构来操作文本文件的要求。具体要求如下:
-
本关要求通过补全
step1/fileTxt.c
文件中ext\fractDigit
函数来实现从已有的当前目录下的文件a.txt
中读取并解析出其中的数值,并将结果写到当前目录下的文件b.txt
中的要求。 -
实际的测试样例参见下文。
测试说明
本关的测试文件是step1/main.c
,其中将会调用你在step1/fileTxt.c
文件中完成的ext\fractDigit
函数来完成本关任务。step1/main.c
的源代码如下所示:
#include <stdio.h>
#include <stdlib.h>
//声明外部函数,函数ext\fractDigit在其它源文件中实现
extern void ext\fractDigit();
int main()
{
//准备文件a.txt的内容
FILE *fp = fopen("a.txt","w"); //打开文件a.txt用于写
char s[1000];
fgets(s, 999, stdin); //从键盘读取一行字符
fputs(s,fp); //将这一行字符写入文件a.txt中
fclose(fp); //关闭fp关联的文件a.txt
ext\fractDigit(); //调用函数,抽取数字写入文件b.txt中
FILE *f = fopen("b.txt","r"); //以读的方式打开文件b.txt
if(f==NULL) //打开失败则返回
return 0;
int n,k=0;
fscanf(f,"%d",&n); //从文件b.txt中读出一个整数到变量n中
while(!feof(f)) //如果文件没结束(读出的不是EOF)
{
k++;
printf("%d ",n); //输出该整数到屏幕
if(k%10==0) //每十组一换行
printf("\n");
fscanf(f,"%d",&n); //读取下一个整数
}
if(k%10!=10) //最后一行没有换行符则补上
printf("\n");
return 0;
}
平台会对你编写的代码进行测试: 测试输入: q12h44h67k854ksd923823sf83wd38457sd433ds,
预期输出: 124 467 854 923 823 833 845 743 3
测试输入: 1212121212343434343445454545450000005656565665dfsd455
预期输出: 121 212 121 234 343 434 344 545 454 545
0 0 565 656 566 545 5
#include <stdio.h>
// 函数extractDigit的功能:从文件a.txt中提取数值写入文件b.txt中
void extractDigit();
// 请在此添加代码,实现extractDigit函数
// 函数extractDigit的功能:从文件a.txt中提取数值写入文件b.txt中
void extractDigit()
{
FILE *fi = fopen("a.txt","r"); // 以读的方式打开文件a.txt
FILE *fo = fopen("b.txt","w"); // 以写的方式打开文件b.txt
if(fi==NULL || fo==NULL) // 如果某个文件打开失败,则返回
return;
/**************Begin******************/
char readADigit(FILE *fi)// 从文件读取一个字符
{
char c = fgetc(fi);
if(c==EOF)
{
return EOF;
}
while(c>'9' || c<'0')// 如果不是数字字符,则继续读取下一个字符
{
c = fgetc(fi);
if(c==EOF)
{
return EOF;
}
}
return c;
}
char c;
int num=0,k=0;
c = readADigit(fi);// 从文件读取一个字符
while(c!=EOF)
{
num=num*10+c-'0';// 计算数字字符构成的整数
k++;
if(k==3)
{
fprintf(fo,"%d ",num);
k=0;
num=0;
}
c = readADigit(fi);
}
if(k!=0)// 如果有不到三位的数值,则写入文件b.txt
{
fprintf(fo,"%d ",num);
}
/**************End********************/
fclose(fi); // 关闭文件fi
fclose(fo); // 关闭文件fo
}
第2关:按格式读写文件存取学生信息
任务描述
本关要求编写函数ReadStudInfo
和SaveResult
。
相关知识(略)
编程要求
本关的编程任务是补全step2/fileTxt.c
文件中ReadStudInfo
函数和SaveResult
函数,以实现按格式使用FILE结构存取学生信息的功能。具体要求如下: 1.ReadStudInfo
函数功能:实现从文本文件中读取学生的基本信息。函数ReadStudInfo
函数原型为:
void ReadStudInfo(const char *fileName, STUDENT stud[]);
其中:
- 参数
fileName
是一个文本文件,位于当前目录,即与源程序文件在同一文件夹下。文件中首先是以字符形式写入的学生人数(整数n
,不超过30
)和课程数量(整数n
,不超过5
),然后是n
个学生的信息,学生信息在结构STUDENT
中定义:struct student
{
long studentID;
char studentName[20];
char sex[4];
struct{
int year;
int month;
int day;
}birthday;
float score[COURSE_MAXNUM];
float total;
float average;
int rank;
};
typedef struct student STUDENT;
- 文件中没有存储 total,average,rank 三项信息。
- 函数
ReadStudInfo
的第二个参数stud
存放读取出来的学生信息。
2.SaveResult
函数功能:实现从文本文件中读取学生的基本信息。函数SaveResult
函数原型为:
void SaveResult(const char *fileName, STUDENT stud[],int n,int m);
其中:
- 参数
fileName
是一个文本文件,位于当前目录,即与源程序文件在同一文件夹下。 - 文件中首先要求以字符形式写入学生人数(整数
n
,不超过30
)和课程数量(整数n
,不超过5
),然后是n
个学生的信息。n
个学生的信息存放在第二个参数stud
开始的n
个结构体数据单元中。 - 每个学生的信息包括学号、姓名、性别、出生日期,若干门课程的成绩、总分、平均分、名次。
测试说明
本关的测试文件是step2/main.c
,其中将会调用你在step2/fileTxt.c
文件中完成的ReadStudInfo
函数和SaveResult
函数。除此之后,step2/main.c
中还对学生信息进行了处理:包括计算总分、平均分和名次。其次还实现了输入测试数据、输出测试结果、写入测试文件(student.txt
)、读取测试文件(result.txt
):
1.调用函数Input()
将标准输入的数据读入内存,然后调用SaveStudInfo()
函数将数据再写入到student.txt
文本文件,以便为**ReadStudInfo()
**函数从文本文件读取学生信息准备测试数据。
2.调用函数ReadResult()
将SaveResult()
函数保存的result.txt
中的学生信息读入内存,并调用Print()
函数进行输出。**SaveResult()
**函数需要将计算出总分、平均分和名次信息的学生信息存入result.txt
。
3.student.txt
的示例如下:
4.result.txt
的示例如下:
5.step2/main.c
主要代码如下:
#include <stdio.h>
#include <stdlib.h>
#define COURSE_MAXNUM 5
//声明结构STUDENT
struct student
{
long studentID;
char studentName[20];
char sex[4];
struct{
int year;
int month;
int day;
}birthday;
float score[COURSE_MAXNUM];
float total;
float average;
int rank;
};
typedef struct student STUDENT;
//声明外部函数,函数在其它源文件中实现
extern void ReadStudInfo(const char *fileName, STUDENT stud[]);
extern void SaveResult(const char *fileName, STUDENT stud[],int n,int m);
//声明本文件中的其它函数
void Input(STUDENT *stud, int n,int m);
void Print(STUDENT *stud, int n,int m);
void TotalAndAverage(STUDENT *stud, int n,int m);
void RankByTotal(STUDENT *stud, int n,int m);
void SaveStudInfo(const char *fileName,STUDENT *stud,int n,int m);
void ReadResult(const char *fileName,STUDENT *stud);
int main()
{
int n,m; //n用于存放学生人数,m用于存放课程门数。
STUDENT *stud; //指向存放学生信息的存储块的首地址
scanf("%d%d",&n,&m); //输入学生总人数
// 动态分配存储
stud = (STUDENT *)malloc(n*sizeof(STUDENT));
Input(stud,n,m);//输入学生信息
//将测试输入信息写入文件
SaveStudInfo("student.txt",stud,n,m);
free(stud);
//打开文件student.txt,以文本文件方式打开用于读
//从文件中读取学生信息到数组stud中
stud = (STUDENT *)malloc(n*sizeof(STUDENT));
ReadStudInfo("student.txt",stud);
// 计算总分
TotalAndAverage(stud,n,m);
// 计算排名
RankByTotal(stud,n,m);
//打开文件result.txt,以文本文件方式打开用于写
//将计算出了总分和平均分以及名次的学生信息写入文件
SaveResult("result.txt",stud,n,m);
free(stud);
//打开文件result.txt,以文本文件方式打开用于读
//从文件中读取学生信息到数组stud中,用于测试是否与预期输出一致
stud = (STUDENT *)malloc(n*sizeof(STUDENT));
ReadResult("result.txt",stud);
//输出学生信息
Print(stud,n,m);
free(stud);
return 0;
}
平台会对你编写的代码进行测试: 测试样例:
#include <stdio.h>
#include <stdlib.h>
#define COURSE_MAXNUM 5
//声明结构STUDENT
struct student
{
long studentID;
char studentName[20];
char sex[4];
struct{
int year;
int month;
int day;
}birthday;
float score[COURSE_MAXNUM];
float total;
float average;
int rank;
};
typedef struct student STUDENT;
//从文件fileName表示的文本文件中读取学生基本信息,
//包括学号、姓名、性别、出生日期,若干门课程的成绩
//文件的第一行存储的信息包含了n和m,即学生的人数和课程门数
void ReadStudInfo(const char *fileName, STUDENT stud[])
{
/***********Begin*****************/
FILE *fp = fopen(fileName,"r"); //打开文本文件student.txt用于读
if(fp == NULL)
{
printf("Failure to open %s!\n",fileName);
exit(0);
}
int n,m;
fscanf(fp,"%d%d",&m,&n);
for(int i=0;i<n;i++)
{
fscanf(fp,"%ld",&stud[i].studentID);
fscanf(fp,"%s",stud[i].studentName);
fscanf(fp,"%s",stud[i].sex);
fscanf(fp,"%d-%d-%d",&stud[i].birthday.year,&stud[i].birthday.month,&stud[i].birthday.day);
for(int j=0;j<m;j++)
fscanf(fp,"%f",&stud[i].score[j]);
}
fclose(fp);//关闭文件
/***********End*******************/
}
//向文件fileName表示的文本文件中写入学生基本信息,
//包括学号、姓名、性别、出生日期,若干门课程的成绩、总分、平均分、名次
//文件的第一行存储的信息应该包括n和m,即学生的人数和课程门数
void SaveResult(const char *fileName, STUDENT stud[],int n,int m)
{
/***********Begin*****************/
FILE *fp = fopen(fileName,"w"); //打开文本文件result.txt用于写
if(fp == NULL)
{
printf("Failure to open %s!\n",fileName);
exit(0);
}
fprintf(fp,"%d %d",n,m);//将n,m写入文件
for(int i=0;i<n;i++)
{
fprintf(fp,"\n%-12ld\t",stud[i].studentID);
fprintf(fp,"%-12s\t",stud[i].studentName);
fprintf(fp,"%-4s\t",stud[i].sex);
fprintf(fp,"%4d-%02d-%02d\t",stud[i].birthday.year,stud[i].birthday.month,stud[i].birthday.day);
for(int j=0;j<m;j++)
fprintf(fp,"%.0f\t",stud[i].score[j]);
fprintf(fp,"%.0f\t",stud[i].total);
fprintf(fp,"%.0f\t",stud[i].average);
fprintf(fp,"%d",stud[i].rank);
}
fclose(fp); //关闭文件
/***********End*******************/
}
第3关:按数据块读写文件存取学生信息
任务描述
本关任务与第2
关任务相似。
相关知识(略)
编程要求
本关的编程任务是补全step2/fileBin.c
文件中ReadStudInfo
函数和SaveResult
函数,以实现按数据块使用FILE结构存取学生信息的功能。具体要求如下:
1.ReadStudInfo
函数功能:实现从二进制文件中读取学生的基本信息。函数ReadStudInfo
函数原型为:
void ReadStudInfo(const char *fileName, STUDENT stud[]);
其中:
- 参数
fileName
是一个二进制格式的文件,位于当前目录,即与源程序文件在同一文件夹下。文件中首先是以二进制数据形式写入的学生人数(整数n
,不超过30
)和课程数量(整数n
,不超过5
),然后是n
个学生的信息,学生信息在结构STUDENT
中定义:struct student
{
long studentID;
char studentName[20];
char sex[4];
struct{
int year;
int month;
int day;
}birthday;
float score[COURSE_MAXNUM];
float total;
float average;
int rank;
};
typedef struct student STUDENT;
- 文件中存储了 total,average,rank 三项信息,但均为初始值0。
- 函数
ReadStudInfo
的第二个参数stud
存放读取出来的学生信息。
2.SaveResult
函数功能:实现从二进制格式文件中读取学生的基本信息。函数SaveResult
函数原型为:
void SaveResult(const char *fileName, STUDENT stud[],int n,int m);
其中:
- 参数
fileName
是一个二进制格式文件,位于当前目录,即与源程序文件在同一文件夹下。 - 文件中首先要求以二进制形式写入学生人数(整数
n
,不超过30
)和课程数量(整数n
,不超过5
),然后是n
个学生的信息。n
个学生的信息存放在第二个参数stud
开始的n
个结构体数据单元中。 - 每个学生的信息包括学号、姓名、性别、出生日期,若干门课程的成绩、总分、平均分、名次。
测试说明
本关的测试文件是step3/main.c
,其中将会调用你在step3/fileBin.c
文件中完成的ReadStudInfo
函数和SaveResult
函数。除此之后,step3/main.c
中还对学生信息进行了处理:包括计算总分、平均分和名次。其次还实现了输入测试数据、输出测试结果、写入测试文件(student.dat
)、读取测试文件(result.dat
):
1.调用函数Input()
将标准输入的数据读入内存,然后调用SaveStudInfo()
函数将数据再写入到student.dat
文本文件,以便为**ReadStudInfo()
**函数从文本文件读取学生信息准备测试数据。
2.调用函数ReadResult()
将SaveResult()
函数保存的result.dat
中的学生信息读入内存,并调用Print()
函数进行输出。**SaveResult()
**函数需要将计算出总分、平均分和名次信息的学生信息存入result.dat
。
3.student.dat
的示例如下:
4.result.dat
的示例如下:
5.step3/main.c
主要代码如下:
#include <stdio.h>
#include <stdlib.h>
#define COURSE_MAXNUM 5
//声明结构STUDENT
struct student
{
long studentID;
char studentName[20];
char sex[4];
struct{
int year;
int month;
int day;
}birthday;
float score[COURSE_MAXNUM];
float total;
float average;
int rank;
};
typedef struct student STUDENT;
//声明外部函数,函数在其它源文件中实现
extern void ReadStudInfo(const char *fileName, STUDENT stud[]);
extern void SaveResult(const char *fileName, STUDENT stud[],int n,int m);
//声明本文件中的其它函数
void Input(STUDENT *stud, int n,int m);
void Print(STUDENT *stud, int n,int m);
void TotalAndAverage(STUDENT *stud, int n,int m);
void RankByTotal(STUDENT *stud, int n,int m);
void SaveStudInfo(const char *fileName,STUDENT *stud,int n,int m);
void ReadResult(const char *fileName,STUDENT *stud);
int main()
{
int n,m; //n用于存放学生人数,m用于存放课程门数。
STUDENT *stud; //指向存放学生信息的存储块的首地址
scanf("%d%d",&n,&m); //输入学生总人数
// 动态分配存储
stud = (STUDENT *)malloc(n*sizeof(STUDENT));
Input(stud,n,m);//输入学生信息
//将测试输入信息写入二进制文件
SaveStudInfo("student.dat",stud,n,m);
free(stud);
//打开文件student.dat,以二进制文件方式打开用于读
//从文件中读取学生信息到数组stud中
stud = (STUDENT *)malloc(n*sizeof(STUDENT));
ReadStudInfo("student.dat",stud);//位于fileBin.c文件中
// 计算总分
TotalAndAverage(stud,n,m);
// 计算排名
RankByTotal(stud,n,m);
//打开文件result.dat,以二进制文件方式打开用于写
//将计算出了总分和平均分以及名次的学生信息写入文件
SaveResult("result.dat",stud,n,m);//位于fileBin.c文件中
free(stud);
//打开文件result.dat,以二进制文件方式打开用于读
//从文件中读取学生信息到数组stud中,用于测试是否与预期输出一致
stud = (STUDENT *)malloc(n*sizeof(STUDENT));
ReadResult("result.dat",stud);
//输出学生信息
Print(stud,n,m);
//释放动态申请的存储块
free(stud);
return 0;
}
平台会对你编写的代码进行测试:
测试样例
#include <stdio.h>
#include <stdlib.h>
#define COURSE_MAXNUM 5
//声明结构STUDENT
struct student
{
long studentID;
char studentName[20];
char sex[4];
struct{
int year;
int month;
int day;
}birthday;
float score[COURSE_MAXNUM];
float total;
float average;
int rank;
};
typedef struct student STUDENT;
//从文件fileName表示的二进制文件中读取学生基本信息,
//包括学号、姓名、性别、出生日期,若干门课程的成绩
//文件的第一行存储的信息包含了n和m,即学生的人数和课程门数
void ReadStudInfo(const char *fileName, STUDENT stud[])
{
/*************Begin***************/
FILE *fp = fopen(fileName,"r");
if(fp == NULL)
{
printf("Failure to open %s!\n",fileName);
exit(0);
}
int n,m;
fread(&n,sizeof(n),1,fp);
fread(&m,sizeof(m),1,fp);
fread(stud,sizeof(STUDENT),n,fp);
fclose(fp);
/*************End*****************/
}
//向文件fileName表示的二进制文件中写入学生基本信息,
//包括学号、姓名、性别、出生日期,若干门课程的成绩、总分、平均分、名次
//文件的第一行存储的信息应该包括n和m,即学生的人数和课程门数
void SaveResult(const char *fileName, STUDENT stud[],int n,int m)
{
/*************Begin***************/
FILE *fp = fopen(fileName,"w");
if(fp == NULL)
{
printf("Failure to open %s!\n",fileName);
exit(0);
}
fwrite(&n,sizeof(n),1,fp);
fwrite(&m,sizeof(m),1,fp);
fwrite(stud,sizeof(STUDENT),n,fp);
fclose(fp);
/*************End*****************/
}