结构体与文件程序设计

(1)设计一个保存学生成绩信息的结构,包括学号、姓名、课程名、平时成绩、考试成绩、总评成绩。分别用函数实现以下功能:

①输入n个学生的信息(平时和考试成绩)
②要求计算并输出学生的总分(平时20%,考试80%)并输出;
③输出总分最高和最低的学生信息。

#include<stdio.h>
#include<string.h>
int main()
{
	int a,i,j,k,n,x,y;
	n = 4;
	struct students
	{
		int num;//学号
		const char* name;//姓名
		const char* subject;//课程名
		int test;//平时成绩
		int exam;//考试成绩
		float score;//总评成绩
	};
	const char* name[] =
	{
		"Li Hua",
		"Li Ming",
		"Tie Zhu",
		"Lily"
	};
	int num[] = { 1,2,3,4 };
	const char* subject[] = { "math" };
	int test[4] = { 0 };
	int exam[4] = { 0 };
	float score[4] = { 0 };
	for (a = 0; a < n; a++)
	{
		printf("请输入学号%d,名字为%s的同学的平时成绩和考试成绩(输入两个成绩用空格分开)\n", a + 1, name[a]);
		scanf_s("%d%d", &test[a], &exam[a]);
		score[a] = test[a] * 0.20 + exam[a] * 0.80;
		printf("该同学的总评成绩为:%.2f\n", score[a]);
	}
	printf("学号\t姓名\t课程名\t平时成绩\t考试成绩\t总评成绩\n");
	for ( i = 0; i <n; i++)
	{
		printf("%d\t%s\t%s\t%d\t\t%d\t\t%.2f\n", num[i], name[i], subject[0], test[i], exam[i], score[i]);
	}
	float max, min;
	max = min = score[0];
	for ( j = 0; j < n; j++)
	{
		if (max < score[j])
		{
			max = score[j];
			x = j;
		}
		else
		{
			max = max;
		}
	}
	printf("%.2f", max);
	for ( k = 0; k < n; k++)
	{
		if (min > score[k])
		{
			min = score[k];
			y = k;
		}
		else
		{
			min = min;
		}
	}
	printf("这些学生中总评成绩最高的学生信息如下:\n");
	printf(" % d\t % s\t % s\t % d\t\t % d\t\t % .2f\n", num[x], name[x], subject[0], test[x], exam[x], score[x]);
	printf("这些学生中总评成绩最低的学生信息如下:\n");
	printf("%d\t%s\t%s\t%d\t\t%d\t\t%.2f\n", num[y], name[y], subject[0], test[y], exam[y], score[y]);
	return 0;
}

(2)从键盘输入n(n<10)本书的名称和单价并存入结构数组中,按照单价从高到低的顺序进行排序并输出。

①编写函数实现排序过程;
②在主函数中输入数据,调用排序函数排序后返回主函数输出排序结果。

#include<stdio.h>
#include<string.h> 
struct Books
{
	char name[100];
	float price;
}book[10];
void paixu(void);
int main(void)
{
	int i;
	float y;
	char b[10];
	for(i=0;i<10;i++)
	{
		printf("请输入第%d本书的名字和价钱(用空格隔开):\n",i+1);
		scanf("%s%f",book[i].name,&book[i].price);  
    }
    paixu();
	printf("排序后:\n");
	printf("书名\t\t价格\n");
	int j;
	for(j=0;j<10;j++)
	{
		printf("%s\t%.2f\n",book[j].name,book[j].price);
	}
	return 0;
} 
void paixu(void)
{
	int z,g;
	char k[100];
	float x;
	for(z=0;z<10;z++)
	{
		for(g=z+1;g<10;g++)
	    if(book[z].price<book[g].price)//从大到小排序 
		{
				x=book[z].price;
				strcpy(k,book[z].name);//strcpy()是拷贝字符串 
				book[z].price=book[g].price;
				strcpy(book[z].name,book[g].name);
				book[g].price=x;
				strcpy(book[g].name,k);
		}
	}
}

文件编程

先用记事本在当前目录下创建一个 data.txt文件,在里面输入保存(1)中的学生成绩(平时及考试成绩),存盘关闭;然后写一个程序来打开这个文件,计算总分后显示在屏幕上,同时输出到结果文件T_data.txt文件中。
第一种编程方法:一开始就已经在程序里面写死,只能在源代码上更改数据

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct Stu
{
	int num;
	char name[100];
	float test;
	float exam;
}stus[]={
    {1,"Li Hua",78,90},
	{2,"Li Ming",89,90},
	{3,"Chen Hua",96,98},
	{4,"Xiao Hua",90,95}
	};
