案例

来源:互联网 发布:mysql 覆盖索引 编辑:程序博客网 时间:2024/04/28 23:05

一 贪吃蛇游戏
#define N 200
#include <graphics.h>
#include <stdlib.h>
#include <dos.h>
#define LEFT 0x4b00
#define RIGHT 0x4d00
#define DOWN 0x5000
#define UP 0x4800
#define ESC 0x011b
int i,key;
int score=0;/*得分*/
int gamespeed=50000;/*游戏速度自己调整*/
struct Food
{
   int x;/*食物的横坐标*/
   int y;/*食物的纵坐标*/
   int yes;/*判断是否要出现食物的变量*/
}food;/*食物的结构体*/
struct Snake
{
   int x[N];
   int y[N];
   int node;/*蛇的节数*/
   int direction;/*蛇移动方向*/
   int life;/* 蛇的生命,0活着,1死亡*/
}snake;
void Init(void);/*图形驱动*/
void Close(void);/*图形结束*/
void DrawK(void);/*开始画面*/
void GameOver(void);/*结束游戏*/
void GamePlay(void);/*玩游戏具体过程*/
void PrScore(void);/*输出成绩*/
/*主函数*/
void main(void)
{
   Init();/*图形驱动*/
   DrawK();/*开始画面*/
   GamePlay();/*玩游戏具体过程*/
   Close();/*图形结束*/
}
/*图形驱动*/
void Init(void)
{
   int gd=DETECT,gm;
   initgraph(&gd,&gm,"c://tc");
   cleardevice();
}
/*开始画面,左上角坐标为(50,40),右下角坐标为(610,460)的围墙*/
void DrawK(void)
{
/*setbkcolor(LIGHTGREEN);*/
   setcolor(11);
   setlinestyle(SOLID_LINE,0,THICK_WIDTH);/*设置线型*/
   for(i=50;i<=600;i+=10)/*画围墙*/
   {
      rectangle(i,40,i+10,49); /*上边*/
      rectangle(i,451,i+10,460);/*下边*/
   }
  for(i=40;i<=450;i+=10)
  {
     rectangle(50,i,59,i+10); /*左边*/
     rectangle(601,i,610,i+10);/*右边*/
  }
}
/*玩游戏具体过程*/
void GamePlay(void)
{
   randomize();/*随机数发生器*/
   food.yes=1;/*1表示需要出现新食物,0表示已经存在食物*/
   snake.life=0;/*活着*/
   snake.direction=1;/*方向往右*/
   snake.x[0]=100;snake.y[0]=100;/*蛇头*/
   snake.x[1]=110;snake.y[1]=100;
   snake.node=2;/*节数*/
   PrScore();/*输出得分*/
   while(1)/*可以重复玩游戏,压ESC键结束*/
   {
      while(!kbhit())/*在没有按键的情况下,蛇自己移动身体*/
      {
  if(food.yes==1)/*需要出现新食物*/
  {
      food.x=rand()%400+60;
      food.y=rand()%350+60;
      while(food.x%10!=0)/*食物随机出现后必须让食物能够在整格内,这样才可以让蛇吃到*/
  food.x++;
      while(food.y%10!=0)
  food.y++;
  food.yes=0;/*画面上有食物了*/
  }
  if(food.yes==0)/*画面上有食物了就要显示*/
  {
              setcolor(GREEN);
              rectangle(food.x,food.y,food.x+10,food.y-10);
  }
         for(i=snake.node-1;i>0;i--)/*蛇的每个环节往前移动,也就是贪吃蛇的关键算法*/
         {
            snake.x[i]=snake.x[i-1];
     snake.y[i]=snake.y[i-1];
  }
       /*1,2,3,4表示右,左,上,下四个方向,通过这个判断来移动蛇头*/
  switch(snake.direction)
  {
     case 1:snake.x[0]+=10;break;
     case 2: snake.x[0]-=10;break;
     case 3: snake.y[0]-=10;break;
     case 4: snake.y[0]+=10;break;
  }
  for(i=3;i<snake.node;i++)/*从蛇的第四节开始判断是否撞到自己了,因为蛇头为两节,第三节不可能拐过来*/
  {
     if(snake.x[i]==snake.x[0]&&snake.y[i]==snake.y[0])
     {
               GameOver();/*显示失败*/
               snake.life=1;
               break;
     }
        }
 if(snake.x[0]<55||snake.x[0]>595||snake.y[0]<55||
    snake.y[0]>455)/*蛇是否撞到墙壁*/
 {
     GameOver();/*本次游戏结束*/
     snake.life=1; /*蛇死*/
 }
 if(snake.life==1)/*以上两种判断以后,如果蛇死就跳出内循环,重新开始*/
           break;
 if(snake.x[0]==food.x&&snake.y[0]==food.y)/*吃到食物以后*/
 {
           setcolor(0);/*把画面上的食物东西去掉*/
           rectangle(food.x,food.y,food.x+10,food.y-10);
    snake.x[snake.node]=-20;snake.y[snake.node]=-20;
          /*新的一节先放在看不见的位置,下次循环就取前一节的位置*/
    snake.node++;/*蛇的身体长一节*/
    food.yes=1;/*画面上需要出现新的食物*/
    score+=10;
    PrScore();/*输出新得分*/
 }
 setcolor(4);/*画出蛇*/
 for(i=0;i<snake.node;i++)
    rectangle(snake.x[i],snake.y[i],snake.x[i]+10,
               snake.y[i]-10);
 delay(gamespeed);
 setcolor(0);/*用黑色去除蛇的的最后一节*/
 rectangle(snake.x[snake.node-1],snake.y[snake.node-1],
 snake.x[snake.node-1]+10,snake.y[snake.node-1]-10);
     }  /*endwhile(!kbhit)*/
    if(snake.life==1)/*如果蛇死就跳出循环*/
        break;
    key=bioskey(0);/*接收按键*/
    if(key==ESC)/*按ESC键退出*/
       break;
    else
       if(key==UP&&snake.direction!=4)
/*判断是否往相反的方向移动*/
   snake.direction=3;
       else
   if(key==RIGHT&&snake.direction!=2)
      snake.direction=1;
   else
      if(key==LEFT&&snake.direction!=1)
  snake.direction=2;
      else
  if(key==DOWN&&snake.direction!=3)
     snake.direction=4;
   }/*endwhile(1)*/
}
/*游戏结束*/
void GameOver(void)
{
    cleardevice();
    PrScore();
   setcolor(RED);
   settextstyle(0,0,4);
   outtextxy(200,200,"GAME OVER");
   getch();
}
/*输出成绩*/
void PrScore(void)
{  
   char str[10];
   setfillstyle(SOLID_FILL,YELLOW);
   bar(50,15,220,35);
   setcolor(6);
   settextstyle(0,0,2);
   sprintf(str,"score:%d",score);
   outtextxy(55,20,str);
}
/*图形结束*/
void Close(void)
{  
    getch();
    closegraph();
}


案例二 计算器
#include <dos.h>   /*DOS接口函数*/
#include <math.h>   /*数学函数的定义*/
#include <conio.h>  /*屏幕操作函数*/
#include <stdio.h>  /*I/O函数*/
#include <stdlib.h>  /*库函数*/
#include <stdarg.h>  /*变量长度参数表*/
#include <graphics.h>  /*图形函数*/
#include <string.h>  /*字符串函数*/
#include <ctype.h>  /*字符操作函数*/
#define UP 0x48    /*光标上移键*/
#define DOWN 0x50  /*光标下移键*/
#define LEFT 0x4b  /*光标左移键*/
#define RIGHT 0x4d  /*光标右移键*/
#define ENTER 0x0d  /*回车键*/
void *rar;       /*全局变量,保存光标图象*/
struct palettetype palette; /*使用调色板信息*/
int  GraphDriver; /* 图形设备驱动*/
int  GraphMode; /* 图形模式值*/
int  ErrorCode;  /* 错误代码*/
int  MaxColors;  /* 可用颜色的最大数值*/
int  MaxX, MaxY; /* 屏幕的最大分辨率*/
double  AspectRatio; /* 屏幕的像素比*/
void drawboder(void); /*画边框函数*/
void initialize(void);  /*初始化函数*/
void computer(void);  /*计算器计算函数*/
void changetextstyle(int font, int direction, int charsize);  /*改变文本样式函数*/
void mwindow(char *header);  /*窗口函数*/
int specialkey(void) ;   /*获取特殊键函数*/
int arrow();     /*设置箭头光标函数*/
/*主函数*/
int main()
{
   initialize();/* 设置系统进入图形模式 */
   computer(); /*运行计算器 */
   closegraph();/*系统关闭图形模式返回文本模式*/
   return(0);   /*结束程序*/
}
/* 设置系统进入图形模式 */
void initialize(void)
{
   int xasp, yasp; /* 用于读x和y方向纵横比*/
   GraphDriver = DETECT; /* 自动检测显示器*/
   initgraph( &GraphDriver, &GraphMode, "" );
/*初始化图形系统*/
   ErrorCode = graphresult();  /*读初始化结果*/
   if( ErrorCode != grOk )  /*如果初始化时出现错误*/
   {
      printf("Graphics System Error: %s/n",
      grapherrormsg( ErrorCode ) ); /*显示错误代码*/
      exit( 1 );  /*退出*/
    }
    getpalette( &palette );  /* 读面板信息*/
    MaxColors = getmaxcolor() + 1; /* 读取颜色的最大值*/
    MaxX = getmaxx();    /* 读屏幕尺寸 */
    MaxY = getmaxy();  /* 读屏幕尺寸 */
    getaspectratio( &xasp, &yasp ); /* 拷贝纵横比到变量中*/
    AspectRatio = (double)xasp/(double)yasp;/* 计算纵横比值*/
}
/*计算器函数*/
void computer(void)
{
    struct viewporttype vp;  /*定义视口类型变量*/
    int color, height, width;
    int x, y,x0,y0, i, j,v,m,n,act,flag=1;
    float num1=0,num2=0,result;  /*操作数和计算结果变量*/
    char cnum[5],str2[20]={""},c,temp[20]={""};
    char str1[]="1230.456+-789*/Qc=^%";/* 定义字符串在按钮图形上显示的符号 */
    mwindow( "Calculator" );  /* 显示主窗口 */
    color = 7;     /*设置灰颜色值*/
    getviewsettings( &vp );    /* 读取当前窗口的大小*/
    width=(vp.right+1)/10;    /* 设置按钮宽度  */
    height=(vp.bottom-10)/10 ;  /*设置按钮高度  */
    x = width /2;   /*设置x的坐标值*/
    y = height/2; /*设置y的坐标值*/
    setfillstyle(SOLID_FILL, color+3);
    bar( x+width*2, y, x+7*width, y+height );
    /*画一个二维矩形条显示运算数和结果*/
    setcolor( color+3 );  /*设置淡绿颜色边框线*/
    rectangle( x+width*2, y, x+7*width, y+height );
     /*画一个矩形边框线*/
    setcolor(RED);  /*设置颜色为红色*/
    outtextxy(x+3*width,y+height/2,"0."); /*输出字符串"0."*/
    x =2*width-width/2;   /*设置x的坐标值*/
    y =2*height+height/2;  /*设置y的坐标值*/
    for( j=0 ; j<4 ; ++j ) /*画按钮*/
    {
       for( i=0 ; i<5 ; ++i )
       {
           setfillstyle(SOLID_FILL, color);
           setcolor(RED);
           bar( x, y, x+width, y+height ); /*画一个矩形条*/
           rectangle( x, y, x+width, y+height );
           sprintf(str2,"%c",str1[j*5+i]);
             /*将字符保存到str2中*/
           outtextxy( x+(width/2), y+height/2, str2);
           x =x+width+ (width / 2) ; /*移动列坐标*/
       }
       y +=(height/2)*3; /* 移动行坐标*/
       x =2*width-width/2;  /*复位列坐标*/
    }
    x0=2*width;
    y0=3*height;
    x=x0;
    y=y0;
    gotoxy(x,y); /*移动光标到x,y位置*/
    arrow();  /*显示光标*/
    putimage(x,y,rar,XOR_PUT);
    m=0;
    n=0;
    strcpy(str2,"");  /*设置str2为空串*/
    while((v=specialkey())!=45)  /*当压下Alt+x键结束程序,否则执行下面的循环*/
    {
       while((v=specialkey())!=ENTER)  /*当压下键不是回车时*/
       {
   putimage(x,y,rar,XOR_PUT); /*显示光标图象*/
   if(v==RIGHT)   /*右移箭头时新位置计算*/
      if(x>=x0+6*width)
                 /*如果右移,移到尾,则移动到最左边字符位置*/
      {
   x=x0;
   m=0;
       }
      else
      {
   x=x+width+width/2;
   m++;
       } /*否则,右移到下一个字符位置*/
   if(v==LEFT) /*左移箭头时新位置计算*/
      if(x<=x0)
      {
   x=x0+6*width;
   m=4;
      } /*如果移到头,再左移,则移动到最右边字符位置*/
      else
      {
  x=x-width-width/2;
  m--;
      } /*否则,左移到前一个字符位置*/
          if(v==UP) /*上移箭头时新位置计算*/
      if(y<=y0)
      {
  y=y0+4*height+height/2;
  n=3;
      } /*如果移到头,再上移,则移动到最下边字符位置*/
      else
      {
                y=y-height-height/2;
                n--;
             } /*否则,移到上边一个字符位置*/
   if(v==DOWN) /*下移箭头时新位置计算*/
      if(y>=7*height)
      {
  y=y0;
                n=0;
      } /*如果移到尾,再下移,则移动到最上边字符位置*/
      else
      {
  y=y+height+height/2;
  n++;
      } /*否则,移到下边一个字符位置*/
          putimage(x,y,rar,XOR_PUT);  /*在新的位置显示光标箭头*/
      }
      c=str1[n*5+m];  /*将字符保存到变量c中*/
      if(isdigit(c)||c=='.')  /*判断是否是数字或小数点*/
      {
   if(flag==-1)  /*如果标志为-1,表明为负数*/
          {
             strcpy(str2,"-"); /*将负号连接到字符串中*/
             flag=1;
          } /*将标志值恢复为1*/
      sprintf(temp,"%c",c); /*将字符保存到字符串变量temp中*/
      strcat(str2,temp); /*将temp中的字符串连接到str2中*/
      setfillstyle(SOLID_FILL,color+3);
      bar(2*width+width/2,height/2,15*width/2,3*height/2);
      outtextxy(5*width,height,str2);  /*显示字符串*/
   }
   if(c=='+')
   {
      num1=atof(str2);  /*将第一个操作数转换为浮点数*/
      strcpy(str2,""); /*将str2清空*/
      act=1;  /*做计算加法标志值*/
      setfillstyle(SOLID_FILL,color+3);
      bar(2*width+width/2,height/2,15*width/2,3*height/2);
      outtextxy(5*width,height,"0."); /*显示字符串*/
   }
   if(c=='-')
   {
      if(strcmp(str2,"")==0) /*如果str2为空,说明是负号,而不是减号*/
   flag=-1;  /*设置负数标志*/
      else
      {
   num1=atof(str2);  /*将第二个操作数转换为浮点数*/
   strcpy(str2,""); /*将str2清空*/
   act=2; /*做计算减法标志值*/
   setfillstyle(SOLID_FILL,color+3);
   bar(2*width+width/2,height/2,15*width/2,3*height/2); /*画矩形*/
   outtextxy(5*width,height,"0."); /*显示字符串*/
      }
   }
   if(c=='*')
   {
      num1=atof(str2); /*将第二个操作数转换为浮点数*/
      strcpy(str2,""); /*将str2清空*/
      act=3; /*做计算乘法标志值*/
      setfillstyle(SOLID_FILL,color+3);      bar(2*width+width/2,height/2,15*width/2,3*height/2);
      outtextxy(5*width,height,"0."); /*显示字符串*/
    }
   if(c=='/')
   {
      num1=atof(str2); /*将第二个操作数转换为浮点数*/
      strcpy(str2,""); /*将str2清空*/
      act=4; /*做计算除法标志值*/
      setfillstyle(SOLID_FILL,color+3);
      bar(2*width+width/2,height/2,15*width/2,3*height/2);
      outtextxy(5*width,height,"0."); /*显示字符串*/
   }
   if(c=='^')
   {
      num1=atof(str2); /*将第二个操作数转换为浮点数*/
      strcpy(str2,""); /*将str2清空*/
      act=5; /*做计算乘方标志值*/
      setfillstyle(SOLID_FILL,color+3); /*设置用淡绿色实体填充*/
      bar(2*width+width/2,height/2,15*width/2,3*height/2); /*画矩形*/
      outtextxy(5*width,height,"0."); /*显示字符串*/
   }
   if(c=='%')
   {
      num1=atof(str2); /*将第二个操作数转换为浮点数*/
      strcpy(str2,"");  /*将str2清空*/
      act=6; /*做计算模运算乘方标志值*/
      setfillstyle(SOLID_FILL,color+3); /*设置用淡绿色实体填充*/
      bar(2*width+width/2,height/2,15*width/2,3*height/2); /*画矩形*/
      outtextxy(5*width,height,"0."); /*显示字符串*/
   }
   if(c=='=')
   {
      num2=atof(str2); /*将第二个操作数转换为浮点数*/
      switch(act)  /*根据运算符号计算*/
      {
   case 1:result=num1+num2;break; /*做加法*/
   case 2:result=num1-num2;break; /*做减法*/
   case 3:result=num1*num2;break; /*做乘法*/
   case 4:result=num1/num2;break; /*做除法*/
   case 5:result=pow(num1,num2);break; /*做x的y次方*/
   case 6:result=fmod(num1,num2);break; /*做模运算*/
      }
      setfillstyle(SOLID_FILL,color+3); /*设置用淡绿色实体填充*/
      bar(2*width+width/2,height/2,15*width/2,3*height/2); /*覆盖结果区*/
      sprintf(temp,"%f",result); /*将结果保存到temp中*/
      outtextxy(5*width,height,temp); /*显示结果*/
   }
   if(c=='c')
   {
      num1=0; /*将两个操作数复位0,符号标志为1*/
      num2=0;
      flag=1;
      strcpy(str2,""); /*将str2清空*/
      setfillstyle(SOLID_FILL,color+3);  /*设置用淡绿色实体填充*/
      bar(2*width+width/2,height/2,15*width/2,3*height/2); /*覆盖结果区*/
      outtextxy(5*width,height,"0."); /*显示字符串*/
   }
   if(c=='Q')exit(0);  /*如果选择了q回车,结束计算程序*/
   }
   putimage(x,y,rar,XOR_PUT); /*在退出之前消去光标箭头*/
   return;  /*返回*/
}
/*窗口函数*/
void mwindow( char *header )
{
   int height;
   cleardevice();   /* 清除图形屏幕 */
   setcolor( MaxColors - 1 );  /* 设置当前颜色为白色*/
   setviewport( 20, 20, MaxX/2, MaxY/2, 1 ); /* 设置视口大小 */
   height = textheight( "H" );           /* 读取基本文本大小  */
   settextstyle( DEFAULT_FONT, HORIZ_DIR, 1 );/*设置文本样式*/
   settextjustify( CENTER_TEXT, TOP_TEXT );/*设置字符排列方式*/
   outtextxy( MaxX/4, 2, header );  /*输出标题*/
   setviewport( 20,20+height+4, MaxX/2+4, MaxY/2+20, 1 );  /*设置视口大小*/
   drawboder(); /*画边框*/
}
void drawboder(void)  /*画边框*/
{
   struct viewporttype vp;  /*定义视口类型变量*/
   setcolor( MaxColors - 1 );  /*设置当前颜色为白色 */
   setlinestyle( SOLID_LINE, 0, NORM_WIDTH );/*设置画线方式*/
   getviewsettings( &vp );/*将当前视口信息装入vp所指的结构中*/
   rectangle( 0, 0, vp.right-vp.left, vp.bottom-vp.top ); /*画矩形边框*/
}
/*设计鼠标图形函数*/
int arrow()
{
   int size;
   int raw[]={4,4,4,8,6,8,14,16,16,16,8,6,8,4,4,4}; /*定义多边形坐标*/
   setfillstyle(SOLID_FILL,2); /*设置填充模式*/
   fillpoly(8,raw);    /*画出一光标箭头*/
   size=imagesize(4,4,16,16);  /*测试图象大小*/
   rar=malloc(size);  /*分配内存区域*/
   getimage(4,4,16,16,rar); /*存放光标箭头图象*/
   putimage(4,4,rar,XOR_PUT); /*消去光标箭头图象*/
   return 0;
}
/*按键函数*/
int specialkey(void)
{
   int key;
   while(bioskey(1)==0);  /*等待键盘输入*/
   key=bioskey(0);   /*键盘输入*/
   key=key&0xff? key&0xff:key>>8;  /*只取特殊键的扫描值,其余为0*/
   return(key);    /*返回键值*/
}


