首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

[有史以来最怪的题]小弟我写了个小程序,为什么要兼容模式才能运行[搞得小弟我想杀人]

2012-02-13 
[有史以来最怪的题]我写了个小程序,为什么要兼容模式才能运行[搞得我想杀人]朋友的作业,写一个小学生成绩

[有史以来最怪的题]我写了个小程序,为什么要兼容模式才能运行[搞得我想杀人]
朋友的作业,写一个小学生成绩管理系统。
我在家用的时候,释放内存到第1502条就崩溃。但是读2次数据就不崩溃了。
在朋友家有的时候,居然读不了文件。只能打开。
但是我无意中启用了windows2k兼容模式,就能用了,并且没有任何故障。
启用95兼容模式的话,能申请内存,但是只能释放掉一个数据。
这是为什么呀?
我的程序里什么都没用呀!都是C标准函数。
就用了一个system( "cls ")来清屏。

不行了!     请各位帮帮忙吧!

代码:
#include   <stdio.h>
#include   <stdlib.h>
#include   <string.h>

#define   MY_QUIT   2

struct   std
{
char   ID[11],name[21];
float   cj[3];
float   num;
struct   std   *next;
};

int   myfree(struct   std   *head);
int   myquit(struct   std   *head);
int   myexit(struct   std   *head);
struct   std   *addstd(struct   std   *head);
struct   std   *delstd(struct   std   *head);
int   dirall(struct   std   *head);
struct   std   *reddat(char   *filen,struct   std   *head);
int   whidat(struct   std   *head);

int   main(void)
{
int   xx,zt=1;
struct   std   *HEAD=NULL;

/*HEAD=reddat(NULL,HEAD);
myquit(HEAD);
*/HEAD=reddat(NULL,HEAD);
while(zt!=MY_QUIT)
{
system( "cls ");
xx=0;
puts( "[NUME]\n\n1:添加记录       \n2:删除记录       \n3:显示全部信息       \n4:读取数据库       \n5:写入数据库     \n0:   退出\n ");
printf( "请输入命令: ");  
scanf( "%d ",&xx);
system( "cls ");
switch(xx)
{
case   0:   zt=myquit(HEAD);break;
case   1:   HEAD=addstd(HEAD);break;
case   2:   HEAD=delstd(HEAD);break;
case   3:   dirall(HEAD);getch();break;
case   4:   HEAD=reddat(NULL,HEAD);getch();break;
case   5:   whidat(HEAD);getch();break;
default   :   if(xx!=0)   printf( "您输入的命令不存在。 ");getch();
}
if(zt==0){puts( "system   error! ");getch();myexit(HEAD);}
}

return   0;
}


int   myfree(struct   std   *head)
{
int   i=0;

printf( "\n正在释放内存...                               ");
while(head-> ID[0]!=0   &&   head-> next!=NULL)
{
printf( "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b%15d ",++i);
/*i++;
if(i==1052   ||   i==1053   ||   i==1054   ||   i==1055)
{
printf( "\n%d学号:%s     姓名:%s     分数:%.2f-%.2f-%.2f     平均分:%.2f ",i,head-> ID,head-> name,head-> cj[0],head-> cj[1],head-> cj[2],head-> num);
}*/
free(head);
head=head-> next;
}
free(head);
puts( "\tOK ");
getch();  
}

int   myquit(struct   std   *head)
{
char   ch;

puts( "您确定您已经对修改过的数据库进行了保存(Y/N)?\n\n为了您的数据安全,退出时程序不会帮助您保存数库. ");
fflush(stdin);
ch=getchar();
if(ch== 'n '   ||   ch== 'N ')return   1;
myfree(head);
return   MY_QUIT;
}

int   myexit(struct   std   *head)
{
char   ch;
system( "cls ");
puts( "程序发生了错误即将退出,无法保存当前数据. ");
myfree(head);
exit(0);
return   MY_QUIT;


}

