您现在的位置: 天下网吧 >> 网吧天地 >> 天下码农 >> 微信小程序 >> 正文

学生信息管理C语言DOS环境运行

2011-1-9vczx佚名

题目分析 及 算法设计 :

        题目中的各个功能都是相对独立的,所以我将各项功能以 带 编号 的菜单形式组织在屏幕上,
        用户通过 输入 编号 执行相应的功能。显示菜单的代码处于一个循环之中,当执行完一个
        子功能后,就又回到循环,显示主菜单,直到用户选择 退出 菜单。

        这种操作方式比其它机制(如:主程序 + 程序参数)更简捷,不必每次用不同的参数重新运行程序,
        以实现相应的功能。
        
        1. 查看文件记录内容 的实现:
            用 循环 读取文件内容,然后显示在屏幕上。
            因为 我们的数据是以结构体的形式存放在文件中的,所以 代码中用了块读取和块写入函数。
            在 循环中设置计数器来统计记录的个数。

        2. 添加记录 的实现:
            让用户根据屏幕提示输入数据,完成对学生信息结构体各项的赋值,待取得足够数据后,
            将数据文件以“追加”方式打开,执行块写入,将整个结构体写入文件。

        3. 删除记录 的实现:
            学号(ID)一般不会重复,所以我在程序中让用户输入想要删除的记录的学号(ID),
            然后在文件中查找,如果不是用户想要删除的记录(即ID不同),就保存在一个临时的文件中,
            这样,就将想要删除的记录与其它记录分离开了,最后,删除原来的数据文件,将临时文件的
            名字改为 原来数据文件的名字。

        4. 统计功能 的实现:
            统计功能模块分为三个小模块:平均分的分数段统计,总分的最高和最低分统计,
            各科的最高和最低分统计。但我并不想分别来写,因为它们都要对所有记录进行扫描,
            而它们又互不干扰,所以我把它们组织在一个循环中,各自都有自己的计算代码和变量,
            所以这个 函数 中的局部变量 很多。

        5. 查找功能 的实现:
            题目要求两种查找方式:按 学号(ID) , 按 姓名(Name)。
            两者是独立的,所以我用了一个参数 isFind_From_ID 来表明是哪种查找方式,进而在在程序
            内部由一个 switch() 选择分支转向不同的代码段去执行。
            具体的查找就是比较相应的项目是否与用户输入的一样,若一样就输出到屏幕。

有关各个变量的作用都已经在代码中表明,非常详细。
===================================================================================
运行效果如下(在dos环境中运行):

############    Main   Menu    ###############
##############################################

        1 .     View the Records in the data file
        2 .     Add New Record
        3 .     Delete an old Record
        4 .     Make a Statistics
        5 .     Find a Record from the ID
        6 .     Find a Record from the Name
        7 .     Quit

##############################################

Input the index of your choice : 1

#########       Start a command         #########

  Name : wewewew                Sex : Female
  ID : 232323           Class : sasas
Math = -858993460       English = -858993460    Compute = -858993460
Philosophy = -858993460         PE = -858993460

------------------------------------------
  Name : ww             Sex : Female
  ID : 2121             Class : 12
Math = 123      English = 123   Compute = 123
Philosophy = 123                PE = 123

------------------------------------------
The current data file have     2       record .

#########        End  a command         #########

Press any key to Return Main Menu ....

#include "stdio.h"
#include "conio.h"
#include "string.h"
#include "stdlib.h"

#define CMD_START printf("\n\n######### Start a command  #########\n");
/* 用来标记一个命令执行的开始*/
#define CMD_END  printf(  "\n#########  End  a command  #########\n\n");
/* 用来标记一个命令执行的结束 ,这两个语句是为了提供更好的用户界面而写的 */
#define  DATA_FILE "data.dat"
/* 这是 数据文件名 */
#define TEMP_FILE  "temp.dat"
/* 这是一个临时的文件的名字,在删除记录的函数中使用的,
详细内容参考 Delete() 函数 */

typedef struct tagStudent
{
char ID[30];  /* 学号 */
char Name[30]; /* 姓名 */
char Class[255]; /* 班级 */
char Sex; /* 性别 ,值为 F 或 f 或 M 或 m */
int Math;  /* 数学成绩 */
int English; /* 英语成绩 */
int Compute; /* 计算机成绩 */
int Philosophy; /* 哲学成绩 */
int  PE;  /* 体育成绩 */
} Student;
/* 这是学生信息结构体 */