int main()
{
	FILE*fp1,*fp2;
	int i;
	if((fp1=fopen("data.txt","w+"))==NULL)
	{
		printf("文件打开失败!\n");
		exit(EXIT_FAILURE); 
	}
	for(i=0;i<4;i++)	
	{
		fscanf(fp1,"%d %s %f %f",&stus[i].num,stus[i].name,&stus[i].test,&stus[i].exam);
		fprintf(fp1,"%d号学生%s平时成绩%f,考试成绩%f\n",stus[i].num,stus[i].name,stus[i].test,stus[i].exam);
//printf是打印输出到屏幕,fprintf是打印输出到文件。 
	}
	printf("成功将数据写入第一个文件!\n");
	fclose(fp1);
	
	if((fp2=fopen("T_data.txt","w+"))==NULL)
	{
		printf("文件打开失败!\n");
		exit(EXIT_FAILURE);
	}
	
	float score[100];
	for(i=0;i<4;i++)
	{
		score[i]=0.2*stus[i].test+0.8*stus[i].exam;
		fscanf(fp1,"%d %s %f %f",&stus[i].num,stus[i].name,&stus[i].test,&stus[i].exam);
		fprintf(fp1,"%d号学生%s的平时成绩:%.2f 考试成绩:%.2f\n",stus[i].num,stus[i].name,stus[i].test,stus[i].exam); 
	    fscanf(fp2,"%f",&score[i]);
	    fprintf(fp2,"%d号学生的总分为:%.2f\n",i+1,score[i]);
	 }

第二种编程方法:可以灵活地将数据写入文档

#include<stdio.h>
#include<string.h>
#include<stdlib.h> 
#ifndef STUDENT_H_INCLUDED
#define STUDENT_H_INCLUDED
typedef struct student//这是student.h 
{
    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

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

void inputInformation(Student* stus, int N)
{
	int i;
	for ( i = 0; i < N; i++)
	{
		printf("学生%d的学号,姓名,平时成绩,考试成绩(空格分隔):\n",i);
		scanf("%s", stus[i].stu_number);
		scanf("%s", stus[i].stu_name);
		scanf("%f", &stus[i].usual_mark);
		scanf("%f", &stus[i].exam_mark);
		stus[i].overall_mark = stus[i].usual_mark * 0.2 + (stus[i].exam_mark)*0.8;
		getchar();
	}
	return;
}

void saveInformation(Student* stus, int N, char* data)
{
	FILE* fp;
	if ((fp=fopen("data.txt","w+"))==NULL)
	{
		printf("文件读取失败!\n");
		return;
	}

		int i;
		for (i = 0; i < N; i++)
		{
			fprintf(fp, "学号=%s,姓名=%s,平时成绩=%.2f,考试成绩=%.2f,总评成绩=%.2f\n", stus[i].stu_number, stus[i].stu_name, stus[i].usual_mark, stus[i].exam_mark, stus[i].overall_mark);
		}
		int j, k;
		Student* temp;
		temp = (Student*)malloc(sizeof(Student));
		for (j=0;j<N;j++)
		{
			for (k=j+1;k<N;k++)
			{
				if (stus[j].overall_mark>stus[k].overall_mark)//从小到大排序
				{
					strcpy(temp->stu_number, stus[j].stu_number);
					strcpy(temp->stu_name, stus[j].stu_name);
					temp->usual_mark = stus[j].usual_mark;
					temp->exam_mark = stus[j].exam_mark;
					temp->overall_mark = stus[j].overall_mark;

					strcpy(stus[j].stu_number, stus[k].stu_number);
					strcpy(stus[j].stu_name,stus[k].stu_name);
					stus[j].usual_mark = stus[k].usual_mark;
					stus[j].exam_mark = stus[k].exam_mark;
					stus[j].overall_mark = stus[k].overall_mark;

					strcpy(stus[k].stu_number, temp->stu_number);
					strcpy(stus[k].stu_name,temp->stu_name);
					stus[k].usual_mark = temp->usual_mark;
					stus[k].exam_mark = temp->exam_mark;
					stus[k].overall_mark = temp->overall_mark;
				}
			}
		}
		int n;
		for (n=0;n<N;n++)
		{
			if (n==0)
			{
				fprintf(fp,"最低分学生:\n");
				fprintf(fp, "学号=%s,姓名=%s,平时成绩=%.2f,考试成绩=%.2f,总评成绩=%.2f\n", stus[n].stu_number, stus[n].stu_name, stus[n].usual_mark, stus[n].exam_mark, stus[n].overall_mark);
			}
			else if (n==N-1)
			{
				fprintf(fp,"最高分学生:\n");
				fprintf(fp, "学号=%s,姓名=%s,平时成绩=%.2f,考试成绩=%.2f,总评成绩=%.2f\n", stus[n].stu_number, stus[n].stu_name, stus[n].usual_mark, stus[n].exam_mark, stus[n].overall_mark);
			}
		}
	fclose(fp);
	return;
}

void outputInformation(char* data)
{
	FILE* fp;
	char ch;
	fp=fopen("data.txt", "r");
	printf("全部学生:\n");
	if(fp==NULL)
	{
		printf("文件打开失败!\n");
	}
	while(!feof(fp))//如果没有遇到文件末尾标志 
	{
		ch=fgetc(fp);
		printf("%c",ch);
	}
	fclose(fp);
	return;
}

}
    printf("第二个文件写入成功!\n"); 
	fclose(fp2);
	for(i=0;i<4;i++)
	{
		printf("%d号学生%s的平时成绩:%.2f,考试成绩:%.2f,总成绩为%.2f\n",
		i+1,stus[i].name,stus[i].test,stus[i].exam,score[i]);
	} 
	return 0; 
}

