(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,所以它是读一小段数据)