int ShowMenu(); /* 在屏幕上打印 主菜单 的函数,它的返回值为 所选 菜单的 项目编号 */
int ReadData(FILE*,Student* ); /* 从一个 打开的数据文件中读取 记录的函数,错误返回 0 */
int WriteData(FILE* , Student* ); /* 向一个数据文件中 写入 记录的函数,错误返回 0 */
void Output_Rec(Student*); /* 在屏幕上 打印 一条记录 */
void Input_Rec(Student*); /* 让用户输入 记录的 各个项目的 值,在添加记录时用到了 */
void CopyRec(Student* , Student* ); /* 复制一条记录 到 另一个记录中 */

/* 题目中要求的函数 */
void  Print(); /* 实现查看数据文件内容的函数 */
void Add();  /* 添加记录的函数 */
void Delete(); /* 删除记录的函数 */
void    Statistics(); /* 对数据进行统计分析的函数 */
void Find(int); /* 实现查找功能的函数,参数决定 是按 ID 查找 还是按 Name 查找 */

int quit; /* 一个全局变量,在下面的 main() 函数中,用来决定何时退出主循环 */

main()
{
int cmd; /* 用户所选的 菜单 项目 的标号 */

quit = 0; /* 初始化 为 不退出 */

/* 这是程序的主循环,每次都将 主菜单打印出来,
供用户选择相应的 序号 来执行相应的功能 */
while( ! quit )
{

  cmd = ShowMenu(); /* 显示 主菜单,并返回用户所选择的 菜单项 的 编号 */

  CMD_START /* 在屏幕上打印一行分隔符,告诉用户这是一个子功能的开始 */

  switch( cmd ) /* 用多项分支 根据 用户的选择 调用 相应的函数 */
  {
     case 1:
    Print(); break; /* 用户选择 1 号菜单,程序执行 查看的数据文件的函数 */
     case 2:
    Add();  break; /* 用户选择 2 号菜单,程序执行 添加记录的函数 */
     case 3:
    Delete(); break; /* 用户选择 3 号菜单,程序执行 删除记录的函数 */
     case 4:
    Statistics(); break; /* 用户选择 4 号菜单,程序执行 统计数据的函数 */
     case 5:
    Find(5); break; /* Find_ID ,5 号菜单执行 按 ID(学号)查找的功能 */
     case 6:
    Find(6); break; /* Find_Name,6 号菜单执行 按 Name(姓名)查找的功能 */
     case 7:
    quit = 1; /* 用户选择了退出菜单 */
    printf(" Thank you for your using .\n\n Happy everyday !!\n\n Bye Bye ....\n");

    break;

     default:
    printf(" Please Input a number between\t1\tto\t7.\n");
    /* 用户所输入的 序号不在所处理的范围内 */
  }

  CMD_END /* 打印一行分隔符,告诉用户 他所选择的菜单的功能已经执行完毕 */

  if (quit != 1) /* 检查用户是否 要求 退出 */
  {
   printf(" Press any key to Return Main Menu ....\n");
   getch(); /* 用 一个 无回显 的 字符输入函数 来实现暂停执行,按 任意键 继续的功能 */
  }

}

}

int ShowMenu()
{

int cmd = 0; /* 保存用户的选择 */

/* 定义 程序所支持的菜单项目 */
char Menu_SeeData[]  = "\t1 .\tView the Records in the data file\n"; /* 查看数据文件 */
char Menu_Add[]   = "\t2 .\tAdd New Record\n"; /* 添加记录 */
char Menu_Delete[]  = "\t3 .\tDelete an old Record\n"; /* 删除记录 */
char Menu_Statistics[]  = "\t4 .\tMake a Statistics\n"; /* 统计分析 */
char Menu_Find_ID[]  = "\t5 .\tFind a Record from the ID\n"; /* 按 学号(ID) 查找 */
char Menu_Find_Name[] = "\t6 .\tFind a Record from the Name\n"; /* 按 姓名(Name) 查找 */
char Menu_Quit[]  = "\t7 .\tQuit\n"; /* 退出 */

/* 在屏幕上打印 主菜单 */
printf("\n\n############    Main   Menu    ###############\n");
printf(    "##############################################\n\n");

printf(Menu_SeeData);
printf(Menu_Add);
printf(Menu_Delete);
printf(Menu_Statistics);
printf(Menu_Find_ID);
printf(Menu_Find_Name);
printf(Menu_Quit);

printf("\n##############################################");

printf("\n\n Input the index of your choice : ");

scanf("%d" , &cmd); /* 接受用户 选择 */

printf("\n");

return cmd; /* 返回用户的输入,交给主循环处理 */

}

