实验七 文件操作程序设计

学生成绩的存储与查询

题目
在这里插入图片描述在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
我们首先得知道在一个项目里可以写很多个程序,但只能有一个主函数
解题:
首先创建一个项目
Devc++会自动生成一个main.c
主函数题目已经提供直接放进去

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include<string.h>
    #include "student.h"
    int main()
    {
        Student* stus;
        char path[1024];
        int N;
        getcwd(path,1024);
        strcat(path,"\\data.txt");
        //输入学生人数
        printf("学生人数N=");
        scanf("%d",&N);
        //创建动态结构体数组
        stus=(Student*)malloc(sizeof(Student)*N);
        //输入各学生学号,姓名,某门课平时、考试成绩(这些字段的值之间用英
        //文逗号隔开),总评成绩根据平时、考试分别占0.2,0.8比例自动计算
        //输入完一个学生后,回车即可输入下一个学生信息
        inputInformation(stus,N);
        //把学生成绩记录存入文件,存入文件后关闭文件
        saveInformation(stus,N,path);
        //释放内存
        free(stus);
        //从文件中读取学生成绩记录,输出最低、最高总评成绩对应的学生完整信息
        printf("全部学生、总评最低和最高学生信息如下:\n");
        outputInformation(path);
        return 0;
    }

在添加一个
点击项目,点击添加
并名名为student.h,题目有个坑给你head.h,我最开始就写的这个

 #ifndef STUDENT_H_INCLUDED//防止重复定义 
    #define STUDENT_H_INCLUDED
    typedef struct student
    {
        char stu_number[20];
        char stu_name[20];
        float usual_mark;
        float exam_mark;
        float overall_mark;
    }Student;
    void inputInformation(Student*stus,int N);
    void saveInformation(Student*stus,int N,char*filename);
    void outputInformation(char*filename);
    #endif

这里有个知识点

 #ifndef STUDENT_H_INCLUDED//防止重复定义 
    #define STUDENT_H_INCLUDED

    #endif

我们知道函数的定义不能重复,如果我写了这个函数,并存放在这个.h的文件中,我写另外一个.h文件时,又要用到它,这时就会造成定义重复问题,所以变产生上面这种写法
翻译:
如果没定义Student.h
就定义Student.h
如果定义了
就不再定义

最后时student.c
注释都在代码里了