struct   std   *addstd(struct   std   *head)
{
struct   std   *sp,*sq,*h=head;
char   ch= 'y ';
int   i;

while(ch== 'y '   ||   ch== 'Y ')
{
head=h;
i=1;
system( "cls ");
puts( "添加新学生\n\n\n ");

sp=(struct   std   *)malloc(sizeof(struct   std));

printf( "学生ID: ");scanf( "%s ",sp-> ID);
printf( "姓     名: ");scanf( "%s ",sp-> name);
do
{
printf( "成   绩1: ");scanf( "%f ",sp-> cj);
printf( "成   绩2: ");scanf( "%f ",sp-> cj+1);
printf( "成   绩3: ");scanf( "%f ",sp-> cj+2);
if(sp-> cj[0]> =0   &&   sp-> cj[1]> =0   &&   sp-> cj[2]> =0)   break;
puts( "请仔细核对成绩. ");
}while(1);
sp-> num   =   (sp-> cj[0]+sp-> cj[1]+sp-> cj[2])/3;
printf( "此学生平均成绩为:%f ",sp-> num);
if(head-> ID[0]   ==   0   ||   sp-> num   > =   head-> num)
{
sp-> next=head;h=sp;
}
else
{
while(sp-> num   <=   head-> num)
{
i++;
sq=head;
head=head-> next;
}
sp-> next=head;
sq-> next=sp;
}

printf( "\t目前排名:%d ",i);
puts( "\n\n按Y键继续添加... ");
ch=getch();
}

return   h;
}

struct   std   *delstd(struct   std   *head)
{
struct   std   *sq,*h=head;

char   ch= 'y ',sid[11];
int   i=0;

while(ch== 'y '   ||   ch== 'Y ')
{
system( "cls ");
puts( "删除学生信息\n\n\n ");
printf( "请输入要删除学生的学号: ");
fflush(stdin);
gets(sid);
head=h;
sq=head;
while(head-> ID[0]   !=   0)
{
if(!strcmp(sid,head-> ID))
{
i=1;
printf( "\n确认删除   学生ID:%s   姓名:%s   的记录(Y/N)?\n ",head-> ID,head-> name);
ch=getch();
if(ch== 'y '   ||   ch== 'Y ')  
{
if(sq   ==   head)   h=h-> next;
sq-> next=head-> next;
free(head);
puts( "记录被成功删除. ");
}
}
sq=head;
head=head-> next;
}
if(!i)   puts( "没有符合条件的记录. ");
i=0;
puts( "\n\n按Y键继续删除其他记录... ");
ch=getch();
}

return   h;
}

int   dirall(struct   std   *head)
{
int   i=0;
char   ch= 'a ';

while(head-> ID[0]!= '\0 ')
{
i++;
if(ch!= 'q ')
{  
printf( "名次:%5d\n学号:%-10s       姓名:%-20s\n分数:%.2f     %.2f     %.2f                   平均分%.2f\n\n ",i,head-> ID,head-> name,head-> cj[0],head-> cj[1],head-> cj[2],head-> num);
puts( "-------------------------------------------------- ");
if(i%4==0)  
{
puts( "按任意键显示下一页,按q键退出... ");
ch=getch();
printf( "\n\n\n\n\n-第%d页-\n-------\n ",i/4+1);
}
}
head=head-> next;
}
system( "cls ");


if(i==0){puts( "\n数据库中没有记录! ");}
else{printf( "\n数据库中共有记录%d条   %d页 ",i,i/4+1);}
return   1;
}

struct   std   *reddat(char   *filen,struct   std   *head)
{
FILE   *fp;
struct   std   *sp,*sq;
int   zt=0;

printf( "开始读取数据库std.dat到程序\t ");
if((fp=fopen( "std.dat ", "r "))==NULL)
{
puts( "open   datefile   error! ");
getch();
myexit(head);
}
head=sp=(struct   std   *)malloc(sizeof(struct   std));
while(!feof(fp))
{
sq=(struct   std   *)malloc(sizeof(struct   std));
zt=fscanf(fp, "%s\t%s\t%f\t%f\t%f\t%f\n ",sq-> ID,sq-> name,sq-> cj,sq-> cj+1,sq-> cj+2,&sq-> num);
/*printf( "%d ",zt);*/
if(zt!=6   &&   zt!=1   ||   (int)(sp-> num*3   -   sp-> cj[0]   -   sp-> cj[1]   -   sp-> cj[2]))  
{
zt=-1;
break;
}
sp-> next=sq;
sp=sq;
}
fclose(fp);
if(zt==-1   ||   sp-> ID[0]!= '# ')
{
puts( "ERROR.\n数据库可能被其他程序编辑过,文件损坏,无法读取. ");
getch();
myexit(head);
}
sp-> ID[0]= '\0 ';
sp-> num=-100;
sp-> next=NULL;
sp=head;
head=head-> next;
printf( "OK.\n正在清理临时变量\t ");
free(sp);
printf( "OK.\n\n数据库读取完毕,没有发生任何异常. ");

return   head;
}