void Print() /* 打印 数据文件的 记录内容 */
{

FILE* fp = NULL; /* 文件指针 */
Student rec; /* 存放从文件中读取的记录 */
int i = 0; /* 实现 计数 和 分屏打印的功能 */

fp = fopen(DATA_FILE , "rb"); /* 以 二进制读 方式 打开数据文件 */
if(fp == NULL) /* 打开文件出错 */
{
  printf(" Can not open the data file : %s\n" , DATA_FILE);
  return ;
}

while(ReadData(fp , &rec)) /* ReadData() 函数出错或到文件末尾时返回 0,可以做循环条件 */
{
  Output_Rec(&rec); /* 正确读取,将记录输出 */
  printf(" ------------------------------------------");
  /* 打印一行分隔符,营造好的用户界面 */

  i++; /* 计数器 加一 */
  if( i % 4 == 0) /* 显示 4 个暂停一下 */
  {
   printf("\n Press any key to continue ... \n");
   getch();
  }
}

printf("\n The current data file have\t%d\trecord .\n" , i );

fclose(fp); /* 关闭文件 */

}

void Add() /* 添加记录 */
{

Student rec;
FILE* fp = NULL;

Input_Rec( &rec ); /* 让用户输入新记录的各项内容 */

fp = fopen(DATA_FILE ,"ab"); /* 以 添加 方式打开数据文件 */
if( fp == NULL)
{
  printf(" Can not open the data file to write into ... \n");
  return ;
}

if( WriteData(fp, &rec) == 1) /* 将 新记录 写入文件,并检查 是否正确写入*/
  printf("\n\n Add New Record Success \n\n");
else
  printf("\n\n Failed to Write New Record into the data file \n");

fclose(fp);

}

void Delete() /* 删除记录 */
{

Student rec;
FILE* fpr,*fpw; /* 两个文件指针,分别用于 读 和 写 */
char buf[30]; /* 接受 用户输入的 ID 缓冲区 */
char cmd[255]; /* 执行的系统命令 */

int del_count; /* 实际 删除的 记录数目 */

del_count = 0;

printf("\n Please type the ID of the record you want me to delete .");
printf("\n The ID : "); /* 提示用户 输入 */
scanf("%s" , buf);

fpr = fopen(DATA_FILE ,"rb"); /* 从 原来的记录文件中读取数据,跳过将要删除的记录 */
if( fpr == NULL)
{
  printf(" Can not open the data file to read record ... \n");
  return ;
}

fpw = fopen(TEMP_FILE,"wb"); /* 打开一个 临时文件 保存不删除的记录 */
if( fpw == NULL)
{
  printf(" Can not open the data file to write into ... \n");
  return ;
}

while(ReadData(fpr , &rec)) /* 读取 要保留的记录 */
{
  if(strcmp(rec.ID , buf) != 0)
  {
   WriteData(fpw, &rec); /* 写入临时文件 ,然后删除 原数据文件,
          再将临时文件该名为原数据文件的名字*/
  }
  else
  {
   del_count++; /* 跳过的记录数目,即删除的数目 */
  }
}

fclose(fpr);
fclose(fpw);

strcpy(cmd , "del "); /* 构造命令串,用 system() 函数执行 */
strcat(cmd ,DATA_FILE);

system(cmd);

rename(TEMP_FILE,DATA_FILE); /* 直接调用 C 语言的改名函数将临时文件改名为数据文件的名字*/

printf("\n I have delete\t%d\trecord .\n" ,del_count);

}

