案例一 贪吃蛇游戏 案例二 计算器 案例三 黑白棋游戏 案例四 迷宫问题 案例五 扫地雷游戏 案例六 速算24 案例七 数据结构CAI系统 案例八 进程调度 案例九 存储管理分区分配算法 案例十 通讯录 案例十一 学生成绩管理 案例十二 工资管理 案例十三 图书借阅管理 案例十四 教师工作量计算 #define N 200 #include #include #include #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;i595||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 /*DOS接口函数*/ #include /*数学函数的定义*/ #include /*屏幕操作函数*/ #include /*I/O函数*/ #include /*库函数*/ #include /*变量长度参数表*/ #include /*图形函数*/ #include /*字符串函数*/ #include /*字符操作函数*/ #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); /*返回键值*/ } /*3.3.4 源程序*/ #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;kk1)/*判断左边*/ { 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;kk1)/*判断上边*/ { 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;ii1&&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;iiscore1)/*开始判断最后的结果*/ outtextxy(100,50,"black win!"); else if(score2 #include #include #include #include #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=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(); } /*5.3.4 源程序*/ #include #include #include #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); } } } /*6.3.4 源程序*/ #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 ; /*返回*/ } /*2. 源程序*/ /***binary.c二分查找程序***/ #include #include #define N 15 /*结点数设为15*/ void find(int x[],int y,int z);/*具体查找过程*/ void Init(int x[],int *n);/*图形初始化*/ void Close();/*图形关闭*/ void Put(int x[],int y);/*输出数值*/ void Up(int x);/*画上箭*/ void Down(int x);/*画下箭*/ void Mid(int x);/*画中间箭*/ void Clr(int x);/*擦除画面上的一些内容*/ void Sort(int x[],int n);/*对随机数组排序*/ void main(void) { int a[N],x; Init(a,&x);/*x为要查找的数*/ Put(a,N); find(a,x,N); Close(); exit(0); } void Mid(int n)/*画中间键*/ { setcolor(WHITE);/*中间箭的颜色为白色,以下三条线画成了箭头,以下两个函数一样*/ line(25+n*40,120,25+n*40,80); line(25+n*40,120,20+n*40,110); line(25+n*40,120,30+n*40,110); } void Down(int n)/*画上箭*/ { setcolor(6); line(25+n*40,120,25+n*40,80); line(25+n*40,120,20+n*40,110); line(25+n*40,120,30+n*40,110); } void Up(int n)/*画下箭*/ { setcolor(6); line(25+n*40,180,25+n*40,220); line(25+n*40,180,20+n*40,190); line(25+n*40,180,30+n*40,190); } void Clr(int y)/*擦除画面上的一些内容*/ { setfillstyle(SOLID_FILL,0);/*每次演示的时候先将下面显示的文字给去处掉*/ bar(0,y+50,640,y-50);/*这里是用矩形的方式*/ } void Put(int a[],int n)/*输出数值*/ { int i; char num[5]; setcolor(GREEN); settextstyle(0,0,2);/*设置字体的大小*/ for(i=0;i"); outtextxy(350,250,str1); } sleep(2);/*间隔一秒好执行下一次*/ } setcolor(11); if(low<=high)/*找到*/ outtextxy(250,350,"FIND"); else/*没找到*/ outtextxy(250,350,"NOT FIND"); } void Sort(int a[],int n)/*冒泡排序,自上而下*/ { int i,j,t; for(i=0;ia[j+1]) { t=a[j]; a[j]=a[j+1]; a[j+1]=t; } /*数据交换*/ } void Init(int a[],int *x)/*图形驱动*/ { int i; int gd=DETECT,gm; randomize();/*随机函数*/ for(i=0;i # include #define N 8 /*定义排序数据为8个*/ void Init(int a[]);/*初始状态*/ void Close(void);/*图形模式结束*/ void Pr(int a[],int n);/*输出数组*/ void DrawChange(int i,int j);/*画交换箭头*/ void Bubble_sort(int a[],int n);/*冒泡排序*/ void main(void) { int i,a[N]; printf("Please enter 8 int number\n"); /*输入8个整数*/ for(i=0;ia[j+1])/*如果前面的大于后面的*/ { flag=1; /*置交换标志*/ DrawChange(i*40+80,j);/*画交换箭头*/ setcolor(RED); outtextxy(100+j*50,i*40+80,num1); outtextxy(100+(j+1)*50,i*40+80,num2); t=a[j];/*交换*/ a[j]=a[j+1]; a[j+1]=t; sleep(1); setfillstyle(SOLID_FILL,BLACK);/*黑巨型的方式把这行给删除*/ bar(0,i*40+60,640,i*40+100); } } Pr(a,i*40+80); /*输出数*/ sleep(1); if(flag==0)break; /*如果本次比较没有发生交换则跳出循环*/ } } /*2. 源程序*/ /***dblink.c***/ #include #include typedef struct Link/*双链表结点定义*/ { int data; struct Link *right; struct Link *left; int num;/*给链表加序号,为了演示时计算正确位置*/ }linkx,*linky; void Init(void);/*图形驱动*/ void Close(void);/*图形关闭*/ void InitList(void);/*建立双链表,边建立边插入*/ void PrLink(linky p,int n);/*每次插入后输出链表*/ void DrawChange(int data,int i,int n);/*画链表插入的指针变化*/ void main(void) { Init();/*图形关闭*/ InitList();/*建立链表*/ Close();/*图形关闭*/ exit(0); } void InitList(void) /*建立双向链表,边建立边插入*/ { linky head,p,q,s; int n=0; char str[5]; randomize();/*随机数发生机*/ setcolor(YELLOW); outtextxy(250,20,"any key to continue"); getch(); head=s=(linky)malloc(sizeof(linkx)); s->data=random(100);/*随机生成100以内的数字*/ s->num=n; sprintf(str,"%d",s->data);/*将数字转换成字符串并输出*/ settextstyle(0,0,2); setcolor(11); outtextxy(50+n*70,50,str);/*显示数据*/ sleep(1); s->right=NULL; s->left=NULL; PrLink(head,n);/*每次插入新数字后都显示当前链表*/ n++; while(n!=7) { s=(linky)malloc(sizeof(linkx)); s->data=random(100); s->num=n; sprintf(str,"%d",s->data);/*将数字转换成字符串并输出*/ setcolor(11); outtextxy(50+n*70,50,str); sleep(1); p=head;/*每生成一个结点,将该结点插入到有序双链表中*/ if(s->data<=head->data)/*小于头结点,插在头*/ { DrawChange(s->data,-1,n);/*显示插入的具体过程*/ s->right=head; s->left=NULL; s->num=0; head->left=s; head=s; q=head->right;/*后面所有数的序号都加1,相当于数据后移*/ while(q!=NULL) { q->num++; q=q->right; } } else/*其他情况*/ { while(s->data>p->data&&p!=NULL) { q=p; p=p->right; } if(p==NULL)/*这个数是当前最大的数,插在尾部*/ { DrawChange(s->data,n-1,n);/*显示插入的具体过程*/ q->right=s; s->right=NULL; s->left=q; s->num=n; } else /*结点插入位置位于两数之间*/ { q->right->left=s; s->right=q->right; s->left=q; q->right=s; s->num=q->num+1; DrawChange(s->data,q->num,n);/*显示插入的具体过程*/ /*后面所有数的序号都加1*/ s=s->right; while(s!=NULL) { s->num++; s=s->right; } } } PrLink(head,n);/*每次插入新数据后都显示新链表*/ n++; } } /*画链表插入的具体过程,data是要插入的数据,i为插入结点前驱结点序号,n为当前结点个数,先将前驱结点和后继之间的指针线擦除,显示新结点插入过程,插入后擦除插入过程,恢复删除的前驱结点的指针线*/ void DrawChange(int data,int i,int n) { char str[5]; setfillstyle(SOLID_FILL,BLACK); setcolor(RED);/*插入链表的新数据用红色显示*/ sprintf(str,"%d",data); outtextxy(50+70*i+35,100+n*50,str);/*输出插入的位置*/ bar(50+70*i+35,100+(n-1)*50-20,50+70*i+65,100+(n-1)*50+20); /*去除插入结点位置原结点间的指针线*/ setcolor(YELLOW); if(i!=-1) /*不是插在头,新结点的前驱指针线*/ { line(50+70*i+34,100+n*50,50+70*i+30,100+n*50); line(50+70*i+30,100+n*50,50+70*i+30,100+n*50-25); line(50+70*i+30,100+n*50-25,50+70*i+27,100+n*50-22); line(50+70*i+30,100+n*50-25,50+70*i+33,100+n*50-22); sleep(1); } if(i!=n-1)/*不是插在尾,新结点的后继指针线*/ { line(50+70*i+61,100+n*50,50+70*i+65,100+n*50); line(50+70*i+65,100+n*50,50+70*i+65,100+n*50-25); line(50+70*i+65,100+n*50-25,50+70*i+62,100+n*50-22); line(50+70*i+65,100+n*50-25,50+70*i+68,100+n*50-22); sleep(1); } setcolor(6); if(i!=-1)/*不是插在头,新结点前驱结点的后继指针线*/ { line(50+70*i+20,100+n*50-25,50+70*i+20,110+n*50); line(50+70*i+20,110+n*50,50+70*i+34,110+n*50); line(50+70*i+34,110+n*50,50+70*i+31,110+n*50-3); line(50+70*i+34,110+n*50,50+70*i+31,110+n*50+3); sleep(1); } if(i!=n-1) /*不是插在尾,新结点后继结点的前驱指针线*/ { line(50+70*i+75,100+n*50-25,50+70*i+75,110+n*50); line(50+70*i+75,110+n*50,50+70*i+61,110+n*50); line(50+70*i+61,110+n*50,50+70*i+64,110+n*50-3); line(50+70*i+61,110+n*50,50+70*i+64,110+n*50+3); } sleep(2); setcolor(WHITE); if(i!=n-1&&i!=-1)/*第一个节点和最后一个结点不恢复指针*/ { line(50+70*i+35,100+(n-1)*50,50+70*i+65,100+(n-1)*50);/*画前驱指针*/ line(50+70*i+35,100+(n-1)*50,50+70*i+40,95+(n-1)*50); line(50+70*i+35,110+(n-1)*50,50+70*i+65,110+(n-1)*50);/*画右指针*/ line(50+70*i+65,110+(n-1)*50,50+70*i+60,115+(n-1)*50); } bar(0,100+(n-1)*50+21,640,120+n*50);/*擦掉插入过程的指针线*/ } void PrLink(linky p,int n)/*每次插入后输出链表*/ { char str[5]; while(p!=NULL)/*不为空就输出*/ { sprintf(str,"%d",p->data); setcolor(GREEN); outtextxy(50+70*p->num,100+n*50,str); /*输出数据*/ setcolor(WHITE); if(p->left!=NULL)/*第一个节点不显示左指针*/ { line(50+70*(p->num-1)+35,100+n*50,50+70*(p->num-1)+65, 100+n*50);/*画左指针*/ line(50+70*(p->num-1)+35,100+n*50,50+70*(p->num-1)+ 40,95+n*50); } if(p->right!=NULL) { line(50+70*p->num+35,110+n*50,50+70*p->num+65,110+n*50);/*画右指针*/ line(50+70*p->num+65,110+n*50,50+70*p->num+60,115+n*50); } p=p->right; } } void Init(void)/*图形驱动*/ { int gd=DETECT,gm; initgraph(&gd,&gm,"c:\\tc"); cleardevice(); } void Close(void)/*图形关闭*/ { getch(); closegraph(); } /*3. 源程序*/ /***dsdemo.c演示系统***/ #include #include #define ESC 0x011b #define ENTER 0x1c0d #define DOWN 0x5000 #define UP 0x4800 struct Snow/*雪的一些参数*/ { int x; int y; int speed;/*雪花的速度*/ }snow[100]; struct Star/*星星的一些参数*/ { int x; int y; int color; }star[200]; int key;/*按键变量*/ int keyx,keyy;/*选项键的坐标*/ int snownum=0;/*雪的个数*/ int size;/*保存区域的大小*/ int change=10;/*变颜色有关*/ void *save1,*save2;/*保存空间*/ void Copy(void);/*保存区域*/ void DrawSnow(void);/*具体实现*/ void Pr(void);/*输出字体*/ void Choose(void);/*选择演示内容*/ void DrawStar(void);/*最后的星星效果*/ void DrawBall(int x,int y,int color);/*画选择的球体*/ void Init(void);/*图形驱动*/ void Close(void);/*图形关闭*/ void main(void) { Init(); Copy(); DrawSnow();/*雪花飘动*/ Choose();/*选择演示内容*/ DrawStar();/*结束画面*/ Close(); exit(0); } void Init(void) { int gd=DETECT,gm; initgraph(&gd,&gm,"c:\\tc"); cleardevice(); } void Close(void)/*图形关闭*/ { getch(); closegraph(); } void Copy(void)/*保存区域*/ { setcolor(0); setfillstyle(SOLID_FILL,15); fillellipse(200,200,4,4); size=imagesize(196,196,204,204);/*定义保存图象区域大小*/ save1=malloc(size);/*申请空间*/ save2=malloc(size); getimage(196,196,204,204,save1);/*保存雪花*/ getimage(96,96,104,104,save2); /*保存背景黑色*/ } void Pr(void)/*在雪中输出文字*/ { settextstyle(0,0,1); if(change>=20&&change<=30||change>=50&&change<=60|| change>=100&&change<=110)/*闪烁效果*/ setcolor(YELLOW); else setcolor(BLACK); outtextxy(250,250,"anykey to continue"); setcolor(change/10);/*变换颜色显示标题*/ settextstyle(0,0,3); outtextxy(100,200,"Data Structure Demo");/*标题*/ } /*显示雪花的具体过程*/ void DrawSnow(void) { int i; int sx[62]; randomize(); for(i=0;i<62;i++) /*定义雪花的x坐标*/ sx[i]=(i+2)*10; cleardevice(); while(!kbhit()) { Pr(); if(snownum!=100)/*生成新的雪花*/ { snow[snownum].speed=2+random(5);/*速度随机定,但不小于2*/ i=random(62); snow[snownum].x=sx[i];/*随机取x坐标*/ snow[snownum].y=10-random(100); } for(i=0;i500) snow[i].y=10-random(200); } change++; if(change==140)/*颜色变化*/ change=10; } } /*画选择的球体x和y为坐标,color为球的颜色*/ void DrawBall(int x,int y,int color) { setcolor(0); setfillstyle(SOLID_FILL,color); fillellipse(x,y+10,10,10); } /*选择演示函数*/ void Choose(void) { int yes;/*判断是否退出选项,1不退出0退出*/ int oyes=1; while(oyes) { Init(); cleardevice(); yes=1; keyx=140; keyy=150; setcolor(11); rectangle(40,40,600,440);/*画边框线/ setcolor(13); settextstyle(0,0,3);/*标题大一些*/ outtextxy(100,70,"Data Structure Demo"); settextstyle(0,0,2);/*其它选项小一些*/ setcolor(RED); outtextxy(200,150,"hanoi tower");/*汉诺塔*/ setcolor(BLUE); outtextxy(200,190,"double link");/*双链表*/ setcolor(GREEN); outtextxy(200,230,"bubble sorting"); /*起泡排序*/ setcolor(YELLOW); outtextxy(200,270,"radix sorting"); /*基数排序*/ setcolor(10); outtextxy(200,310,"binary serach"); /*二分查找*/ setcolor(MAGENTA); outtextxy(200,350,"binary tree"); /* 二叉树遍历*/ setcolor(WHITE); outtextxy(200,390,"exit");/*结束程序*/ DrawBall(keyx,keyy,11); while(yes) /*选项的循环条件*/ { key=bioskey(0); if(key==ESC)/*退出系统*/ break; if(key==UP)/*上键盘操作*/ { DrawBall(keyx,keyy,BLACK);/*先用黑色在原来位置去除球*/ if(keyy!=150) keyy-=40; else keyy=390; DrawBall(keyx,keyy,11);/*新位置输出球*/ } if(key==DOWN)/*下键盘操作*/ { DrawBall(keyx,keyy,BLACK);/*先用黑色在原来位置去除球*/ if(keyy!=390) keyy+=40; else keyy=150; DrawBall(keyx,keyy,11);/*新位置输出球*/ } if(key==ENTER)/*确定键*/ { switch(keyy)/*判断内容*/ { case 150:system("hanoi");yes=0;break;/*调用汉诺塔*/ case 190:system("dblink");yes=0;break;/*调用双链表*/ case 230:system("bubble");yes=0;break;/*调用起泡排序*/ case 270:system("radix");yes=0;break;/*调用基数排序*/ case 310:system("binary");yes=0;break;/*调用二分查找*/ case 350:system("tree2");yes=0;break; /*调用二叉树*/ case 390: yes=0;oyes=0;/*exit选项*/ }/*endswitch*/ } /*endenter*/ } /*endwhile*/ } /*endwhile*/ } /*结束画面*/ void DrawStar(void) { int i; cleardevice(); setcolor(GREEN); settextstyle(0,0,2); while(!kbhit()) { for(i=0;i<200;i++)/*随机生成星星*/ { star[i].x=random(640); star[i].y=random(480); star[i].color=random(13)+1; } for(i=0;i<200;i++)/*输出星星*/ { putpixel(star[i].x,star[i].y,star[i].color); delay(100); } outtextxy(100,200,"Thank you for use this system"); sleep(1); for(i=0;i<200;i++)/*去除星星*/ { putpixel(star[i].x,star[i].y,0); delay(50); } } } /*5. 源程序*/ /********hanoi.c*********/ #include struct H { int data[15];/*存放每个盘的代号*/ int top;/*每个塔的具体高度*/ }num[3];/*三个塔*/ void move(char x,char y,struct H num[3]);/*移动的具体过程*/ void hanoi(char x,char y,char z,int n,struct H num[3]);/*递归*/ void Init(void);/*初始化*/ void Close(void);/*图形关闭*/ int computer=1;/*自动控制与手动控制的标志*/ int speed=0;/*全局变量speed主要是演示过程的速度*/ void main(void) { Init();/*初始状态*/ Close();/*图形关闭*/ exit(0); } void Init(void)/*初始化*/ { int gd=DETECT,gm; int i,n,color; clrscr(); printf("please input n(n<=10): ");/*输入要演示的盘子数*/ scanf("%d",&n); printf("Please input 1 or 2:\n1.computer 2.people\n"); scanf("%d",&i); if(i==2)/*选择手动控制标志为0*/ computer=0; if(n<1||n>10) n=10;/*越界的话n当10处理*/ if(computer)/*如果是自动控制的话输入速度*/ { printf("please input speed: ");/*输入速度*/ scanf("%d",&speed); } initgraph(&gd,&gm,"c:\\tc"); cleardevice(); for(i=0;i<3;i++) num[i].top=-1;/*三个地方的高度开始都为-1*/ for(i=0;i"); outtextxy(310,30,num2); settextstyle(0,0,2); setfillstyle(SOLID_FILL,BLACK);/*把原来的地方移去涂黑*/ bar(100+150*(x-97)-(33-3*num[x-97].data[num[x-97].top]), 400-20*num[x-97].top-8,100+150*(x-97)+(33-3* num[x-97].data[num[x-97].top]),400-20*num[x-97].top+8); num[y-97].top++;/*入栈,目标点的top加1*/ num[y-97].data[num[y-97].top]=num[x-97].data[num[x-97].top];/*在目标点盘子的代号与源点盘子的代号相同*/ num[x-97].top--;/*出栈,原来地方的top减1*/ setfillstyle(SOLID_FILL,num[y-97].data[num[y-97].top]+1);/*盘子颜色代码是栈顶盘子代号加1*/ bar(100+150*(y-97)-(33-3*num[y-97].data[num[y-97].top]), 400-20*num[y-97].top-8,100+150*(y-97)+ (33-3*num[y-97].data[num[y-97].top]),400-20*num[y-97].top+8); if(computer)/*自动控制就用delay*/ delay(speed);/*延时函数*/ else getch();/*手动控制的话就自己按键盘来控制*/ } void hanoi(char one,char two,char three,int n,struct H num[3])/*递归n为盘子数,num为堆栈*/ { if(n==1) move(one,three,num);/*如果盘子为1,将这个盘子从塔座A移动到塔座C*/ else { hanoi(one,three,two,n-1,num);/*将塔座A的前n-1个盘子移到塔座B*/ move(one,three,num);/*将塔座A的第n个盘子移到塔座C*/ hanoi(two,one,three,n-1,num); /*将塔座B的n-1个盘子移到塔座C*/ } } void Close(void)/*图形关闭*/ { getch(); closegraph(); } /*3. 源程序*/ /***radix.c *****/ #define N 52 #include #include void Init(void);/*图形驱动*/ void Close(void);/*图形关闭*/ void Play(void);/*发牌的具体过程*/ void Rand(int i,int j);/*随机发牌函数*/ void Sort(); void DrawPuke(int kind,int x,int y,char num);/*画牌*/ char p[4][13]= {{'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','A'}, {'2','3','4','5','6','7','8','9','0','J','Q','K','A'}}; /*10用0来表示*/ struct Pai { char num; char kind; int realnum; int link; }newp[52]; /****主函数*****/ void main(void) { Init();/*初始化*/ Play(); getch(); cleardevice(); /*清屏*/ Sort(); /*排序*/ Close(); /*关闭*/ exit(0); } /**随机发牌函数,i和j代表行和列,共4行13列*/ void Rand(int i,int j) { int kind,num; char n; randomize();/*随机种子数*/ while(1)/*循环条件是可以有牌发为止*/ { kind=random(4);/*生成4以内的随机数*/ num=random(13); /*生成13以内的随机数*/ if(p[kind][num]!=-1)/*牌发好以后相应位置的元素置-1*/ { n=p[kind][num];/*从扑克牌中取数*/ p[kind][num]=-1; newp[j*4+i].kind=kind;/*将牌的花色保存*/ newp[j*4+i].num=n; /*将牌的面值符号保存*/ newp[j*4+i].realnum=num; /*将牌的对应十进制数值保存*/ break; } } DrawPuke(kind,i,j,n);/*显示牌*/ } /*画牌函数,kind花色, i代表行,j代表列,num表示面值符号 */ void DrawPuke(int kind,int i,int j,char num) { char str[3]; bar(50+j*45-15,50+i*100-30,50+j*45+15,50+i*100+30);/*画空牌*/ setcolor(BLUE); rectangle(50+j*45-13,50+i*100-28,50+j*45+13,50+i*100+28); switch(kind)/*花式的判断*/ { case 0:setcolor(BLACK);sprintf(str,"%c",3);break;/* a黑桃*/ case 1:setcolor(RED);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,1); outtextxy(50+j*45-11,50+i*100-26,str);/*显示牌的左上角花色*/ outtextxy(50+j*45+5,50+i*100+20,str); /*显示牌的右下角花色*/ if(num!='0')/*输出其它牌*/ { settextstyle(0,0,2); sprintf(str,"%c",num); outtextxy(50+j*45-5,50+i*100-5,str);/*显示牌的大小*/ } else/*输出10的时候*/ { sprintf(str,"%d",10); outtextxy(50+j*45-6,50+i*100-5,str); } } void Play(void)/*发牌的具体过程*/ { int i,j; for(j=0;j<13;j++) { for(i=0;i<4;i++) { Rand(i,j);/*随机发牌*/ delay(10000);/*延时*/ } } } /*基数排序*/ void Sort() { int i,j,k,t,p,f[13],e[13]; for(i=0;i #include #include #include #include typedef struct TREE { char data;/*树的结点数据*/ struct TREE *lchild; struct TREE *rchild; int x;/*树的x坐标*/ int y;/*树的y坐标*/ }Tree; struct OUTPUT { int x;/*三种遍历的x坐标*/ int y;/*三种遍历的y坐标*/ int num; }s; int nodeNUM=0;/*统计当前的结点数字,最多26个*/ char way;/*自动建立树和手动建立树的标志,2手动,1自动*/ char str[3];/*显示结点数据的字符串*/ void Init();/*图形初始化*/ void Close();/*图形关闭*/ Tree *CreatTree();/*文本模式下创建树的过程*/ Tree *InitTree(int h,int t,int w);/*创建树,h层次,t横坐标,w树之间的宽度,n树的建立方式*/ void DrawTree(Tree *t);/*用图形显示创建好的树*/ void Preorder(Tree *t);/*前序遍历*/ void Midorder(Tree *t);/*中序遍历*/ void Posorder(Tree *t);/*后序遍历*/ void DrawNode(Tree *t,int color);/*遍历时显示每个结点的过程*/ void ClrScr();/*清空树的区域*/ void main() { Tree *root; randomize(); root=CreatTree();/*创建树*/ Init(); DrawTree(root);/*每次遍历前显示白色的树*/ sleep(1); s.x=100;s.y=300;s.num=1;/*每次遍历前设置显示遍历顺序显示的x,y坐标*/ Preorder(root);/*前序遍历*/ getch(); ClrScr(); DrawTree(root); sleep(1); s.x=100; s.y=350; s.num=1; Midorder(root);/*中序遍历*/ getch(); ClrScr(); DrawTree(root); sleep(1); s.x=100; s.y=400; s.num=1; Posorder(root);/*后序遍历*/ Close(); } /*清空树的区域*/ void ClrScr() { setcolor(BLACK); setfillstyle(SOLID_FILL,BLACK); bar(0,20,640,280); } /*文本模式下创建树的过程*/ Tree *CreatTree() { Tree *root; clrscr(); printf("please input n\n"); printf("1.computer creat\n"); printf("2.people creat\n"); way=getch();/*输入创建树的方法,1电脑自动建立,2人工手动建立*/ if(way!='2') way='1';/*其他数字默认自动建立*/ if(way=='2')/*手动建立提示输入结点*/ printf("Please creat the tree\n"); root=InitTree(1,320,150); system("pause"); return root; } /*生成二叉树,h表示层次,t表示横坐标,w表示结点左右子树的宽度,随机数n确定结点是空或非空,如n为0,则为空*,但要限定确保结点数不少于三个*/ Tree *InitTree(int h,int t,int w) { char ch; int n;/*自动建立时随机赋值判断是否是NULL的标志*/ Tree *node; if(way=='2')/*手动建立需要自己输入*/ scanf("%c",&ch); else/*自动建立的赋值*/ { n=random(5); if(n==0&&nodeNUM>=3)/*随机赋值时候确保自动建立的二叉树有三个结点*/ ch='.'; else ch=65+random(25); } if(ch=='.')/*输入空格代表NULL*/ return NULL; else { if(h==6||nodeNUM==26)/*如果树的层次已经到5或者结点树到达26个就自动返回NULL*/ return NULL; node=(Tree*)malloc(sizeof(Tree)); node->data=ch; node->x=t;/*树的x坐标是传递过来的横坐标*/ node->y=h*50;/*树的y坐标与层次大小有关*/ nodeNUM++; node->lchild=InitTree(h+1,t-w,w/2); node->rchild=InitTree(h+1,t+w,w/2); } return node; } /*用图形显示创建好的树*/ void DrawTree(Tree *t) { if(t!=NULL) { setcolor(BLACK); setfillstyle(SOLID_FILL,BLACK); fillellipse(t->x,t->y,9,9); setcolor(WHITE); circle(t->x,t->y,10); /*画圆*/ sprintf(str,"%c",t->data);/*将内容转换成字符串输出*/ outtextxy(t->x-3,t->y-2,str); if(t->lchild!=NULL)/*左子树*/ { line(t->x-5,t->y+12,t->lchild->x+5,t->lchild->y-12); DrawTree(t->lchild); } if(t->rchild!=NULL)/*右子树*/ { line(t->x+5,t->y+12,t->rchild->x-5,t->rchild->y-12); DrawTree(t->rchild); } } } /*遍历时显示每个结点的过程*/ void DrawNode(Tree *t,int color) { setcolor(YELLOW); setfillstyle(SOLID_FILL,YELLOW); fillellipse(t->x,t->y,10,10); setcolor(RED); sprintf(str,"%c",t->data);/*将内容转换成字符串输出*/ outtextxy(t->x-3,t->y-2,str); setcolor(color); outtextxy(s.x,s.y,str); setcolor(RED); sprintf(str,"%d",s.num);/*将遍历次序用数字显示在树的结点上*/ outtextxy(t->x-3,t->y-20,str); s.num++; sleep(1); } /*前序遍历*/ void Preorder(Tree *t) { if(t!=NULL) { s.x+=15; DrawNode(t,GREEN); Preorder(t->lchild); Preorder(t->rchild); } } /*中序遍历*/ void Midorder(Tree *t) { if(t!=NULL) { Midorder(t->lchild); s.x+=15; DrawNode(t,YELLOW); Midorder(t->rchild); } } /*后序遍历*/ void Posorder(Tree *t) { if(t!=NULL) { Posorder(t->lchild); Posorder(t->rchild); s.x+=15; DrawNode(t,BLUE); } } /*图形初始化*/ void Init() { int gd=DETECT,gm; initgraph(&gd,&gm,"c:\\tc"); cleardevice(); setcolor(YELLOW); outtextxy(250,10,"anykey to continue"); setcolor(RED); outtextxy(20,300,"preorder"); outtextxy(20,350,"midorder"); outtextxy(20,400,"posorder"); getch(); } /*图形关闭*/ void Close() { getch(); closegraph(); } /*8.3.2 源程序*/ #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->prioprio)) { 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); } } /*9.3.2 源程序*/ /***pcb.c***/ #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->sizenext; 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->sizesize) /*修改最大块值和最大块个数*/ { 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->sizesize) /*修改最大块值和最大块数*/ { 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->addressaddress) &&(back1->address+back1->size>before->address)) ||((back1->address>=before->address) &&(back1->addressaddress+before->size))) check=0; else before=before->next; if(check==0) printf("Error input!!\n"); return check; /*返回检查结果*/ } /*10.3.2源程序*/ /******头文件(.h)***********/ #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;in-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;in-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=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=0&&id0) /*比较大小*/ { 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;i14); /*选择项不在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;iscore[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;iscore[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;iscore[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->sumsum&&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"); } /*12.3.2 源程序*/ /******头文件(.h)***********/ #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 #include #include #include #include #include #define LEFT 0x4b00 /*左*/ #define RIGHT 0x4d00 /*右*/ #define DOWN 0x5000 /*下*/ #define UP 0x4800 /*上*/ #define SPACE 0x3920 /*空格*/ #define ESC 0x011b /* ESC键*/ #define ENTER 0x1c0d /*回车键*/ #define Backspace 0xe08 /*擦除键*/ #define ALT_B 12288 /*组合键ALT_B */ #define ALT_M 12800/*组合键ALT_M */ #define ALT_H 8960/*组合键ALT_H */ int key;/*按键变量*/ int textx,texty;/*光标坐标,x行,y列*/ struct menustruct/*菜单用的结构体*/ { char name[10];/*主菜单名*/ char str[10][20];/*选项*/ int n;/*选项数*/ }ml[3];/*使用了3个,可根据需要增删*/ typedef struct BookList/*书的结构体*/ { char num[20];/*图书编号*/ char name[20];/*书名*/ int price;/*书的价格*/ char person[20];/*借阅人*/ int yes;/*判断书是否存在或者已经借出,1存在,0借出*/ struct BookList *next; }Book; typedef struct MemberList/*会员的结构体*/ { char name[20];/*会员的姓名*/ char sex[2];/*会员的性别*/ int age;/*会员的年龄*/ struct MemberList *next; }Member; char save[4096];/*保存文本区域空间*/ /*char sav1[4096];*/ char c[4096];/*清屏专用空间*/ int i,j;/*常用变量*/ void Menu();/*初始化界面*/ void Selectitem();/*定义菜单*/ void DrawSelectitem();/*显示主菜单*/ void BlackText(int x,int y,char *z);/*选中菜单*/ void RedText(int x,int y,char *z);/*正常菜单*/ void Run();/*具体操作过程*/ void DrawMl(int n);/*显示下拉菜单*/ void MoveMl(int n,int x);/*菜单选项的控制*/ void Enter(int m,int n);/*菜单选项的具体功能*/ void BookAdd();/*添加图书*/ void BookConsult();/*图书查询*/ void BookDel();/*删除图书资料*/ void BookBorrow();/*借书*/ void BookReturn(); /*还书*/ void MemberAdd(); /*增加会员*/ void MemberConsult();/*查询会员*/ void MemberDel(); /*删除会员*/ void MemberBook(); /*查询会员借书信息*/ void Help(); /*帮助*/ void Ver(); /*版本信息*/ void ClrScr();/*自定义清屏函数*/ void DrawFrame(int left,int up,int right,int down,int textcolor,int backgroundcolor);/*画边框*/ /***主函数****/ void main(void) { Menu();/*初始化界面*/ Run();/*具体操作过程*/ } /*初始化界面*/ void Menu() { system("cls"); /*调用系统的清屏命令*/ textbackground(BLUE);/*将背景设置为蓝色*/ window(1,1,25,80); clrscr(); textx=3;/*光标初始化位置*/ texty=2; gotoxy(1,2); printf("%c",218);/*画左上角*/ for(i=0;i<78;i++) printf("%c",196); /*画水平直线*/ printf("%c",191);/*画右上角*/ for(i=3;i<=23;i++) { gotoxy(1,i); printf("%c",179); /*画垂直线*/ gotoxy(80,i); printf("%c",179); } printf("%c",192); /*画左下角*/ for(i=0;i<78;i++) printf("%c",196); printf("%c",217); /*画右下角*/ gotoxy(1,1); textcolor(7); /*设置灰色*/ for(i=0;i<80;i++) cprintf("%c",219);/*用符号实现画主菜单的灰色背景区*/ Selectitem(); /*调用选项函数*/ DrawSelectitem(); /*画选项*/ gettext(2,3,78,23,c); /*保存当前文本区域*/ } /*定义菜单*/ void Selectitem() { strcpy(ml[0].name,"Book");/*下面的具体选项补空格是为了各菜单黑色背景相同*/ strcpy(ml[0].str[0],"Add ");/*添加图书*/ strcpy(ml[0].str[1],"Consult ");/*查询图书*/ strcpy(ml[0].str[2],"Del ");/*删除图书资料*/ strcpy(ml[0].str[3],"Borrow ");/*借书*/ strcpy(ml[0].str[4],"Return ");/*还书*/ strcpy(ml[0].str[5],"Exit ");/*退出系统*/ ml[0].n=6; /*保存菜单的项数*/ strcpy(ml[1].name,"Member"); strcpy(ml[1].str[0],"Add ");/*添加新会员*/ strcpy(ml[1].str[1],"Consult ");/*查询会员资料*/ strcpy(ml[1].str[2],"Del ");/*删除会员资料*/ strcpy(ml[1].str[3],"Member&book "); ml[1].n=4; strcpy(ml[2].name,"Help");/*系统帮助*/ strcpy(ml[2].str[0],"This System "); strcpy(ml[2].str[1],"Ver "); ml[2].n=2; } /*显示主单名*/ void DrawSelectitem() { for(i=0;i<3;i++) RedText(i,1,ml[i].name); /*显示主菜单名,且首字母为红色*/ } /*正常显示菜单*/ void RedText(int x,int y,char *z) { textbackground(7); /*设置背景颜色为浅灰色*/ gotoxy(3+x*20,y); for(j=0;z[j];j++) { if(j==0) textcolor(RED);/*第一个字母显示红色*/ else textcolor(BLACK); /*设置黑色*/ cprintf("%c",z[j]); /*输出菜单名*/ } } /*显示选中菜单*/ void BlackText(int x,int y,char *z) { textbackground(0); /*设置背景颜色为黑色*/ textcolor(15); /*设置文本颜色为白色*/ gotoxy(3+20*x,y);/*定位坐标*/ cputs(z); /*输出菜单名字符串*/ } /*按键操作过程*/ void Run() { while(1) { gotoxy(texty,textx); key=bioskey(0);/*接收按键*/ switch(key) { case ALT_B: case ESC: DrawMl(0);break; /*显示下拉菜单1*/ case ALT_M: DrawMl(1);break;/*显示下拉菜单2*/ case ALT_H: DrawMl(2);/*显示下拉菜单3*/ case UP: /*上光标键的操作控制*/ { if(textx==3) textx=23; textx--; gotoxy(texty,textx); }break; case DOWN: /*下光标键的操作控制*/ { if(textx==23) textx=3; textx++; gotoxy(texty,textx); }break; case LEFT: /*左光标键的操作控制*/ { if(texty==2) texty=79; texty--; gotoxy(texty,textx); }break; case Backspace: /*擦除键的设置*/ { if(texty==2&&textx==3) continue; else { if(texty!=2) texty--; /*擦除键的细节问题,先擦去东西,然后光标还要往后退一格*/ else if(texty==2) { texty=78; textx--; } gotoxy(texty,textx); printf(" "); gotoxy(texty,textx); } }break;/*end case 0xe08*/ case RIGHT: /*右光标键的操作控制*/ { if(texty==79) texty=2; texty++; gotoxy(texty,textx); }break; case SPACE: /*空格键的操作*/ { if(texty==79) continue; else { gotoxy(texty,textx); /*空格的细节操作*/ printf(" "); texty++; gotoxy(texty,textx); } }break; case ENTER: /*回车的控制操作*/ { if(textx==23) continue; textx++; texty=2; gotoxy(texty,textx); }break; default : /*非控制键的结果*/ { if(texty==79&&textx==23)/*到达最后就不再输出*/ continue; else if(texty==79&&textx!=23) /*到行的最后*/ { textx++; texty=2; } gotoxy(texty,textx);/*输出结果*/ printf("%c",key); if(texty==79) /*如果texty==79就不执行*/ continue; else /*如果没到行尾就继续执行,使光标向前移动一位*/ texty++; } } }/*大循环的大括号*/ } /*画边框函数*/ void DrawFrame(int l,int u,int r,int d,int tcolor,int bcolor) { textbackground(bcolor); /*背景颜色*/ textcolor(bcolor); /*文本颜色*/ for(i=l;i<=r;i++) /*输出背景区域*/ { for(j=u;j<=d;j++) { gotoxy(i,j); printf("%c",219); /*输出背景字符*/ } } textcolor(tcolor);/*边框颜色*/ for(i=u+1;inext=p;/*新记录插入到链表的尾*/ } p->next=NULL;/*最后一个结点的后继为空*/ fclose(fp); ClrScr(); printf("Input the book name: "); gets(bookname); /*输入图书名*/ p=head; while(p!=NULL)/*按名字查找要删除的图书*/ { if(strcmp(p->name,bookname)==0)/*找到要删除的图书*/ { if(p==head) /*如果是第一个结点*/ head=head->next; else q->next=p->next;/*不是第一个结点*/ break; } q=p; /*指针后移*/ p=p->next; } fp=fopen("book.txt","wb");/*删除后从链表的头开始重新保存*/ while(head!=NULL) { fwrite(head,sizeof(Book),1,fp);/*块写*/ head=head->next; } fclose(fp); ClrScr(); } /*借书*/ void BookBorrow() { FILE *fp; Book consultbook; Member consultmember; char bookname[20],membername[20]; int flag=0,mflag=0; ClrScr(); gotoxy(2,3); printf("Input the mermber name: "); gets(membername); /*输入会员名*/ if((fp=fopen("member.txt","rb"))==NULL)/*没找到文件*/ { gotoxy(3,3); printf("Cannot open file\n!"); return; } else while(!feof(fp))/*查询会员资料*/ { fread(&consultmember,sizeof(Member),1,fp); if(strcmp(consultmember.name,membername)==0) { mflag=1; /*是会员标志*/ break; } } fclose(fp); if(mflag==0) { gotoxy(2,4); printf("You not is a member,pleas register!");/*不是会员不能借书*/ return; } gotoxy(3,5); printf("Input the book name: "); gets(bookname); /*输入图书名*/ ClrScr(); if((fp=fopen("book.txt","rb+"))==NULL)/*没找到文件*/ { gotoxy(2,3); printf("Cannot open file\n!"); return; } while(!feof(fp))/*查询图书资料*/ { fread(&consultbook,sizeof(Book),1,fp); if(strcmp(consultbook.name,bookname)==0) { if(consultbook.yes==0)/*图书已经借出的判断*/ { gotoxy(2,3); printf("This book has borrowed\n!"); break; } else { consultbook.yes=0; /*作借出标志*/ strcpy(consultbook.person,membername);/*登记借书会员*/ fseek(fp,-1L*sizeof(Book),1);/*从当前位置前移一条记录指针*/ fwrite(&consultbook,sizeof(Book),1,fp);/*写记录*/ gotoxy(2,3); printf("Borrowed succ!"); flag=1;/*借出书标志*/ break; } } } if(flag!=1) { ClrScr(); gotoxy(2,3); printf("Borrowed fail!\n");/*借书失败*/ } fclose(fp); } /*还书*/ void BookReturn() { FILE *fp; Book consultbook; char bookname[20]; int flag=0; ClrScr(); if((fp=fopen("book.txt","rb+"))==NULL)/*没找到文件*/ { gotoxy(2,3); printf("cannot open file\n!"); return; } printf("Input the book name: "); gets(bookname); /*输入图书名*/ ClrScr(); while(!feof(fp))/*查询图书资料*/ { fread(&consultbook,sizeof(Book),1,fp); if(strcmp(consultbook.name,bookname)==0) { if(consultbook.yes==0)/*图书已经借出的判断*/ { consultbook.yes=1;/*作图书未借书标志,表示已还书*/ strcpy(consultbook.person,""); fseek(fp,-1L*sizeof(Book),1); fwrite(&consultbook,sizeof(Book),1,fp); gotoxy(2,3); printf("Return book succ!"); flag=1; break; } } } if(flag!=1) printf("Return fail!\n"); fclose(fp); } /*清除屏幕*/ void ClrScr() { int i,j; puttext(2,3,78,23,c);/*刚开始已经用gettext把蓝色的一块地方保存下来,现在再还原*/ gotoxy(2,3); } /*会员注册*/ void MemberAdd() { FILE *fp; Member consultmember; fp=fopen("member.txt","rb"); if(fp==NULL)/*如果没会员就新建*/ fp=fopen("member.txt","wb"); else/*如果有会员就添加*/ { fclose(fp); fp=fopen("member.txt","ab");/*追加方式打开*/ } ClrScr(); gotoxy(2,3); printf("Intput new member name: ");/*逐个输入会员的资料*/ gets(consultmember.name); gotoxy(2,4); printf("Input member sex: "); gets(consultmember.sex); gotoxy(2,5); printf("Please input member age: "); scanf("%d%*c",&consultmember.age); fwrite(&consultmember,sizeof(Member),1,fp);/*写入记录*/ fclose(fp); ClrScr(); } /*查询会员*/ void MemberConsult() { FILE *fp; Member consultmember; char membername[20]; int flag=0; ClrScr(); gotoxy(2,3); printf("Input the member name: ");/*输入要查询的会员名*/ gets(membername); fp=fopen("member.txt","rb"); if(fp==NULL)/*没找到文件*/ { ClrScr(); gotoxy(2,3); printf("Error!"); fclose(fp); return; } while(!feof(fp))/*查询会员资料*/ { fread(&consultmember,sizeof(Member),1,fp); if(strcmp(consultmember.name,membername)==0)/*比较*/ { ClrScr(); gotoxy(2,3); printf("This member %s information as follow:",consultmember.name); gotoxy(2,4); printf("This member'sex is %s",consultmember.sex); gotoxy(2,5); printf("This member 's age is %d",consultmember.age); flag=1; break; } } if(flag==0) { ClrScr(); gotoxy(2,3); printf("No found this member!"); } fclose(fp); } /*删除会员资料*/ void MemberDel() { FILE *fp; Member *head,*p,*q; char membername[20]; fp=fopen("member.txt","rb"); if(fp==NULL)/*没找到文件*/ { gotoxy(2,3); printf("Error!"); fclose(fp); return; } head=p=q=(Member*)malloc(sizeof(Member));/*将文件内容放入链表*/ fread(p,sizeof(Member),1,fp); while(!feof(fp)) { q=p; p=(Member*)malloc(sizeof(Member)); fread(p,sizeof(Member),1,fp);/*读记录*/ q->next=p;/*链入到链表的尾部*/ } p->next=NULL; fclose(fp); ClrScr(); printf("Input the member name: ");/*输入会员名*/ gets(membername); p=head; while(p!=NULL)/*按名字查找要删除的书*/ { if(strcmp(p->name,membername)==0)/*查找会员*/ { if(p==head) head=head->next;/*如果是第一条记录*/ else q->next=p->next;/*不是第一条记录*/ break; } q=p; /*没找到,则指针后移继续找*/ p=p->next; } fp=fopen("member.txt","wb");/*删除后重新保存*/ while(head!=NULL) { fwrite(head,sizeof(Member),1,fp);/*块写*/ head=head->next; } fclose(fp); ClrScr(); } /*查询会员所借的图书*/ void MemberBook() { FILE *fp; Book consultbook; Member consultmember; char bookname[20],membername[20]; int flag=0,mflag=0,i=0; ClrScr(); gotoxy(2,3); printf("Input the mermber name: ");/*输入会员名*/ gets(membername); if((fp=fopen("member.txt","rb"))==NULL)/*没找到文件*/ { gotoxy(3,3); printf("Cannot open file\n!"); return; } else while(!feof(fp))/*查询会员资料,确认会员*/ { fread(&consultmember,sizeof(Member),1,fp); if(strcmp(consultmember.name,membername)==0) { mflag=1; break; } } fclose(fp); if(mflag==0) { gotoxy(2,4); printf("Not the member!"); return; } ClrScr(); if((fp=fopen("book.txt","rb+"))==NULL)/*没找到文件*/ { gotoxy(2,3); printf("Cannot open file\n!"); return; } while(!feof(fp))/*查询图书资料*/ { fread(&consultbook,sizeof(Book),1,fp); gotoxy(2,3); printf("This member %s has borrowed book as follow:",membername); gotoxy(2,4); printf("********************************************"); if(strcmp(consultbook.person,membername)==0)/*借阅人比较*/ { gotoxy(2,5+i*4); printf("Book name is %s",consultbook.name); gotoxy(2,6+i*4); printf("This book num is %s",consultbook.num); gotoxy(2,7+i*4); printf("This book's price is %d",consultbook.price); printf("\n"); i++; flag=1; } } if(flag!=1) { ClrScr(); gotoxy(2,3); printf("no Borrow book!\n"); } else { gotoxy(2,i*4+6); printf("******total is %d*********",i);/*显示总数*/ } fclose(fp); } /*帮助文件*/ void Help() { ClrScr(); DrawFrame(10,5,50,8,0,7); /*画边框*/ gotoxy(15,6); cprintf("click menu to run each funtion");/*输出字符串*/ getch(); ClrScr(); } /***版本信息***/ void Ver() { ClrScr(); DrawFrame(10,5,50,8,0,7); /*画边框*/ gotoxy(15,6); cprintf("Ver 1.0 finished by zhuyun");/*输出字符串*/ getch(); ClrScr(); } /*1. mouse.c源程序*/ /***mouse.c***/ #include "dos.h" /*鼠标光标显示*/ void MouseOn() { _AX=0x01; geninterrupt(0x33);/*产生软中断*/ } /*鼠标光标隐藏*/ void MouseOff() { _AX=0x02; geninterrupt(0x33); } /*设置鼠标当前位置x和y*/ void MouseSetXY(int x,int y) { _CX=x; _DX=y; _AX=0x04; geninterrupt(0x33); } /*读取鼠标状态,x和y返回鼠标位置,status返回鼠标击键操作代码 */ void MouseStatus(int *x,int *y,int *status) { union REGS regs; /*寄存器变量*/ regs.x.ax=3; int86(0x33,®s,®s); *x=regs.x.cx; *y=regs.x.dx; *status=regs.x.bx; } /*7. teacher.c源程序*/ /******* teacher.c***********/ /******头文件、函数原型及全局变量定义***********/ #include "stdio.h" #include "bios.h" #include "dos.h" #include "conio.h" #include "stdlib.h" #include "string.h" #include "mem.h" #include "ctype.h" #include "alloc.h" #include "stdio.h" #include "graphics.h" #include "d:\cbook\14\c14_m.c" /*根据实际存放位置设*/ typedef struct t1 { char no[11]; char name[15]; char sex[5]; char profess[15]; char dept[15]; char class[15]; float workload; float lessonf; struct t1 *prior; struct t1 *next; }TEACHER; TEACHER *First; TEACHER *Last; TEACHER *p; void init(); /*初始化双链表*/ void firstr(); /*显示头一条*/ void lastr();/*显示最后一条*/ void priorr(); /*显示前一条*/ void nextr();/*显示下一条*/ void clear(); /*清除显示信息*/ void delete(); /*删除当前记录*/ void save(); /*保存*/ void load();/*读入文件*/ void sort();/*排序*/ void create(); /*创建双链表*/ void print(TEACHER*p); /*输出数据*/ void run(int m,int n); /*调用各功能*/ void button(int buttonx1,int buttony1,int buttonx2, int buttony2,char *name,int stat); /*按钮*/ void wins(int x1,int y1,int x2,int y2); /*窗口*/ void realwin(int x1,int y1,int x2,int y2);/*校验窗口*/ void mousewin(); /*主控界面*/ void cross(int y1,int x2,int press); /*关闭按钮*/ char *Str[]={"First","Prior","Next","Last","Clear", "Delete","Load","Save","Sort","Exit"}; /*命令项*/ /*********主函数**********/ void main() { char ch; int gdriver,gmode,i,j; init(); printf("Do you create new table(Y/N)\n"); ch=getchar(); if(ch=='Y'||ch=='y') create(); gdriver=DETECT; initgraph(&gdriver,&gmode,""); mousewin(); closegraph(); } /**按钮实现函数,buttonx1和 buttony1为按钮的左上角的坐标,buttonx2和 buttony2为按钮的右下角的坐标,*name为按钮上显示的字符串名,stat为按钮类型,0为平面,1为凸起,2为凹下,3为兰色平面*/ void button(int buttonx1,int buttony1,int buttonx2, int buttony2,char *name,int stat) { if(stat==0) /*显示平面按钮*/ { setcolor(BLACK); outtextxy(buttonx1+3,buttony1+4,name); } if(stat==1) /*显示凸起按钮*/ { setfillstyle(1,WHITE); bar(buttonx1,buttony1,buttonx2,buttony2); setfillstyle(1,DARKGRAY); bar(buttonx1+1,buttony1+1,buttonx2,buttony2); setfillstyle(1,LIGHTGRAY); bar(buttonx1+1,buttony1+1,buttonx2-1,buttony2-1); setcolor(BLACK); outtextxy(buttonx1+3,buttony1+4,name); } if(stat==2) /*显示凹下按钮*/ { setfillstyle(1,DARKGRAY); bar(buttonx1,buttony1,buttonx2,buttony2); setfillstyle(1,WHITE); bar(buttonx1+1,buttony1+1,buttonx2,buttony2); setfillstyle(1,LIGHTGRAY); bar(buttonx1+1,buttony1+1,buttonx2-1,buttony2-1); setcolor(BLACK); outtextxy(buttonx1+3,buttony1+4,name); } if(stat==3) /*显示平面兰色背景按钮*/ { setfillstyle(1,DARKGRAY); bar(buttonx1,buttony1,buttonx2,buttony2); setfillstyle(1,WHITE); bar(buttonx1+1,buttony1+1,buttonx2,buttony2); setfillstyle(1,BLUE); bar(buttonx1+1,buttony1+1,buttonx2-1,buttony2-1); setcolor(WHITE); outtextxy(buttonx1+3,buttony1+4,name); } } /****窗口函数,x1和y1为左上角坐标,x2和y2为右下角坐标*/ void wins(int x1,int y1,int x2,int y2) { char lable[][10]={"No","Name","Sex", "Profess","Dept", "Class","Workload","LessonF"}; /*标签信息*/ int m,n; setfillstyle(1,WHITE);/*画窗口*/ bar(x1,y1,x2,y2); setfillstyle(1,LIGHTGRAY); bar(x1+1,y1+1,x2,y2); setfillstyle(1,BLUE); /*画兰色标题栏*/ bar(x1+3,y1+3,x2-3,y1+20); cross(y1,x2,0); /*画关闭按钮*/ outtextxy(x1+5,y1+8,"teacher LessonF");/*输出标题文字*/ for(m=0;m<4;m++) for(n=0;n<2;n++) { button(x1+n*250+20,y1+50+m*30+20,x1+n*250+90, y1+50+m*30+40,lable[n+m*2],2);/*标签信息*/ setfillstyle(1,WHITE); bar(x1+n*250+100,y1+50+m*30+20,x1+n*250+200,y1+50+m*30+40); /*白色背景显示数据区*/ } settextstyle(0,0,1); for(m=0;m<2;m++) for(n=0;n<5;n++) button(x1+n*100+10,y1+200+m*30+20,x1+n*100+80, y1+200+m*30+40,Str[n+m*5],1); /*显示凸起命令按钮*/ } /*关闭按钮函数y1和x2分别是窗口的左上角的y坐标和右下角的x坐标,*/ void cross(int y1,int x2,int press) { if(press==1) setfillstyle(1,BLACK); else setfillstyle(1,WHITE); bar(x2-17,y1+5,x2-5,y1+18);/*画矩形区域*/ setfillstyle(1,LIGHTGRAY); bar(x2-16,y1+6,x2-5,y1+18); setwritemode(EMPTY_FILL);/*用背景颜色填充*/ setcolor(BLACK); setlinestyle(0,0,3); /*设置线型*/ line(x2-14,y1+8,x2-8,y1+16);/*画交叉线*/ line(x2-8,y1+8,x2-14,y1+16); } /*鼠标操作控制处理函数*/ void mousewin() { union REGS inregs,outregs; int x1,y1,i,m,n,state; int press=0,close=0,cpress=0; int winx1=70,winy1=100,winx2=570,winy2=400;/*设置窗口坐标*/ MouseSetXY(50,50); /*设置鼠标位置*/ MouseOn(); /*显示鼠标*/ wins(winx1,winy1,winx2,winy2);/*显示窗口主界面*/ while(1) { press=0;/*是否选择了exit菜单*/ cpress=0; /*是否单击了命令按钮*/ MouseStatus(&x1,&y1,&state);/*读鼠标状态*/ while(x1>winx1+3&&x1winy1+21&&y1winx1+3&&x1winy1+35&&y1winx1+3&&x1winy1+21&&y1winx1+3&& x1winy1+35&&y1winx1+3&&x1winy1+21&&y1winx2-17&&y1>winy1+5&&x1winx1+5&&y1>winy1+220&&x180&&x1<150) if(y1>320&&y1<340)/*单击了First命令按钮*/ {m=0;n=0;} else {m=1;n=0;} /*单击了Delete命令按钮*/ if(x1>180&&x1<250) if(y1>320&&y1<340) {m=0;n=1;} /*单击了Prior命令按钮*/ else {m=1;n=1;} /*单击了Load命令按钮*/ if(x1>280&&x1<350) if(y1>320&&y1<340) {m=0;n=2;} /*单击了Next命令按钮*/ else {m=1;n=2;} /*单击了Save命令按钮*/ if(x1>380&&x1<450) if(y1>320&&y1<340) {m=0;n=3;} /*单击了Last命令按钮*/ else {m=1;n=3;} /*单击了Sort命令按钮*/ if(x1>480&&x1<550) if(y1>320&&y1<340) {m=0;n=4;} /*单击了Clear命令按钮*/ else {m=1;n=4;} /*单击了Exit命令按钮*/ cpress=1; break; } } } if(cpress==1) { button(winx1+n*100+10,winy1+200+m*30+20,winx1+n*100+80, winy1+200+m*30+40,Str[n+m*5],2); /*单击的按钮凹下显示*/ run(m,n); /*调用相应的功能*/ } } /*结束while(1)*/ } /********功能调用函数,参数m和n代表按钮行和列位置********/ void run(int m,int n) { switch(n+m*5) { case 0:firstr();break; case 1:priorr();break; case 2:nextr();break; case 3:lastr();break; case 4:clear();break; case 5:delete();break; case 6:load();break; case 7:save();break; case 8:sort();break; case 9:exit(0); }/*结束switch*/ } /*13. teacherfun.c源程序*/ /*** teacherfun.c ***/ #include "d:\cbook\14\c14_t.c" /*根据实际存放位置修改此路径*/ /*初始化双链表*/ void init() { First=(TEACHER *)malloc(sizeof(TEACHER)); /*为头结点申请空间*/ Last=First; /*将尾指针指向头结点*/ First->prior=Last; /*设置头结点的前驱指针*/ Last->next=First; /*设置头结点的后继指针*/ p=First; /*设置当前记录指针为头结点*/ } /*创建教师信息循环双链表*/ void create() { int unit,flag=0; float temp; TEACHER *info; /*新增结点*/ init(); for(;;) { if(flag==1)break; /*标志为1,不再输入*/ clrscr(); /*清屏*/ printf("Please enter teacher infomation\n"); printf("input @ end enter\n"); info=(TEACHER *)malloc(sizeof(TEACHER));/*为新增结点申请空间*/ if(!info) /*没有空间出错处理*/ { printf("\nout of memory"); exit(0); } printf("No:"); /*开始提示输入*/ scanf("%s",info->no); if(info->no[0]=='@')/*输入@结束输入*/ { flag=1;break;} printf("Name:"); scanf("%s",info->name); printf("Sex:"); scanf("%s",info->sex); printf("Profess:"); scanf("%s",info->profess); printf("Dept:"); scanf("%s",info->dept); printf("Class:"); scanf("%s",info->class); printf("Workload:"); scanf("%f",&temp); info->workload=temp; if(strcmp(info->profess,"prof"))unit=25; /*教授*/ if(strcmp(info->profess,"aprof"))unit=20;/*副教授*/ if(strcmp(info->profess,"lect"))unit=15;/*讲师*/ if(strcmp(info->profess,"ass"))unit=10;/*助教*/ info->lessonf=unit*info->workload;/*根据职称计算代课费*/ info->next=Last->next;/*新插入结点插在表末尾*/ info->prior=Last; /*新结点的前驱为原来的尾结点*/ Last->next=info; /*原来尾结点的后继为新结点*/ Last=info; /*新的尾结点为新结点*/ First->prior=Last;/*头结点的前驱为尾指针*/ } return; } /*显示第一条记录*/ void firstr() { if(First==Last)return; clear(); p=First->next; print(p); } /*显示最后一条记录*/ void lastr() { if(First==Last)return; clear(); p=Last; print(p); } /*显示前一条记录*/ void priorr() { if(First==Last) return; if(p->prior!=First) p=p->prior; else p=Last; clear(); print(p); } /*显示下一条记录*/ void nextr() { if(First==Last) return; if(p==Last) p=First->next; else p=p->next; clear(); print(p); } /*从文件读数据*/ void load() { TEACHER *p1; FILE *fp; if((fp=fopen("data.txt","rb"))==NULL) { printf("can not open file\n"); return; } while(First->next!=First) /*如果当前表不空,删除当前表*/ { p1=First->next; First->next=p1->next; free(p1); } free(First); First=(TEACHER*)malloc(sizeof(TEACHER)); /*创建头结点*/ if(!First) { printf("out of memory!\n"); return; } Last=First; First->prior=Last; Last->next=First; p=First; while(!feof(fp)) /*当文件不为空时读数据*/ { p1=(TEACHER*)malloc(sizeof(TEACHER)); if(!p1) { printf("out of memory!\n"); return; } if(1!=fread(p1,sizeof(TEACHER),1,fp)) break; /*读数据*/ p1->next=Last->next; /*将新读出的数据链在当前表尾*/ p1->prior=Last; Last->next=p1; Last=Last->next; First->prior=Last; } fclose(fp); /*关闭文件*/ } /*保存数据到磁盘文件*/ void save() { FILE *fp; /*定义指向文件的指针*/ TEACHER *p1; /* 定义移动指针*/ if((fp=fopen("data.txt","wb"))==NULL) /*为输出打开一个文本文件,如没有则建立*/ { printf("can not open file\n"); /*如不能打开文件,显示提示信息,结束程序*/ return; /*返回*/ } p1=First; /*移动指针从头指针开始*/ while(p1->next!=First) /*如p1不为空*/ { fwrite(p1->next,sizeof(TEACHER),1,fp); /*写入一条记录*/ p1=p1->next; /*指针后移,处理下一条记录*/ } fclose(fp); /*关闭文件*/ } /*删除记录*/ void delete() { TEACHER *p1; if(First==Last) return;/*表为空*/ if(p==First) /*p为头结点*/ p=First->next; if(p==Last)/*p为尾结点*/ Last=p->prior; p1=p; /*一般情况*/ p=p->next; p1->prior->next=p1->next; p1->next->prior=p1->prior; free(p1); } /*输出记录*/ void print(TEACHER *p) { int x1=70,y1=100; char str[20]; outtextxy(x1+110,y1+75, p->no); outtextxy(x1+360,y1+75,p->name); outtextxy(x1+110,y1+105,p->sex); outtextxy(x1+360,y1+105,p->profess); outtextxy(x1+110,y1+135,p->dept); outtextxy(x1+360,y1+135,p->class); sprintf(str,"%f",p->workload); outtextxy(x1+110,y1+165,str); sprintf(str,"%f",p->lessonf); outtextxy(x1+360,y1+165,str); } /*****清除界面显示信息******/ void clear() { int x1=70,y1=100,m,n; for(m=0;m<4;m++) for(n=0;n<2;n++) { setfillstyle(1,WHITE);/*白色覆盖原有信息*/ bar(x1+n*250+100,y1+50+m*30+20,x1+n*250+200,y1+50+m*30+40); } } /*sort排序函数*/ void sort() { TEACHER *p0,*p00,*p1,*p11,*templast; if(First->next==First||First->next->next==First)return; p00=First; /*作排好序表的表头和第一个结点*/ p0=First->next; p1=p0->next; First->prior=p0; p0->next=First; templast=p0; while(p1!=First) /*当p1没有转回到表头时*/ { p11=p1; /*将p11作为待插入结点*/ p1=p1->next; /*p1指向下一个待排序结点*/ p00=First; /*从头结点开始寻找插入位置*/ p0=p00->next; /*p0是p00的后继*/ while(p0!=First&&p11->workload>p0->workload) { p00=p0;/*当新插入结点比当前表结点大时,指针后移*/ p0=p0->next; } if( p0==First)/*如果p0移到了头结点*/ { p11->next=p00->next; p11->prior=p00; p00->next=p11; p0->prior=p11; templast=p11; } else /*新插入结点介于p00和p0之间*/ { p11->next=p0; p11->prior=p00; p0->prior=p11; p00->next=p11; } } Last=templast; /*设置尾指针*/ p=First; /*设置当前记录指针*/ }