C语言课程设计报告.docx
《C语言课程设计报告.docx》由会员分享,可在线阅读,更多相关《C语言课程设计报告.docx(28页珍藏版)》请在冰豆网上搜索。
![C语言课程设计报告.docx](https://file1.bdocx.com/fileroot1/2023-4/21/fdd09f24-47a7-4b92-b401-c302a3b47e5d/fdd09f24-47a7-4b92-b401-c302a3b47e5d1.gif)
C语言课程设计报告
《C程序设计》课程设计
学部:
机械与电子信息学部
专业:
移动通信技术
班级:
28011001
学号:
2801100136
姓名:
戴注勇
指导教师:
杜丽芳
2011年6月
文档资料的统一要求:
1、文档中的正文字体用五号宋体。
2、第1章,第2章,第3章设计任务任意选2个,第4章必做。
3、每个问题均要有算法分析,源程序代码,编译示图,运行结果示图。
4、文件名命名中要有学生姓名。
5、没有按要求做的同学则视为本课程设计不合格。
6、每次上机所做的内容用移动磁盘带走。
第1章分支与循环
1.1算法与范例
1.递推算法
递推算法是循环程序设计的精华之一,在很多情况下使用递推算法能使程序简练,同时还能节省计算时间。
递推算法的基本思想:
利用前一项的值来推算出当前项的值,即利用前一项的值乘以(或加上)某一系数得到当前项的值。
使用递推算法的前提是必须有一项的值(一般是最前项)是已知的。
使用递推算法的关键是如何根据多项式推出递推公式。
【示范】求
(即1!
+2!
+3!
+…+20!
)的程序
【编程提示】若多项式第1项为t1,第2项为t2,……,第20项为t20,则
第1项t1=1!
第2项t2=2!
=1!
*2=t1*2
第3项t3=3!
=2!
*3=t2*3,
……
第20项t20=20!
=19!
*20=t19*20
可以推出多项式后一项等于前一项乘以某一系数这一规律,故求某一项的递推公式为:
ti=ti-1*n(n=1to20)。
因此知道了多项式第1项1!
,就可以利用递推公式求出后面的每一项,每求一项累加求和。
【参考程序】
#include
intmain()
{doublesum=0,t=1;
intn;
for(n=1;n<=20;n++)
{
t=t*n;//递推公式
sum=sum+t;
}
printf("1!
+2!
+...+20!
=%22.15e\n",sum);
return0;
}
2.测试法
在实际应用中,有许多问题是无法用解释方法实现的,这时采用测试法来求解是一种很有效的方法。
测试法的基本思想是假设各种可能的解,让计算机进行测试,如果测试结果满足条件,则假设的解就是所要求的解。
如果所要求的解是多值的,则假设的解也应是多值的,在程序设计中,实现多值解的假设往往使用多重循环进行组合。
测试法求解的程序设计有两个要点:
⑴通过循环列出所有可能的解。
⑵对所有列出的可能的解进行条件测试。
【示范】百钱买百鸡问题
已知公鸡每只5元,母鸡每只3元,小鸡1元买3只。
要求用100元钱正好买100只鸡,问公鸡、母鸡、小鸡各多少只?
【编程提示】设公鸡、母鸡、小鸡分别为a、b、c只,依据题目能列出下列两个方程:
a+b+c=100
5a+3b+c/3=100
三个未知数,只有两个方程,故是个多解问题。
可采用多重循环组合出各种可能的a、b、c的值。
通过循环列出公鸡、母鸡和小鸡可能的只数,再对可能的只数进行条件测试。
100元钱,全部买公鸡最多只能买20只,即公鸡的只数a的范围是:
a=0to20
100元钱,全部买母鸡最多只能买33只,即母鸡的只数b的范围是:
b=0to33
100元钱,全部买小鸡最多只能买100只,即小鸡的只数c的范围是:
c=0to100
【参考程序】:
#include
intmain()
{inta,b,c;
printf("公鸡母鸡小鸡\n");
for(a=0;a<=20;a++)
for(b=0;b<=33;b++)
for(c=0;c<=100;c++)
if((a+b+c==100&&5*a+3*b+c/3.0==100)
printf("%d%d%d\n",a,b,c);
return0;
}
1.2设计任务
1.若一个口袋中放有12个球,其中有3个红色球,3个白色球和6个黑色球,从中任取8个球,问共有多少不同的颜色搭配。
2.输入年月日,求它是该年的第几天。
注:
闰年的2月有29天,平年的2月有28天。
3.简单计算器。
请编写一个程序计算表达式:
data1opdata2的值。
其中op为运算符+、-、*、/。
4.猜数游戏。
由计算机“想”一个数请人猜,如果猜对了,则游戏结束,否则计算机给出提示,告诉人所猜的数是太大还是太小,直到猜对为止。
计算机记录人猜的次数,以此可以反映出猜数者“猜”的水平。
1.3实现过程
1.3.1设计任务1的实现过程
【算法分析】(用文字或流程图进行描述)
用测试法,可采用多重循环组合出各种可能的a、b、c的值。
通过循环列出红球、白球和黑球可能的个数,再对可能的个数进行条件测试。
若a+b+c==8,则
当a=0,b=0,c=0;则不成立
当a=1,b=1,c=1;则不成立
如此反复下去
直到求出取球的总数
【源程序代码】
#include
intmain()
{
inta,b,c,m=0;
printf("不同的着颜色搭配有:
");
for(a=0;a<=6;a++)
for(b=0;b<=3;b++)
for(c=0;c<=3;c++)
if(a+b+c==8)
m+=1;
printf("%d\n",m);
return0;
}
【编译示图】(示图中要有0error,0warning的提示)
【运行结果示图】
1.3.2设计任务2的实现过程
【算法分析】(用文字或流程图进行描述)
这是一个多分支选择问题,根据月份将天数分为了12个周期.如果用IF语句来处理至少要用12层嵌套的IF,进行了12次检查.用SWITCH语句,进行一次检查就可以了.
再根据关系表达式year%4==0&&year%100||year%400==0来检查闰年的2月有29天,平年的2月有28天.
【源程序代码】
#include
intmain()
{
intmonth,year,day,sum,i=0;
printf("Inputtheyear,themouthandtheday:
\n");
scanf("%d%d%d",&year,&month,&day);
switch(month)
{case12:
i=i+30;
case11:
i=i+31;
case10:
i=i+30;
case9:
i=i+31;
case8:
i=i+31;
case7:
i=i+30;
case6:
i=i+31;
case5:
i=i+30;
case4:
i=i+31;
case3:
i=i+28;
case2:
i=i+31;
case1:
;
default:
;
}
sum=i+day;
if(((year%4==0&&year%100)||(year%400==0))&&(month>2))
sum=sum+1;
printf("thedayisthe%ddayin%dyear\n",sum,year);
}
【编译示图】(示图中要有0error,0warning的提示)
【运行结果示图】
第2章数组与函数
2.1启示与范例
【示范1】输入n个学生的成绩,并求出其中高于平均分的人数。
【编程提示】用程序来实现本题的要求,首先有两个值得思考的问题:
一是数据结构的选择;二是数组的长度。
①数据结构的选择:
n个学生的成绩是否有必要开辟数组来存放还是定义变量来存放?
从任务要求分析知,两次用学生成绩,一次是求平均分;另一次是将每个学生的成绩与平均分比较,高于平均分要输出。
因此有必要将其定义数组。
②数组的长度定义:
学生个数n的具体数值一般表示在编写程序时是未知的,而在程序执行时由使用者随意确定。
即n是一个变量,其值需要用输入来确定。
这样一来,存放n个分数的数组a,其长度的定义就必须注意,既不能定义为inta[n];因为数组长度要求是常量,而n是一个变量,又不能将n定义成符号常量,因为n的具体值是未知的。
对于这种情况的处理方法一般是:
将数组的长度定义较大,让使用者在此范围内随意使用,当然这个长度的定义有其原则,那就是既不让使用者感到长度不够,又不至于定义过大而浪费内存,这种情况视应用情况而定。
【参考程序】
#include
intmain()
{
inti,a[1000],num=0,n;
floataver=0;
printf("输入学生个数n\n");
scanf("%d",&n);
printf("输入学生的成绩存放到数组a中\n");
for(i=0;i{
scanf("%d",&a[i]);
aver=aver+a[i];
}
aver=aver/n;
for(i=0;iif(a[i]>=aver)
num++;
printf("高于平均分的人数是:
%d\n",num);
return0;
}
【示范2】输入任意个学生的学号及成绩,然后按顺序输出高分的前十名。
【编程提示】依据设计任务的要求需要考虑几个问题:
初始数据的数据结构选择;采用的算法如何实现及相关的数据结构;任意个数据的实现问题。
①初始数据的数据结构选择问题:
所谓任意个学生,应该是个数不限,因此,对于存放初始数据的数据结构不宜选择为数组。
并且,从算法实现的角度考虑,每个学生的数据输入后只需使用一次,没有再保留的必要,因此可选择简单变量作数据结构来存放一个学生的数据,而且每个学生的初始数据都用同一个数据结构存放,即对一个学生的数据使用完后就将该数据结构让给下一个学生的数据使用。
②算法的实现及相关的数据结构:
本题核心的算法是排序,由设计任务可知只要求前十名的排序结果,因此算法上不需考虑对所有学生数据进行排序,只考虑对前十名排序即可。
因此,应选择合适的数据结构来存放前十名排序结果的数据,显然,选择数组是最合适的。
关于算法的实现可采用插入排序法最为合适。
即存放排序结果的数组始终是存放当前已插入数据的前十名的排序结果,而后每输入一个学生的数据就进行一次插入排序更新这一排序结果。
③任意个的实现:
对于本题的程序来说,总体结构还是一个循环结构,每次循环的任务是输入一个学生的数据并进行插入排序。
问题是何时结束循环?
循环结束的条件是什么?
对用户输入的有用数据,循环继续;对用户输入的无用数据即输入数据为负数时,循环结束。
④为了使程序更加清晰。
主程序只提供输入学生的学号、成绩,并且输出前十名的学号及成绩;子函数实现插入排序的过程。
【参考程序】
#include
voidinsertsort(intnum[],inta[],intn,intnumber,intscore)
{
inti,j;
for(i=0;iif(score>a[i])
break;
if(i>=n)
return;
for(j=n-2;j>=i;j--)
{
num[j]=num[j-1];
a[j]=a[j-1];
}
num[i]=number;
a[i]=score;
}
intmain()
{
inti,num[10],a[10],number,score;
for(i=0;i<10;i++)
{
a[i]=0;
num[i]=0;
}
while
(1)
{
printf("输入学生的学号及学生成绩:
\n");
scanf("%d%d",&number,&score);
if(number<0||score<0)
break;
insertsort(num,a,10,number,score);
}
for(i=0;i<10;i++)
printf("前十名学生学号%d成绩是%d\n",num[i],a[i]);
return0;
}
2.2设计任务
1.有一个一维数组score[],内存放10个学生的成绩,要求编写三个函数分别求学生的平均成绩,求10个学生的最高分,求10个学生的最低分。
2.编写一个函数,将输入的一串字符中的小写字母转变成大写字母,并输出所有的大写字母。
3.输入10个学生姓名,按字典顺序将排在最前面的学生姓名输出。
即在字符数组中求最小字符串。
4.用函数法求N*N的对角线的和。
其中的N是用户通过键盘输入的任意值。
2.3实现过程
2.3.1设计任务1实现过程
【算法分析】(用文字或流程图进行描述)
调用三个函数可以得到三个函数返回值,现在希望通过函数调用能得到达3个结果。
分析可知:
main函数在调用average函数时,把实参数组score的首元素地址和整数10传递给形参数组array和形参变量n,函数average的值是return语句带回的aver的值.
分析可知:
main函数在调用max函数时,把实参数组score的首元素地址和整数10传递给形参数组array和形参变量n,函数max的值是return语句带回的max的值.
分析可知:
main函数在调用min函数时,把实参数组score的首元素地址和整数10传递给形参数组array和形参变量n,函数min的值是return语句带回的min的值.
【源程序代码】
#include
intmain()
{
floataverage(floatarray[],intn);
floatmax(floatarray[],intn);
floatmin(floatarray[],intn);
floatave,maxi,mini,score[10];
inti;
printf("pleaseenter10score:
");
for(i=0;i<10;i++)
scanf("%f",&score[i]);
ave=average(score,10);
maxi=max(score,10);
mini=min(score,10);
printf("max=%6.2f\nmin=%6.2f\naverage=%6.2f\n",maxi,mini,ave);
return0;
}
floataverage(floatarray[],intn)
{inti;
floataver,sum=array[0];
for(i=1;isum=sum+array[i];
aver=sum/n;
return(aver);
}
floatmax(floatarray[],intn)
{
inti;
floatmax=array[0];
for(i=1;iif(array[i]>max)
max=array[i];
return(max);
}
floatmin(floatarray[],intn)
{inti;
floatmin=array[0];
for(i=1;iif(array[i]min=array[i];
return(min);
}
【编译示图】(示图中要有0error,0warning的提示)
【运行结果示图】
2.3.2设计任务2实现过程
【算法分析】(用文字或流程图进行描述)
通过调用voidbianhuan(charb[])函数将字符串中小写字母换成大写字母.
因为小写字母与大写字母相差32,可得if(b[i]>=97&&b[i]<=122)。
【源程序代码】
#include
intmain()
{
voidbianhuan(charb[]);
chara[10];
inti;
for(i=0;i<10;i++)
scanf("%c",&a[i]);
bianhuan(a);
for(i=0;i<10;i++)
printf("%c",a[i]);
return0;
}
voidbianhuan(charb[])
{inti;
for(i=0;i<10;i++)
{if(b[i]>=97&&b[i]<=122)
b[i]=b[i]-32;}
}
【编译示图】(示图中要有0error,0warning的提示)
【运行结果示图】
第3章指针
3.1启示与范例
指针变量作为函数参数最常见有以下两种用法:
①用于接受实参变量的地址,从而可以在函数中通过访问指针变量所指向的内存单元来达到间接地访问实参变量。
这样,函数中既可引用实参变量原来的值,也可将结果存入实参变量所在的单元,达到双向传递的效果。
②用于接受实参数组的首地址,从而可以在函数中通过访问指针变量所指向的内存单元来达到间接访问实参数组的各元素,这样,函数中既可以引用实参数组各元素的值,也可以将结果存入实参数组的各元素中。
【示范】通过改变指针的指向来引用不同元素法:
编写输入100名学生的成绩,输出其中高于平均分的人数。
【参考程序】
#include
intover_aver_number(int*a,intn)
{
inti,number=0;
floataver=0;
for(i=0;iaver+=*a++;/*a++的作用是每执行一次循环就让指针变量a指向下一个元素,使以后的访问就直接访问a所指向的内存单元,不需再作地址计算。
*/
aver/=n;
a-=n;//a-=n的作用是使a恢复其初始指向。
for(i=0;iif(*a++>=aver)
number++;
returnnumber;
}
intmain()
{
inti,number,a[100];//a是数组名,是指针常量。
printf("\nEntera:
");
for(i=0;i<100;i++)
scanf("%d",&a[i]);
number=over_aver_number(a,100);
printf("\n输出高于平均分的人数number=%d",number);
return0;
}
3.2设计任务
1.已知一个整型数组a[5],其各元素值为4,6,8,10,12。
使用指针法求该数组元素之积。
2.100个围成一圈,从第1个人开始,每数到3的人出圈。
问最后一个出圈的人是哪一个。
3.编写两个排序函数,要求一个函数完成从小到大排序,一个函数完成从大到小排序,并编写主函数完成:
①输入n个数;
②组织调用排序函数对n个数按从大到小排序并输出;
③组织调用排序函数对n个数按从小到大排序并输出;
3.3实现过程
3.3.1设计任务1实现过程
【算法分析】(用文字或流程图进行描述)
使作指针用于接受实参数组的首地址,从而可以在函数中通过访问指针变量所指向的内存单元来达到间接访问实参数组的各元素,通过改变指针的指向来引用不同元素.
再用累乘来求数组元素之积.
【源程序代码】
#include
intmain()
{
inta[5]={4,6,8,10,12};
int*p,s=1;
for(p=a;p<=a+4;p++)/*由于数组名表示数组的首地址*/
s=s*(*p);/*这里的*p是p贮存的数据*/
printf("%d\n",s);
return0;
}
【编译示图】(示图中要有0error,0warning的提示)
【运行结果示图】
3.3.2设计任务2实现过程
【算法分析】(用文字或流程图进行描述)
1.变量进行宏定义。
2.通过变指针的指向来引用不同元素,来分别指向顺序的指向下一个要出圈的人。
3.使用while循环来分别指向下一个。
如此反复下去,到求出最后一个出圈的人是谁。
【源程序代码】
#definenmax100
#include
intmain()
{
inti,k,m,n,num[nmax],*p;
printf("pleaseinputthetotalofnumbers(n<=%d):
",nmax);
scanf("%d",&n);
p=num;
for(i=0;i*(p+i)=i+1;
i=0;k=0;m=0;
while(m{
if(*(p+i)!
=0)k++;
if(k==3)
{*(p+i)=0;
k=0;
m++;
}
i++;
if(i==n)i=0;
}
while(*p==0)p++;
printf("%disleft\n",*p);
}
【编译示图】(示图中要有0error,0warning的提示)
【运行结果示图】
第4章综合设计题
4.1设计任务
运用C语言开发一个“比赛评分系统”。
评委打分原则:
满分10分,评委打分后,去掉一个最高分和一个最低分,最后的平均分为参赛选手的最后得分(精确到小数点后两位)。
要求该系统实现以下功能:
①假设参赛人数为20人,评委为10人。
(有兴趣的同学可拓展为参赛人数为n人,评委为m人)。
并对参赛选手和评委分别编号,序号从1开始,顺序编号。
②选手按编号顺序依次参加比赛,统计最后得分。
③比赛结束,按从高分到低分每行5人依次打印选手的得分情况。
④公布选手获奖。
取一等奖1名,二等奖2名,三等奖3名。
4.2设计过程
【算法分析】(用文字或流程图进行描述)
注:
本次比赛共有20位参赛选手,有10位评委为他们评分,从语言表达、参赛技巧两个方面进行打分,每小项5分,每位选手最高分为10分。
每位选手的最终得分是去掉一个最高分、去掉一个最低分,取剩余评委的平均分,为此选手的最终得分。
主程序由三个程序模块构成,分别为自编函数sort,average,arran。
每一个模块用来实现一个特定的功能,由主程序调用其他函数,其他函数也可以互相调用,以减少重复编写程序段的工作量。
在选手评分录入完成后,为了准确计算出选手的最终得分,程序首先调用了average函数。
从六个评委的评分中先通过调用sort函数将评分按大小进行排序,然后去掉一个最低分,去掉一个最高分,用average函数算出平均数aver作为选手得分。
选手姓名录入完成以及选手最终得分名次排序后,还必须将选手得分与选手姓名一一对应,程序在此调用arran函数。
arran函数通过定义一维数组num[]和二维数组name[][]实现了选手得分以及选手姓名的一一对应。
函数调用至此结束。
首先我们先定义一个整型变量,i,j。
和一个最大的的值max变量,temp1表示分数的高低,然后再定义一个字符型数组tem