void Statistics() /* 统计分析函数 */
{
int i50,i60,i70,i80,i90; /*平均分小于60 ,60-69,70-79,80-89,>=90 的分数段的学生数目*/
float avg; /*平均分*/

int sum ,sum_high,sum_low; /* 总分,总分最高分,总分最低分 */
Student stu_high,stu_low; /* 总分最高和最低 学生的信息 */

Student stu_math_high,stu_english_high; /* 各科 最高分的学生记录副本 */
Student stu_compute_high,stu_philosophy_high,stu_PE_high;

Student stu_math_low,stu_english_low; /* 各科最低的学生记录副本 */
Student stu_compute_low, stu_philosophy_low ,stu_PE_low;

FILE* fp;
Student rec;

int count; /* 一个计数器,用于判断是否第一次读取数据 */

count = sum = sum_high = sum_low = i50 = i60 = i60 = i70 =i80 = i90 = 0;
fp = NULL; /* 对 数据初始化 */
fp = fopen(DATA_FILE ,"rb");
if(fp == NULL)
{
  printf("\nCan not open the data file to read ...\n");
  return;
}

while(ReadData(fp , &rec)) /* 读取数据 */
{
  count++; /* 计数器 加一 */

  sum = rec.Math + rec.English + rec.Compute + rec.PE+ rec.Philosophy; /* 求和 */

  /* average */
  avg = ((float)sum) / 5; /* 平均分 */
  /* 下面对各个分数段进行统计 */
  if(avg < 60)
   i50++;
  else if(avg <70)
   i60++;
  else if(avg < 80)
   i70++;
  else if(avg < 90)
   i80++;
  else
   i90++;

  /*highest  and  loeest*/
  if(count <= 1) /* 第一次读取,执行初始化,不进行比较 */
  {
   sum_high = sum_low = sum;
   CopyRec(&stu_high , &rec);
   CopyRec(&stu_low ,&rec);
  }
  else
  {
   if(sum > sum_high)
   {
    sum_high = sum; /* 得到最高总分 */
    CopyRec(&stu_high , &rec); /* 保存总分最高的学生的信息 */
   }

   if(sum < sum_low)
   {
    sum_low = sum; /* 得到最低分 */
    CopyRec(&stu_low , &rec); /* 保存总分最低的学生的信息 */
   }
  }

  /* subject highest and low */
  if(count == 1) /* 同上面一样,执行初始化 */
  {
   CopyRec(&stu_math_high,&rec);
   CopyRec(&stu_english_high , &rec);
   CopyRec(&stu_compute_high, &rec);
   CopyRec(&stu_philosophy_high,&rec);
   CopyRec(&stu_PE_high , &rec);

   CopyRec(&stu_math_low,&rec);
   CopyRec(&stu_english_low , &rec);
   CopyRec(&stu_compute_low, &rec);
   CopyRec(&stu_philosophy_low,&rec);
   CopyRec(&stu_PE_low , &rec);

  }
  else
  {
   /* High */
   /* 保存各科的最高分的学生的信息 */
   if(rec.Math > stu_math_high.Math)
    CopyRec(&stu_math_high ,&rec);

   if(rec.English > stu_english_high.English)
    CopyRec(&stu_english_high ,&rec);

   if(rec.Compute > stu_compute_high.Compute)
    CopyRec(&stu_compute_high , &rec);

   if(rec.Philosophy > stu_philosophy_high.Philosophy)
    CopyRec(&stu_philosophy_high , &rec);

   if(rec.PE > stu_PE_high.PE)
    CopyRec(&stu_PE_high , &rec);

   /* low */
   /* 保存各科的最低分的学生的信息 */
   if(rec.Math < stu_math_low.Math)
    CopyRec(&stu_math_low ,&rec);

   if(rec.English < stu_english_low.English)
    CopyRec(&stu_english_low ,&rec);

   if(rec.Compute < stu_compute_low.Compute)
    CopyRec(&stu_compute_low , &rec);

   if(rec.Philosophy < stu_philosophy_low.Philosophy)
    CopyRec(&stu_philosophy_low , &rec);

   if(rec.PE < stu_PE_low.PE)
    CopyRec(&stu_PE_low , &rec);

  }
  
}/* While End */

if(count < 1)
{
  printf("\n There is no record in the data file .\n");
}
else
{
  /* average */
  /* 输出平均分的分段统计信息 */
  printf("\n The count in each segment :\n");
  printf("\t    <  60\t:\t%d\n",i50);
  printf("\t60  -  69\t:\t%d\n",i60);
  printf("\t70  -  79\t:\t%d\n",i70);
  printf("\t80  -  90\t:\t%d\n",i80);
  printf("\t   >=  90\t:\t%d\n",i90);
  printf(" ------------------------------------------");

  getch();

  /*highest  and  loeest*/
  /* 输出总分最高的学生的信息 */
  printf("\n The Highest Mark Student:\n");
  printf(" The Mark is : %d\n" , sum_high);
  printf(" The student is :\n");
  Output_Rec(&stu_high);

  /* 输出总分最高的学生的信息 */
  printf("\n The Lowest Mark Student:\n");
  printf(" The Mark is : %d\n" , sum_low);
  printf(" The student is :\n");
  Output_Rec(&stu_low);
  printf(" ------------------------------------------\n");

  getch();

  /* subject highest and low */
  /* 输出各科最高和最低分的统计信息 */
  printf(" The Highest\tMath :\n");
  Output_Rec(&stu_math_high);
  printf(" The Lowest Math :\n");
  Output_Rec(&stu_math_low);
  printf(" ------------------------------------------\n");

  getch(); /* 暂停 ,按任意键继续 */

  printf(" The Highest English :\n");
  Output_Rec(&stu_english_high);
  printf(" The Lowest English :\n");
  Output_Rec(&stu_english_low);
  printf(" ------------------------------------------\n");

  getch();

  printf(" The Highest Compute :\n");
  Output_Rec(&stu_compute_high);
  printf(" The Lowest Compute :\n");
  Output_Rec(&stu_compute_low);
  printf(" ------------------------------------------\n");

  getch();

  printf(" The Highest Philosophy :\n");
  Output_Rec(&stu_philosophy_high);
  printf(" The Lowest Philosophy :\n");
  Output_Rec(&stu_philosophy_low);
  printf(" ------------------------------------------\n");

  getch();

  printf(" The Highest PE :\n");
  Output_Rec(&stu_PE_high);
  printf(" The Lowest PE :\n");
  Output_Rec(&stu_PE_low);
  printf(" ------------------------------------------\n");

}
fclose(fp);

}