#include<stdio.h>
#include <stdlib.h>
#include<string.h>
#include "student.h"
//请在下面给出程序中所用到的自定义函数的完整定义
//打开文件的标准代码 FILE*fp=fopen("file","r");
/*FILE*fp=fopen("file","r");
 if(fp)
 {
 fscanf(fp,...);
 fclose(fp);
}
 else{

}**/
 void inputInformation(Student*stus,int N)//根据意思很好理解就是写入数据  Student*stus 就是数组结构Student stus[] 
 {//这个函数还是比较简单的 
 	int i; 
 	for(i=0;i<N;i++)//
 	{
 		printf("学生%d的学号,姓名,平时成绩,考试成绩(空格分隔):\n",i);
 		scanf("%s",(stus+i)->stu_number);//这里用%s,注意看我们定义的机构中stu_number是数组
		scanf("%s",(stus+i)->stu_name);
		scanf("%f",&(stus+i)->usual_mark);
		scanf("%f",&(stus+i)-> exam_mark);
		(stus+i)->overall_mark=0.2*(stus+i)->usual_mark+0.8*(stus+i)->exam_mark;
	 }
 
 }

 void saveInformation(Student*stus,int N,char*filename)//main函数中,我们将path里面装个一个文本data.txt 
 {//现在我们要数据放入文件中储蓄起来 
    int i;
 	FILE*pf=NULL;//C语言中w与wb. w:打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。. 
	//若文件不存在则建立该文件。. wb:只写方式打开或新建一个二进制文件,只允许写数据。
    pf=fopen(filename,"wb");
    for(i=0;i<N;i++)
    {
    	fprintf(pf,"%s %s %f %f %f\n",(stus+i)->stu_number,(stus+i)->stu_name,(stus+i)->usual_mark,(stus+i)-> exam_mark,(stus+i)->overall_mark);
	}// int fprintf(FILE *stream, const char *format, ...) 发送格式化输出到流 stream 中
	fclose(pf);
	pf=NULL;
 }
 
 void outputInformation(char*filename)//输出文本中的内容,并且比较大小 
 {
 	int i=0;
 	Student*stus=(Student*)malloc(sizeof(Student)*10);//给10个空间就够了 
 	FILE*pf=fopen(filename,"rb");//rb代表打开一个已有的二进制文件,允许读取文件
 	printf("全部学生:\n");
 	fscanf(pf,"%s %s %f %f %f",stus->stu_number,stus->stu_name,&stus->usual_mark,&stus->exam_mark,&stus->overall_mark);
 	/*fscanf 函数原型为 int fscanf(FILE * stream, const char * format, [argument...]); 其功能为根据数据格式(format),
	 从输入流(stream)中读入数据,存储到argument中,遇到空格和换行时结束。fscanf位于C标准库头文件<stdio.h>中。
   */
 	while(!feof(pf))// feof()是检测流上的文件结束符的函数,如果文件结束,则返回非0值,否则返回0
    //一般在文件操作,中经常使用feof()判断文件是否结束。
    //题目说了该文件还能读取所以要这么写 
	{
		i++;
		fscanf(pf,"%s %s %f %f %f",(stus+i)->stu_number,(stus+i)->stu_name,&(stus+i)->usual_mark,&(stus+i)-> exam_mark,&(stus+i)->overall_mark);//根据题目的意思除了能存储数据 
	  }  
   int k;
   for(k=0;k<i;k++)
   {
   	printf("学号=%s,姓名=%s,平时成绩=%.2f,考试成绩=%.2f,总评成绩=%.2f\n",(stus+k)->stu_number,(stus+k)->stu_name,(stus+k)->usual_mark,(stus+k)-> exam_mark,(stus+k)->overall_mark);
   }
   fclose(pf);
    pf=NULL;
   //最后用以前学习的方法进行比较大小
   //这里换成了结构之间的比较 
      float min= (stus+0)->overall_mark;
	  float max= (stus+0)->overall_mark;
	  Student*Max=(stus+0);
	  Student*Min=(stus+0);
	  for(k=1;k<i;k++)
	  {
	  	if(min>(stus+k)->overall_mark)
	  	{
	  		min=(stus+k)->overall_mark;
	  		Min=(stus+k);
		  }
	  }
	  printf("最低分学生:\n");
	  printf("学号=%s,姓名=%s,平时成绩=%.2f,考试成绩=%.2f,总评成绩=%.2f\n",Min->stu_number,Min->stu_name,Min->usual_mark,Min->exam_mark,Min->overall_mark);
	   for(k=1;k<i;k++)
	  {
	  	if(max<(stus+k)->overall_mark)
	  	{
	  		max=(stus+k)->overall_mark;
	  		Max=(stus+k);
		  }
	  } 
	  printf("最高分学生:\n");
	  printf("学号=%s,姓名=%s,平时成绩=%.2f,考试成绩=%.2f,总评成绩=%.2f",Max->stu_number,Max->stu_name,Max->usual_mark,Max->exam_mark,Max->overall_mark);
  } 

运行结果

在这里插入图片描述

遇到的问题

首先写完这个函数的时候我的就写了一排
问题在哪里?
对什么时候取地址符搞混了
fprintf
fscanf
这两函数是不一样
以及printf
以及用完这个文件
记得关闭这个空间
也就是最后pf=NULL
错误的运行

在这里插入图片描述

最后,最后
一定注意平台的编译器,对空格,对换黄,对符号是英文还是中文很敏感细心点!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Back~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值