fgets()的例子

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
int main()
{
	char a[1024];
	FILE*fp1;
	if((fp1=fopen("data.txt","w+"))==NULL)//C的运行环境
	{
		printf("文件打开失败!\n");
		exit(EXIT_FAILURE);
	}//将下列数据写入data.txt文档中 
	fputs("姓名     平时成绩    考试成绩\n",fp1);
	fputs("Li Hua      85         90\n",fp1);
	fputs("Li Ming     80         90\n", fp1);
	fputs("Tie Zhu     78         95\n", fp1);
	fputs("Lily        90         95\n", fp1);//这一行在屏幕上出现两次,但在data.txt文档中是没有出现两次 
	fclose(fp1);
	if((fp1=fopen("data.txt","r"))==NULL)
	{
		printf("文件打开失败!\n");
		exit(EXIT_FAILURE);
	}
	while(!feof(fp1))//如果未遇到文件的结束标志
	{             //feof()这个函数是来判断指针是否到达文件尾部
		fgets(a,1024,fp1);//因为fgets()函数在遇到EOF或者换行字符"\n"时结束 ;
		//在读取到最后一行的换行字符时,认为这一行已经读取结束 。
		//那么如果还没读入任何字符就遇到EOF,则保持原来的内容 ,函数返回NULL,因而在显示屏上最后一句会重复 
		printf("%s",a); 
	}
	return 0;
}    

小总结

  • c++中strcpy与strcpy_s(都是拷贝字符串)的使用。
    详细请看:https://blog.csdn.net/leowinbow/article/details/82380252
  • 对于 Windows 系统,使用 fread() 和 fwrite() 时应该以二进制的形式打开文件。
  • C与C++打开文件不同:在C种,打开文件用fp1=fopen(“data.txt”,”r+”);但在C++里,则要用fopen_s()函数,且fopen_s()不接受两个参数,可用fopen_s(&fp1,”data.txt”,”w+”)。
    详细请看:https://zhidao.baidu.com/question/1381989473982577100.html
  • 输出文件中的内容到屏幕上:
    有以下两种方法:
    第一种
While(!feof(fp))//如果未遇到文件的结束标志
{
Ch=getc(fp);//从文件中读入一个字符
Printf(%c”,ch);//把ch的字符显示在显示屏上
}

第二种

Ch=fgetc(fp);
While(!Feof(fp))
{
printf(%c”,ch);
fscanf(fp,%c”,&ch)//读取字符
}
  • fgets:从文件中读取一行数据存入缓冲区(fgets遇到回车才会结束,不对空格和回车做任何转换就录入到缓冲区,结束后再往缓冲区写多一个\0,所以它是读一行数据)
  • fscanf:从文件中读取一段数据存入缓冲区(fscanf遇到空格或回车就结束,它会把空格或回车转换为\0,所以它是读一小段数据)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值