void Find(int isFind_From_ID) /* 查找函数 */
{

char buf[30]; /* 接受用户输入的条件的缓冲区 */
Student rec;
int find_count; /* 查找到的记录数目 */
FILE* fp;

find_count = 0;

fp = fopen(DATA_FILE ,"rb");
if( fp == NULL)
{
  printf("\n Can not open the data file to search ...\n");
  return;
}

switch(isFind_From_ID)
{
case 5: /*ID,按 学号查找*/

  printf("\n Please Input the ID : ");
  scanf("%s",buf); /* 提示用户输入 */

  while(ReadData(fp , &rec)) /* 读取数据 */
  {
   if(strcmp(rec.ID , buf) == 0) /* 比较 */
   {
    find_count++;
    Output_Rec(&rec); /* 输出符合条件的记录 */
    printf(" ------------------------------------------\n");
   }
  }
  break;

case 6: /*Name ,按 姓名 查找*/

  printf("\n Please Input the Name : ");
  scanf("%s",buf);

  while(ReadData(fp , &rec))
  {
   if(strcmp(rec.Name , buf) == 0)
   {
    find_count++;
    Output_Rec(&rec);
    printf(" ------------------------------------------\n");
   }
  }

  break;

default:
  printf(" \nPlease type right index ...\n"); /*处理isFind_From_ID既不是5也不是6的情况*/

}

if(find_count >0) /* 输出找到的记录数目 */
{
  printf("\n Have find out\t%d\trecord\n" ,find_count);
}
else
{
  printf("\n I'm very sorry .\n I failed to find out the one you want .\n");
  printf("\n I suggest that you change some other key words .\n");
}

fclose(fp);

}


int ReadData(FILE* fp, Student* Dest_Rec) /* 读取数据记录 */
{
int r;
if(( fp == NULL ) || ( Dest_Rec == NULL))
  return 0; /* ERROR */

r = fread(Dest_Rec ,sizeof(Student) ,1 ,fp);
if(r != 1)
  return 0;

return 1;

}

int WriteData(FILE* fp, Student* Src_Rec) /* 写入数据记录 */
{
int r;
if((fp == NULL) || (Src_Rec == NULL))
  return 0; /* ERROR */

r = fwrite(Src_Rec , sizeof(Student) , 1, fp);
if(r != 1)
  return 0;

return 1;

}

void Output_Rec( Student* stu) /* 在屏幕上输出 一个学生的信息 */
{
printf("\n");

printf("  Name : %s", stu->Name);
printf("\t\tSex : ");
if( stu->Sex == 'M' || stu->Sex == 'm' )
  printf("Male");
else
  printf("Female");

printf("\n  ID : %s\t\tClass : %s\n",stu->ID ,stu->Class);

printf("Math = %d\tEnglish = %d\tCompute = %d\n" ,stu->Math ,stu->English, stu->Compute);
printf("Philosophy = %d\t\tPE = %d\n", stu->Philosophy ,stu->PE);

printf("\n");
}

void Input_Rec( Student* stu) /* 让用户输入 一个学生的各项信息 */
{

if(stu == NULL)
  return;

printf("\n Name = ");
scanf("%s",stu->Name);

/* 下面这段代码实现只能输入 F ,f ,M ,m 的功能 */
printf("\tSex = (F|M) ");
while(1)
{
  stu->Sex = getch(); /* 无回显输入 */

  if(stu->Sex == 'F' || stu->Sex == 'f' || stu->Sex == 'M' || stu->Sex == 'm')
  {
   printf("%c",stu->Sex); /* 将用户输入的字符输出,模拟正常输入数据时的回显 */
   break;
  }
}

/* 下面 给出提示,让用户输入结构体的各项内容 */
printf("\n ID = ");
scanf("%s" , stu->ID);

printf("\n Class = ");
scanf("%s" , stu->Class);

printf("\n Math = ");
scanf("%d", &(stu->Math));

printf("\n English = ");
scanf("%d" ,&(stu->English));

printf("\n Compute = ");
scanf("%d" , &(stu->Compute));

printf("\n Philosophy = ");
scanf("%d" , &(stu->Philosophy));

printf("\n PE = ");
scanf("%d" , &(stu->PE));

printf("\n");

}

