柴群 梁剑波
摘要:C程序设计是计算机科学与技术专业中开设的比较重要、基础的专业课,大部分学生接触程序设计都是从该门课开设的。学过的学生普遍反映C程序设计比较难,不容易掌握。该文根据《C程序设计》教学经验,从算法出发,总结出“五步编程法”,帮助学生编程快速入门,以提高学生编程水平和编程能力。
关键词:C程序设计;五步编程法;算法;编程
中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2017)31-0140-02
通过总结最近几个学期的《C程序设计》的期末考试试卷发现,学生对于C程序的掌握较差,得分率很低,原因主要存在两个方面:(1)对C语言语法死记硬背,不能灵活使用,当题目有变化时就不知道如何处理。(2)拿到题目后不知如何编写符合题意的程序,不能将书本的知识解决现实问题。
对于第一种情况,说明这些同学C语言知识掌握不牢,可以通过大量的练习来提高其编程能力。对于第二种情况,笔者总结了“五步编程法”来进行针对性教学,实践表明,可以很好地提高学生的编程能力。
1 第一步——算法分析
算法从广义上来说,是为了解决一个问题而采取的方法和步骤,它分为数值运算算法和非数值运算算法两大类。数值运算的目的是求数值解,例如求解方程的跟、求一个函数的定积分等,都属于数值运算范畴,这类算法往往都有现成的模型、公式,可供学生使用。而非数值运算算法包括的就十分广泛,最常见的是用于事务管理领域,这类算法运算的种类繁多,要求各异,只有一些典型的非数值运算算法,如排序算法,查找算法等。C程序设计所涉及的算法基本上以数值运算算法为主,也接触一些典型的非数值运算算法,这样算法具有一定的规律,可以引导学生查找这些算法的规律,提高学生的编程能力。①
在这一步中,学生的主要是任务是寻找算法,并将算法用数学公式表达出来。
例如求ax2+bx+c=0方程的根。a,b,c由键盘输入,设b2-4ac>0,且a≠0。这是一个典型的二元一次方程,在中学的时候就知道,求解方程的根的公式是:
[x1=-b+b2-4ac2a] …………①
[x2=-b-b2-4ac2a] …………②
为了表达方便,可以将公式分为两项:
[p=-b2a],[q=b2-4ac2a],则公式①、②可变为
[x1=p+q] …………③
[ x2=p-q] …………④
有了这些公式,只要知道a、b、c的值就可以求出方程的根。
2 第二步——將算法用C语言语句表示
C语言有自己的语法规则,在这一步,学生需要将数学公式转换成符合C语言语法规则的表达式,并将该表达式转换成可以执行的C语句。
根据C语言的语法规则,[p=-b2a]可以表示为
[p=-b/(2*a)] …………⑤
[q=b2-4ac2a]可以表示为
[q=sqrt(b*b-4*a*c)/(2*a)] …………⑥
其中 disc=b*b-4*a*c …………⑦
sqrt()是编译系统提供数学函数,作用是求解[x],它在使用时必须在源文件中加入#include
公式⑤⑥⑦在C语言中被称为表达式,表达式转换成可执行的C语句的方法是在表达式后面加上“;”。根据语法规则,公式③④⑤⑥⑦转换成C语句为:
disc=b*b-4*a*c; …………⑧
[p=-b/(2*a)]; …………⑨
[q=sqrt(disc)/(2*a)]; …………⑩
[ x1=p+q]; …………?
[ x2=p-q]; …………?
3 第三步——将得到的C语句填充到程序的主函数的函数体中
C语言规定,程序的执行总是从主函数(main)开始,并从主函数结束。而且C语言的输入输出都是通过库函数实现,这个库函数被包含在stdio.h的头文件中。C语言的main()函数语法格式(加上两个头文件,#include
#include
#include
void main()
{
函数体
} …………?
将⑧~?填充到?中得到程序为:
#include
void main()
{
disc=b*b-4*a*c; …………⑧
[p=-b/(2*a)]; …………⑨
[q=sqrt(disc)/(2*a)]; …………⑩
[ x1=p+q]; …………?
[ x2=p-q]; …………?
} …………?
4 第四步——查漏补缺
C语言规定,任何变量必须“先定义、后使用”,例中disc,p,q,a,b,c,x1,x2都是变量,这些变量都需要在使用前先定义,在语句⑧之前添加给变量定义的语句。设变量a,b,c为整型,其它的变量为浮点型。根据语法规则,补充语句(带阴影部分),得到源程序为:
#include
#include
void main()
{
int a,b,c;
float disc,p,q,x1,x2;
disc=b*b-4*a*c; …………⑧
[p=-b/(2*a)]; …………⑨
[q=sqrt(disc)/(2*a)]; …………⑩
[ x1=p+q]; …………?
[ x2=p-q]; …………?
} …………?
很多变量在使用前需要给它一个初始的值,这个过程被称为赋初值。C语言一般通过两种形式实现,一个是通过赋值语句,一个是通过输入函数scanf。使用输入函数,可以通过人机界面实现数据的输入,编制的程序复用性高,是常见的变量赋值的方法,本题要求是通过输入函数实现对a,b,c赋初值的。根据语法规则,补充语句(带阴影部分),得到源程序为:
#include
#include
void main()
{
int a,b,c;
float disc,p,q,x1,x2;
scanf(“%d%d%d”,&a,&b,&c);
disc=b*b-4*a*c; …………⑧
[p=-b/(2*a)]; …………⑨
[q=sqrt(disc)/(2*a)]; …………⑩
[ x1=p+q]; …………?
[ x2=p-q]; …………?
} …………?
编程的目的是想求解方程的根,输入a,b,c就要得到方程的解(假设方程有解),因此还要加上输出语句(用printf实现)。根据语法规则,补充语句(带阴影部分),得到源程序为:
#include
void main()
{
int a,b,c;
float disc,p,q,x1,x2;
scanf(“%d%d%d”,&a,&b,&c);
disc=b*b-4*a*c; …………⑧
[p=-b/(2*a)]; …………⑨
[q=sqrt(disc)/(2*a)]; …………⑩
[ x1=p+q]; …………?
[ x2=p-q]; …………?
printf(“方程的两个根分别是x1=%f\n,x2=%f\n”,x1,x2);
} …………?
至此,一个完整的求解二元一次方程根的源程序已经编写完成,下面就要进行第五步,编译、排错、执行。
5 第五步——反复进行编译、排错、执行程序,直至输出正确的结果
编译的作用首先是对源程序进行检查,判断有没有语法方面的错误,如有,则给出错误信息,通知编程人员进行修改。修改程序后还要重新进行编译,如果有错,还要进行修改。这个过程会反复执行,直到没有语法错误为止。
对没有语法错误的源程序进行连接处理,得到.obj文件。编译系统在对.obj文件进行处理得到可执行文件.exe,运行该文件即可得到结果。
这里需要注意的是,由于编译只能发现语法错误,不能发现逻辑错误,因此有时会出现源程序没有语法错误,但是却得不到正确的结果。这就要对源程序进行单步调试,观察变量的值,寻找逻辑错误。本例中语句⑨就存在逻辑错误,初学者很难发现。运算符“[/]”的左右两边都是整型数值时,得到的数据也是整型,如果b<2*a,p的值就会是0,而不是一个小数,因此需要将计算的结果转换成小数,语句⑨可修改为,[p=-b/(2.0*a)]; 这样得到的程序才能计算出正确的结果。
在学生掌握“五步编程法”基础上,可以继续对第一步、第二步进行扩充到选择结构、循环结构、复合结构,从数值运算扩充到非数值运算,从而慢慢地提高学生的编程能力,解决学生编程难的问题。
参考文献:
[1] 谭浩强.C程序设计[M].四版.北京:清华大学出版社,16-17.