案例三 黑白棋游戏
#include "graphics.h"  /*图形系统头文件*/
#define LEFT 0x4b00  /*光标左键值*/
#define RIGHT 0x4d00 /*光标右键值*/
#define DOWN 0x5000 /*光标下键值*/
#define UP 0x4800 /*光标上键值*/
#define ESC 0x011b /* ESC键值*/
#define ENTER 0x1c0d /* 回车键值*/
int a[8][8]={0},key,score1,score2;/*具体分数以及按键与存放棋子的变量*/
char playone[3],playtwo[3];/*两个人的得分转换成字符串输出*/
void playtoplay(void);/*人人对战函数*/
void DrawQp(void);/*画棋盘函数*/
void SetPlayColor(int x);/*设置棋子第一次的颜色*/
void MoveColor(int x,int y);/*恢复原来棋盘状态*/
int QpChange(int x,int y,int z);/*判断棋盘的变化*/
void DoScore(void);/*处理分数*/
void PrintScore(int n);/*输出成绩*/
void playWin(void);/*输出胜利者信息*/
/******主函数*********/
void main(void)
{
   int gd=DETECT,gr;
   initgraph(&gd,&gr,"c://tc"); /*初始化图形系统*/
   DrawQp();/*画棋盘*/
   playtoplay();/*人人对战*/
   getch();
   closegraph();/*关闭图形系统*/
}
void DrawQp()/*画棋盘*/
{
   int i,j;
   score1=score2=0;/*棋手一开始得分都为0*/
   setbkcolor(BLUE);
   for(i=100;i<=420;i+=40)
   {
      line(100,i,420,i);/*画水平线*/
      line(i,100,i,420); /*画垂直线*/
   }
   setcolor(0);/*取消圆周围的一圈东西*/
   setfillstyle(SOLID_FILL,15);/*白色实体填充模式*/
   fillellipse(500,200,15,15); /*在显示得分的位置画棋*/
   setfillstyle(SOLID_FILL,8); /*黑色实体填充模式*/
   fillellipse(500,300,15,15);
   a[3][3]=a[4][4]=1;/*初始两个黑棋*/
   a[3][4]=a[4][3]=2;/*初始两个白棋*/
   setfillstyle(SOLID_FILL,WHITE);
   fillellipse(120+3*40,120+3*40,15,15);
   fillellipse(120+4*40,120+4*40,15,15);
   setfillstyle(SOLID_FILL,8);
   fillellipse(120+3*40,120+4*40,15,15);
   fillellipse(120+4*40,120+3*40,15,15);
   score1=score2=2; /*有棋后改变分数*/
   DoScore();/*输出开始分数*/
}
void playtoplay()/*人人对战*/
{
   int x,y,t=1,i,j,cc=0;
   while(1)/*换棋手走棋*/
   {
      x=120,y=80;/*每次棋子一开始出来的坐标,x为行坐标,y为列坐标*/
      while(1) /*具体一个棋手走棋的过程*/
      {
  PrintScore(1);/*输出棋手1的成绩*/
  PrintScore(2);/*输出棋手2的成绩*/
  SetPlayColor(t);/*t变量是用来判断棋手所执棋子的颜色*/
  fillellipse(x,y,15,15);
  key=bioskey(0);/*接收按键*/
  if(key==ESC)/*跳出游戏*/
     break;
  else
  if(key==ENTER)/*如果按键确定就可以跳出循环*/
  {
     if(y!=80&&a[(x-120)/40][(y-120)/40]!=1
&&a[(x-120)/40][(y-120)/40]!=2)/*如果落子位置没有棋子*/
     {
        if(t%2==1)/*如果是棋手1移动*/
    a[(x-120)/40][(y-120)/40]=1;
        else/*否则棋手2移动*/
    a[(x-120)/40][(y-120)/40]=2;
     if(!QpChange(x,y,t))/*落子后判断棋盘的变化*/
     {
        a[(x-120)/40][(y-120)/40]=0;/*恢复空格状态*/
        cc++;/*开始统计尝试次数*/
        if(cc>=64-score1-score2) /*如果尝试超过空格数则停步*/
        {
    MoveColor(x,y);
    fillellipse(x,y,15,15);
    break;
        }
        else
    continue;/*如果按键无效*/
     }
     DoScore();/*分数的改变*/
     break;/*棋盘变化了,则轮对方走棋*/
  }
  else/*已经有棋子就继续按键*/
     continue;
      }
      else /*四个方向按键的判断*/
  if(key==LEFT&&x>120)/*左方向键*/
  {
     MoveColor(x,y);
     fillellipse(x,y,15,15);
     SetPlayColor(t);
     x-=40;
     fillellipse(x,y,15,15);
  }
      else
  if(key==RIGHT&&x<400&&y>80)/*右方向键*/
  {
     MoveColor(x,y);
     fillellipse(x,y,15,15);
     SetPlayColor(t);
     x+=40;
     fillellipse(x,y,15,15);
  }
      else
  if(key==UP&&y>120)/*上方向键*/
  {
     MoveColor(x,y);
     fillellipse(x,y,15,15);
     SetPlayColor(t);
     y-=40;
     fillellipse(x,y,15,15);
  }
      else
  if(key==DOWN&&y<400)/*下方向键*/
  {
     MoveColor(x,y);
     fillellipse(x,y,15,15);
     SetPlayColor(t);
     y+=40;
     fillellipse(x,y,15,15);
  }
      }
      if(key==ESC)/*结束游戏*/
  break;
      if((score1+score2)==64||score1==0||score2==0)/*格子已经占满或一方棋子为0判断胜负*/
      {
  playWin();/*输出最后结果*/
  break;
      }
      t=t%2+1; /*一方走后,改变棋子颜色即轮对方走*/
      cc=0;  /*计数值恢复为0*/
   } /*endwhile*/
}
void SetPlayColor(int t)/*设置棋子颜色*/
{
   if(t%2==1)
      setfillstyle(SOLID_FILL,15);/*白色*/
   else
      setfillstyle(SOLID_FILL,8);/*灰色*/
}
void MoveColor(int x,int y)/*走了一步后恢复原来格子的状态*/
{
   if(y<100)/*如果是从起点出发就恢复蓝色*/
      setfillstyle(SOLID_FILL,BLUE);
   else/*其他情况如果是1就恢复白色棋子,2恢复黑色棋子,或恢复蓝色棋盘*/
      switch(a[(x-120)/40][(y-120)/40])
      {
  case 1:
      setfillstyle(SOLID_FILL,15);break; /*白色*/
  case 2:
      setfillstyle(SOLID_FILL,8);break; /*黑色*/
  default:
     setfillstyle(SOLID_FILL,BLUE); /*蓝色*/
      }
}
int QpChange(int x,int y,int t)/*判断棋盘的变化*/
{
   int i,j,k,kk,ii,jj,yes;
   yes=0;
   i=(x-120)/40; /*计算数组元素的行下标*/
   j=(y-120)/40; /*计算数组元素的列下标*/
   SetPlayColor(t);/*设置棋子变化的颜色*/
   /*开始往8个方向判断变化*/
   if(j<6)/*往右边*/
   {
   for(k=j+1;k<8;k++)
      if(a[i][k]==a[i][j]||a[i][k]==0)/*遇到自己的棋子或空格结束*/
  break;
      if(a[i][k]!=0&&k<8)
      {
  for(kk=j+1;kk<k&&k<8;kk++)/*判断右边*/
  {
     a[i][kk]=a[i][j]; /*改变棋子颜色*/
     fillellipse(120+i*40,120+kk*40,15,15);
  }
      if(kk!=j+1) /*条件成立则有棋子改变过颜色*/
  yes=1;
      }
   }
   if(j>1)/*判断左边*/
   {
      for(k=j-1;k>=0;k--)
  if(a[i][k]==a[i][j]||!a[i][k])
     break;
      if(a[i][k]!=0&&k>=0)
      {
  for(kk=j-1;kk>k&&k>=0;kk--)
  {
     a[i][kk]=a[i][j];
     fillellipse(120+i*40,120+kk*40,15,15);
  }
 if(kk!=j-1)
     yes=1;
      }
   }
   if(i<6)/*判断下边*/
   {
      for(k=i+1;k<8;k++)
  if(a[k][j]==a[i][j]||!a[k][j])
     break;
      if(a[k][j]!=0&&k<8)
      {
  for(kk=i+1;kk<k&&k<8;kk++)
  {
     a[kk][j]=a[i][j];
     fillellipse(120+kk*40,120+j*40,15,15);
  }
  if(kk!=i+1)
     yes=1;
      }
   }
   if(i>1)/*判断上边*/
   {
      for(k=i-1;k>=0;k--)
  if(a[k][j]==a[i][j]||!a[k][j])
     break;
      if(a[k][j]!=0&&k>=0)
      {
  for(kk=i-1;kk>k&&k>=0;kk--)
  {
     a[kk][j]=a[i][j];
     fillellipse(120+kk*40,120+j*40,15,15);
  }
  if(kk!=i-1)
     yes=1;
      }
   }
   if(i>1&&j<6)/*右上*/
   {
      for(k=i-1,kk=j+1;k>=0&&kk<8;k--,kk++)
  if(a[k][kk]==a[i][j]||!a[k][kk])
     break;
      if(a[k][kk]&&k>=0&&kk<8)
      {
  for(ii=i-1,jj=j+1;ii>k&&k>=0;ii--,jj++)
  {
     a[ii][jj]=a[i][j];
     fillellipse(120+ii*40,120+jj*40,15,15);
  }
      if(ii!=i-1)
  yes=1;
      }
   }
   if(i<6&&j>1)/*左下*/
   {
      for(k=i+1,kk=j-1;k<8&&kk>=0;k++,kk--)
  if(a[k][kk]==a[i][j]||!a[k][kk])
     break;
      if(a[k][kk]!=0&&k<8&&kk>=0)
      {
  for(ii=i+1,jj=j-1;ii<k&&k<8;ii++,jj--)
  {
     a[ii][jj]=a[i][j];
     fillellipse(120+ii*40,120+jj*40,15,15);
  }
      if(ii!=i+1)
  yes=1;
      }
   }
   if(i>1&&j>1)/*左上*/
   {
      for(k=i-1,kk=j-1;k>=0&&kk>=0;k--,kk--)
  if(a[k][kk]==a[i][j]||!a[k][kk])
     break;
      if(a[k][kk]!=0&&k>=0&&kk>=0)
      {
  for(ii=i-1,jj=j-1;ii>k&&k>=0;ii--,jj--)
  {
     a[ii][jj]=a[i][j];
     fillellipse(120+ii*40,120+jj*40,15,15);
  }
      if(ii!=i-1)
  yes=1;
      }
   }
   if(i<6&&j<6)/* 右下*/
   {
      for(k=i+1,kk=j+1;kk<8&&kk<8;k++,kk++)
  if(a[k][kk]==a[i][j]||!a[k][kk])
     break;
      if(a[k][kk]!=0&&kk<8&&k<8)
      {
  for(ii=i+1,jj=j+1;ii<k&&k<8;ii++,jj++)
  {
     a[ii][jj]=a[i][j];
     fillellipse(120+ii*40,120+jj*40,15,15);
  }
      if(ii!=i+1)
  yes=1;
      }
   }
   return yes;/*返回是否改变过棋子颜色的标记*/
}
void DoScore()/*处理分数*/
{
   int i,j;
   score1=score2=0;/*重新开始计分数*/
   for(i=0;i<8;i++)
      for(j=0;j<8;j++)
  if(a[i][j]==1)/*分别统计两个人的分数*/
     score1++;
  else
     if(a[i][j]==2)
        score2++;
}
void PrintScore(int playnum)/*输出成绩*/
{
   if(playnum==1)/*清除以前的成绩*/
   {
      setfillstyle(SOLID_FILL,BLUE);
      bar(550,100,640,400);
   }
   setcolor(RED);
   settextstyle(0,0,4);/*设置文本输出样式*/
   if(playnum==1)/*判断输出哪个棋手的分,在不同的位置输出*/
   {
      sprintf(playone,"%d",score1);
      outtextxy(550,200,playone);
   }
   else
   {
      sprintf(playtwo,"%d",score2);
      outtextxy(550,300,playtwo);
   }
   setcolor(0);
}
void playWin()/*输出最后的胜利者结果*/
{
   settextstyle(0,0,4);
   setcolor(12);
   if(score2>score1)/*开始判断最后的结果*/
      outtextxy(100,50,"black win!");
   else
      if(score2<score1)
  outtextxy(100,50,"white win!");
      else
  outtextxy(60,50,"you all win!");
}


案例四 迷宫问题
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#define N 20/*迷宫的大小,可改变*/
int  oldmap[N][N];/*递归用的数组,用全局变量节约时间*/
int  yes=0;/*yes是判断是否找到路的标志,1找到,0没找到*/
int  way[100][2],wayn=0;/*way数组是显示路线用的,wayn是统计走了几个格子*/
void Init(void);/*图形初始化*/
void Close(void);/*图形关闭*/
void DrawPeople(int *x,int *y,int n);/*画人工探索物图*/
void PeopleFind(int (*x)[N]);/*人工探索*/
void WayCopy(int (*x)[N],int (*y)[N]);/*为了8个方向的递归,把旧迷宫图拷贝给新数组*/
int  FindWay(int (*x)[N],int i,int j);/*自动探索函数*/
void MapRand(int (*x)[N]);/*随机生成迷宫函数*/
void PrMap(int (*x)[N]);/*输出迷宫图函数*/
void Result(void);/*输出结果处理*/
void Find(void);/*成功处理*/
void NotFind(void);/*失败处理*/
void main(void)/*主函数*/
{
   int map[N][N]; /*迷宫数组*/
   char ch;
   clrscr();
   printf("/n Please select hand(1) else auto/n");/*选择探索方式*/
   scanf("%c",&ch);
   Init();  /*初始化*/
   MapRand(map);/*生成迷宫*/
   PrMap(map);/*显示迷宫图*/
   if(ch=='1')
      PeopleFind(map);/*人工探索*/
   else
      FindWay(map,1,1);/*系统自动从下标1,1的地方开始探索*/
   Result();/*输出结果*/
   Close();
}
void Init(void)/*图形初始化*/
{
   int gd=DETECT,gm;
   initgraph(&gd,&gm,"c://tc");
}
void DrawPeople(int *x,int *y,int n)/*画人工控制图*/
{/*如果将以下两句注释掉,则显示人工走过的路径,*/
   setfillstyle(SOLID_FILL,WHITE);  /*设置白色实体填充样式*/
   bar(100+(*y)*15-6,50+(*x)*15-6,100+(*y)*15+6,50+(*x)*15+6);
/*恢复原通路*/
   switch(n)/*判断x,y的变化,8个方向的变化*/
   {
      case 1: (*x)--;break; /*上*/
      case 2: (*x)--;(*y)++;break ;/*右上*/
      case 3: (*y)++;break;  /*右*/
      case 4: (*x)++;(*y)++;break; /*右下*/
      case 5: (*x)++;break;  /*下*/
      case 6: (*x)++;(*y)--;break; /*左下*/
      case 7: (*y)--;break;  /*左*/
      case 8: (*x)--;(*y)--;break; /*左上*/
   }
   setfillstyle(SOLID_FILL,RED);/*新位置显示探索物*/
   bar(100+(*y)*15-6,50+(*x)*15-6,100+(*y)*15+6,50+(*x)*15+6);
}
void PeopleFind(int (*map)[N])/*人工手动查找*/
{
   int x,y;
   char c=0;/*接收按键的变量*/
   x=y=1;/*人工查找的初始位置*/
   setcolor(11);
   line(500,200,550,200);
   outtextxy(570,197,"d");
   line(500,200,450,200);
   outtextxy(430,197,"a");
   line(500,200,500,150);
   outtextxy(497,130,"w");
   line(500,200,500,250);
   outtextxy(497,270,"x");
   line(500,200,450,150);
   outtextxy(445,130,"q");
   line(500,200,550,150);
   outtextxy(550,130,"e");
   line(500,200,450,250);
   outtextxy(445,270,"z");
   line(500,200,550,250);
   outtextxy(550,270,"c");/*以上是画8个方向的控制介绍*/
   setcolor(YELLOW);
   outtextxy(420,290,"Press 'Enter' to end");/*压回车键结束*/
   setfillstyle(SOLID_FILL,RED);
   bar(100+y*15-6,50+x*15-6,100+y*15+6,50+x*15+6);/*入口位置显示*/
   while(c!=13)/*如果按下的不是回车键*/
   {
      c=getch();/*接收字符后开始各个方向的探索*/
      if(c=='w'&&map[x-1][y]!=1)
  DrawPeople(&x,&y,1);/*上*/
      else
  if(c=='e'&&map[x-1][y+1]!=1)
     DrawPeople(&x,&y,2);/*右上*/
  else
     if(c=='d'&&map[x][y+1]!=1)
        DrawPeople(&x,&y,3);/*右*/
     else
        if(c=='c'&&map[x+1][y+1]!=1)
    DrawPeople(&x,&y,4);/*右下*/
        else
    if(c=='x'&&map[x+1][y]!=1)
       DrawPeople(&x,&y,5);/*下*/
    else
       if(c=='z'&&map[x+1][y-1]!=1)
   DrawPeople(&x,&y,6); /*左下*/
       else
   if(c=='a'&&map[x][y-1]!=1)
      DrawPeople(&x,&y,7); /*左*/
   else if(c=='q'&&map[x-1][y-1]!=1)
      DrawPeople(&x,&y,8); /*左上*/
   }
   setfillstyle(SOLID_FILL,WHITE); /*消去红色探索物,恢复原迷宫图*/
   bar(100+y*15-6,50+x*15-6,100+y*15+6,50+x*15+6);
   if(x==N-2&&y==N-2)/*人工控制找成功的话*/
      yes=1; /*如果成功标志为1*/
}
void WayCopy(int (*oldmap)[N],int (*map)[N])/*拷贝迷宫数组 */
{
   int i,j;
   for(i=0;i<N;i++)
      for(j=0;j<N;j++)
  oldmap[i][j]=map[i][j];
}
int FindWay(int (*map)[N],int i,int j)/*递归找路*/
{
   if(i==N-2&&j==N-2)/*走到出口*/
   {
      yes=1;/*标志为1,表示成功*/
      return;
   }
   map[i][j]=1;/*走过的地方变为1*/
   WayCopy(oldmap,map); /*拷贝迷宫图*/
   if(oldmap[i+1][j+1]==0&&!yes)/*判断右下方是否可走*/
   {
      FindWay(oldmap,i+1,j+1);
      if(yes)/*如果到达出口了,再把值赋给显示路线的way数组,也正是这个原因,所以具体路线是从最后开始保存*/
      {
  way[wayn][0]=i;
  way[wayn++][1]=j;
  return;
      }
   }
   WayCopy(oldmap,map);
   if(oldmap[i+1][j]==0&&!yes)/*判断下方是否可以走,如果标志yes已经是1也不用找下去了*/
   {
      FindWay(oldmap,i+1,j);
      if(yes)
      {
  way[wayn][0]=i;
  way[wayn++][1]=j;
  return;
      }
   }
   WayCopy(oldmap,map);
   if(oldmap[i][j+1]==0&&!yes)/*判断右方是否可以走*/
   {
      FindWay(oldmap,i,j+1);
      if(yes)
      {
  way[wayn][0]=i;
  way[wayn++][1]=j;
  return;
      }
   }
   WayCopy(oldmap,map);
   if(oldmap[i-1][j]==0&&!yes)/*判断上方是否可以走*/
   {
      FindWay(oldmap,i-1,j);
      if(yes)
      {
  way[wayn][0]=i;
  way[wayn++][1]=j;
  return;
      }
   }
   WayCopy(oldmap,map);
   if(oldmap[i-1][j+1]==0&&!yes)/*判断右上方是否可以走*/
   {
      FindWay(oldmap,i-1,j+1);
      if(yes)
      {
  way[wayn][0]=i;
  way[wayn++][1]=j;
  return;
      }
   }
   WayCopy(oldmap,map);
   if(oldmap[i+1][j-1]==0&&!yes)/*判断左下方是否可以走*/
   {
      FindWay(oldmap,i+1,j-1);
      if(yes)
      {
  way[wayn][0]=i;
  way[wayn++][1]=j;
  return;
      }
   }
   WayCopy(oldmap,map);
   if(oldmap[i][j-1]==0&&!yes)/*判断左方是否可以走*/
   {
      FindWay(oldmap,i,j-1);
      if(yes)
      {
  way[wayn][0]=i;
  way[wayn++][1]=j;
  return;
      }
   }
   WayCopy(oldmap,map);
   if(oldmap[i-1][j-1]==0&&!yes)/*判断左上方是否可以走*/
   {
      FindWay(oldmap,i-1,j-1);
      if(yes)
      {
  way[wayn][0]=i;
  way[wayn++][1]=j;
  return;
      }
   }
   return;
}
void MapRand(int (*map)[N])/*开始的随机迷宫图*/
{
   int i,j;
   cleardevice();/*清屏*/
   randomize(); /*随机数发生器*/
   for(i=0;i<N;i++)
   {
      for(j=0;j<N;j++)
      {
  if(i==0||i==N-1||j==0||j==N-1)/*最外面一圈为墙壁*/
     map[i][j]=1;
  else
     if(i==1&&j==1||i==N-2&&j==N-2)/*出发点与终点表示为可走的*/
        map[i][j]=0;
     else
        map[i][j]=random(2);/*其它的随机生成0或1*/
      }
   }
}
void PrMap(int (*map)[N])/*输出迷宫图*/
{
   int i,j;
   for(i=0;i<N;i++)
      for(j=0;j<N;j++)
  if(map[i][j]==0)
  {
     setfillstyle(SOLID_FILL,WHITE);/*白色为可走的路*/
     bar(100+j*15-6,50+i*15-6,100+j*15+6,50+i*15+6);
  }
  else
  {
     setfillstyle(SOLID_FILL,BLUE);/*蓝色为墙壁*/
     bar(100+j*15-6,50+i*15-6,100+j*15+6,50+i*15+6);
  }
}
void Find(void)/*找到通路*/
{
   int i;
   setfillstyle(SOLID_FILL,RED);/*红色输出走的具体路线*/
   wayn--;
   for(i=wayn;i>=0;i--)
   {
      bar(100+way[i][1]*15-6,50+way[i][0]*15-6,100+
      way[i][1]*15+6,50+way[i][0]*15+6);
      sleep(1);/*控制显示时间*/
   }
   bar(100+(N-2)*15-6,50+(N-2)*15-6,100+
 (N-2)*15+6,50+(N-2)*15+6); /*在目标点标红色*/
   setcolor(GREEN);
   settextstyle(0,0,2);/*设置字体大小*/
   outtextxy(130,400,"Find a way!");
}
void NotFind(void)/*没找到通路*/
{
   setcolor(GREEN);
   settextstyle(0,0,2);/*设置字体大小*/
   outtextxy(130,400,"Not find a way!");
}
void Result(void)/*结果处理*/
{
   if(yes)/*如果找到*/
      Find();
   else/*没找到路*/
      NotFind();
   getch();
}
void Close(void)/*图形关闭*/
{
   closegraph();
}