/* 因为结构体不能直接用 等号(=)赋值,写一个赋值函数 */
void CopyRec(Student* dest_stu, Student* src_stu)
{
/* 复制 源记录 的各项到 目标记录*/
strcpy(dest_stu->Name ,src_stu->Name);
strcpy(dest_stu->ID ,src_stu->ID);
strcpy(dest_stu->Class ,src_stu->Class);
dest_stu->Sex = src_stu->Sex;
dest_stu->Math = src_stu->Math;
dest_stu->English = src_stu->English;
dest_stu->Compute = src_stu->Compute;
dest_stu->Philosophy = src_stu->Philosophy;
dest_stu->PE = src_stu->PE;
}

void Find(int isFind_From_ID) /* 查找函数 */
{

char buf[30]; /* 接受用户输入的条件的缓冲区 */
Student rec;
int find_count; /* 查找到的记录数目 */
FILE* fp;

find_count = 0;

fp = fopen(DATA_FILE ,"rb");
if( fp == NULL)
{
  printf("\n Can not open the data file to search ...\n");
  return;
}

switch(isFind_From_ID)
{
case 5: /*ID,按 学号查找*/

  printf("\n Please Input the ID : ");
  scanf("%s",buf); /* 提示用户输入 */

  while(ReadData(fp , &rec)) /* 读取数据 */
  {
   if(strcmp(rec.ID , buf) == 0) /* 比较 */
   {
    find_count++;
    Output_Rec(&rec); /* 输出符合条件的记录 */
    printf(" ------------------------------------------\n");
   }
  }
  break;

case 6: /*Name ,按 姓名 查找*/

  printf("\n Please Input the Name : ");
  scanf("%s",buf);

  while(ReadData(fp , &rec))
  {
   if(strcmp(rec.Name , buf) == 0)
   {
    find_count++;
    Output_Rec(&rec);
    printf(" ------------------------------------------\n");
   }
  }

  break;

default:
  printf(" \nPlease type right index ...\n"); /*处理isFind_From_ID既不是5也不是6的情况*/

}

if(find_count >0) /* 输出找到的记录数目 */
{
  printf("\n Have find out\t%d\trecord\n" ,find_count);
}
else
{
  printf("\n I'm very sorry .\n I failed to find out the one you want .\n");
  printf("\n I suggest that you change some other key words .\n");
}

fclose(fp);

}


int ReadData(FILE* fp, Student* Dest_Rec) /* 读取数据记录 */
{
int r;
if(( fp == NULL ) || ( Dest_Rec == NULL))
  return 0; /* ERROR */

r = fread(Dest_Rec ,sizeof(Student) ,1 ,fp);
if(r != 1)
  return 0;

return 1;

}

int WriteData(FILE* fp, Student* Src_Rec) /* 写入数据记录 */
{
int r;
if((fp == NULL) || (Src_Rec == NULL))
  return 0; /* ERROR */

r = fwrite(Src_Rec , sizeof(Student) , 1, fp);
if(r != 1)
  return 0;

return 1;

}

void Output_Rec( Student* stu) /* 在屏幕上输出 一个学生的信息 */
{
printf("\n");

printf("  Name : %s", stu->Name);
printf("\t\tSex : ");
if( stu->Sex == 'M' || stu->Sex == 'm' )
  printf("Male");
else
  printf("Female");

printf("\n  ID : %s\t\tClass : %s\n",stu->ID ,stu->Class);

printf("Math = %d\tEnglish = %d\tCompute = %d\n" ,stu->Math ,stu->English, stu->Compute);
printf("Philosophy = %d\t\tPE = %d\n", stu->Philosophy ,stu->PE);

printf("\n");
}

