C语言程序
课程设计
完成任务:
用二分法求方程根
矩阵求逆
链
制作
二十四点游戏
学籍管理程序
专业:计算机科学与技术
班级:计二班
学号:0705010225
姓名:李海波
本人于2008年9月1号在计算机中心6号机房25号机器上完成了本次课程设计。课程设计过程中使用的操作系统是Windows 2000,主要开发平台VC++ 6.0。
任务二 用二分法求方程根
目的与意义
用二分法求方程f(x)==x3-x-1=0在区间[1.0,1.5]内的一个实根,要求准确到小数点后第2位。
任务分析
方程在区间[1.0,1.5]上单调并且存在一个根。取区间中点,确定方程的根在左右哪个区间
(或者恰好是区间中点)内,这样一次就可以把区间缩小一半,重复做此步骤直到满足精确度为止。
方程的近似根为区间中点。
取区间中点:
只需用区间的两个端点相加,在除以2即可。
确定根所在位置:
区间[a,b]中,取中点c=(a+b)/2,与a,b构成两个区间:[a,c]与[c,b]。而方程的根的位置有三种可能1.在区间[a,c]中;2.在区间[c,b]中;3.根就是中点c。若中点就是方程的根,则可以直接输出。若不是这是剩下两种情况。若f(c)*f(a)<0,则根在区间[a,c]中,若f(b)*f(a)<0,则根在区间[b,c]中,两者只有一种情况成立。
验证是否满足精确度:
精确到小数点后两位,就是说0.01.。由于是用二分法,所以到了0.01后,还要继续二分,直到0.01后才能满足精确度。也就是说,区间左右值相减要小于0.001时,输出区间中点即可。
数据结构设计
此程序将涉及三个变量:区间的两个端点,区间中点。由于要精确到小数点后两位,所以必须设置为float类型。还有一个函数,由于只需要验证返回值的正负,所以只需用int类型就可以了。后来在函数运行中出现错误,更改为float类型(具体错误将在“代码调试与运行”部分说明)。
关键算法设计
本程序比较小,原本只用一个main函数就可以完成,可是由于方程的函数每次输入比较麻烦,所以设置了一个简单的函数:
Int hanshu(float x)
{
return x*x*x-x-1;
}
用它来返回方程函数的带入值。
程序的关键在于不断二分,确定根所在位置的循环算法。此循环代码如下:
do
{
f=(a+b)/2;
if(hanshu(f)==0)
{printf("方程的根为%.2f\n",f);break;}
if(hanshu(a)*hanshu(f)<0)
b=f;
else
a=f;
}while(b-a>0.001);
首先给f赋值为区间中点。若它满足hanshu(f)==0,说明f为方程的根,直接输出f,并用break语句,结束循环。如果不满足,则验证根在哪个区间,并执行相应赋值,形成新的区间,继续执行循环。循环在执行到满足精确度时结束,即b-a<=0.001,结束循环。
输出方程的根最好区分开此根是近似根还是准确根。所以把输出分为两部分。一部分在循环内,验证区间中点为准确根的时候输出。若要输出近似根则要循环结束后,所以输出语句在循环结构外面。为了验证循环结束后得到的根f是不是准确根,顾输出语句在if语句内。代码如下:
if(b-a<0.01)
printf("方程的近似根为%.2f\n",f);
代码调试与运行
原程序运行时结果出人预料:
方程的根为1.25
注意到1.25恰好是原来区间的中点,而根据输出来看,1.25是方程的精确根。可是经过计算我得到方程的根应该在1.3到1.4之间。
会输出这个结果,也就是说程序执行了
if(hanshu(f)==0)
{printf("方程的根为%.2f\n",f);break;};
为什么会这样?我想起返回函数带入值的函数hanshu()的返回值是int。如果返回值没有整数部分,就会返回0。所以把它更改为float类型,最终得到结果:1.33。
屏幕显示为:
方程的近似根为1.33
小结与体会
每项数据在数据设定时需要细致详细的考虑数据的用途,以及可能出现的错误。注意每种数据的范围以防止程序运行中出错。一个简单的程序,也不能保证一次编写毫无错误。尤其在DEBUGE系统不能检验出错误,但是结果又不是期望值时,必须重新检查程序,任何细小的地方都可能是出错的原因。
本人于2008年9月2号到2008年9月5号在计算机中心6号机房14号机器上尝试了本次课程设计。课程设计过程中使用的操作系统是Windows 2000,主要开发平台VC++ 6.0。由于各种原因至今没有完成,个大函数已经完成,但是在运行中出现错误的原因没有找到。
任务一 矩阵求逆
·目的与意义
给定一个8X8的矩阵A,求出它的逆矩阵A-1。
矩阵的元素由键盘中输入,首先判断矩阵是否可逆,若可逆则求出其逆矩阵并在屏幕上用适当格式显示出来。
程序可以把矩阵求逆这一复杂的运算由计算机代替计算,既可以保证结果的准确,又可以高速度的完成复杂的计算。
·任务分析
根据线性数学的学习知道,矩阵求逆有两种
:单位矩阵化归法、伴随矩阵法。
根据指导上的分析,第一种需要三个函数。那就是:行交换、将第n行乘以e、第i行乘以k加到第j行。这三个函数都不难做,但是如何利用这三个函数,求出逆矩阵我却无从下手。我只好用另外一种方法做。
用伴随矩阵求逆矩阵需要两个函数:求矩阵行列式、计算代数余子式。而这两个函数在使用中又相互使用,也就是相互调用。利用相互调用,就可以吧求你矩阵所需的的代数余子式和矩阵行列式求出来。
求出矩阵行列式就可以验证矩阵是否存在逆矩阵。
由代数余子式得到矩阵的伴随矩阵,两者相除就可以得到矩阵的逆矩阵了。
·数据结构设计
程序里输入输出都是矩阵,自然用二维数组。矩阵不见得都是整数,所以用float来定义最好。在带入两个函数时需要函数的阶数,这个一定是正整数,用int定义就可以。两个函数举证的行列式肯定是用float定义。求代数余子式的函数还要传入行数和列数,用int定义就好。
·关键算法
程序关键算法就是两个。一是计算方阵的行列式,另一个是计算方阵对于某个元素的代数余子式。
由于两个函数相互调用,所以在函数中会有另一个函数的函数声明。我的求方阵行列式函数声名为float hangleishi(int n,float x[8][8]),其中n表示方阵的阶数。求代数余子式的函数声明为float yuzishi(int n,float x[8][8],int i,int j),其中n表示阶数,i,j表示求方阵对于第i行,第j列的代数余子式。
求方阵行列式的函数代码如下:
float hangleishi(int n,float x[8][8])
{
float h;
int i=0;
float yuzishi(int n,float x[8][8],int i,int j);/*函数声明*/
if (n=2)
h=x[0][0]*x[1][1]-x[0][1]*x[1][0];
else
for(i=0;i
2时,函数执行else 的语句。语句中使用了求代数余子式的函数,是求行列式的一般求法,也是普遍求法。没有技巧,但是编程简单,算法也容易实现。n=2时,就可以直接算出来,返回h即方阵的行列式。降阶在函数yuzishi()中实现。
求代数余子式的函数如下:
float yuzishi(int n,float x[8][8],int i,int j)
{
int a=1,c=0,d=0;
float h=0;
float y[8][8];
for(c=0;cshuzi=n;
p1->next=NULL;
if(head==NULL)
head=p1;
else
p2->next=p1;
p2=p1;
scanf("%d",&n);
}
}
return head;}
首先确定链表是否已经创建,如果已经创建,就结束函数返回。如果没有就进入创建函数。
由用户输入n的数值,如果不是结束识别符(999999),函数就会用malloc申请一个新空间,并强制赋值为struct zhengshu*类型,并赋值给指针P1。如果head为空,就把p1的值赋给head,否则赋给p2。这样继续下一次循环,p1又被重新赋值。知道用户输入999999,结束循环 。
返回值head赋值给原来的head,表头被改变,链表创建完成。
插入函数分为几个部分,一个是查询部分,另一个是插入部分。查询部分与其他的函数基本相同。查询部分在此介绍,以后部分不再做具体介绍。查询部分代码如下:
printf("请输入插入点前面的整数数值\n");
scanf("%d",&a);
p1=head;
do
{
if(p1->shuzi==a)
{
b++;
printf("检索成功!\n");
break;
}
} while(p1->next!=NULL)
先由用户输入插入节点前面的节点数值,这样搜索开始。搜索中,定义一个指针。当指针指向的节点不为空时,则验证是否节点值为要搜索的数值。如果不是,则继续赋值为下一个节点。这个搜索函数有一定弊病,那就是不能找到第一个节点值,所以在这个函数之前,我已经设置了函数问用户是否把节点插入在第一个位置。这样对这个漏洞做了有效的补救。
插入函数第二部分,插入操作部分:
printf("请输入新节点的数值\n");
scanf("%d",&a);
p2=(struct zhengshu*)malloc(sizeof(struct zhengshu));
p3=p1;
p1=p1->next;
p2->shuzi=a;
p3->next=p2;
p2->next=p1;
printf("插入结点成功!\n");
这是插入函数的一部分,是在把新节点插入到链表中间位置时的函数。插入到最前端和最后端函数稍有不同,已插入中间为例介绍。
首先要求用户输入新节点的值,然后用malloc函数申请一个新空间,把类型转换为struct zhengshu *,并把它赋值给指针p2。这样在经过一系列赋值语句,就可以使前面节点的的指针指向新节点,而新节点下的新指针指向下个节点,完成新节点的插入。
节点的修改比插入节点要简单一些,只需找到节点并对节点的数值重新赋值就可以了。而节点的删除函数跟节点修改很相似,只不过是把赋值语句更改为空间释放,并多加一个指针赋值而已。下面只介绍节点的删除函数:
if(b==0)
printf("链表中无此节点 \n");
else
{
if(p1->next!=NULL)
{
p2=p1;
p1=p1->next;
p2->next=p1->next;
free(p1);
printf("删除节点成功!\n");
}
else
{
p2->next=NULL;
free(p1);
}
}
大家可以看到,我在前面的搜索语句中加入了一个b++语句。这个语句的作用是来判断查询语句的循环结束,究竟使由于p1->next==0还是找到了要查找的数值,由于break跳出的循环。如果b被重新赋值说明成功搜索到了节点。
在这个函数里,首先看b是不是还为0,如果是说明没有找到节点,输出未找到。如果不是,则说明找到了节点,而且这是p1的next正指向这个节点。把它赋值给P2,并使p1指向下一个节点,也就是要查找的节点。然后执行p2->next=p1->next,这样就把p1所指的节点,从链表中摘下来了。然后用free语句把空间释放,就完成了节点的删除。
链表的撤销函数跟删除函数很是相像,只是依次释放各个节点罢了。我编的函数代码如下:
struct zhengshu *chexiao(struct zhengshu *head)
{
struct zhengshu *p;
p=head;
if(p==NULL)
printf("链表未创建\n");
else
{
while(head!=NULL)
{
p=head;
head=head->next;
free(p);
}
printf("链表撤消成功!\n");
}
return head;
}
如果链表没有创建则直接返回。如果找到了,就用一个指针指向它,并把他的空间释放,而这时head已经指向了下一个节点,指针又会被重新赋值。循环一直到head指向NULL时结束,这时链表的空间都被释放,链表撤销结束。
链表的输出不过是一个循环的输出语句,在此不做介绍。结束函数也只是一些场面话,没有什么具体意义。下面使纵览全局的主函数:
void main()
{
printf("欢迎使用本链表制作程序!!!\n海波制作群预祝您身体健康,万事如意!\n如果您使用中发现BUG,请与我们联系\n");
printf("电话:15898523371 QQ:279528056 联系人:李海波\n\n\n\n");
void caidan();
struct zhengshu *chuangjian(struct zhengshu *head);
struct zhengshu *charu(struct zhengshu *head);
struct zhengshu *xiugai(struct zhengshu *head);
struct zhengshu *shanchu(struct zhengshu *head);
struct zhengshu *chexiao(struct zhengshu *head);
void print(struct zhengshu *head);
void jieshu ();
struct zhengshu *head;
int a=0;
head=NULL;
loop:
caidan();
scanf("%d",&a);
switch(a)
{
case 1:
head=chuangjian(head);goto loop;
case 2: head=charu(head);goto loop;
case 4: head=xiugai(head);goto loop;
case 3:
head=shanchu(head);goto loop;
case 5:
head=chexiao(head);goto loop;
case 6: print(head);goto loop;
case 7: jieshu();
}
}
主函数的布局我尽量做得规范。最上面是所有函数的声明,然后是各种类型变量的定义,之后就是loop后面的语句。Loop后首先执行菜单函数,输出菜单。然后是switch语句执行相应函数,执行结束后直接由goto语句返回loop。这样菜单再次输出,功能在此重新选择。
调试与运行
调试过程中出现了很多错误,还有一些设计上不合理的地方。这些错误大部分已经被更正,或是做了修改和补救。例如,插入节点查询函数采用查找节点数值的方式,无法找到最前面数值的问题。我加了一个询问语句,和表头节点的插入补救。结束函数,由于都是printf语句,真正的exe文件执行的时候会执行玩这些立刻结束,我加了一个输入语句,使用户可以看清楚结束的话,在自己想结束的时候输入一个字符结束程序。
我已经对程序里各项功能做了比较详细的测试,程序的功能可以正常运行,不会出现意想不到的结果。
但是在测试中发现了一个问题,至今没有解决。那就是,按照节点数值查找,无法解决有相同节点的问题。如果有两个节点,程序只会对第一个节点进行操作,会完全忽略掉。这样使整个程序变得和不完整。因为几乎所有的重要函数都用到了查询函数。如果更改查询函数,就会“牵一发而动全身”,整个程序各部分都要重新更改,由于时间关系我没有做改动,这时本程序需要改进的地方。
小结与体会
这个程序是我独立完成的第一个比较大的程序,当然对于那些真正的大程序来说,这个不尔尔。可是对我来说不一样,我真的用心在做。做的过程中遇到不少麻烦,也曾经止步不前,可是我最终还是把它成功编写出来了,我觉得很有成就感。
虽然程序中还有很多弊病在里面,说不上一个完善的程序,但它终究是我努力的结果。
在编写程序时,一边写就会一边发现很多的问题。写得时间越长,发现的问题也越来越多。一个个把问题解决掉真的很开心。可是我觉得,真正编写程序不应该是这样的。应该在写程序之前,就把所有的问题想清楚。这样可以给自己剩下大量的时间,而且程序看起来也会浑然一体,而不是“各自为战”。
这个程序还让我感觉的,各个函数相互独立的方式编辑函数很有优越性。一个函数只负责而且可以独立负责一个功能,就可以避免,函数之间相互调用,把简单的问题复杂化。这样很容易找到问题发生的地方,并修改不必考虑对其他函数的影响。
本人于2008年9月9号到2008年9月12日在计算机中心6号机房12号机器上尝试完成了本次课程设计。但是由于时间关系,没有能全部完成程序的编写任务。课程设计过程中使用的操作系统是Windows 2000,主要开发平台VC++ 6.0。
任务五 学籍管理
目的与意义
在某大学的一个专业,里面有四个班,每个班最多可以有40个学生。每个学生有学号、性别、籍贯等数据。在某个学期,他们开了高等数学一、英语一、线性数学、离散数学一、高等物理、思想品德教育、体育等8们课程,每门学分依次为3、3、2、2、2、1、2.。编制一个程序,使用户方便管理他们的学籍信息。
需要输出没管的功能菜单。对于每个学生,可以进行基本情况的录入、查询、修改、删除。还有学生成绩的录入,查询,个人加权成绩计算,修改等。还要完成班里加权成绩的平均分计算和排名。要求所有的数据用文件形式存取。还要设置管理员的权限和密码管理。
任务分析
根据我以前编写链表程序的经验,我想这次还是采取各个函数独立完成一项功能,彼此不相互调用的形式完成这次编程任务。
首先要建立一个菜单,菜单上显示所有的功能,以便于用户选择相应的功能。但是美观很难做到,因为我知道机房的gotoxy的函数是不能用的。我就决定先把真材实料的东西做完,至于美观,在做完各个函数之后再去考虑。
四个班的文件分开存放的,也就是说分4个文件存放。这样在执行其他功能时,必须要用户输入要进行操作的班级,不过这样省去了在一个文件中分出四个班的麻烦。
录入函数是一个比较重要的函数,因为所有的操作都是再文件的进行的,所以难度增加了不少。但是这是必须的,总不能输入一次看一次。录入函数中,肯定是用“w”形式打开文件,因为这里只有文件的写入。我想这函数肯定要设计一个结构体的类型的。所以用fwrite函数成块写入文件是最恰当的。
查询个人信息函数中,文件用“r”,也就是只读形式打开。当然是用fread函数成块读出文件信息,并对它进行操作。查询至少要两种查询路线,也就是按姓名和按学号。这两种都是常用的搜索,所以都要包括在内。
查询班级信息函数,必须输出班级的加权平均分。我决定在录入函数中直接由程序算出学生的加权成绩存储起来。另外是班级排名,使用冒泡法排序代码简单,又容易实现。
由于时间关系,删除,修改和管理权限、密码设置都没有完成。
数据结构设计
这里的数据用结构体是毫无疑问的。我的数据类型定义为:
typedef struct
{
char xingming[9];
char xuehao[11];
char xingbie[3];
char jiguan[9];
float chengji[9];
}xue;
学号、姓名、性别、籍贯都用char,也就是字符串类型定义。单科成绩共有8门,用float定义一个9个元素的数组,最后的用来存放学生的加权成绩。我在程序里还定义了一个结构体:
typedef struct
{
char xingming[9];
char xuehao[11];
float jiaquan;
}ss;
这是在班级加权成绩是用到的数据类型。因为在班级排名时,我们只关心学生的姓名、学号还有他的成绩,所以我们只使用这三个元素,没有必要在用原类型了。
关键算法
菜单函数只是一些输入函数,用来提示用户选择相应的功能。由于没有在美观上下工夫,所以我的菜单函数十分简单,只是一些输出函数而已。
信息的录入函数如下:void luru()
{
printf("您要录入哪个班的成绩?请输入数字\n");
int a=0;
FILE *p;
xue b;
scanf("%d",&a);
switch(a)
{
case 1: p=fopen("c:\\yiban.txt","w");break;
case 2: p=fopen("c:\\erban.txt","w");break;
case 3: p=fopen("c:\\sanban.txt","w");break;
case 4: p=fopen("c:\\siban.txt","w");break;
}
do
{
printf("请输入学生的基本信息,依次输入姓名,学号,性别,籍贯(省名),中间用空格搁开\n");
scanf("%s %s %s %s",&b.xingming,&b.xuehao,&b.xingbie,&b.jiguan);
printf("请输入此学生的成绩(按照数学,英语,线形数学,离散数学,物理,品德,体育的顺序),中间逗号搁开\n");
scanf("%f,%f,%f,%f,%f,%f,%f",&b.chengji[0],&b.chengji[1],&b.chengji[2],&b.chengji[3],&b.chengji[4],&b.chengji[5],&b.chengji[6]);
b.chengji[7]=(b.chengji[0]*3+b.chengji[1]*3+b.chengji[2]*2+b.chengji[3]*2+b.chengji[4]*2+b.chengji[5]+b.chengji[6]*2)/(3+3+2+2+1+2+2);
fwrite(&b,sizeof(b),1,p);
printf("继续录入请输入1,结束录入请输入2\n");
scanf("%d",&a);
}while(a==1);
fclose(p);
}
先打开或建立相应的文件,这里需要用户输入要录入的班级,以便把文件分开管理。打开成功后,开始请用户录入信息。信息先存放在一个变量里,然后在一个人的成绩完全输入完成后,直接算出学生的加权成绩,全部存入变量。然后全部写入文件。然后询问用户是否还要继续输入,用户只要输入相应指令,就可以继续或结束输入。
查询函数中包括了两种查询方式:学号查询和姓名查询。两个部分大致相同,这里只介绍下其中之一:学号查询.
printf("请输入学生的学号\n");
scanf("%s",&c);
while(fread(&d,sizeof(d),1,p)!=0)
{
if(strcmp(d.xuehao,c)==0)
{
printf("姓名,学号,性别,籍贯");
printf("%s,%s,%s,%s",d.xingming,d.xuehao,d.xingming,d.jiguan);
printf("高等数学一,英语一,线形数学,离散数学,高等物理,思想品德,体育,加权成绩\n");
printf("%7.1f,%7.1f,%7.1f,%7.1f,%7.1f,%7.1f,%7.1f,%7.1f",d.chengji[0],d.chengji[1],d.chengji[2],d.chengji[3],d.chengji[4],d.chengji[5],d.chengji[6],d.chengji[7]);
}
}
if(fread(&d,sizeof(d),1,p)==0)
printf("查询结束,该班无此人信息\n");
先由用户输入学生的学号,然后开始读取函数数据。函数数据存放在一个变量p中。用strcmp函数验证是不是两个字符串相同,相同的话就输出这个学生的成绩。后面有个if语句。当没有找到这个学号时就会运行,显示没有找到。
查询班级成绩,要函数比较麻烦。因为我把班级的排名也放在这里面,所以代码有些长。但是有大部分跟查询函数类似,下面是排名的函数:
for(j=0;j!=0;)
{
j=0;
for(k=0;k<=40;k++)
{
if(u[k].jiaquan<=u[k+1].jiaquan)
{
m=u[k];
u[k]=u[k+1];
u[k+1]=m;
j++;
}
}}
用的是课本上说的冒泡排序法。当初只是知道了这种思想,自己写出代码后发现与课本上不是太一样,不过功能相同,没有什么差别。实现排名后,只要依次输出各项数据就可以了。
调试与运行
调试运行的时候自然错误很多,我对他们做了更爱和补救。
在编写查询函数时,发现一个问题到现在也没有解决。那就是在获取用户要查找的学生信息时,用gets函数不行。不知道为什么,程序会自动跳过这一句,直接进行下面的语句。到现在也没有弄明白这是为什么,我只好用scanf代替了gets。
小结与体会
程序因为时间关系没有写完,我很遗憾。本来指导老师告诉我,这个程序太大,建议四人一组共同完成编程任务。可是我没有听,否则应该可以把它写完的。今后不管是学习还是生活,都要重视团队合作的力量。
另外在编写过程中发现,一些自认为很简单的问题,自己写起来总是出错。可见古人所说的眼高手低还是有道理的。凡事尤其是编写程序,切记不可在不动手的情况下,低估程序的难度。
本人于2008年9月8号在计算机中心6号机房5号机器上完成了本次课程设计。课程设计过程中使用的操作系统是Windows 2000,主要开发平台VC++ 6.0。
任务四 黑白棋游戏、
任务和意义
设计一个程序完成黑白棋,两人对弈。
任务分析
黑白棋的玩法大家都知道,而要实现一人与电脑对弈的模式牵扯到人工智能方面的知识,远在我的水平之外。所以只好编写两人对弈的模式。
开始自己也想过很多,可是后来发现这些都是枉然。这个程序的难度完全超越了我目前的水平。所以把附录上的程序敲入到电脑里。对这已经编好的程序看了好久,由于程序代码太长,而我自己的水平又确实有限,只是看懂了部分代码。
关键算法
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();/*输出开始分数*/
}
主函数只有函数的声明,以及函数的调用。我认为自己编写过得程序,主函数的已经非常的整齐,可是我不得不承认,我与真正的大使级变成大师确实还有很远的一段距离。
由于程序设计大量的显示方面的函数,我完全没有接触过。看了好久也始终是一头雾水。总觉得每个函数都不可缺少,却又不知道为什么。
调试与运行
原本老师说,这个程序可能村子几个小错误。可是我用debuge系统没有检查出错误,只是不能够运行而已。找到了正确的运行环境,我是用了这个程序。用它跟同学对弈了一下,没有发祥任何异常现象,可以说没有任何错误。
小结与体会
当我看着这份代码为n行的程序时,大致有两个感觉。一是感觉,这么长的代码,写他的人要多大的耐力;第二,肯定有很多错误。
可是当晚把它打完、运行后,我不得不承认它一点错误都没有。我完全被它折服了,其实是被编写它的老师折服了。意识到自己究竟有多么渺小,水平到底有多么的粗浅。
觉得自己路还有很长,可是我并不气馁。因为我相信,终有一天,我也可以做这样的程序出来,可是这一天距离我还有好远。
雄关漫道真如铁,而今迈步从头越!
附录(各个程序)
二分法:
#include
float hanshu(float x)
{
return x*x*x-x-1;
}
void main ()
{
float a=1,b=1.5,f;
do
{
f=(a+b)/2;
if(hanshu(f)==0)
{printf("方程的根为%.2f\n",f);break;}
if(hanshu(a)*hanshu(f)<0)
b=f;
else
a=f;
}while(b-a>0.001);
if(b-a<0.001)
printf("方程的近似根为%.2f\n",f);
}
矩阵求逆(未调试成功):
#include
float hangleishi(int n,float x[8][8])
{
float h;
int i=0;
float yuzishi(int n,float x[8][8],int i,int j);
if (n=2)
h=x[0][0]*x[1][1]-x[0][1]*x[1][0];
else
for(i=0;i
#include
struct zhengshu
{
int shuzi;
struct zhengshu *next;
};
void main()
{
printf("欢迎使用本链表制作程序!!!\n海波制作群预祝您身体健康,万事如意!\n如果您使用中发现BUG,请与我们联系\n");
printf("电话:15898523371 QQ:279528056 联系人:李海波\n\n\n\n");
void caidan();
struct zhengshu *chuangjian(struct zhengshu *head);
struct zhengshu *charu(struct zhengshu *head);
struct zhengshu *xiugai(struct zhengshu *head);
struct zhengshu *shanchu(struct zhengshu *head);
struct zhengshu *chexiao(struct zhengshu *head);
void print(struct zhengshu *head);
void jieshu ();
struct zhengshu *head;
int a=0;
head=NULL;
loop:
caidan();
scanf("%d",&a);
switch(a)
{
case 1:
head=chuangjian(head);goto loop;
case 2: head=charu(head);goto loop;
case 4: head=xiugai(head);goto loop;
case 3:
head=shanchu(head);goto loop;
case 5:
head=chexiao(head);goto loop;
case 6: print(head);goto loop;
case 7: jieshu();
}
}
/***********************链表菜单*************************/
void caidan()
{
printf("请输入数字选择您要使用的功能\n");
printf("1.创建链表\n");
printf("2.插入一个新的节点\n");
printf("3.删除链表一个节点\n");
printf("4.修改某个结点值\n");
printf("5.撤消链表\n");
printf("6.显示链表\n");
printf("7.结束\n");
}
/* 链表的创建 */
struct zhengshu *chuangjian(struct zhengshu *head)
{
if(head!=NULL)
printf("链表已创建\n");
else
{
int n;
struct zhengshu *p1=NULL,*p2=NULL;
printf("依次输入各个节点的整数,输入999999结束\n");
scanf("%d",&n);
while(n!=999999)
{
p1=(struct zhengshu*)malloc(sizeof(struct zhengshu));
p1->shuzi=n;
p1->next=NULL;
if(head==NULL)
head=p1;
else
p2->next=p1;
p2=p1;
scanf("%d",&n);
}
}
return head;
}
/*****************链表节点的插入**********************/
struct zhengshu *charu(struct zhengshu *head)
{
if(head==NULL)
{
printf("链表未创建\n");
}
else
{
int a=0,b=0;
struct zhengshu *p1,*p2,*p3;
printf("若要把新节点放在最前面,请输入1;否则输入数字2\n");
int i;
scanf("%d",&i);
switch(i)
{
case 1:
{
printf("请输入新节点值\n");
scanf("%d",&a);
p1=(struct zhengshu *)malloc(sizeof(struct zhengshu));
p1->next=head->next;
p1->shuzi=head->shuzi;
head->next=p1;
head->shuzi=a;
printf("插入新节点成功!\n");
goto jieshu;
}
case 2:
{
printf("请输入插入点前面的整数数值\n");
scanf("%d",&a);
p1=head;
do
{
if(p1->shuzi==a)
{
b++;
printf("检索成功!\n");
break;
}
p1=p1->next;
}while(p1->next!=NULL);
if(b==0)
{
printf("链表中无此节点或此节点在最末端,新结点将插入链表最末端\n");
printf("输入新节点的数值\n");
scanf("%d",&a);
p2=(struct zhengshu*)malloc(sizeof(struct zhengshu));
p1->next=p2;
p2->next=NULL;
p2->shuzi=a;
printf("插入节点成功!\n");
}
else
{
printf("请输入新节点的数值\n");
scanf("%d",&a);
p2=(struct zhengshu*)malloc(sizeof(struct zhengshu));
p3=p1;
p1=p1->next;
p2->shuzi=a;