案例五 扫地雷游戏
#include <graphics.h>
#include <stdlib.h>
#include <dos.h>
#define LEFTPRESS 0xff01
#define LEFTCLICK 0xff10
#define LEFTDRAG 0xff19
#define MOUSEMOVE 0xff08
struct
{
   int num;/*格子当前处于什么状态,1有雷,0已经显示过数字或者空白格子*/
   int roundnum;/*统计格子周围有多少雷*/
   int flag;/*右键按下显示红旗的标志,0没有红旗标志,1有红旗标志*/
}Mine[10][10];
int gameAGAIN=0;/*是否重来的变量*/
int gamePLAY=0;/*是否是第一次玩游戏的标志*/
int mineNUM;/*统计处理过的格子数*/
char randmineNUM[3];/*显示数字的字符串*/
int Keystate;
int MouseExist;
int MouseButton;
int MouseX;
int MouseY;
void Init(void);/*图形驱动*/
void MouseOn(void);/*鼠标光标显示*/
void MouseOff(void);/*鼠标光标隐藏*/
void MouseSetXY(int,int);/*设置当前位置*/
int  LeftPress(void);/*左键按下*/
int  RightPress(void);/*鼠标右键按下*/
void MouseGetXY(void);/*得到当前位置*/
void Control(void);/*游戏开始,重新,关闭*/
void GameBegain(void);/*游戏开始画面*/
void DrawSmile(void);/*画笑脸*/
void DrawRedflag(int,int);/*显示红旗*/
void DrawEmpty(int,int,int,int);/*两种空格子的显示*/
void GameOver(void);/*游戏结束*/
void GameWin(void);/*显示胜利*/
int  MineStatistics(int,int);/*统计每个格子周围的雷数*/
int  ShowWhite(int,int);/*显示无雷区的空白部分*/
void GamePlay(void);/*游戏过程*/
void Close(void);/*图形关闭*/
void main(void)
{
   Init();
   Control();
   Close();
}
void Init(void)/*图形开始*/
{
   int gd=DETECT,gm;
   initgraph(&gd,&gm,"c://tc");
}
void Close(void)/*图形关闭*/
{
   closegraph();
}
void MouseOn(void)/*鼠标光标显示*/
{
   _AX=0x01;
   geninterrupt(0x33);
}
void MouseOff(void)/*鼠标光标隐藏*/
{
   _AX=0x02;
   geninterrupt(0x33);
}
void MouseSetXY(int x,int y)/*设置当前位置*/
{
   _CX=x;
   _DX=y;
   _AX=0x04;
   geninterrupt(0x33);
}
int LeftPress(void)/*鼠标左键按下*/
{
   _AX=0x03;
   geninterrupt(0x33);
   return(_BX&1);
}
int RightPress(void)/*鼠标右键按下*/
{
   _AX=0x03;
   geninterrupt(0x33);
   return(_BX&2);
}
void MouseGetXY(void)/*得到当前位置*/
{
   _AX=0x03;
   geninterrupt(0x33);
   MouseX=_CX;
   MouseY=_DX;
}
void Control(void)/*游戏开始,重新,关闭*/
{
   int gameFLAG=1;/*游戏失败后判断是否重新开始的标志*/
   while(1)
   {
      if(gameFLAG)/*游戏失败后没判断出重新开始或者退出游戏的话就继续判断*/
      {
  GameBegain(); /*游戏初始画面*/
  GamePlay();/*具体游戏*/
  if(gameAGAIN==1)/*游戏中重新开始*/
  {
     gameAGAIN=0;
     continue;
  }
      }
   MouseOn();
   gameFLAG=0;
   if(LeftPress())/*判断是否重新开始*/
   {
      MouseGetXY();
      if(MouseX>280&&MouseX<300&&MouseY>65&&MouseY<85)
      {
  gameFLAG=1;
  continue;
      }
   }
   if(kbhit())/*判断是否按键退出*/
      break;
   }
   MouseOff();
}
void DrawSmile(void)/*画笑脸*/
{
   setfillstyle(SOLID_FILL,YELLOW);
   fillellipse(290,75,10,10);
   setcolor(YELLOW);
   setfillstyle(SOLID_FILL,BLACK);/*眼睛*/
   fillellipse(285,75,2,2);
   fillellipse(295,75,2,2);
   setcolor(BLACK);/*嘴巴*/
   bar(287,80,293,81);
}
void DrawRedflag(int i,int j)/*显示红旗*/
{
   setcolor(7);
   setfillstyle(SOLID_FILL,RED);
   bar(198+j*20,95+i*20,198+j*20+5,95+i*20+5);
   setcolor(BLACK);
   line(198+j*20,95+i*20,198+j*20,95+i*20+10);
}
void DrawEmpty(int i,int j,int mode,int color)/*两种空格子的显示*/
{
   setcolor(color);
   setfillstyle(SOLID_FILL,color);
   if(mode==0)/*没有单击过的大格子*/
      bar(200+j*20-8,100+i*20-8,200+j*20+8,100+i*20+8);
   else
      if(mode==1)/*单击过后显示空白的小格子*/
  bar(200+j*20-7,100+i*20-7,200+j*20+7,100+i*20+7);
}
void GameBegain(void)/*游戏开始画面*/
{
   int i,j;
   cleardevice();
   if(gamePLAY!=1)
   {
      MouseSetXY(290,70); /*鼠标一开始的位置,并作为它的初始坐标*/
      MouseX=290;
      MouseY=70;
   }
   gamePLAY=1;/*下次按重新开始的话鼠标不重新初始化*/
   mineNUM=0;
   setfillstyle(SOLID_FILL,7);
   bar(190,60,390,290);
   for(i=0;i<10;i++)/*画格子*/
      for(j=0;j<10;j++)
  DrawEmpty(i,j,0,8);
   setcolor(7);
   DrawSmile();/*画脸*/
   randomize();
   for(i=0;i<10;i++)/*100个格子随机赋值有没有地雷*/
      for(j=0;j<10;j++)
      {
  Mine[i][j].num=random(8);/*如果随机数的结果是1表示这个格子有地雷*/
  if(Mine[i][j].num==1)
     mineNUM++;/*现有雷数加1*/
  else
     Mine[i][j].num=2;
  Mine[i][j].flag=0;/*表示没红旗标志*/
      }
   sprintf(randmineNUM,"%d",mineNUM); /*显示这次总共有多少雷数*/
   setcolor(1);
   settextstyle(0,0,2);
   outtextxy(210,70,randmineNUM);
   mineNUM=100-mineNUM;/*变量取空白格数量*/
   MouseOn();
}
void GameOver(void)/*游戏结束画面*/
{
   int i,j;
   setcolor(0);
   for(i=0;i<10;i++)
      for(j=0;j<10;j++)
  if(Mine[i][j].num==1)/*显示所有的地雷*/
  {
     DrawEmpty(i,j,0,RED);
     setfillstyle(SOLID_FILL,BLACK);
     fillellipse(200+j*20,100+i*20,7,7);
  }
}
void GameWin(void)/*显示胜利*/
{
   setcolor(11);
   settextstyle(0,0,2);
   outtextxy(230,30,"YOU WIN!");
}
int MineStatistics(int i,int j)/*统计每个格子周围的雷数*/
{
   int nNUM=0;
   if(i==0&&j==0)/*左上角格子的统计*/
   {
      if(Mine[0][1].num==1)
  nNUM++;
      if(Mine[1][0].num==1)
  nNUM++;
      if(Mine[1][1].num==1)
  nNUM++;
   }
   else
      if(i==0&&j==9)/*右上角格子的统计*/
      {
  if(Mine[0][8].num==1)
     nNUM++;
  if(Mine[1][9].num==1)
     nNUM++;
  if(Mine[1][8].num==1)
     nNUM++;
      }
     else
  if(i==9&&j==0)/*左下角格子的统计*/
  {
     if(Mine[8][0].num==1)
        nNUM++;
     if(Mine[9][1].num==1)
        nNUM++;
     if(Mine[8][1].num==1)
        nNUM++;
  }
 else
     if(i==9&&j==9)/*右下角格子的统计*/
     {
        if(Mine[9][8].num==1)
    nNUM++;
        if(Mine[8][9].num==1)
    nNUM++;
        if(Mine[8][8].num==1)
    nNUM++;
     }
     else if(j==0)/*左边第一列格子的统计*/
     {
        if(Mine[i][j+1].num==1)
    nNUM++;
        if(Mine[i+1][j].num==1)
    nNUM++;
        if(Mine[i-1][j].num==1)
    nNUM++;
        if(Mine[i-1][j+1].num==1)
    nNUM++;
        if(Mine[i+1][j+1].num==1)
    nNUM++;
     }
     else if(j==9)/*右边第一列格子的统计*/
     {
        if(Mine[i][j-1].num==1)
    nNUM++;
        if(Mine[i+1][j].num==1)
    nNUM++;
        if(Mine[i-1][j].num==1)
    nNUM++;
        if(Mine[i-1][j-1].num==1)
    nNUM++;
        if(Mine[i+1][j-1].num==1)
    nNUM++;
     }
     else if(i==0)/*第一行格子的统计*/
     {
        if(Mine[i+1][j].num==1)
    nNUM++;
        if(Mine[i][j-1].num==1)
    nNUM++;
        if(Mine[i][j+1].num==1)
    nNUM++;
        if(Mine[i+1][j-1].num==1)
    nNUM++;
        if(Mine[i+1][j+1].num==1)
    nNUM++;
      }
      else if(i==9)/*最后一行格子的统计*/
      {
        if(Mine[i-1][j].num==1)
    nNUM++;
        if(Mine[i][j-1].num==1)
    nNUM++;
        if(Mine[i][j+1].num==1)
    nNUM++;
        if(Mine[i-1][j-1].num==1)
    nNUM++;
        if(Mine[i-1][j+1].num==1)
    nNUM++;
     }
     else/*普通格子的统计*/
     {
        if(Mine[i-1][j].num==1)
    nNUM++;
        if(Mine[i-1][j+1].num==1)
    nNUM++;
        if(Mine[i][j+1].num==1)
    nNUM++;
        if(Mine[i+1][j+1].num==1)
    nNUM++;
        if(Mine[i+1][j].num==1)
    nNUM++;
        if(Mine[i+1][j-1].num==1)
    nNUM++;
        if(Mine[i][j-1].num==1)
    nNUM++;
        if(Mine[i-1][j-1].num==1)
    nNUM++;
      }
   return(nNUM);/*把格子周围一共有多少雷数的统计结果返回*/
}
int ShowWhite(int i,int j)/*显示无雷区的空白部分*/
{
   if(Mine[i][j].flag==1||Mine[i][j].num==0)/*如果有红旗或该格处理过就不对该格进行任何判断*/
      return;
   mineNUM--;/*显示过数字或者空格的格子就表示多处理了一个格子,当所有格子都处理过了表示胜利*/
   if(Mine[i][j].roundnum==0&&Mine[i][j].num!=1)/*显示空格*/
   {
      DrawEmpty(i,j,1,7);
      Mine[i][j].num=0;
   }
   else
      if(Mine[i][j].roundnum!=0)/*输出雷数*/
      {
  DrawEmpty(i,j,0,8);
  sprintf(randmineNUM,"%d",Mine[i][j].roundnum);
  setcolor(RED);
  outtextxy(195+j*20,95+i*20,randmineNUM);
  Mine[i][j].num=0;/*已经输出雷数的格子用0表示已经用过这个格子*/
  return ;
      }
 /*8个方向递归显示所有的空白格子*/
   if(i!=0&&Mine[i-1][j].num!=1)
      ShowWhite(i-1,j);
   if(i!=0&&j!=9&&Mine[i-1][j+1].num!=1)
      ShowWhite(i-1,j+1);
   if(j!=9&&Mine[i][j+1].num!=1)
      ShowWhite(i,j+1);
   if(j!=9&&i!=9&&Mine[i+1][j+1].num!=1)
      ShowWhite(i+1,j+1);
   if(i!=9&&Mine[i+1][j].num!=1)
      ShowWhite(i+1,j);
   if(i!=9&&j!=0&&Mine[i+1][j-1].num!=1)
      ShowWhite(i+1,j-1);
   if(j!=0&&Mine[i][j-1].num!=1)
      ShowWhite(i,j-1);
   if(i!=0&&j!=0&&Mine[i-1][j-1].num!=1)
      ShowWhite(i-1,j-1);
}
void GamePlay(void)/*游戏过程*/
{
   int i,j,Num;/*Num用来接收统计函数返回一个格子周围有多少地雷*/
   for(i=0;i<10;i++)
      for(j=0;j<10;j++)
  Mine[i][j].roundnum=MineStatistics(i,j);/*统计每个格子周围有多少地雷*/
   while(!kbhit())
   {
      if(LeftPress())/*鼠标左键盘按下*/
      {
  MouseGetXY();
  if(MouseX>280&&MouseX<300&&MouseY>65&&MouseY<85)/*重新来*/
  {
     MouseOff();
     gameAGAIN=1;
     break;
  }
  if(MouseX>190&&MouseX<390&&MouseY>90&&MouseY<290)/*当前鼠标位置在格子范围内*/
  {
     j=(MouseX-190)/20;/*x坐标*/
     i=(MouseY-90)/20;/*y坐标*/
     if(Mine[i][j].flag==1)/*如果格子有红旗则左键无效*/
        continue;
     if(Mine[i][j].num!=0)/*如果格子没有处理过*/
     {
        if(Mine[i][j].num==1)/*鼠标按下的格子是地雷*/
        {
    MouseOff();
    GameOver();/*游戏失败*/
    break;
        }
        else/*鼠标按下的格子不是地雷*/
        {
    MouseOff();
    Num=MineStatistics(i,j);
    if(Num==0)/*周围没地雷就用递归算法来显示空白格子*/
       ShowWhite(i,j);
    else/*按下格子周围有地雷*/
    {
       sprintf(randmineNUM,"%d",Num);/*输出当前格子周围的雷数*/
       setcolor(RED);
       outtextxy(195+j*20,95+i*20,randmineNUM);
       mineNUM--;
    }
        MouseOn();
        Mine[i][j].num=0;/*点过的格子周围雷数的数字变为0表示这个格子已经用过*/
        if(mineNUM<1)/*胜利了*/
        {
    GameWin();
    break;
        }
     }
  }
      }
   }
   if(RightPress())/*鼠标右键键盘按下*/
   {
      MouseGetXY();
      if(MouseX>190&&MouseX<390&&MouseY>90&&MouseY<290)/*当前鼠标位置在格子范围内*/
      {
  j=(MouseX-190)/20;/*x坐标*/
  i=(MouseY-90)/20;/*y坐标*/
  MouseOff();
  if(Mine[i][j].flag==0&&Mine[i][j].num!=0)/*本来没红旗现在显示红旗*/
  {
     DrawRedflag(i,j);
     Mine[i][j].flag=1;
  }
  else
     if(Mine[i][j].flag==1)/*有红旗标志再按右键就红旗消失*/
     {
        DrawEmpty(i,j,0,8);
        Mine[i][j].flag=0;
     }
      }
      MouseOn();
      sleep(1);
      }
   }
}