void Input_Rec( Student* stu) /* 让用户输入 一个学生的各项信息 */
{

if(stu == NULL)
  return;

printf("\n Name = ");
scanf("%s",stu->Name);

/* 下面这段代码实现只能输入 F ,f ,M ,m 的功能 */
printf("\tSex = (F|M) ");
while(1)
{
  stu->Sex = getch(); /* 无回显输入 */

  if(stu->Sex == 'F' || stu->Sex == 'f' || stu->Sex == 'M' || stu->Sex == 'm')
  {
   printf("%c",stu->Sex); /* 将用户输入的字符输出,模拟正常输入数据时的回显 */
   break;
  }
}

/* 下面 给出提示,让用户输入结构体的各项内容 */
printf("\n ID = ");
scanf("%s" , stu->ID);

printf("\n Class = ");
scanf("%s" , stu->Class);

printf("\n Math = ");
scanf("%d", &(stu->Math));

printf("\n English = ");
scanf("%d" ,&(stu->English));

printf("\n Compute = ");
scanf("%d" , &(stu->Compute));

printf("\n Philosophy = ");
scanf("%d" , &(stu->Philosophy));

printf("\n PE = ");
scanf("%d" , &(stu->PE));

printf("\n");

}

/* 因为结构体不能直接用 等号(=)赋值,写一个赋值函数 */
void CopyRec(Student* dest_stu, Student* src_stu)
{
/* 复制 源记录 的各项到 目标记录*/
strcpy(dest_stu->Name ,src_stu->Name);
strcpy(dest_stu->ID ,src_stu->ID);
strcpy(dest_stu->Class ,src_stu->Class);
dest_stu->Sex = src_stu->Sex;
dest_stu->Math = src_stu->Math;
dest_stu->English = src_stu->English;
dest_stu->Compute = src_stu->Compute;
dest_stu->Philosophy = src_stu->Philosophy;
dest_stu->PE = src_stu->PE;
}

void Find(int isFind_From_ID) /* 查找函数 */
{

char buf[30]; /* 接受用户输入的条件的缓冲区 */
Student rec;
int find_count; /* 查找到的记录数目 */
FILE* fp;

find_count = 0;

fp = fopen(DATA_FILE ,"rb");
if( fp == NULL)
{
  printf("\n Can not open the data file to search ...\n");
  return;
}

switch(isFind_From_ID)
{
case 5: /*ID,按 学号查找*/

  printf("\n Please Input the ID : ");
  scanf("%s",buf); /* 提示用户输入 */

  while(ReadData(fp , &rec)) /* 读取数据 */
  {
   if(strcmp(rec.ID , buf) == 0) /* 比较 */
   {
    find_count++;
    Output_Rec(&rec); /* 输出符合条件的记录 */
    printf(" ------------------------------------------\n");
   }
  }
  break;

case 6: /*Name ,按 姓名 查找*/

  printf("\n Please Input the Name : ");
  scanf("%s",buf);

  while(ReadData(fp , &rec))
  {
   if(strcmp(rec.Name , buf) == 0)
   {
    find_count++;
    Output_Rec(&rec);
    printf(" ------------------------------------------\n");
   }
  }

  break;

default:
  printf(" \nPlease type right index ...\n"); /*处理isFind_From_ID既不是5也不是6的情况*/

}

if(find_count >0) /* 输出找到的记录数目 */
{
  printf("\n Have find out\t%d\trecord\n" ,find_count);
}
else
{
  printf("\n I'm very sorry .\n I failed to find out the one you want .\n");
  printf("\n I suggest that you change some other key words .\n");
}

fclose(fp);

}


int ReadData(FILE* fp, Student* Dest_Rec) /* 读取数据记录 */
{
int r;
if(( fp == NULL ) || ( Dest_Rec == NULL))
  return 0; /* ERROR */

r = fread(Dest_Rec ,sizeof(Student) ,1 ,fp);
if(r != 1)
  return 0;

return 1;

}

int WriteData(FILE* fp, Student* Src_Rec) /* 写入数据记录 */
{
int r;
if((fp == NULL) || (Src_Rec == NULL))
  return 0; /* ERROR */

r = fwrite(Src_Rec , sizeof(Student) , 1, fp);
if(r != 1)
  return 0;

return 1;

}

void Output_Rec( Student* stu) /* 在屏幕上输出 一个学生的信息 */
{
printf("\n");

printf("  Name : %s", stu->Name);
printf("\t\tSex : ");
if( stu->Sex == 'M' || stu->Sex == 'm' )
  printf("Male");
else
  printf("Female");

printf("\n  ID : %s\t\tClass : %s\n",stu->ID ,stu->Class);

printf("Math = %d\tEnglish = %d\tCompute = %d\n" ,stu->Math ,stu->English, stu->Compute);
printf("Philosophy = %d\t\tPE = %d\n", stu->Philosophy ,stu->PE);

printf("\n");
}