int   whidat(struct   std   *head)
{
FILE   *fp,*fp1;
char   ch;

printf( "开始备份数据库为stdb.dat\t ");
fp1=fopen( "stdb.dat ", "w ");
if((fp=fopen( "std.dat ", "r+ "))==fp1)
{
puts( "open   datefile   error! ");
getch();
myexit(head);
}
while(!feof(fp))
{
ch=fgetc(fp);
fputc(ch,fp1);
}
fclose(fp1);
printf( "OK.\n开始保存新的数据到数据库\t ");
fseek(fp,0L,SEEK_SET);
while(head-> ID[0]!= '\0 ')
{
fprintf(fp, "%s\t%s\t%f\t%f\t%f\t%f\n ",head-> ID,head-> name,head-> cj[0],head-> cj[1],head-> cj[2],head-> num);
head=head-> next;
}
fputc( '# ',fp);
fclose(fp);
printf( "OK.\n\n写入数据库操作执行完毕.没有发生任何异常. ");

return   1;
}


[解决办法]
debug啊……
[解决办法]
说明可能不是标准的win32程序.
改用vc编来看一下.
[解决办法]
程序中有两处释放了堆内存又使用指针进行读操作:
free(head);
head=head-> next;
分别在myfree和delstd中。可以先把head-> next保存起来再复制给head来解决这个问题。
以下是我对这两个函数的修改:
struct std *delstd(struct std *head)
{
struct std *sq,*h=head,*temp;

char ch= 'y ',sid[11];
int i=0;

while(ch== 'y ' || ch== 'Y ')
{
system( "cls ");
puts( "删除学生信息\n\n\n ");
printf( "请输入要删除学生的学号: ");
fflush(stdin);
gets(sid);
head=h;
sq=head;
while(head-> ID[0] != 0)
{
if(!strcmp(sid,head-> ID))
{
i=1;
printf( "\n确认删除 学生ID:%s 姓名:%s 的记录(Y/N)?\n ",head-> ID,head-> name);
ch=getch();
if(ch== 'y ' || ch== 'Y ')
{


if(sq == head) h=h-> next;
sq-> next=head-> next;
temp=head-> next; /////////// <------
free(head);
puts( "记录被成功删除. ");
}
}
else temp=head-> next; //////////////////////// <-------
sq=head;
head=temp; //////////////////////////////////// <-------
}
if(!i) puts( "没有符合条件的记录. ");
i=0;
puts( "\n\n按Y键继续删除其他记录... ");
ch=getch();
}

return h;
}
int myfree(struct std *head)
{
int i=0;
struct std *temp;
printf( "\n正在释放内存... ");
while(head-> ID[0]!=0 && head-> next!=NULL)
{
printf( "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b%15d ",++i);
temp=head-> next; ////////////////// <-------------
free(head);
head=temp;////////////////// <--------------
}
free(head);
puts( "\tOK ");
getch();
}
(以上代码在xp sp2+ vc 7.0和devc++4.9.9.2下测试通过)
个人认为 在win2000兼容模式下能够正常运行是因为win2000的堆管理器释放内存后并未改写原内存,而xp为了安全起见已经改写或移动了释放过的内存块,任何试图访问已经释放的内存都将引起程序崩溃。

关于兼容模式请参考:
1。关于windows程序的兼容模式
http://mazolen.spaces.live.com/blog/cns!8d71d5c962ea5113!142.entry
2。Microsoft Windows 2000 应用程序兼容性
http://blog.csdn.net/ghj1976/archive/2001/03/10/3404.aspx

热点排行