案例六 速算24
#define N 20
#define COL 100
#define ROW 40
#include "stdio.h"
#include "time.h" /*系统时间函数*/
#include "graphics.h" /*图形函数*/
#include "alloc.h"/*动态地址分配函数*/
#include "stdlib.h" /*库函数*/
#include "string.h" /*字符串函数*/
#include "ctype.h" /*字符操作函数*/
char p[4][13]={
{'A','2','3','4','5','6','7','8','9','0','J','Q','K'},/*扑克牌,10用0来表示*/
{'A','2','3','4','5','6','7','8','9','0','J','Q','K'},
{'A','2','3','4','5','6','7','8','9','0','J','Q','K'},
{'A','2','3','4','5','6','7','8','9','0','J','Q','K'}};
typedef struct node
{
   int data;
   struct node  *link;
}STACK1; /*栈1*/
typedef struct node2
{
   char data;
   struct node2 *link;
}STACK2; /*栈2*/
void init(void);/*图形驱动*/
void close(void);/*图形关闭*/
void play(void);/*发牌的具体过程*/
void rand1(int j);/*随机发牌函数*/
void change(char *e,char *a);  /*中缀变后缀函数*/
int computer(char *s);  /*后缀表达式计算函数*/
STACK1 *initstack1(STACK1 *top);   /*栈1初始化*/
STACK1 *push(STACK1 *top,int x); /*栈1入栈运算*/
STACK1 *pop(STACK1 *top); /*栈1删除栈顶元素*/
int topx(STACK1 *top); /*栈1读栈顶元素*/
STACK1 *ptop(STACK1 *top,int *x); /*栈1读出栈顶元素值并删除栈顶元素*/
int empty(STACK1 *top); /*判栈1是否为空函数*/
STACK2 *initstack2(STACK2 *top); /*栈2初始化*/
STACK2 *push2(STACK2 *top,char x); /*栈2入栈运算*/
STACK2 *pop2(STACK2 *top); /*栈2删除栈顶元素*/
char topx2(STACK2 *top); /*栈2读栈顶元素*/
STACK2 *ptop2(STACK2 *top,char *x); /*栈2读出栈顶元素值并删除栈顶元素*/
int empty2(STACK2 *top); /*判栈2是否为空函数*
int text1(char *s) ; /*显示文本*/
main()
{
   char s[N],s1[N],ch;
   int i,result;
   int gdriver, gmode;
   clrscr(); /*清屏*/
   init(); /*初始化函数*/
   while(1)
   {
      setbkcolor(BLACK); /*设置背景颜色*/
      cleardevice();/*清屏*/
      play();  /*发牌*/
      gotoxy(1,15); /*移动光标*/
      printf("--------------------Note-------------------/n");
      printf("  Please enter express accroding to above four number/n"); /*提示信息*/
      printf("  Format as follows:2.*(5.+7.)/n");/*提示输入字符串格式*/
      printf(" ----------------------------------------------/n");
      scanf("%s%c",s1,&ch); /*输入字符串压回车键*/
      change(s1,s); /*调用change函数将中缀表达式s1转换为后缀表达式s*/
      result=computer(s); /*计算后缀表达式的值,返回结果result */
      if(result==24) /*如果结果等于24*/
  text1("very good"); /*调用函数text1显示字符串"very good"*/
      else
  text1("wrong!!!");/*否则函数text1显示字符串"wrong!!!"*/
      printf("Continue (y/n)?/n"); /*提示信息,是否继续*/
      scanf("%c",&ch); /*输入一字符*/
      if(ch=='n'||ch=='N') /*如果该字符等于n或N*/
  break;   /*跳出循环,程序结束*/
   } /*否则,开始下一轮循环*/
   close();
   return; /*返回*/
}
void rand1(int j)/*随机发牌函数*/
{
   int kind,num;
   char str[3],n;
   randomize();
   while(1)/*循环直到有牌发*/
   {
      kind=random(4); /*花色随机数*/
      num=random(13); /*大小随机数*/
      if(p[kind][num]!=-1) /*该数未取过*/
      {
  n=p[kind][num]; /*取相应位置的扑克牌数*/
  p[kind][num]=-1; /*牌发好以后相应位置的元素置-1*/
  break;
      }
   }
   switch(kind)/*花式的判断*/
   {
      case 0:setcolor(RED);sprintf(str,"%c",3);break; /*红桃*/
      case 1:setcolor(BLACK);sprintf(str,"%c",3);break; /*黑桃*/
      case 2:setcolor(RED);sprintf(str,"%c",4);break; /*方片*/
      case 3:setcolor(BLACK);sprintf(str,"%c",5);break; /*草花*/
   }
   settextstyle(0,0,2);
   outtextxy(COL+j*100-30,ROW+100-46,str);/*显示左上角花色*/
   outtextxy(COL+j*100+16,ROW+100+32,str); /*显示右下角花色*/
   if(n!='0')/*输出其他牌*/
   {
      settextstyle(0,0,3);
      sprintf(str,"%c",n);
      outtextxy(COL+j*100-5,ROW+100-5,str);/*显示牌的大小*/
   }
   else/*输出10的时候*/
   {
      sprintf(str,"%d",10);
      outtextxy(COL+j*100-6,ROW+100-5,str);
   }
}
void play(void)/*发牌的具体过程*/
{
   int j;
   for(j=0;j<4;j++)
   {
      bar(COL+j*100-35,ROW+100-50,COL+j*100+35,ROW+1*100+50);/*画空牌*/
      setcolor(BLUE);
      rectangle(COL+j*100-32,ROW+100-48,COL+j*100+32,ROW+100+48);  /*画矩形框*/
      rand1(j); /*随机取牌*/
      delay(10000); /*延时显示*/
   }
}
void init(void)/*图形驱动*/
{
   int gd=DETECT,gm;
   initgraph(&gd,&gm,"c://tc");
   cleardevice();
}
void close(void)/*图形关闭*/
{
   closegraph();
}
void change(char *e,char *a) /*中缀字符串e转后缀字符串a函数*/
{
   STACK2 *top=NULL; /* 定义栈顶指针*/
   int i,j;char w;
   i=0;
   j=0;
   while(e[i]!='/0') /*当字符串没有结束时*/
   {
      if(isdigit(e[i])) /*如果字符是数字*/
      {
  do{
     a[j]=e[i];  /*将数字原样拷贝到数组a中*/
     i++;   /*e数组的下标加1*/
     j++;  /*a数组的下标加1*/
   }while(e[i]!='.'); /*直到字符为数字结束符“.”为止*/
  a[j]='.';j++; /*将数字结束符“.”拷贝到a数组依然保持结束标记*/
      }
      if(e[i]=='(')  /*如果字符是“(”时*/
  top=push2(top,e[i]); /*将其压入堆栈*/
      if(e[i]==')')  /*如果字符是“)”时*/
      {
  top=ptop2(top,&w); /*取出栈顶元素,并从栈顶删除该元素*/
  while(w!='(')  /*如果字符不是“(”时反复循环*/
  {
     a[j]=w;  /*将栈顶元素存入a数组*/
     j++;  /*下标加1*/
     top=ptop2(top,&w) ; /*取出栈顶元素,并从栈顶删除该元素*/
  }
      }
      if(e[i]=='+'||e[i]=='-') /*如果字符是加或减号时*/
      {
  if(!empty2(top))  /*如栈不为空*/
  {
     w=topx2(top);
     while(w!='(') /*当栈顶元素不是“(”时反复循环*/
     {
        a[j]=w;
        j++; /*将栈顶元素存入表达式a中,a的下标加1*/
        top=pop2(top); /*删除栈顶元素*/
        if(empty2(top)) /*如果栈为空*/
    break; /*跳出循环*/
        else
    w=topx2(top); /*否则读栈顶元素*/
     }
  }
       top=push2(top,e[i]); /*将当前e的字符元素压入堆栈*/
      }
      if(e[i]=='*'||e[i]=='/') /*如果字符是乘或除号时*/
      {
  if(!empty2(top)) /*如栈不为空*/
  {
     w=topx2(top); /*读栈顶元素存入w*/
     while(w=='*'||w=='/')/*当栈顶元素是乘或除时反复循环*/
     {
        a[j]=w;
        j++; /*将栈顶元素存入字符串a中,a的下标加1*/
        top=pop2(top); /*删除栈顶元素*/
        if(empty2(top)) /*如果栈为空*/
    break; /*跳出循环*/
        else
    w=topx2(top); /*否则读栈顶元素*/
     }
  }
  top=push2(top,e[i]); /*将当前e字符元素压入堆栈*/
      }
      i++; /*e的下标加1*/
   }
   while(!empty2(top)) /*当不为空时反复循环*/
      top=ptop2(top,&a[j++]); /*将栈顶元素存入数组a中*/
   a[j]='/0';  /*将字符串结束标记写入最后一个数组元素中构成字符串*/
}
int computer(char *s)  /* 计算函数*/
{
   STACK1 *top=NULL;
   int i,k,num1,num2,result;
   i=0;
   while(s[i]!='/0')  /*当字符串没有结束时作以下处理*/
   {
      if(isdigit(s[i])) /*判字符是否为数字*/
      {
  k=0;  /*k初值为0*/
  do{
     k=10*k+s[i]-'0';  /*将字符连接为十进制数字*/
     i++;   /*i加1*/
  }while(s[i]!='.'); /*当字符不为‘.’时重复循环*/
  top=push(top,k); /*将生成的数字压入堆栈*/
      }
      if(s[i]=='+')  /*如果为'+'号*/
      {
  top=ptop(top,&num2); /*将栈顶元素取出存入num2中*/
  top=ptop(top,&num1);  /*将栈顶元素取出存入num1中*/
  result=num2+num1;  /*将num1和num2相加存入result中*/
  top=push(top,result);  /*将result压入堆栈*/
      }
      if(s[i]=='-')  /*如果为'-'号*/
      {
  top=ptop(top,&num2); /*将栈顶元素取出存入num2中*/
  top=ptop(top,&num1); /*将栈顶元素取出存入num1中*/
  result=num1-num2; /*将num1减去num2结果存入result中*/
  top=push(top,result); /*将result压入堆栈*/
      }
      if(s[i]=='*')  /*如果为'*'号*/
      {
  top=ptop(top,&num2); /*将栈顶元素取出存入num2中*/
  top=ptop(top,&num1); /*将栈顶元素取出存入num1中*/
  result=num1*num2; /*将num1与num2相乘结果存入result中*/
  top=push(top,result); /*将result压入堆栈*/
      }
      if(s[i]=='/') /*如果为'/'号*/
      {
  top=ptop(top,&num2); /*将栈顶元素取出存入num2中*/
  top=ptop(top,&num1); /*将栈顶元素取出存入num1中*/
  result=num1/num2; /*将num1除num2结果存入result中*
  top=push(top,result); /*将result压入堆栈*/
      }
      i++;  /*i加1*/
   }
   top=ptop(top,&result); /*最后栈顶元素的值为计算的结果*/
   return result;  /*返回结果*/
}
STACK1 *initstack1(STACK1 *top) /*初始化*/
{
   top=NULL; /*栈顶指针置为空*/
   return top;  /*返回栈顶指针*/
}
STACK1 *push(STACK1 *top,int x) /*入栈函数*/
{
   STACK1 *p;  /*临时指针类型为STACK1*/
   p=(STACK1 *)malloc(sizeof(STACK1));  /*申请STACK1大小的空间*/
   if(p==NULL)  /*如果p为空*/
   {
      printf("memory is overflow/n!!"); /*显示内存溢出*/
      exit(0);   /*退出*/
   }
   p->data=x; /*保存值x到新空间*/
   p->link=top;  /*新结点的后继为当前栈顶指针*/
   top=p;  /*新的栈顶指针为新插入的结点*/
   return top; /*返回栈顶指针*/
}
STACK1 *pop(STACK1 *top) /*出栈*/
{
   STACK1 *q; /*定义临时变量*/
   q=top;  /*保存当前栈顶指针*/
   top=top->link; /*栈顶指针后移*/
   free(q);  /*释放q*/
   return top; /*返回栈顶指针*/
}
int topx(STACK1 *top)  /*读栈顶元素*/
{
   if(top==NULL)  /*栈是否为空*/
   {
      printf("Stack is null/n"); /*显示栈为空信息*/
      return 0;   /*返回整数0*/
   }
   return top->data; /*返回栈顶元素*/
}
STACK1 *ptop(STACK1 *top,int *x) /*取栈顶元素,并删除栈顶元素*/
{
   *x=topx(top);  /*读栈顶元素*/
   top=pop(top); /*删除栈顶元素*/
   return top; /*返回栈顶指针*/
}
int empty(STACK1 *top) /*判栈是否为空*/
{
   if(top==NULL) /*如果为空*/
      return 1;  /*返回1*/
   else
      return 0; /*否则返回0*/
}
STACK2 *initstack2(STACK2 *top) /*初始化*/
{
   top=NULL; /*栈顶指针置为空*/
   return top; /*返回栈顶指针*/
}
STACK2 *push2(STACK2 *top,char x) /*入栈函数*/
{
   STACK2 *p; /*临时指针类型为STACK2*/
   p=(STACK2 *)malloc(sizeof(STACK2)); /*申请STACK2大小的空间*/
   if(p==NULL) /*如果p为空*/
   {
      printf("memory is overflow/n!!"); /*显示内存溢出*/
      exit(0); /*退出*/
   }
   p->data=x; /*保存值x到新空间*/
   p->link=top; /*新结点的后继为当前栈顶指针*/
   top=p; /*新的栈顶指针为新插入的结点*/
   return top; /*返回栈顶指针*/
}
STACK2 *pop2(STACK2 *top) /*出栈*/
{
   STACK2 *q; /*定义临时变量*/
   q=top; /*保存当前栈顶指针*/
   top=top->link; /*栈顶指针后移*/
   free(q); /*释放q*/
   return top; /*返回栈顶指针*/
}
char topx2(STACK2 *top) /*读栈顶元素*/
{
   if(top==NULL) /*栈是否为空*/
   {
      printf("Stack is null/n"); /*显示栈为空信息*/
      return ''; /*返回空字符*/
   }
   return top->data; /*返回栈顶元素*/
}
STACK2 *ptop2(STACK2 *top,char *x) /*取栈顶元素,并删除栈顶元素*/
{
   *x=topx2(top); /*读栈顶元素*/
   top=pop2(top); /*删除栈顶元素*/
   return top; /*返回栈顶指针*/
}
int empty2(STACK2 *top) /*判栈是否为空*/
{
   if(top==NULL) /*如果为空*/
      return 1; /*返回1*/
   else
      return 0; /*否则返回0*/
}

int text1(char *s)
{
   setbkcolor(BLUE); /*设置背景颜色为蓝色*/
   cleardevice(); /*清除屏幕*/
   setcolor(12); /*设置文本颜色为淡红色*/
   settextstyle(1, 0, 8);/*三重笔划字体, 放大8倍*/
   outtextxy(120, 120, s); /*输出字符串s*/
   setusercharsize(2, 1, 4, 1);/*水平放大2倍, 垂直放大4倍*/
   setcolor(15);   /*设置文本颜色为*白色/
   settextstyle(3, 0, 5); /*无衬字笔划, 放大5倍*/
   outtextxy(220, 220, s); /*输出字符串s*/
   getch(); /*键盘输入任一字符*/
   return ; /*返回*/
}


案例七 数据结构CAI系统
案例八 进程调度
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
typedef struct node
{
   char name[10];  /*进程标识符*/
   int prio;   /*进程优先数*/
   int round;  /*进程时间轮转时间片*/
   int cputime; /*进程占用CPU时间*/
   int needtime; /*进程到完成还要的时间*/
   int count;  /*计数器*/
   char state; /*进程的状态*/
   struct node *next; /*链指针*/
}PCB;
PCB *finish,*ready,*tail,*run; /*队列指针*/
int N; /*进程数*/
/*将就绪队列中的第一个进程投入运行*/
firstin()
{
   run=ready;   /*就绪队列头指针赋值给运行头指针*/
   run->state='R';   /*进程状态变为运行态*/
   ready=ready->next;  /*就绪对列头指针后移到下一进程*/
}
/*标题输出函数*/
void prt1(char a)
{
   if(toupper(a)=='P') /*优先数法*/
      printf("  name     cputime  needtime  priority  state/n");
   else
      printf("  name     cputime  needtime   count   round     state/n");
}
/*进程PCB输出*/
void prt2(char a,PCB *q)
{
   if(toupper(a)=='P')  /*优先数法的输出*/
      printf("  %-10s%-10d%-10d%-10d %c/n",q->name,
       q->cputime,q->needtime,q->prio,q->state);
   else/*轮转法的输出*/
      printf("  %-10s%-10d%-10d%-10d%-10d %-c/n",q->name,
       q->cputime,q->needtime,q->count,q->round,q->state);
}
/*输出函数*/
void prt(char algo)
{
   PCB *p;
   prt1(algo);  /*输出标题*/
   if(run!=NULL) /*如果运行指针不空*/
      prt2(algo,run); /*输出当前正在运行的PCB*/
   p=ready;  /*输出就绪队列PCB*/
   while(p!=NULL)
   {
      prt2(algo,p);
      p=p->next;
   }
   p=finish;  /*输出完成队列的PCB*/
   while(p!=NULL)
   {
      prt2(algo,p);
      p=p->next;
   }
   getch();  /*压任意键继续*/
}
/*优先数的插入算法*/
insert1(PCB *q)
{
   PCB *p1,*s,*r;
   int b;
   s=q;  /*待插入的PCB指针*/
   p1=ready; /*就绪队列头指针*/
   r=p1; /*r做p1的前驱指针*/
   b=1;
   while((p1!=NULL)&&b)  /*根据优先数确定插入位置*/
      if(p1->prio>=s->prio)
      {
  r=p1;
  p1=p1->next;
      }
      else
  b=0;
   if(r!=p1)  /*如果条件成立说明插入在r与p1之间*/
   {
      r->next=s;
      s->next=p1;
   }
   else
   {
      s->next=p1;  /*否则插入在就绪队列的头*/
      ready=s;
   }
}
/*轮转法插入函数*/
insert2(PCB *p2)
{
   tail->next=p2;  /*将新的PCB插入在当前就绪队列的尾*/
   tail=p2;
   p2->next=NULL;
}
/*优先数创建初始PCB信息*/
void create1(char alg)
{
   PCB *p;
   int i,time;
   char na[10];
   ready=NULL; /*就绪队列头指针*/
   finish=NULL;  /*完成队列头指针*/
   run=NULL; /*运行队列指针*/
   printf("Enter name and time of process/n"); /*输入进程标识和所需时间创建PCB*/
   for(i=1;i<=N;i++)
   {
      p=malloc(sizeof(PCB));
      scanf("%s",na);
      scanf("%d",&time);
      strcpy(p->name,na);
      p->cputime=0;
      p->needtime=time;
      p->state='w';
      p->prio=50-time;
      if(ready!=NULL) /*就绪队列不空调用插入函数插入*/
  insert1(p);
      else
      {
  p->next=ready; /*创建就绪队列的第一个PCB*/
  ready=p;
      }
   }
   clrscr();
   printf("          output of priority:/n");
   printf("************************************************/n");
   prt(alg);  /*输出进程PCB信息*/
   run=ready; /*将就绪队列的第一个进程投入运行*/
   ready=ready->next;
   run->state='R';
}
/*轮转法创建进程PCB*/
void create2(char alg)
{
   PCB *p;
   int i,time;
   char na[10];
   ready=NULL;
   finish=NULL;
   run=NULL;
   printf("Enter name and time of round process/n");
   for(i=1;i<=N;i++)
   {
      p=malloc(sizeof(PCB));
      scanf("%s",na);
      scanf("%d",&time);
      strcpy(p->name,na);
      p->cputime=0;
      p->needtime=time;
      p->count=0; /*计数器*/
      p->state='w';
      p->round=2;  /*时间片*/
      if(ready!=NULL)
  insert2(p);
      else
      {
  p->next=ready;
  ready=p;
  tail=p;
      }
   }
   clrscr();
   printf("              output of round/n");
   printf("************************************************/n");
   prt(alg);   /*输出进程PCB信息*/
   run=ready;  /*将就绪队列的第一个进程投入运行*/
   ready=ready->next;
   run->state='R';
}
/*优先数调度算法*/
priority(char alg)
{
   while(run!=NULL)  /*当运行队列不空时,有进程正在运行*/
   {
      run->cputime=run->cputime+1;
      run->needtime=run->needtime-1;
      run->prio=run->prio-3; /*每运行一次优先数降低3个单位*/
      if(run->needtime==0)  /*如所需时间为0将其插入完成队列*/
      {
  run->next=finish;
  finish=run;
  run->state='F';  /*置状态为完成态*/
  run=NULL;  /*运行队列头指针为空*/
  if(ready!=NULL) /*如就绪队列不空*/
     firstin(); /*将就绪对列的第一个进程投入运行*/
      }
      else /*没有运行完同时优先数不是最大,则将其变为就绪态插入到就绪队列*/
  if((ready!=NULL)&&(run->prio<ready->prio))
  {
     run->state='W';
     insert1(run);
     firstin(); /*将就绪队列的第一个进程投入运行*/
  }
      prt(alg); /*输出进程PCB信息*/
   }
}
/*时间片轮转法*/
roundrun(char alg)
{
   while(run!=NULL)
   {
      run->cputime=run->cputime+1;
      run->needtime=run->needtime-1;
      run->count=run->count+1;
      if(run->needtime==0)/*运行完将其变为完成态,插入完成队列*/
      {
  run->next=finish;
  finish=run;
  run->state='F';
  run=NULL;
  if(ready!=NULL)
     firstin(); /*就绪对列不空,将第一个进程投入运行*/
      }
      else
  if(run->count==run->round)  /*如果时间片到*/
  {
     run->count=0;  /*计数器置0*/
     if(ready!=NULL) /*如就绪队列不空*/
     {
        run->state='W'; /*将进程插入到就绪队列中等待轮转*/
        insert2(run);
        firstin(); /*将就绪对列的第一个进程投入运行*/
     }
  }
      prt(alg); /*输出进程信息*/
   }
}
/*主函数*/
main()
{
   char algo;  /*算法标记*/
   clrscr();
   printf("type the algorithm:P/R(priority/roundrobin)/n");
   scanf("%c",&algo); /*输入字符确定算法*/
   printf("Enter process number/n");
   scanf("%d",&N); /*输入进程数*/
   if(algo=='P'||algo=='p')
   {
      create1(algo); /*优先数法*/
      priority(algo);
   }
   else
      if(algo=='R'||algo=='r')
      {
  create2(algo); /*轮转法*/
  roundrun(algo);
      }
}