void Input_Rec( Student* stu) /* 让用户输入 一个学生的各项信息 */
{

if(stu == NULL)
  return;

printf("\n Name = ");
scanf("%s",stu->Name);

/* 下面这段代码实现只能输入 F ,f ,M ,m 的功能 */
printf("\tSex = (F|M) ");
while(1)
{
  stu->Sex = getch(); /* 无回显输入 */

  if(stu->Sex == 'F' || stu->Sex == 'f' || stu->Sex == 'M' || stu->Sex == 'm')
  {
   printf("%c",stu->Sex); /* 将用户输入的字符输出,模拟正常输入数据时的回显 */
   break;
  }
}

/* 下面 给出提示,让用户输入结构体的各项内容 */
printf("\n ID = ");
scanf("%s" , stu->ID);

printf("\n Class = ");
scanf("%s" , stu->Class);

printf("\n Math = ");
scanf("%d", &(stu->Math));

printf("\n English = ");
scanf("%d" ,&(stu->English));

printf("\n Compute = ");
scanf("%d" , &(stu->Compute));

printf("\n Philosophy = ");
scanf("%d" , &(stu->Philosophy));

printf("\n PE = ");
scanf("%d" , &(stu->PE));

printf("\n");

}

/* 因为结构体不能直接用 等号(=)赋值,写一个赋值函数 */
void CopyRec(Student* dest_stu, Student* src_stu)
{
/* 复制 源记录 的各项到 目标记录*/
strcpy(dest_stu->Name ,src_stu->Name);
strcpy(dest_stu->ID ,src_stu->ID);
strcpy(dest_stu->Class ,src_stu->Class);
dest_stu->Sex = src_stu->Sex;
dest_stu->Math = src_stu->Math;
dest_stu->English = src_stu->English;
dest_stu->Compute = src_stu->Compute;
dest_stu->Philosophy = src_stu->Philosophy;
dest_stu->PE = src_stu->PE;
}

/*

题目分析 及 算法设计 :

  题目中的各个功能都是相对独立的,所以我将各项功能以 带 编号 的菜单形式组织在屏幕上,
  用户通过 输入 编号 执行相应的功能。显示菜单的代码处于一个循环之中,当执行完一个
  子功能后,就又回到循环,显示主菜单,直到用户选择 退出 菜单。

  这种操作方式比其它机制(如:主程序 + 程序参数)更简捷,不必每次用不同的参数重新运行程序,
  以实现相应的功能。
  
  1. 查看文件记录内容 的实现:
   用 循环 读取文件内容,然后显示在屏幕上。
   因为 我们的数据是以结构体的形式存放在文件中的,所以 代码中用了块读取和块写入函数。
   在 循环中设置计数器来统计记录的个数。

  2. 添加记录 的实现:
   让用户根据屏幕提示输入数据,完成对学生信息结构体各项的赋值,待取得足够数据后,
   将数据文件以“追加”方式打开,执行块写入,将整个结构体写入文件。

  3. 删除记录 的实现:
   学号(ID)一般不会重复,所以我在程序中让用户输入想要删除的记录的学号(ID),
   然后在文件中查找,如果不是用户想要删除的记录(即ID不同),就保存在一个临时的文件中,
   这样,就将想要删除的记录与其它记录分离开了,最后,删除原来的数据文件,将临时文件的
   名字改为 原来数据文件的名字。

  4. 统计功能 的实现:
   统计功能模块分为三个小模块:平均分的分数段统计,总分的最高和最低分统计,
   各科的最高和最低分统计。但我并不想分别来写,因为它们都要对所有记录进行扫描,
   而它们又互不干扰,所以我把它们组织在一个循环中,各自都有自己的计算代码和变量,
   所以这个 函数 中的局部变量 很多。

  5. 查找功能 的实现:
   题目要求两种查找方式:按 学号(ID) , 按 姓名(Name)。
   两者是独立的,所以我用了一个参数 isFind_From_ID 来表明是哪种查找方式,进而在在程序
   内部由一个 switch() 选择分支转向不同的代码段去执行。
   具体的查找就是比较相应的项目是否与用户输入的一样,若一样就输出到屏幕。

有关各个变量的作用都已经在代码中表明,非常详细。
  
*/

欢迎访问最专业的网吧论坛,无盘论坛,网吧经营,网咖管理,网吧专业论坛 https://bbs.txwb.com

关注天下网吧微信/下载天下网吧APP/天下网吧小程序,一起来超精彩

本文来源:vczx 作者:佚名

声明
声明:本站所发表的文章、评论及图片仅代表作者本人观点,与本站立场无关。若文章侵犯了您的相关权益,请及时与我们联系,我们会及时处理,感谢您对本站的支持!联系邮箱:support@txwb.com,系统开号,技术支持,服务联系QQ:1175525021本站所有有注明来源为天下网吧或天下网吧论坛的原创作品,各位转载时请注明来源链接!
天下网吧 网吧天下