案例九 存储管理分区分配算法
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define MAX 32767
typedef struct node   /*设置分区描述器*/
{
   int address,size;
   struct node *next;
}RECT;
/*函数原型*/
RECT *assignment(RECT *head,int application);
void acceptment1(RECT *head,RECT *back1);
void acceptment2(RECT *head,RECT *back1) ;
int backcheck(RECT *head,RECT *back1);
void print(RECT *head);
/*变量声明*/
RECT *head,*back,*assign1,*p;
int application1,maxblocknum;
char way;
/*主函数*/
main()
{
   char choose[10];
   int check;
   head=malloc(sizeof(RECT)); /*建立可利用区表的初始状态*/
   p=malloc(sizeof(RECT));
   head->size=MAX;
   head->address=0;
   head->next=p;
   maxblocknum=1;
   p->size=MAX;
   p->address=0;
   p->next=NULL;
   print(head);  /*输出可利用表初始状态*/
   printf("Enter the way(best or first(b/f)/n");/*选择适应策略*/
   scanf("%c",&way);
   do{
      printf("Enter the assign or accept(as/ac)/n");
      scanf("%s",choose); /*选择分配或回收*/
      if(strcmp(choose,"as")==0) /*as为分配*/
      {
  printf("Input application:/n");
  scanf("%d",&application1);/*输入申请空间大小*/
  assign1=assignment(head,application1);/*调用分配函数*/
  if(assign1->address==-1)/*分配不成功*/
     printf("Too large application!,assign fails!!/n/n");
  else
     printf("Success!!ADDRESS=%5d/n",assign1->address); /*分配成功*/
  print(head); /*输出*/
      }
      else
  if(strcmp(choose,"ac")==0) /*回收*/
  {
     back=malloc(sizeof(RECT));
     printf("Input Adress and Size!!/n");
     scanf("%d%d",&back->address,&back->size);/*输入回收地址和大小*/
     check=backcheck(head,back); /*检查*/
     if(check==1)
     {
        if(tolower(way)=='f')/*首先适应算法*/
    acceptment1(head,back); /*首先适应*/
        else
    acceptment2(head,back);/*最佳适应*/
        print(head);
     }
  }
   }while(!strcmp(choose,"as")||!strcmp(choose,"ac"));
}
/*分配函数*/
RECT *assignment(RECT *head,int application)
{
   RECT *after,*before,*assign;
   assign=malloc(sizeof(RECT)); /*分配申请空间*/
   assign->size=application;
   assign->next=NULL;
   if(application>head->size||application<=0)
      assign->address=-1; /*申请无效*/
   else
   {
      before=head;
      after=head->next;
      while(after->size<application)/*查找适应的结点*/
      {
  before=before->next;
  after=after->next;
      }
      if(after->size==application) /*结点大小等于申请大小则完全分配*/
      {
  if(after->size==head->size)
     maxblocknum--;
  before->next=after->next;
  assign->address=after->address;
  free(after);
      }
      else
      {
  if(after->size==head->size) maxblocknum--;
  after->size=after->size-application; /*大于申请空间则截取相应大小分配*/
  assign->address=after->address+after->size;
  if(tolower(way)=='b')/*如果是最佳适应,将截取后剩余结点重新回收到合适位置*/
  {
     before->next=after->next;
     back=after;
     acceptment2(head,back);
  }
      }
      if(maxblocknum==0) /*修改最大数和头结点值*/
      {
  before=head;
  head->size=0;
  maxblocknum=1;
  while(before!=NULL)
  {
     if(before->size>head->size)
     {
        head->size=before->size;
        maxblocknum=1;
     }
     else
        if(before->size==head->size)
    maxblocknum++;
     before=before->next;
  }
      }
   }
   assign1=assign;
   return assign1; /*返回分配给用户的地址*/
}
void acceptment1(RECT *head,RECT *back1)/*首先适应*/
{
   RECT *before,*after;
   int insert;
   before=head;
   after=head->next;
   insert=0;
   while(!insert) /*将回收区插入空闲区表*/
   {
      if((after==NULL)||
  ((back1->address<=after->address)&&
    (back1->address>=before->address)))
      {
  before->next=back1;
  back1->next=after;
  insert=1;
      }
      else
      {
  before=before->next;
  after=after->next;
      }
   }
   if(back1->address==before->address+before->size)/*与上一块合并*/
   {
      before->size=before->size+back1->size;
      before->next=back1->next;
      free(back1);
      back1=before;
   }
   if(after!=NULL&&(after->address==back1->address+back1->size))
   {  /*与下一块合并*/
      back1->size=back1->size+after->size;
      back1->next=after->next;
      free(after);
   }
   if(head->size<back1->size) /*修改最大块值和最大块个数*/
   {
      head->size=back1->size;
      maxblocknum=1;
   }
   else
      if(head->size==back1->size)
  maxblocknum++;
}
/*最佳适应,back1为回收结点的地址*/
void acceptment2(RECT *head,RECT *back1)
{
   RECT *before,*after;
   int insert ;
   insert=0;
   before=head;
   after=head->next;
   if(head->next==NULL) /*如果可利用区表为空*/
   {
      head->size=back1->size;
      head->next=back1;
      maxblocknum++;
      back1->next=NULL;
   }
   else
   {
      while(after!=NULL) /*与上一块合并*/
      if(back1->address==after->size+after->address)
      {
  before->next=after->next;
  back->size=after->size+back1->size;
  free(after);
  after=NULL;
      }
      else
      {
  after=after->next;
  before=before->next;
      }
      before=head;
      after=head->next;
      while(after!=NULL)
      if(after->address==back1->size+back1->address) /*与下一块合并*/
      {
  back1->size=back1->size+after->size;
  before->next=after->next;
  free(after);
  after=NULL;
      }
      else
      {
  before=before->next;
  after=after->next;
      }
      before=head;/*将回收结点插入到合适的位置*/
      after=head->next;
      do{
  if(after==NULL||(after->size>back1->size))
  {
     before->next=back1;
     back1->next=after;
     insert=1;
  }
  else
  {
     before=before->next;
     after=after->next;
  }
      }while(!insert);
      if(head->size<back1->size) /*修改最大块值和最大块数*/
      {
  head->size=back1->size;
  maxblocknum++;
      }
      else
  if(head->size==back1->size)
     maxblocknum++;
   }
}

void print(RECT *head) /*输出链表*/
{
   RECT *before,*after;
   int index,k;
   before=head->next;
   index=1;
   if(head->next==NULL)
      printf("NO part for assignment!!/n");
   else
   {
      printf("*****index*******address********end*********size*****/n");
      while(before!=NULL)
      {
  printf("----------------------------------------------------/n");
  printf("     %-13d%-13d%-13d%-13d/n",index,before->address,before->address+before->size-1,before->size);
  printf("----------------------------------------------------/n");
  index++;
  before=before->next;
      }
   }
}
/*检查回收块的合法性,back1为要回收的结点地址*/
int backcheck(RECT *head,RECT *back1)
{
   RECT *before,*after;
   int check=1;
   if(back1->address<0||back1->size<0)
      check=0;/*地址和大小不能为负*/
   before=head->next;
   while((before!=NULL)&&check)/*地址不能和空闲区表中结点出现重叠*/
      if(((back1->address<before->address)
  &&(back1->address+back1->size>before->address))
  ||((back1->address>=before->address)
 &&(back1->address<before->address+before->size)))
  check=0;
      else
  before=before->next;
   if(check==0)
      printf("Error input!!/n");
   return check;  /*返回检查结果*/
}


案例十 通讯录
#include "stdio.h"   /*I/O函数*/
#include "stdlib.h" /*标准库函数*/
#include "string.h"/*字符串函数*/
#include "ctype.h" /*字符操作函数*/
#define M 50  /*定义常数表示记录数*/
typedef struct /*定义数据结构*/
{
   char name[20]; /*姓名*/
   char units[30];  /*单位*/
   char tele[10];  /*电话*/
}ADDRESS;
/******以下是函数原型*******/
int enter(ADDRESS t[]); /*输入记录*/
void list(ADDRESS t[],int n); /*显示记录*/
void search(ADDRESS t[],int n); /*按姓名查找显示记录*/
int delete(ADDRESS t[],int n); /*删除记录*/
int  add(ADDRESS t[],int n); /*插入记录*/
void save(ADDRESS t[],int n); /*记录保存为文件*/
int load(ADDRESS t[]);  /*从文件中读记录*/
void display(ADDRESS t[]); /*按序号查找显示记录*/
void sort(ADDRESS t[],int n); /*按姓名排序*/
void qseek(ADDRESS t[],int n); /*快速查找记录*/
void copy();  /*文件复制*/
void print(ADDRESS temp); /*显示单条记录*/
int find(ADDRESS t[],int n,char *s) ; /*查找函数*/
int menu_select();  /*主菜单函数*/
/******主函数开始*******/
main()
{
   int i;
   ADDRESS adr[M];  /*定义结构体数组*/
   int length;  /*保存记录长度*/
   clrscr();  /*清屏*/
   for(;;)/*无限循环*/
   {
      switch(menu_select())   /*调用主菜单函数,返回值整数作开关语句的条件*/
      {
  case 0:length=enter(adr);break;/*输入记录*/
  case 1:list(adr,length);break; /*显示全部记录*/
  case 2:search(adr,length);break; /*查找记录*/
  case 3:length=delete(adr,length);break; /*删除记录*/
  case 4:length=add(adr,length);  break;   /*插入记录*/
  case 5:save(adr,length);break; /*保存文件*/
  case 6:length=load(adr); break; /*读文件*/
  case 7:display(adr);break;  /*按序号显示记录*/
  case 8:sort(adr,length);break; /*按姓名排序*/
  case 9:qseek(adr,length);break; /*快速查找记录*/
  case 10:copy();break; /*复制文件*/
  case 11:exit(0); /*如返回值为11则程序结束*/
      }
   }
}
/*菜单函数,函数返回值为整数,代表所选的菜单项*/
menu_select()
{
   char s[80];
   int c;
   gotoxy(1,25);/*将光标定为在第25行,第1列*/
   printf("press any key enter menu....../n");/*提示压任意键继续*/
   getch(); /*读入任意字符*/
   clrscr(); /*清屏*/
   gotoxy(1,1);
   printf("********************MENU*********************/n/n");
   printf("  0. Enter record/n");
   printf("  1. List the file/n");
   printf("  2. Search record on name/n");
   printf("  3. Delete a record/n");
   printf("  4. add record /n");
   printf("  5. Save the file/n");
   printf("  6. Load the file/n");
   printf("  7. display record on order/n");
   printf("         8. sort to make new file/n");
   printf("         9. Quick seek record/n");
   printf("  10. copy the file to new file/n");
   printf("         11. Quit/n");
   printf("***********************************************/n");
   do{
      printf("/n  Enter you choice(0~11):"); /*提示输入选项*/
      scanf("%s",s); /*输入选择项*/
      c=atoi(s); /*将输入的字符串转化为整型数*/
   }while(c<0||c>11); /*选择项不在0~11之间重输*/
   return c; /*返回选择项,主程序根据该数调用相应的函数*/
}
/***输入记录,形参为结构体数组,函数值返回类型为整型表示记录长度*/
int  enter(ADDRESS t[])
{
   int i,n;
   char *s;
   clrscr(); /*清屏*/
   printf("/nplease input num /n"); /*提示信息*/
   scanf("%d",&n); /*输入记录数*/
   printf("please input record /n"); /*提示输入记录*/
   printf("name             unit                     telephone/n");
   printf("------------------------------------------------/n");
   for(i=0;i<n;i++)
   {
      scanf("%s%s%s",t[i].name,t[i].units,t[i].tele);  /*输入记录*/
      printf("----------------------------------------------/n");
   }
   return n;  /*返回记录条数*/
}
/*显示记录,参数为记录数组和记录条数*/
void list(ADDRESS t[],int n)
{
   int i;
   clrscr();
   printf("/n/n*******************ADDRESS******************/n");
   printf("name               unit                     telephone/n");
   printf("------------------------------------------------/n");
   for(i=0;i<n;i++)
   printf("%-20s%-30s%-10s/n",t[i].name,t[i].units,t[i].tele);
   if((i+1)%10==0)   /*判断输出是否达到10条记录*/
   {
      printf("Press any key continue.../n"); /*提示信息*/
      getch();  /*压任意键继续*/
   }
   printf("************************end*******************/n");
}
/*查找记录*/
void search(ADDRESS t[],int n)
{
   char s[20];   /*保存待查找姓名字符串*/
   int i;   /*保存查找到结点的序号*/
   clrscr();   /*清屏*/
   printf("please search name/n");
   scanf("%s",s); /*输入待查找姓名*/
   i=find(t,n,s); /*调用find函数,得到一个整数*/
   if(i>n-1)  /*如果整数i值大于n-1,说明没找到*/
      printf("not found/n");
   else
      print(t[i]);  /*找到,调用显示函数显示记录*/
}
/*显示指定的一条记录*/
void print(ADDRESS temp)
{
   clrscr();
   printf("/n/n********************************************/n");
   printf("name                unit                      telephone/n");
   printf("------------------------------------------------/n");
   printf("%-20s%-30s%-10s/n",temp.name,temp.units,temp.tele);
   printf("**********************end***********************/n");
}
/*查找函数,参数为记录数组和记录条数以及姓名s */
int find(ADDRESS t[],int n,char *s)
{
   int i;
   for(i=0;i<n;i++)/*从第一条记录开始,直到最后一条*/
   {
      if(strcmp(s,t[i].name)==0)  /*记录中的姓名和待比较的姓名是否相等*/
      return i;   /*相等,则返回该记录的下标号,程序提前结结束*/
   }
   return i;  /*返回i值*/
}
/*删除函数,参数为记录数组和记录条数*/
int delete(ADDRESS t[],int n)
{
   char s[20];  /*要删除记录的姓名*/
   int ch=0;
   int i,j;
   printf("please deleted name/n"); /*提示信息*/
   scanf("%s",s);/*输入姓名*/
   i=find(t,n,s); /*调用find函数*/
   if(i>n-1)  /*如果i>n-1超过了数组的长度*/
      printf("no found not deleted/n"); /*显示没找到要删除的记录*/
   else
   {
      print(t[i]); /*调用输出函数显示该条记录信息*/
      printf("Are you sure delete it(1/0)/n");  /*确认是否要删除*/
      scanf("%d",&ch);  /*输入一个整数0或1*/
      if(ch==1)  /*如果确认删除整数为1*/
      {
  for(j=i+1;j<n;j++)  /*删除该记录,实际后续记录前移*/
  {
     strcpy(t[j-1].name,t[j].name); /*将后一条记录的姓名拷贝到前一条*/
     strcpy(t[j-1].units,t[j].units); /*将后一条记录的单位拷贝到前一条*/
     strcpy(t[j-1].tele,t[j].tele); /*将后一条记录的电话拷贝到前一条*/
  }
  n--;  /*记录数减1*/
      }
   }
   return n;  /*返回记录数*/
}
/*插入记录函数,参数为结构体数组和记录数*/
int add(ADDRESS t[],int n)/*插入函数,参数为结构体数组和记录数*/
{
   ADDRESS temp;  /*新插入记录信息*/
   int i,j;
   char s[20]; /*确定插入在哪个记录之前*/
   printf("please input record/n");
   printf("************************************************/n");
   printf("name                unit                      telephone/n");
   printf("--------------------------------------------------/n");
   scanf("%s%s%s",temp.name,temp.units,temp.tele); /*输入插入信息*/
   printf("------------------------------------------------/n");
   printf("please input locate name /n");
   scanf("%s",s); /*输入插入位置的姓名*/
   i=find(t,n,s);  /*调用find,确定插入位置*/
   for(j=n-1;j>=i;j--)   /*从最后一个结点开始向后移动一条*/
   {
      strcpy(t[j+1].name,t[j].name); /*当前记录的姓名拷贝到后一条*/
      strcpy(t[j+1].units,t[j].units); /*当前记录的单位拷贝到后一条*/
      strcpy(t[j+1].tele,t[j].tele); /*当前记录的电话拷贝到后一条*/
   }
   strcpy(t[i].name,temp.name); /*将新插入记录的姓名拷贝到第i个位置*/
   strcpy(t[i].units,temp.units); /*将新插入记录的单位拷贝到第i个位置*/
   strcpy(t[i].tele,temp.tele); /*将新插入记录的电话拷贝到第i个位置*/
   n++;   /*记录数加1*/
   return n; /*返回记录数*/
}
/*保存函数,参数为结构体数组和记录数*/
void save(ADDRESS t[],int n)
{
   int i;
   FILE *fp;  /*指向文件的指针*/
   if((fp=fopen("record.txt","wb"))==NULL)  /*打开文件,并判断打开是否正常*/
   {
      printf("can not open file/n");/*没打开*/
      exit(1);  /*退出*/
   }
   printf("/nSaving file/n"); /*输出提示信息*/
   fprintf(fp,"%d",n);  /*将记录数写入文件*/
   fprintf(fp,"/r/n");  /*将换行符号写入文件*/
   for(i=0;i<n;i++)
   {
      fprintf(fp,"%-20s%-30s%-10s",t[i].name,t[i].units,t[i].tele);/*格式写入记录*/
      fprintf(fp,"/r/n"); /*将换行符号写入文件*/
   }
   fclose(fp);/*关闭文件*/
   printf("****save success***/n"); /*显示保存成功*/
}
/*读入函数,参数为结构体数组*/
int load(ADDRESS t[])
{
   int i,n;
   FILE *fp; /*指向文件的指针*/
   if((fp=fopen("record.txt","rb"))==NULL)/*打开文件*/
   {
      printf("can not open file/n");  /*不能打开*/
      exit(1);  /*退出*/
   }
   fscanf(fp,"%d",&n); /*读入记录数*/
   for(i=0;i<n;i++)
      fscanf(fp,"%20s%30s%10s",t[i].name,t[i].units,t[i].tele); /*按格式读入记录*/
   fclose(fp);  /*关闭文件*/
   printf("You have success read data from file!!!/n"); /*显示保存成功*/
   return n; /*返回记录数*/
}
/*按序号显示记录函数*/
void display(ADDRESS t[])
{
   int id,n;
   FILE *fp; /*指向文件的指针*/
   if((fp=fopen("record.txt","rb"))==NULL) /*打开文件*/
   {
      printf("can not open file/n"); /*不能打开文件*/
      exit(1);  /*退出*/
   }
   printf("Enter order number.../n"); /*显示信息*/
   scanf("%d",&id);  /*输入序号*/
   fscanf(fp,"%d",&n); /*从文件读入记录数*/
   if(id>=0&&id<n) /*判断序号是否在记录范围内*/
   {
      fseek(fp,(id-1)*sizeof(ADDRESS),1); /*移动文件指针到该记录位置*/
      print(t[id]); /*调用输出函数显示该记录*/
      printf("/r/n");
   }
   else
      printf("no %d number record!!!/n ",id); /*如果序号不合理显示信息*/
   fclose(fp);  /*关闭文件*/
}
/*排序函数,参数为结构体数组和记录数*/
void sort(ADDRESS t[],int n)
{
   int i,j,flag;
   ADDRESS temp; /*临时变量做交换数据用*/
   for(i=0;i<n;i++)
   {
      flag=0;  /*设标志判断是否发生过交换*/
      for(j=0;j<n-1;j++)
      if((strcmp(t[j].name,t[j+1].name))>0) /*比较大小*/
      {
  flag=1;
  strcpy(temp.name,t[j].name);  /*交换记录*/
  strcpy(temp.units,t[j].units);
  strcpy(temp.tele,t[j].tele);
  strcpy(t[j].name,t[j+1].name);
  strcpy(t[j].units,t[j+1].units);
  strcpy(t[j].tele,t[j+1].tele);
  strcpy(t[j+1].name,temp.name);
  strcpy(t[j+1].units,temp.units);
  strcpy(t[j+1].tele,temp.tele);
      }
      if(flag==0)break;  /*如果标志为0,说明没有发生过交换循环结束*/
   }
   printf("sort sucess!!!/n"); /*显示排序成功*/
}
/*快速查找,参数为结构体数组和记录数*/
void qseek(ADDRESS t[],int n)
{
   char s[20];
   int l,r,m;
   printf("/nPlease  sort before qseek!/n"); /*提示确认在查找之前,记录是否已排序*/
   printf("please enter  name for qseek/n"); /*提示输入*/
   scanf("%s",s); /*输入待查找的姓名*/
   l=0;r=n-1;  /*设置左边界与右边界的初值*/
   while(l<=r) /*当左边界<=右边界时*/
   {
      m=(l+r)/2; /*计算中间位置*/
      if(strcmp(t[m].name,s)==0) /*与中间结点姓名字段做比较判是否相等*/
      {
  print(t[m]); /*如果相等,则调用print函数显示记录信息*/
  return ; /*返回*/
      }
      if(strcmp(t[m].name,s)<0)  /*如果中间结点小*/
  l=m+1;  /*修改左边界*/
      else
  r=m-1; /*否则,中间结点大,修改右边界*/
   }
   if(l>r)   /*如果左边界大于右边界时*/
      printf("not found/n"); /*显示没找到*/
}
/*复制文件*/
void copy()
{
   char outfile[20]; /*目标文件名*/
   int i,n;
   ADDRESS temp[M];  /*定义临时变量*/
   FILE *sfp,*tfp; /*定义指向文件的指针*/
   clrscr();/*清屏*/
   if((sfp=fopen("record.txt","rb"))==NULL) /*打开记录文件*/
   {
      printf("can not open file/n"); /*显示不能打开文件信息*/
      exit(1); /*退出*/
   }
   printf("Enter outfile name,for example c://f1//te.txt:/n"); /*提示信息*/
   scanf("%s",outfile); /*输入目标文件名*/
   if((tfp=fopen(outfile,"wb"))==NULL) /*打开目标文件*/
   {
      printf("can not open file/n"); /*显示不能打开文件信息*/
      exit(1); /*退出*/
   }
   fscanf(sfp,"%d",&n); /*读出文件记录数*/
   fprintf(tfp,"%d",n);/*写入目标文件数*/
   fprintf(tfp,"/r/n"); /*写入换行符*/
   for(i=0;i<n;i++)
   {
      fscanf(sfp,"%20s%30s%10s/n",temp[i].name,temp[i].units,
 temp[i].tele); /*读入记录*/
      fprintf(tfp,"%-20s%-30s%-10s/n",temp[i].name,
 temp[i].units,temp[i].tele); /*写入记录*/
      fprintf(tfp,"/r/n"); /*写入换行符*/
   }
   fclose(sfp); /*关闭源文件*/
   fclose(tfp); /*关闭目标文件*/
   printf("you have success copy  file!!!/n"); /*显示复制成功*/
}


案例十一 学生成绩管理
#include "stdio.h"    /*I/O函数*/
#include "stdlib.h"   /*其它说明*/
#include "string.h"   /*字符串函数*/
#include "conio.h"   /*屏幕操作函数*/
#include "mem.h"   /*内存操作函数*/
#include "ctype.h"   /*字符操作函数*/
#include "alloc.h"   /*动态地址分配函数*/
#define N 3       /*定义常数*/
typedef struct z1   /*定义数据结构*/
{
   char no[11];
   char name[15];
   int score[N];
   float sum;
   float average;
   int order;
   struct z1 *next;
 }STUDENT;
/*以下是函数原型*/
STUDENT  *init();      /*初始化函数*/
STUDENT *create();   /*创建链表*/
STUDENT *delete(STUDENT *h);   /*删除记录*/
void print(STUDENT *h);   /* 显示所有记录*/
void search(STUDENT *h);    /*查找*/
void save(STUDENT *h);     /*保存*/
STUDENT *load();        /*读入记录*/
void computer(STUDENT *h);  /*计算总分和均分*/
STUDENT *insert(STUDENT *h);   /*插入记录*/
void append();            /*追加记录*/
void copy();            /*复制文件*/
STUDENT *sort(STUDENT *h);    /*排序*/
STUDENT *index(STUDENT *h);  /*索引*/
void total(STUDENT *h);       /*分类合计*/
int menu_select();            /*菜单函数*/
/******主函数开始*******/
main()
{
   int i;
   STUDENT *head;     /*链表定义头指针*/
   head=init();          /*初始化链表*/
   clrscr();            /*清屏*/
   for(;;)             /*无限循环*/
   {
      switch(menu_select())     /*调用主菜单函数,返回值整数作开关语句的条件*/
      {                     /*值不同,执行的函数不同,break 不能省略*/
  case 0:head=init();break;   /*执行初始化*/
  case 1:head=create();break; /*创建链表*/
  case 2:head=delete(head);break; /*删除记录*/
  case 3:print(head);break;   /*显示全部记录*/
  case 4:search(head);break;  /*查找记录*/
  case 5:save(head);break;  /*保存文件*/
  case 6:head=load(); break;  /*读文件*/
  case 7:computer(head);break;  /*计算总分和均分*/
  case 8:head=insert(head);  break; /*插入记录*/
  case 9:copy();break;    /*复制文件*/
  case 10:head=sort(head);break;  /*排序*/
  case 11:append();break;     /*追加记录*/
  case 12:head=index(head);break;  /*索引*/
  case 13:total(head);break;   /*分类合计*/
  case 14:exit(0);       /*如菜单返回值为14程序结束*/
      }
   }
}
/*菜单函数,返回值为整数*/
menu_select()
{
   char *menu[]={"***************MENU***************",  /*定义菜单字符串数组*/
   " 0. init list",    /*初始化*/
   " 1. Enter list",   /*输入记录*/
   " 2. Delete a record from list",  /*从表中删除记录*/
   " 3. print list ",       /*显示单链表中所有记录*/
   " 4. Search record on name",   /*按照姓名查找记录*/
   " 5. Save the file",          /*将单链表中记录保存到文件中*/
   " 6. Load the file",        /*从文件中读入记录*/
   " 7. compute the score",    /*计算所有学生的总分和均分*/
   " 8. insert record to list ",   /*插入记录到表中*/
   " 9. copy the file to new file",   /*复制文件*/
   " 10. sort to make new file",   /*排序*/
   " 11. append  record to file",   /*追加记录到文件中*/
   " 12. index on nomber",       /*索引*/
   " 13. total on nomber",      /*分类合计*/
   " 14. Quit"};              /*退出*/
   char s[3];       /*以字符形式保存选择号*/
   int c,i;        /*定义整形变量*/
   gotoxy(1,25);        /*移动光标*/
   printf("press any key enter menu....../n");   /*压任一键进入主菜单*/
   getch();                       /*输入任一键*/
   clrscr();                     /*清屏幕*/
   gotoxy(1,1);             /*移动光标*/
   textcolor(YELLOW);   /*设置文本显示颜色为黄色*/
   textbackground(BLUE);   /*设置背景颜色为蓝色*/
   gotoxy(10,2);          /*移动光标*/
   putch(0xc9);        /*输出左上角边框┏*/
   for(i=1;i<44;i++)
      putch(0xcd);    /*输出上边框水平线*/
   putch(0xbb);            /*输出右上角边框  ┓*/
   for(i=3;i<20;i++)
   {
      gotoxy(10,i);putch(0xba);   /*输出左垂直线*/
      gotoxy(54,i);putch(0xba);
   }   /*输出右垂直线*/
   gotoxy(10,20);putch(0xc8);  /*输出左上角边框┗*/
   for(i=1;i<44;i++)
      putch(0xcd);      /*输出下边框水平线*/
   putch(0xbc);                 /*输出右下角边框┛*/
   window(11,3,53,19);       /* 制作显示菜单的窗口,大小根据菜单条数设计*/
   clrscr();              /*清屏*/
   for(i=0;i<16;i++)       /*输出主菜单数组*/
   {
      gotoxy(10,i+1);
      cprintf("%s",menu[i]);
   }
   textbackground(BLACK);   /*设置背景颜色为黑色*/
   window(1,1,80,25);       /*恢复原窗口大小*/
   gotoxy(10,21);       /*移动光标*/
   do{
      printf("/n  Enter you choice(0~14):");    /*在菜单窗口外显示提示信息*/
      scanf("%s",s);           /*输入选择项*/
      c=atoi(s);            /*将输入的字符串转化为整形数*/
   }while(c<0||c>14);    /*选择项不在0~14之间重输*/
   return c;              /*返回选择项,主程序根据该数调用相应的函数*/
}
STUDENT *init()
{
   return NULL;
}

/*创建链表*/
STUDENT *create()
{
   int i; int s;
   STUDENT *h=NULL,*info;  /* STUDENT指向结构体的指针*/
   for(;;)
   {
      info=(STUDENT *)malloc(sizeof(STUDENT));  /*申请空间*/
      if(!info)   /*如果指针info为空*/
      {
  printf("/nout of memory");   /*输出内存溢出*/
  return NULL;           /*返回空指针*/
      }
      inputs("enter no:",info->no,11);   /*输入学号并校验*/
      if(info->no[0]=='@') break;    /*如果学号首字符为@则结束输入*/
      inputs("enter name:",info->name,15); /*输入姓名,并进行校验*/
      printf("please input %d score /n",N);  /*提示开始输入成绩*/
      s=0;         /*计算每个学生的总分,初值为0*/
      for(i=0;i<N;i++)    /*N门课程循环N次*/
      {
  do{
     printf("score%d:",i+1);    /*提示输入第几门课程*/
     scanf("%d",&info->score[i]);    /*输入成绩*/
     if(info->score[i]>100||info->score[i]<0) /*确保成绩在0~100之间*/
     printf("bad data,repeat input/n");  /*出错提示信息*/
  }while(info->score[i]>100||info->score[i]<0);
  s=s+info->score[i];   /*累加各门课程成绩*/
      }
      info->sum=s;    /*将总分保存*/
      info->average=(float)s/N;  /*求出平均值*/
      info->order=0;    /*未排序前此值为0*/
      info->next=h;   /*将头结点做为新输入结点的后继结点*/
      h=info;    /*新输入结点为新的头结点*/
   }
   return(h);   /*返回头指针*/
}
/*输入字符串,并进行长度验证*/
inputs(char *prompt, char *s, int count)
{
   char p[255];
   do{
      printf(prompt);  /*显示提示信息*/
      scanf("%s",p);  /*输入字符串*/
      if(strlen(p)>count)printf("/n too long! /n"); /*进行长度校验,超过count值重输入*/
   }while(strlen(p)>count);
   strcpy(s,p); /*将输入的字符串拷贝到字符串s中*/
}
/*输出链表中结点信息*/
void print(STUDENT *h)
{
   int i=0;     /* 统计记录条数*/
   STUDENT *p;  /*移动指针*/
   clrscr();     /*清屏*/
   p=h;      /*初值为头指针*/
   printf("/n/n/n****************************STUDENT********************************/n");
   printf("|rec|nO        |      name     | sc1| sc2| sc3|   sum  |  ave  |order|/n");
   printf("|---|----------|---------------|----|----|----|--------|-------|-----|/n");
   while(p!=NULL)
   {
       i++;
       printf("|%3d |%-10s|%-15s|%4d|%4d|%4d| %4.2f | %4.2f | %3d |/n", i, p->no,p->name,p->score[0],p->score[1],
p->score[2],p->sum,p->average,p->order);
       p=p->next;
   }
   printf("**********************************end*********************************/n");
}
/*删除记录*/
STUDENT *delete(STUDENT *h)
{
   STUDENT *p,*q;  /*p为查找到要删除的结点指针,q为其前驱指针*/
   char s[11];     /*存放学号*/
   clrscr();       /*清屏*/
   printf("please deleted no/n");      /*显示提示信息*/
   scanf("%s",s);   /*输入要删除记录的学号*/
   q=p=h;    /*给q和p赋初值头指针*/
   while(strcmp(p->no,s)&&p!=NULL)   /*当记录的学号不是要找的,或指针不为空时*/
   {
      q=p;       /*将p指针值赋给q作为p的前驱指针*/
      p=p->next;      /*将p指针指向下一条记录*/
   }
   if(p==NULL)     /*如果p为空,说明链表中没有该结点*/
      printf("/nlist no %s student/n",s);
   else       /*p不为空,显示找到的记录信息*/
   {
      printf("*****************************have found***************************/n");
      printf("|no        |      name     | sc1| sc2| sc3|   sum  |  ave  |order|/n");
      printf("|----------|---------------|----|----|----|--------|-------|-----|/n");
      printf("|%-10s|%-15s|%4d|%4d|%4d| %4.2f | %4.2f | %3d |/n", p->no,
       p->name,p->score[0],p->score[1],p->score[2],p->sum,
       p->average,p->order);
      printf("********************************end*******************************/n");
      getch();      /*压任一键后,开始删除*/
      if(p==h)    /*如果p==h,说明被删结点是头结点*/
  h=p->next;     /*修改头指针指向下一条记录*/
      else
  q->next=p->next; /*不是头指针,将p的后继结点作为q的后继结点*/
      free(p);          /*释放p所指结点空间*/
      printf("/n have deleted No %s student/n",s);
      printf("Don't forget save/n");/*提示删除后不要忘记保存文件*/
   }
   return(h);      /*返回头指针*/
}
/*查找记录*/
void search(STUDENT *h)
{
   STUDENT *p;    /*  移动指针*/
   char s[15];    /*存放姓名的字符数组*/
   clrscr();    /*清屏幕*/
   printf("please enter name for search/n");
   scanf("%s",s);    /*输入姓名*/
   p=h;    /*将头指针赋给p*/
   while(strcmp(p->name,s)&&p!=NULL)  /*当记录的姓名不是要找的,或指针不为空时*/
   p=p->next;     /*移动指针,指向下一结点*/
   if(p==NULL)         /*如果指针为空*/
      printf("/nlist no %s student/n",s);   /*显示没有该学生*/
   else           /*显示找到的记录信息*/
   {
      printf("/n/n*****************************havefound***************************/n");
      printf("|nO        |      name     | sc1| sc2| sc3|   sum  |  ave  |order|/n");
      printf("|----------|---------------|----|----|----|--------|-------|-----|/n");
      printf("|%-10s|%-15s|%4d|%4d|%4d| %4.2f | %4.2f | %3d |/n", p->no,
p->name,p->score[0],p->score[1],p->score[2],p->sum,p->average,p->order);
      printf("********************************end*******************************/n");
   }
}
/*插入记录*/
STUDENT  *insert(STUDENT *h)
{
   STUDENT *p,*q,*info; /*p指向插入位置,q是其前驱,info指新插入记录*/
   char s[11];  /*保存插入点位置的学号*/
   int s1,i;
   printf("please enter location  before the no/n");
   scanf("%s",s);   /*输入插入点学号*/
   printf("/nplease new record/n");      /*提示输入记录信息*/
   info=(STUDENT *)malloc(sizeof(STUDENT));   /*申请空间*/
   if(!info)
   {
      printf("/nout of memory");   /*如没有申请到,内存溢出*/
      return NULL;             /*返回空指针*/
   }
   inputs("enter no:",info->no,11); /*输入学号*/
   inputs("enter name:",info->name,15); /*输入姓名*/
   printf("please input %d score /n",N);  /*提示输入分数*/
   s1=0;    /*保存新记录的总分,初值为0*/
   for(i=0;i<N;i++)    /*N门课程循环N次输入成绩*/
   {
      do{        /*对数据进行验证,保证在0~100之间*/
  printf("score%d:",i+1);
  scanf("%d",&info->score[i]);
  if(info->score[i]>100||info->score[i]<0)
     printf("bad data,repeat input/n");
      }while(info->score[i]>100||info->score[i]<0);
      s1=s1+info->score[i];    /*计算总分*/
   }
   info->sum=s1;    /*将总分存入新记录中*/
   info->average=(float)s1/N;  /*计算均分*/
   info->order=0;         /*名次赋值0*/
   info->next=NULL;     /*设后继指针为空*/
   p=h;               /*将指针赋值给p*/
   q=h;             /*将指针赋值给q*/
   while(strcmp(p->no,s)&&p!=NULL)    /*查找插入位置*/
   {
      q=p;                 /*保存指针p,作为下一个p的前驱*/
      p=p->next;          /*将指针p后移*/
   }
   if(p==NULL)      /*如果p指针为空,说明没有指定结点*/
      if(p==h)      /*同时p等于h,说明链表为空*/
  h=info;   /*新记录则为头结点*/
      else
  q->next=info;  /*p为空,但p不等于h,将新结点插在表尾*/
   else
      if(p==h)     /*p不为空,则找到了指定结点*/
      {
  info->next=p; /*如果p等于h,则新结点插入在第一个结点之前*/
  h=info;    /*新结点为新的头结点*/
      }
      else
      {
  info->next=p;   /*不是头结点,则是中间某个位置,新结点的后继为p*/
  q->next=info;  /*新结点作为q的后继结点*/
      }
   printf("/n ----have inserted %s student----/n",info->name);    printf("---Don't forget save---/n");     /*提示存盘*/
   return(h);         /*返回头指针*/
}
/*保存数据到文件*/
void save(STUDENT *h)
{
   FILE *fp;         /*定义指向文件的指针*/
   STUDENT *p;    /* 定义移动指针*/
   char outfile[10];  /*保存输出文件名*/
   printf("Enter outfile name,for example c://f1//te.txt:/n"); /*提示文件名格式信息*/
   scanf("%s",outfile);
   if((fp=fopen(outfile,"wb"))==NULL) /*为输出打开一个二进制文件,如没有则建立*/
   {
      printf("can not open file/n");
      exit(1);
   }
   printf("/nSaving file....../n");  /*打开文件,提示正在保存*/
   p=h;                    /*移动指针从头指针开始*/
   while(p!=NULL)        /*如p不为空*/
   {
      fwrite(p,sizeof(STUDENT),1,fp);/*写入一条记录*/
      p=p->next;        /*指针后移*/
   }
   fclose(fp);      /*关闭文件*/
   printf("-----save success!!-----/n");  /*显示保存成功*/
}
/* 从文件读数据*/
STUDENT *load()
{
   STUDENT *p,*q,*h=NULL;    /*定义记录指针变量*/
   FILE *fp;            /* 定义指向文件的指针*/
   char infile[10];       /*保存文件名*/
   printf("Enter infile name,for example c://f1//te.txt:/n");   scanf("%s",infile);           /*输入文件名*/
   if((fp=fopen(infile,"rb"))==NULL)   /*打开一个二进制文件,为读方式*/
   {
      printf("can not open file/n");    /*如不能打开,则结束程序*/
      exit(1);
   }
   printf("/n -----Loading file!-----/n");
   p=(STUDENT *)malloc(sizeof(STUDENT));   /*申请空间*/
   if(!p)
   {
      printf("out of memory!/n");    /*如没有申请到,则内存溢出*/
      return h;       /*返回空头指针*/
   }
   h=p;         /*申请到空间,将其作为头指针*/
   while(!feof(fp))  /*循环读数据直到文件尾结束*/
   {
      if(1!=fread(p,sizeof(STUDENT),1,fp))
  break;  /*如果没读到数据,跳出循环*/
      p->next=(STUDENT *)malloc(sizeof(STUDENT));  /*为下一个结点申请空间*/
      if(!p->next)
      {
  printf("out of memory!/n");  /*如没有申请到,则内存溢出*/
  return h;
      }
      q=p;   /*保存当前结点的指针,作为下一结点的前驱*/
      p=p->next;   /*指针后移,新读入数据链到当前表尾*/
   }
   q->next=NULL;   /*最后一个结点的后继指针为空*/
   fclose(fp);       /*关闭文件*/
   printf("---You have success read data from file!!!---/n");
   return h;   /*返回头指针*/
}
/*追加记录到文件*/
void append()
{
   FILE *fp;      /*定义指向文件的指针*/
   STUDENT *info;    /*新记录指针*/
   int s1,i;
   char infile[10];    /*保存文件名*/
   printf("/nplease new record/n");
   info=(STUDENT *)malloc(sizeof(STUDENT));   /*申请空间*/
   if(!info)
   {
      printf("/nout of memory");   /*没有申请到,内存溢出本函数结束*/
      return ;
   }
   inputs("enter no:",info->no,11);    /*调用inputs输入学号*/
   inputs("enter name:",info->name,15); /*调用inputs输入姓名*/
   printf("please input %d score /n",N);   /*提示输入成绩*/
   s1=0;
   for(i=0;i<N;i++)
   {
      do{
  printf("score%d:",i+1);
  scanf("%d",&info->score[i]);  /*输入成绩*/
  if(info->score[i]>100||info->score[i]<0)printf("bad data,repeat input/n");
      }while(info->score[i]>100||info->score[i]<0); /*成绩数据验证*/
      s1=s1+info->score[i];      /*求总分*/
   }
   info->sum=s1;      /*保存总分*/
   info->average=(float)s1/N;  /*求均分*/
   info->order=0;      /*名次初始值为0*/
   info->next=NULL;  /*将新记录后继指针赋值为空*/
   printf("Enter infile name,for example c://f1//te.txt:/n");    scanf("%s",infile);         /*输入文件名*/
   if((fp=fopen(infile,"ab"))==NULL)  /*向二进制文件尾增加数据方式打开文件*/
   {
      printf("can not open file/n");   /*显示不能打开*/
      exit(1);             /*退出程序*/
   }
   printf("/n -----Appending record!-----/n");
   if(1!=fwrite(info,sizeof(STUDENT),1,fp))   /*写文件操作*/
   {
      printf("-----file write error!-----/n");
      return;              /*返回*/
   }
   printf("-----append  sucess!!----/n");
   fclose(fp);       /*关闭文件*/
}
/*文件拷贝*/
void copy()
{
   char outfile[10],infile[10];
   FILE *sfp,*tfp;        /*源和目标文件指针*/
   STUDENT *p=NULL;   /*移动指针*/
   clrscr();    /*清屏*/
   printf("Enter infile name,for example c://f1//te.txt:/n");
   scanf("%s",infile);         /*输入源文件名*/
   if((sfp=fopen(infile,"rb"))==NULL)   /*二进制读方式打开源文件*/
   {
      printf("can not open input file/n");
      exit(0);
   }
   printf("Enter outfile name,for example c://f1//te.txt:/n");   /*提示输入目标文件名*/
   scanf("%s",outfile);  /*输入目标文件名*/
   if((tfp=fopen(outfile,"wb"))==NULL)  /*二进制写方式打开目标文件*/
   {
      printf("can not open output file /n");
      exit(0);
   }
   while(!feof(sfp))   /*读文件直到文件尾*/
   {
      if(1!=fread(p,sizeof(STUDENT),1,sfp))
  break; /*块读*/
      fwrite(p,sizeof(STUDENT),1,tfp);   /*块写*/
   }
   fclose(sfp);    /*关闭源文件*/
   fclose(tfp);   /*关闭目标文件*/
   printf("you have success copy  file!!!/n");   /*显示成功拷贝*/
}
/*排序*/
STUDENT *sort(STUDENT *h)
{
   int i=0;                  /*保存名次*/
   STUDENT *p,*q,*t,*h1;   /*定义临时指针*/
   h1=h->next;           /*将原表的头指针所指的下一个结点作头指针*/
   h->next=NULL;        /*第一个结点为新表的头结点*/
   while(h1!=NULL)    /*当原表不为空时,进行排序*/
   {
      t=h1;            /*取原表的头结点*/
      h1=h1->next;     /*原表头结点指针后移*/
      p=h;           /*设定移动指针p,从头指针开始*/
      q=h;         /*设定移动指针q做为p的前驱,初值为头指针*/
      while(t->sum<p->sum&&p!=NULL)  /*作总分比较*/
      {
  q=p;            /*待排序点值小,则新表指针后移*/
  p=p->next;
      }
      if(p==q)      /*p==q,说明待排序点值大,应排在首位*/
      {
  t->next=p;     /*待排序点的后继为p*/
  h=t;         /*新头结点为待排序点*/
      }
      else    /*待排序点应插入在中间某个位置q和p之间,如p为空则是尾部*/
      {
  t->next=p;   /*t的后继是p*/
  q->next=t;    /*q的后继是t*/
      }
   }
   p=h;               /*已排好序的头指针赋给p,准备填写名次*/
   while(p!=NULL)  /*当p不为空时,进行下列操作*/
   {
      i++;       /*结点序号*/
      p->order=i;   /*将名次赋值*/
      p=p->next;   /*指针后移*/
   }
   printf("sort sucess!!!/n");   /*排序成功*/
   return h;      /*返回头指针*/
}
/*计算总分和均值*/
void computer(STUDENT *h)
{
   STUDENT *p;   /*定义移动指针*/
   int i=0;  /*保存记录条数初值为0*/
   long s=0;   /*总分初值为0*/
   float average=0;  /*均分初值为0*/
   p=h;        /*从头指针开始*/
   while(p!=NULL)    /*当p不为空时处理*/
   {
      s+=p->sum;    /*累加总分*/
      i++;         /*统计记录条数*/
      p=p->next;   /*指针后移*/
   }
   average=(float)s/i;/* 求均分,均分为浮点数,总分为整数,所以做类型转换*/
   printf("/n--All students sum score is:%ld  average is %5.2f/n",s,average);
}
/*索引*/
STUDENT *index(STUDENT *h)
{
   STUDENT *p,*q,*t,*h1;  /*定义临时指针*/
   h1=h->next;    /*将原表的头指针所指的下一个结点作头指针*/
   h->next=NULL;   /*第一个结点为新表的头结点*/
   while(h1!=NULL)  /*当原表不为空时,进行排序*/
   {
      t=h1;        /*取原表的头结点*/
      h1=h1->next;   /*原表头结点指针后移*/
      p=h;   /*设定移动指针p,从头指针开始*/
      q=h;   /*设定移动指针q做为p的前驱,初值为头指针*/
      while(strcmp(t->no,p->no)>0&&p!=NULL)  /*作学号比较*/
      {
  q=p;           /*待排序点值大,应往后插,所以新表指针后移*/
  p=p->next;
      }
      if(p==q)   /*p==q,说明待排序点值小,应排在首位*/
      {
  t->next=p;  /*待排序点的后继为p*/
  h=t;    /*新头结点为待排序点*/
      }
      else     /*待排序点应插入在中间某个位置q和p之间,如p为空则是尾部*/
      {
  t->next=p;    /*t的后继是p*/
  q->next=t;     /*q的后继是t*/
      }
   }
   printf("index sucess!!!/n");  /*索引排序成功*/
   return h;    /*返回头指针*/
}
/*分类合计*/
void total(STUDENT *h)
{
   STUDENT *p,*q;   /*定义临时指针变量*/
   char sno[9],qno[9],*ptr;    /*保存班级号的*/
   float s1,ave;        /*保存总分和均分*/
   int i;       /*保存班级人数*/
   clrscr();    /*清屏*/
   printf("/n/n  *******************Total*****************/n");
   printf("---class---------sum--------------average----/n");
   p=h;       /*从头指针开始*/
   while(p!=NULL)  /*当p不为空时做下面的处理*/
   {
      memcpy(sno,p->no,8);  /*从学号中取出班级号*/
      sno[8]='/0';          /*做字符串结束标记*/
      q=p->next;        /*将指针指向待比较的记录*/
      s1=p->sum;      /*当前班级的总分初值为该班级的第一条记录总分*/
      ave=p->average;  /*当前班级的均分初值为该班级的第一条记录均分*/
      i=1;          /*统计当前班级人数*/
      while(q!=NULL)   /*内循环开始*/
      {
  memcpy(qno,q->no,8);   /*读取班级号*/
  qno[8]='/0';     /*做字符串结束标记*/
  if(strcmp(qno,sno)==0)  /*比较班级号*/
  {
     s1+=q->sum;     /*累加总分*/
     ave+=q->average; /*累加均分*/
     i++;         /*累加班级人数*/
     q=q->next;   /*指针指向下一条记录*/
  }
  else
     break;  /*不是一个班级的结束本次内循环*/
      }
      printf("%s     %10.2f           %5.2f/n",sno,s1,ave/i);
      if(q==NULL)
  break;   /*如果当前指针为空,外循环结束,程序结束*/
      else
  p=q;   /*否则,将当前记录作为新的班级的第一条记录开始新的比较*/
   }
   printf("---------------------------------------------/n");
}


案例十二 工资管理
#include "stdio.h"    /*I/O函数*/
# include "bios.h"  /*ROM基本输入输出函数*/
#include "dos.h"    /*dos接口函数*/
#include "conio.h"   /*屏幕操作函数*/
#include "stdlib.h"   /*其它说明*/
#include "string.h"  /*字符串函数*/
#include "mem.h"  /*内存操作函数*/
#include "ctype.h" /*字符操作函数*/
#include "alloc.h"  /*动态地址分配函数*/
/****变量定义*******/
typedef struct z1    /*定义数据结构*/
{
   char no[11];     /*编号*/
   char name[15];  /*姓名*/
   float jbgz;     /*基本工资*/
   float koukuan; /*扣款*/
   float yfgz;  /*应发工资*/
   float shuijin;  /*税金*/
   float sfgz;   /*实发工资*/
   struct z1 *prior;/*前驱指针*/
   struct z1 *next;/*后继指针*/
}SALARY;     /*结构体类型名*/
struct z1 *First;   /*双链表头指针*/
struct z1 *Last;   /*双链表尾指针*/
/******函数原型*********/
void init();    /*初始化*/
void create();  /*创建链表*/
void calc();   /*计算应发工资*/
void delete(); /*删除*/
void search(); /*查找*/
void save();  /*保存文件*/
void load();  /*读取文件*/
void computer(); /*计算所需各种票面张数*/
void insert();  /*插入*/
void append(); /*追加*/
void copy(); /*复制文件*/
void sort();  /*排序*/
void index();  /*索引*/
void total();  /*分类合计*/
void list(); /*显示所有数据*/
void print(SALARY *p);  /*输出单条记录*/
void display();  /*随意逐条显示*/
float fax(float x);  /*计算税金*/
int menu_select();  /*主菜单*/
/*******主函数开始**********/
main()
{
   int i;
   clrscr();
   for(;;)
   {
      switch(menu_select())   /*调用菜单函数返回一个整数值*/
      {
  case 0:init();break;    /*初始化*/
  case 1:create();break; /*输入数据创建双链表*/
  case 2:list();break;  /*显示所有数据*/
  case 3:display();break;  /*单条显示*/
  case 4:calc();break;  /*计算实发工资*/
  case 5:search();break;  /*查找职工信息数据*/
  case 6:delete();break;  /*删除记录*/
  case 7:insert();break;  /*插入记录*/
  case 8:append();break;  /*追加记录*/
  case 9:save();break;  /*保存文件*/
  case 10:load(); break;  /*读取文件*/
  case 11:copy();break;  /*复制文件*/
  case 12:sort();break;  /*按实发工资升序排序*/
  case 13:computer();break; /*计算所需票面数*/
  case 14:index();break;  /*按职工号索引*/
  case 15:total();break;  /*按部门求合计*/
  case 16:exit(0);    /*退出*/
      }
   }
}
/*菜单函数,函数返回值为整型,代表所选的菜单项*/
menu_select()
{
   char *f[]= {     /*定义菜单字符串数组*/
   "**************MENU*************", /*菜单的标题行*/
   " 0. init list", /*初始化双链表*/
   " 1. Enter list", /*输入数据,创建双链表*/
   " 2. List all /n",  /*显示所有记录*/
   " 3. Display record by step", /*显示单条记录*/
   " 4. Calc the salary", /*计算实发工资*/
   " 5. Search record on name", /*查找记录*/
   " 6. Delete a record", /*删除记录*/
   " 7. Insert record to list", /*插入记录*/
   " 8. Append  record to file", /*追加记录*/
   " 9. Save data to the file",  /*保存文件*/
   " 10. Load data from the file",/*读取文件*/
   " 11. Copy the file to new file", /*复制文件*/
   " 12. Sort on sfgz",  /*排序*/
   " 13. Computer ticket number", /*计算所需票面数*/
   " 14. Index on number",  /*索引*/
   " 15. Total on number",  /*分类合计*/
   " 16. Quit" };  /*退出*/
   char s[80];
   int  i;
   int key=0; /*记录所压键值*/
   int c=0;
   gotoxy(1,25); /*移动光标*/
   printf("press any key enter menu....../n");/*压任意键进入主菜单*/
   getch();
   clrscr();  /*清屏*/
   textcolor(YELLOW); /*设置文本颜色为黄色*/
   textbackground(BLUE);  /*设置背景颜色为兰色*/
   gotoxy(10,2);
   putch(0xda); /*输出左上角边框┏*/
   for(i=1;i<44;i++)
   putch(0xc4); /*输出上边框水平线*/
   putch(0xbf);  /*输出右上角边框  ┓*/
   for(i=3;i<22;i++)/*输出左右两边的垂直线*/
   {
      gotoxy(10,i);putch(0xb3);
      gotoxy(54,i);putch(0xb3);
   }
   gotoxy(10,22);putch(0xc0); /*输出左上角边框┗*/
   for(i=1;i<44;i++)
      putch(0xc4);  /*输出下边框水平线*/
   putch(0xd9);  /*输出右下角边框┛*/
   window(11,3,53,21); /* 制作显示菜单的窗口,大小根据菜单条数设计*/
   clrscr();   /*清屏*/
   for(i=0;i<18;i++)
   {
      gotoxy(10,i+1);
      cprintf("%s",f[i]); /*输出菜单项数组*/
   }
   i=1;
   gotoxy(10,2);  /*设置默认选项在第一项*/
   textbackground(LIGHTGREEN);/*设置背景颜色为浅绿*/
   cprintf("%s",f[1]);  /*输出菜单项,表示选中*/
   gotoxy(10,2);  /*移动光标到菜单的第一项*/
   while(key!=13)   /*所压键不是回车键时*/
   {
      while(bioskey(1)==0);  /*查询是否压下了一个键*/
      key=bioskey(0);   /*返回下一个在键盘压下的键*/
      key=key&0xff?key&0xff:key>>8; /*对所压的键进行判断*/
      gotoxy(10,i+1);
      textbackground(BLUE);/*设置背景颜色为蓝色*/
      cprintf("%s",f[i]);  /*输出菜单项*/
      if(key==72) i=i==1?17:i-1; /*如压向上光标键↑,i减1,如已到第一行再上移,则到最后一行*/
      if(key==80)i=i==17?1:i+1; /*如压向下光标键↓,i加1,如已到最后一行再下移,则到第一行*/
      gotoxy(10,i+1); /*光标移动i的下一项*/
      textbackground(LIGHTGREEN); /*将背景颜色设为浅绿*/
      cprintf("%s",f[i]);  /*输出菜单项*/
      c=i-1;  /*给代表菜单选项的整数赋值*/
   }
   textbackground(BLACK);  /*设置背景颜色为黑色*/
   window(1,1,80,25);  /*恢复原窗口大小*/
   return c;  /*返回代表菜单选项的整数值*/
}
/*初始化函数*/
void init()
{
   First=NULL;
   Last=NULL;
}
/*输入数据,创建双链表*/
void create()
{
   int x; /*记录行坐标*/
   int i; /*记录输入记录数*/
   int flag=0; /*做结束标记*/
   float temp;   /*定义临时变量*/
   SALARY *info,*p; /*定义临时变量*/
   if(First!=NULL)
   init();/*如果头指针为空,调用初始化函数*/
   p=First; /*从头指针开始*/
   for(;;)
   {
      if(flag==1)
  break; /*如果flag=1,结束输入*/
      i=0;
      x=0;   /*确定移动的行坐标*/
      clrscr(); /*清屏*/
      gotoxy(1,3);
      printf("*************gongziguanli*************");/*输出标题*/
      gotoxy(1,4);
      printf("                      --Enter @ end--");/*提示输入@结束*/
      gotoxy(1,5);
      printf("|------------------------------------|");/*输出表格的起始线*/
      gotoxy(1,6);
      printf("|    no    |      name      |  jbgz  |");/*输出字段标题,注意空格数*/
      for(;;)
      {
  gotoxy(1,7+x);
  printf("|----------|----------------|--------|");/*输出表格的水平线*/
  info=(SALARY *)malloc(sizeof(SALARY));/*申请一个记录空间*/
  if(!info)
  {
     printf("/nout of memory");/*如没有得到空间,输出内存溢出信息*/
     exit(0);/*退出程序*/
  }
  info->next=NULL;/*新结点的后继为空*/
  info->prior=NULL;/*新结点的前驱为空*/
  gotoxy(1,8+x);printf("|"); /*输出数据间的分割线*/
  gotoxy(12,8+x);printf("|");
  gotoxy(29,8+x);printf("|");
  gotoxy(38,8+x);printf("|");
  gotoxy(2,8+x);/*光标到输入编号位置*/
  inputs(info->no,10);/*输入编号,并验证长度不超过10*/
  if(info->no[0]=='@')
  {
     flag=1;
     break;
  } /*编号首字符为@结束输入*/
  gotoxy(13,8+x);  /*光标到输入姓名位置*/
  inputs(info->name,14); /*输入姓名,并验证长度不超过14*/
  gotoxy(30,8+x); /*光标到输入基本工资位置*/
  scanf("%f",&temp); /*输入基本工资到临时变量*/
  info->jbgz=temp; /*基本工资赋值*/
  info->koukuan=0; /*初始扣款为0,待计算工资时输入*/
  info->sfgz=0; /*初始实发工资为0,待计算工资时计算*/
  info->shuijin=0; /*初始税金为0,待计算工资时计算*/
  info->yfgz=0; /*初始应发工资为0,待计算工资时计算*/
  if(p==NULL)/*如果p为空,说明输入的是第一个结点*/
  {
     First=Last=info;/*头指针和尾指针*/
     First->prior=NULL; /*头指针的前驱是空*/
     Last->next=NULL; /*尾指针的后继是空*/
  }
  else /*插入的结点不是第一结点,则插入在头结点之前*/
  {
     info->next=p;/*新结点的后继指向原来的头结点*/
     info->prior=p->prior;/*新结点的前驱指向原来的头结点的前驱*/
     p->prior=info;/*原来结点的前驱指向新结点*/
  }
  p=info;  /*新结点变为p结点,暂时的头结点*/
  First=info; /*新结点变为头结点*/
  x+=2;   /*因为水平线,将光标下移两行*/
  gotoxy(1,8+x);
  i++;   /*输入记录数加1*/
  if(i%9==0)
     break; /*输入9个记录,换一页输入*/
      }
      gotoxy(1,8+x);
   }
   printf("|----------|----------------|--------|");/*输出结尾水平线*/
}
/*字符串输入和验证函数*/
inputs(char *s, int count)
{
   char p[255];
   do{
      scanf("%s",p);/*输入字符串*/
      if(strlen(p)>count)printf("/n too long! /n");/*进行长度校验,超过count值重输入*/
   }while(strlen(p)>count);
   strcpy(s,p); /*将输入的字符串拷贝到字符串s中*/
}
/*显示链表*/
void list()
{
   int i=0,n;  /*记录输出行数*/
   SALARY *p; /*定义移动指针*/
   clrscr();  /*清屏*/
   p=First;  /*从头指针开始*/
   while(i%10==0&&p!=NULL)  /*外循环控制换页*/
   {
      i=0;       /*记录一页的输出行数*/
      clrscr();   /*清屏*/
      printf("/n/n/n"); /*换行三次*/
      printf("*************************************SALARY***********************************/n");   /*输出大标题*/
      printf("|nO        |      name     |   jbgz  | koukuan |   yfgz  | shuijin |   sfgz  |/n");  /*输出字段标题*/
      printf("|----------|---------------|---------|---------|---------|---------|---------|/n");  /*输出水平线*/
      while(p!=NULL)  /*当p不为空时*/
      {
  printf("|%-10s|%-15s|%9.2f|%9.2f|%9.2f|%9.2f|%9.2f|/n",
  p->no,p->name,p->jbgz,p->koukuan,p->yfgz,p->shuijin,p->sfgz);
  p=p->next;  /*指针后移*/
  i++;   /*输出行数加1 */
  if(i%10==0)
     break;  /*如果满10行,跳出内循环*/
      }
      printf("****************************************end***********************************/n");  /*输出本页的结束行*/
      printf("Press any key congtinue.../n");
      getch(); /*输出一页暂停一下,压任意键继续*/
   }  /*返回到外循环,准备下一页的输出*/
}
/*单条显示记录*/
void display()
{
   int ch;   /*菜单选项字符*/
   SALARY *p;  /*定义临时指针*/
   clrscr();  /*清屏*/
   p=First;  /*从头指针开始*/
   if(p==NULL)  /*指针为空,即链表为空,返回主函数*/
   {
      printf("record is empty!/n");
      return;
   }
   else
   {
      print(p);   /*调用输出函数显示头结点信息*/
      for(;;)  /*循环开始*/
      {
  printf("/n/n0. Quit 1. Prior      2.  Next      3.  First        4.Last /n/n");
/*菜单项Quit退出 Prior前驱 Next后继  First第一条 Last最后一条*/
  printf("/nplease select 0~4:"); /*提示输入菜单选项0~4*/
  scanf("%d",&ch); /*输入菜单选项0~4*/
  if(ch==0) break;  /*如果选项为0,退出*/
  switch(ch)   /*开关语句根据选项字符判断*/
  {
     case 1:p=p->prior;if(p==NULL)p=First;break;  /*指向前驱,没有前驱指向第一个*/
     case 2:p=p->next;if(p==NULL) p=Last;break; /*指向后继,没有后继指向最后一个*/
     case 3:p=First;break;  /*指向第一个结点*/
     case 4:p=Last;break; /*指向最后一个结点*/
  }
  print(p);  /*调用输出函数显示指针所指结点信息*/
      }
   }
}
/*输出指针所指结点信息*/
void print(SALARY *p)
{
   if(p)   /*如果指针不为空,则显示信息*/
   {
      clrscr();  /*清屏*/
      printf("/n/n/n");  /*换行*/
      printf("************************************SALARY************************************/n");  /*输出标题信息*/
      printf("|no        |      name     |   jbgz  | koukuan|   yfgz  | shuijin |   sfgz   |/n"); /*输出字段标题*/
      printf("|----------|---------------|---------|---------|---------|---------|---------|/n"); /*输出分割线*/
      printf("|%-10s|%-15s|%9.2f|%9.2f|%9.2f|%9.2f|%9.2f|/n", p->no,p->name,
      p->jbgz,p->koukuan,p->yfgz,p->shuijin,p->sfgz);/*输出结点信息*/
      printf("***************************************end***************************** *******/n");  /*输出结束标记*/
   }
}
/*计算实发工资*/
void calc()
{
   int x; /*行坐标*/
   int i=0; /*记录数*/
   float temp; /*临时变量扣款*/
   SALARY *p;  /*移动指针*/
   clrscr();   /*清屏*/
   p=First;  /*从头指针开始*/
   while(p!=NULL)  /*当p不为空时,也就是有记录时,外循环控制换页*/
   {
      x=0;
      clrscr();
      gotoxy(1,3);
      printf("***************************gongziguanli************************************");   /*输出标题*/
      gotoxy(1,5);
      printf("|--------------------------------------------------------------------------|");
      gotoxy(1,6);/*下面输出字段标题*/
      printf("|    no    |      name      |  jbgz  |  koukuan |  yfgz  |shuijin |  sfgz  |");
      while(p!=NULL) /*当p不为空时,也就是有记录时,内循环控制处理9条*/
      {
  gotoxy(1,7+x);
  printf("|----------|----------------|--------|----------|--------|--------|--------|");
  gotoxy(1,8+x);printf("|");
  gotoxy(12,8+x);printf("|");
  gotoxy(29,8+x);printf("|");
  gotoxy(38,8+x);printf("|");
  gotoxy(49,8+x);printf("|");
  gotoxy(58,8+x);printf("|");
  gotoxy(67,8+x);printf("|");
  gotoxy(76,8+x);printf("|");
  gotoxy(2,8+x);
  printf("%-10s",p->no); /*输出编号*/
  gotoxy(13,8+x);
  printf("%-15s",p->name); /*输出姓名*/
  gotoxy(30,8+x);
  printf("%.2f",p->jbgz);  /*输出基本工资*/
  gotoxy(39,8+x);
  scanf("%f",&temp);  /*输入扣款*/
  p->koukuan=temp; /*扣款字段赋值*/
  p->yfgz=p->jbgz-p->koukuan; /*计算应发工资=基本工资-扣款*/
  gotoxy(50,8+x);
  printf("%.2f",p->yfgz);  /*输出应发工资*/
  gotoxy(59,8+x);
  p->shuijin=(p->yfgz-1000)*fax(p->yfgz); /*否则按税率计算税金*/
  printf("%.2f",p->shuijin);  /*输出税金*/
  gotoxy(68,8+x);
  p->sfgz=p->yfgz-p->shuijin;  /*计算实发工资*/
  printf("%-8.2f",p->sfgz);  /*输出实发工资*/
  x+=2;   /*行坐标下移两行*/
  i++;   /*记录数加1*/
  if(i%9==0)break;  /*记录数超过9条,跳出内循环*/
  p=p->next;   /*指针后移,处理下一条*/
      }
      gotoxy(1,7+x);
      printf("|----------|----------------|--------|----------|--------|--------|--------|/n"); /*输出结束行*/
      printf("Press any key congtinue.../n");
      getch();
   }
}
/*根据应发工资,计算税率*/
float fax(float x)
{
   float f1;
   if(x<1000)
      return 0;   /*小于1000,返回0*/
   switch((int)(x/1000))
   {
      case 1:f1=0.05;break; /*1000~1999,返回0.05*/
      case 2:f1=0.1;break; /*2000~2999,返回0.1*/
      case 3:f1=0.15;break; /*3000~3999,返回0.15*/
      case 4:f1=0.2;break; /*4000~4999,返回0.2*/
      default:f1=0.3;break; /*5000以上,返回0.3*/
   }
   return f1;
}
/*计算票面张数*/
void computer()
{
   SALARY *p;
   int i=0,a[7]={0},t100,t50,t20,t10,t5,t2,t1;/*设置数组和临时变量保存票面张数*/
   float t;   /*过渡变量,保存当前剩余工资*/
   p=First;  /*移动指针从头指针开始*/
   while(p!=NULL)  /*当p不为空时*/
   {
      t100=(int)p->sfgz/100;  /*计算100元张数*/
      a[0]=a[0]+t100;   /*累加保存*/
      t=p->sfgz-t100*100; /*剩余工资*/
      t50=(int)(t/50); /*计算50元张数*/
      a[1]=a[1]+t50; /*累加保存*/
      t=t-t50*50; /*剩余工资*/
      t20=(int)(t/20);   /*计算20元张数*/
      a[2]=a[2]+t20; /*累加保存*/
      t=t-t20*20; /*剩余工资*/
      t10=(int)(t/10); /*计算10元张数*/
      a[3]=a[3]+t10; /*累加保存*/
      t=t-t10*10; /*剩余工资*/
      t5=(int)(t/5); /*计算5元张数*/
      a[4]=a[4]+t5; /*累加保存*/
      t=t-t5*5; /*剩余工资*/
      t2=(int)(t/2); /*计算2元张数*/
      a[5]=a[5]+t2; /*累加保存*/
      t=t-t2*2; /*剩余工资*/
      t1=(int)(t); /*计算1元张数*/
      a[6]=a[6]+t1; /*累加保存*/
      p=p->next;  /*指针后移,处理下一条记录*/
   }
   clrscr();  /*清屏*/
   printf("/n/n/n***********ticket number***************/n"); /*输出标题*/
   printf("--100-----50------20-----10-----5------2------1------/n");
     /*输出张数标题*/
   for(i=0;i<7;i++)
      printf("%5d  ",a[i]);/*输出所需的张数*/
   printf("/n");/*换行*/
}
/*按编号查找记录*/
SALARY *find(char *no)
{
   SALARY *p; /*定义移动指针*/
   p=First;  /*从头指针开始*/
   while(p) /*当p不为空时*/
   {
      if(!strcmp(no,p->no))
  return p; /*比较相等,查找成功,返回指针*/
      p=p->next; /*不相等指针后移*/
   }
   printf("not found/n");  /*没有找到*/
   return NULL; /*返回为空指针*/
}
/*删除结点*/
void delete()
{
   SALARY *p; /*定义临时变量,p指向要删除的结点p*/
   char s[11]; /*要删除结点的编号*/
   clrscr();  /*清屏*/
   printf("please deleted no/n"); /*提示输入信息*/
   scanf("%s",s);   /*输入要删除的职工编号*/
   if((p=find(s))!=NULL) /*调用查找函数,如果找到做下面的处理*/
   {
      if(First==p)    /*如果是第一个结点*/
      {
  First=p->next;  /*将头指针指向其后继结点*/
  if(First)    /*如头指针不为空*/
     First->prior=NULL;  /*将头结点的前驱设为空*/
  else
     Last=NULL;   /*否则头为空,尾也为空*/
      }
      else   /*删除的不是第一个结点*/
      {
  p->prior->next=p->next;  /*p的前驱的后继指向p原来的后继*/
  if(p!=Last)   /*如果p不是最后个结点*/
     p->next->prior=p->prior;  /*p后继的前驱指向p原来的前驱*/
  else
     Last=p->prior;/*如p是最后一个结点,修改尾指针为p的前驱*/
      }
      free(p);  /*删除结点后,不要忘记释放空间*/
      printf("/n have deleted %s SALARY/n",s);
      printf("Don't forget save/n");
   }
}
/*按姓名查找结点*/
void search()
{
   SALARY *p;  /*移动指针*/
   char s[15];  /*保存姓名*/
   clrscr(); /*清屏*/
   printf("please enter name for search/n"); /*提示输入*/
   scanf("%s",s);  /*输入要查找人的姓名*/
   p=First;  /*移动指针从头指针开始*/
   while(strcmp(p->name,s)&&p!=NULL) /*做比较判断*/
      p=p->next;   /*没找到,指针后移继续查找*/
   if(p==NULL)  /*指针为空,说明没有找到*/
      printf("/nlist no %s SALARY/n",s); /*显示没找到信息*/
   else
   {
      printf("/n/n"); /*换行*/
      print(p);  /*查找成功,调用输出函数输出指针p所指记录*/
   }
}
/*插入结点*/
void insert()
{
   SALARY *p,*info; /* info为新结点,p为新结点的后继*/
   char s[11];  /*保存查找的姓名*/
   float temp; /*临时变量*/
   clrscr(); /*清屏*/
   printf("please enter location  before the no/n"); /*提示输入在哪个结点之前插入*/
   scanf("%s",s);  /*输入指定结点的编号*/
   printf("/nplease new record/n");  /*提示输入记录*/
   clrscr();/*清屏*/
   gotoxy(1,3); /*定位光标,按表格形式输入新结点信息*/
   printf("**************gongziguanli************");
   gotoxy(1,5);
   printf("|------------------------------------|");
   gotoxy(1,6);
   printf("|    no    |      name      |  jbgz  | ");
   gotoxy(1,7);
   printf("|----------|----------------|--------|");
   info=(SALARY *)malloc(sizeof(SALARY)); /*申请空间*/
   if(!info)
   {
      printf("/nout of memory"); /*如没有得到空间,内存溢出*/
      exit(0);  /*退出程序*/
   }
   info->next=NULL;  /*新结点的后继为空*/
   info->prior=NULL; /*新结点的前驱为空*/
   gotoxy(1,8);printf("|");
   gotoxy(12,8);printf("|");
   gotoxy(29,8);printf("|");
   gotoxy(38,8);printf("|");
   gotoxy(2,8);
   inputs(info->no,10);  /*输入新结点的编号,并校验*/
   gotoxy(13,8);
   inputs(info->name,14); /*输入新结点的姓名,并校验*/
   gotoxy(30,8);
   scanf("%f",&temp);   /*输入基本工资*/
   info->jbgz=temp;  /*给基本工资字段赋值*/
   info->koukuan=0; /*扣款初始为0*/
   info->yfgz=0;  /*应发工资初始为0*/
   info->shuijin=0; /*税金初始为0*/
   info->sfgz=0; /*实发工资初始为0*/
   printf("|----------|----------------|--------|");
   p=First;  /*移动指针从头指针开始*/
   while(strcmp(p->no,s)&&p!=NULL) /*查找结点确定插入位置*/
      p=p->next;  /*指针后移,继续查找*/
   if(p==NULL)  /*如p为空*/
      if(p==First) /*如p为头指针,说明链表为空*/
      {
  First=info;  /*新结点为头指针*/
  First->prior=NULL; /*头结点的前驱为空*/
  Last=First;  /*唯一结点,尾指针等于头指针*/
      }
      else  /*新结点插在尾部*/
      {
  Last->next=info;
  info->prior=Last;
  Last=info;  /*尾指针指向新结点*/
      }
   else
      if(p==First)  /*p不为空,但p为头指针,新结点插在第一个结点位置*/
      {
  info->prior=NULL; /*新结点的前驱为空*/
  info->next=p; /*新结点的后继为p*/
  p->prior=info; /*p的前驱是新结点*/
  First=info; /*修改头指针指向新结点*/
      }
      else /*新结点插入在中间某一个位置p之前*/
      {
  info->next=p; /*新结点的后继是p*/
  info->prior= p->prior; /*新结点的前驱是p的前驱*/
  p->prior->next=info; /*p的前驱的后继是新结点*/
  p->prior=info; /*p的前驱是新结点*/
      }
   printf("/n/n/n ----have inserted %s SALARY----/n",info->name);
   printf("/n---Don't forget save---/n"); /*提醒调用保存文件存盘*/
}
/*保存文件*/
void save()
{
   FILE *fp;  /*定义指向文件的指针*/
   SALARY *p; /*定义移动指针*/
   char outfile[10]; /*保存输出文件名*/
   clrscr();/*清屏*/
   printf("Enter outfile name,for example c://f1//te.txt:/n");/*提示输入文件名格式信息*/
   scanf("%s",outfile);
   if((fp=fopen(outfile,"wb"))==NULL) /*为输出打开一个二进制文件*/
   {
      printf("can not open file/n");
      return; /*返回*/
   }
   printf("/nSaving file....../n");
   p=First; /*移动指针从头指针开始*/
   while(p!=NULL) /*如p不为空*/
   {
      fwrite(p,sizeof(SALARY),1,fp); /*写入一条记录*/
      p=p->next;  /*指针后移,处理下一条记录*/
   }
   fclose(fp); /*关闭文件*/
   printf("-----save success!!-----/n");/*显示保存成功*/
}
/*读文件*/
void load()
{
   SALARY *p,*q=NULL; /*定义记录指针变量*/
   FILE *fp; /* 定义指向文件的指针*/
   char infile[10]; /*保存文件名*/
   clrscr();/*清屏*/
   printf("Enter infile name,for example c://f1//te.txt:/n");/*输入文件名格式*/
   scanf("%s",infile); /*输入文件名*/
   if((fp=fopen(infile,"rb"))==NULL) /*打开一个二进制文件,为读方式*/
   {
      printf("can not open file/n"); /*如不能打开,则结束程序*/
      return; /*返回*/
   }
   while(First) /*当表不为空时,清空链表*/
   {
      p=First; /*从头指针开始*/
      First=First->next; /*删除头结点*/
      free(p); /*释放空间*/
   }
   printf("/n -----Loading file!-----/n"); /*显示正在读文件*/
   First=(SALARY *)malloc(sizeof(SALARY)); /*为头指针申请空间*/
   if(!First) /*如果没有得到空间 显示内存溢出*/
   {
      printf("out of memory!/n");
      return;  /*返回*/
   }
   p=First; /*将头指针赋值给p*/
   while(!feof(fp)) /*当文件不空时*/
   {
      if(1!=fread(p,sizeof(SALARY),1,fp))break; /*将记录读到p所指的结点*/
      p->next=(SALARY *)malloc(sizeof(SALARY));/*为p的后继申请空间*/
      if(!p->next)  /*如果没有得到空间显示内存溢出*/
      {
  printf("out of memory!/n");
  return; /*返回*/
      }
      p->prior=q; /*得到空间,则链接指针关系p的前驱为q*/
      q=p;  /*保存p做为新的p结点的前驱*/
      p=p->next;  /*p指针后移*/
   }
   q->next=NULL; /*q的后继为空*/
   Last=q;  /*尾指针为q*/
   First->prior=NULL; /*头指针的前驱为空*/
   fclose(fp); /*关闭文件*/
   printf("---You have success read data from file!!!---/n"); /*显示成功读入记录*/
}
/*追加记录*/
void append()
{
   FILE *fp;   /*定义指向文件的指针*/
   SALARY *info; /*指向追加信息的指针*/
   char infile[10]; /*保存文件名*/
   float temp; /*临时变量*/
   clrscr(); /*清屏*/
   gotoxy(1,3);
   printf("**************gongziguanli************");
   gotoxy(1,5);
   printf("|------------------------------------|");
   gotoxy(1,6);
   printf("|    no    |      name      |  jbgz  | ");
   gotoxy(1,7);
   printf("|----------|----------------|--------|");
   info=(SALARY *)malloc(sizeof(SALARY)); /*申请追加信息的空间*/
   if(!info)
   {
      printf("/nout of memory"); /*没有空间,内存溢出*/
      exit(0);  /*结束程序*/
   }
   info->next=NULL;  /*新信息的后继为空*/
   info->prior=NULL; /*新信息的前驱为空*/
   gotoxy(1,8);printf("|");
   gotoxy(12,8);printf("|");
   gotoxy(29,8);printf("|");
   gotoxy(38,8);printf("|");
   gotoxy(2,8);
   inputs(info->no,10); /*输入编号并校验*/
   gotoxy(13,8);
   inputs(info->name,14); /*输入姓名并校验*/
   gotoxy(30,8);
   scanf("%f",&temp); /*输入基本工资*/
   info->jbgz=temp;
   info->koukuan=0; /*扣款为0*/
   info->yfgz=0; /*应发工资为0*/
   info->shuijin=0; /*税金为0*/
   info->sfgz=0; /*实发工资为0*/
   printf("|----------|----------------|--------|");
   printf("/n/n/nEnter infile name,for example c://f1//te.txt:/n"); /*提示输入文件名*/
   scanf("%s",infile);
   if((fp=fopen(infile,"ab"))==NULL) /*打开文件*/
   {
      printf("can not open file/n");
      return;  /*返回*/
   }
   printf("/n -----Appending record!-----/n");
   if(1!=fwrite(info,sizeof(SALARY),1,fp)) /*向文件中追加记录*/
   {
      printf("-----file write error!-----/n"); /*写函数返回值不为1,说明写入错误*/
      return;  /*返回*/
   }
   printf("-----append  sucess!!----/n");/*显示追加成功*/
   fclose(fp);/*关闭文件*/
}
/*文件复制*/
void copy()
{
   char outfile[10],infile[10];  /*保存源文件名和目标文件名*/
   FILE *sfp,*tfp;  /*定义指向源文件和目标文件的指针*/
   SALARY *p=NULL;  /*定义临时指针,暂存读出的记录*/
   clrscr();
   printf("Enter infile name,for example c://f1//te.txt:/n");
   scanf("%s",infile); /*输入源文件名*/
   if((sfp=fopen(infile,"rb"))==NULL) /*二进制读方式打开源文件*/
   {
      printf("can not open input file/n"); /*显示不能打开文件信息*/
      return; /*返回*/
   }
   printf("Enter outfile name,for example c://f1//te.txt:/n");  /*提示输入目标文件名*/
   scanf("%s",outfile); /*输入目标文件名*/
   if((tfp=fopen(outfile,"wb"))==NULL) /*二进制写方式打开目标文件*/
   {
      printf("can not open output file /n");
      return;
   }
   while(!feof(sfp)) /*读文件直到文件尾*/
   {
      if(1!=fread(p,sizeof(SALARY),1,sfp))
  break;/*块读*/
      fwrite(p,sizeof(SALARY),1,tfp); /*块写*/
   }
   fclose(sfp); /*关闭源文件*/
   fclose(tfp); /*关闭目标文件*/
   printf("you have success copy  file!!!/n");/*显示成功拷贝*/
}
/*排序*/
void sort()
{
   SALARY *p0,*p00,*p1,*p11,*p2; /*定义临时指针*/
   int i=1;  /*统计当前排第几个结点*/
   clrscr(); /*清屏*/
   printf("/n/n start sort..../n"); /*开始排序*/
   p1=p11=p2=First;
   while(p1!=NULL) /*当p1不为空时*/
   {
      p0=p1;    /*待比较结点从p1开始*/
      p2=p1;    /*p2从当前待排序位置开始*/
      while(p2->next!=NULL) /*p2的后继不为空时*/
      {
  if(p0->sfgz>p2->next->sfgz)  /*找当前最小结点*/
  {
     p00=p2;   /*找到当前最小结点记录其前驱指针*/
     p0=p2->next;  /*记录当前最小值结点的指针p0*/
  }
  p2=p2->next;  /*指针后移*/
      }
      Last=p0;  /*当前最小结点为尾结点*/
      if(p1!=p0)  /*判断最小结点是否是当前排序位置,不是则作指针修改*/
      {
  p00->next=p0->next;  /*将p00的后继指向p0的后继*/
  p0->next->prior=p00; /*p0的后继的前驱为p00*/
  p0->next=p1;  /*p0的后继指向下个排序位置p1*/
  p1->prior=p0; /*p1的前驱为p0*/
  if(i==1)
  {
     First=p0;   /*作头指针*/
     First->prior=NULL; /*头指针的前驱为空*/
  }
  else   /*不是第一个结点*/
  {
     p11->next=p0;   /*p11的后继指向p0*/
     p0->prior=p11; /*p0的前驱指向p11*/
  }
  p11=p1=p0; /*因p0是排好序的最后一个结点,p1是下一个将要排序的位置,所以将p0赋值给p1和p11*/
      }
      i++;  /*排好序的结点数加1*/
      p1=p1->next; /*p1后移指向下一个待排序位置*/
   }
   printf("sort sucess!!!/n");  /*输出排序成功*/
}
/*索引*/
void index()
{
   SALARY *p,*q,*t,*h1; /*定义临时指针*/
   clrscr();/*清屏*/
   printf("/n/n start index...../n/n"); /*显示开始索引*/
   h1=First->next; /*将原表的头指针所指的下一个结点作头指针*/
   First->next=NULL; /*第一个结点为新表的头结点*/
   Last=First; /*尾指针等于头指针*/
   while(h1!=NULL) /*当原表不为空时,进行排序*/
   {
      t=h1; /*取原表的头结点*/
      h1=h1->next; /*原表头结点指针后移*/
      p=First; /*设定移动指针p,从头指针开始*/
      q=First; /*设定移动指针q做为p的前驱,初值为头指针*/
      while(strcmp(t->no,p->no)>0&&p!=NULL) /*作编号比较*/
      {
  q=p; /*待排序点值大,应往后插,所以新表指针后移*/
  p=p->next;
      }
      if(p==q)  /*p==q,说明待排序点值小,应排在首位*/
      {
  t->next=p; /*待排序点的后继为p*/
  p->prior=t; /*p的前驱结点指向待排序结点*/
  First=t; /*新头结点为待排序点*/
  First->prior=NULL; /*头指针的前驱为空*/
      }
      else /*待排序点应插入在中间某个位置q和p之间,如p为空则是尾部*/
      {
  t->next=p; /*t的后继是p*/
  t->prior=q; /*t的前驱是q*/
  q->next=t; /*q的后继是t*/
  if(p==NULL) /*判p是否为空*/
     Last=t;   /*将t赋值为尾指针*/
  else
     p->prior=t; /*否则将t赋值给p的前驱*/
      }
   }
   printf("index sucess!!!/n");/*索引排序成功*/
}
/*分类合计*/
void total()
{
   struct t1  /*定义结构体保存合计数据*/
   {
      char u[7];  /*部门*/
      float s;   /*合计实发工资*/
   }unit[20];   /*定义一个单位部门数不超过20个*/
   SALARY *p,*q;  /*定义临时指针变量*/
   char sno[7],qno[7],*ptr; /*保存部门号*/
   float s1;  /*保存合计值*/
   int i,j;  /*控制变量*/
   p=First;  /*从指针开始*/
   i=0;  /*统计部门数*/
   clrscr();/*清屏*/
   while(p!=NULL) /*当p不为空时做下面的处理*/
   {
      memcpy(sno,p->no,6); /*从编号中取出部门号*/
      sno[6]='/0'; /*做字符串结束标记*/
      q=p->next; /*将指针指向待比较的记录*/
      s1=p->sfgz;  /*当前部门的实发工资初值作为该部门合计值的初值*/
      while(q!=NULL) /*内循环开始*/
      {
  memcpy(qno,q->no,6); /*读部门号*/
  qno[6]='/0'; /*做字符串结束标记*/
  if(strcmp(qno,sno)==0) /*比较部门号*/
  {
     s1+=q->sfgz; /*累加实发工资*/
     q=q->next; /*指针指向下一条记录*/
  }
  else
     break; /*不是一个部门的结束本次内循环*/
      }
      strcpy(unit[i].u,sno); /*将部门号写入部门结构体数组中*/
      unit[i].s=s1;    /*将实发工资写入部门结构体数组中*/
      i++;       /*部门数累加*/
      if(q==NULL)  /*如果q为空,跳出循环*/
  break;
      else
  p=q;   /*否则,将q赋值给p*/
   }
   printf("/n/n**************Total table**************/n");/*输出合计标题*/
   printf("/n--no-------unit------------total---------/n"); /*输出序号、部门、合计字段标题*/
   for(j=0;j<i;j++)
      printf("   %d        %s             %10.2f/n",j,unit[j].u,unit[j].s); /*输出合计值*/
   printf("----------------------------------------/n");
}

 

原创粉丝点击