C语言程序设计入门之抽象编程

前言

多年的计算机程序设计语言教学实践发现,很多学生刚刚接触时常常会感到计算机语言中的许多概念和方法非常抽象,常常搞不清楚,不能很好地理解和掌握。其实计算机程序中弥漫着大大小小的抽象。编程的实质就是抽象与表达。将现实世界的问题抽象成容易处理的可计算对象,然后使用计算语言来实现它。那究竟什么是抽象编程,以及如何进行抽象编程。今天我们就来谈谈它。
通常说来,抽象是指为了某种目的,对一个概念或一种现象包含的信息进行过滤,移除不相关的信息,只保留与某种最终目的相关的信息。例如,在下图中,我们可以看到一个“黑白相间的皮质足球”,然后进一步过滤它的色彩、材料、用途等信息,得到一般性的概念,也就是“球”。从另外一个角度看,抽象就是简化事物,抓住事物本质的过程。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

从现实场景中首先抽象出其中的“足球”,再进一步抽象出“球体”

抽象是针对问题的特征对现实事物的紧密相关的属性的提炼过程及结果。抽象是人类认识世界的基本法则之一,在现实世界中一些事物、状态或过程之间总是存在着某些相似的方面,把这些方面集中和概括起来,暂时忽略它们之间的差异,或者说抽出事物的本质特性而暂时不考虑其细节,这就是抽象。
掌握抽象程序设计方法可以减少对C语言等计算机语言操作的神秘感,使得初学者更加容易学习和掌握程序设计、更好地理解和学会编写简单的程序,尽快地完成程序设计入门学习和实践,提升程序设计水平和使用计算机解决实际问题的能力。

1. 程序入门抽象:变量和过程抽象

变量来源于数学,在初等数学中,变量是表示数字的字母字符,具有任意性和未知性。把变量当作是显式数字一样,对其进行代数计算,可以在单个计算中解决很多问题。在计算机语言中,变量是能存储计算结果或表示值的抽象概念,变量具有通用性和代表性。比如在计算圆形面积等程序中的半径变量可以代表所有的圆半径。同理如果“家长”是一个变量的话,那它就可以代表“所有学生的家长”,每一时刻代表一个具体学生的“家长“。
计算机高级语言处理数据要全部通过变量和常量实现,绝大部分通过变量实现。初学者往往难以确定程序设计所需要的变量,难以动手编程。
这是程序设计入门的最基础抽象,很多初学者在学习初期,就是不知道如何下手编程。实际上程序设计过程就是实际解决问题(模拟手工计算)的过程,所以程序设计的三步曲(过程)就是输入、计算和输出。
变量根据在程序中的作用可分为:输入变量或已知变量,输出变量或结果变量,辅助变量或临时变量。明确这个问题,对于简单的或已有已知简单公式的问题,初学者可以根据题意比较容易设定以上变量并进行编程处理。
初学者同时要完成C语言表达式的构建及从初等数学表达式到C语言表达式的转变,用以完成所需的数据处理。
如很多教材上的温度转换问题:根据输入的华氏温度值,将其转换为对应的摄氏温度值。
解决该问题可设置输入变量1个,即要输入的温度值h,结果变量1个,为根据温度转换公式计算的温度值c。解决过程就是首先输入华氏温度值,然后根据温度转换公式进行计算,最后将计算结果输出。
又如已知矩形的两边长,求其周长和面积。解决该问题则可设置输入变量2个,为矩形的两边长a、b,结果变量也是2个,分别为其周长c和面积area。
再如已知三角形的三边长,求其面积。解决该问题则可设置输入变量为3个,即三边长a、b、c,结果变量1个,即其面积area,为了处理方便可设置中间变量s=(a+b+c)/2。
由此可以看出,输入变量、输出变量和临时中间变量的设置都是根据问题实际来进行。一般情况下,至少有一个输出变量,因为这是程序的执行结果,而输入变量可以没有,此时程序执行一个相对固定的结果。如使用无穷级数法计算圆周率的值和“韩信点兵”问题求解。

2.程序结构抽象:顺序、选择、循环

通过上面知识的学习,我们知道如同人们解决日常生活中的各种问题一样,计算机程序也是按照一定顺序和步骤解决所给定的问题。几乎所有编程语言,都会有三种基本的程序结构:顺序结构、选择结构和循环结构。
顺序结构就是一条一条地从上到下执行语句,所有的语句都会被执行到,执行过的语句不会再次执行。例如,求1+2+3+4+5的和,就可以一个数一个数地依次累加。
选择结构就是根据条件来判断执行哪些语句,如果给定的条件成立,就执行相应的语句,如果不成立,就执行另外一些语句。如,根据用户输入的年龄来输出不同的内容。
如果年龄小于18用户还未成年,应该好好学习;大于等于18,小于等于30,则应该珍惜青春,多做有益的事情;大于30,小于60,为社会中坚力量,就要工作的同时注意身体;大于等于60,就请安享晚年,我们会记得您对社会的贡献。
循环结构就是在达到指定条件前,重复执行某些语句。如使用双重循环结构来输出九九乘法表。
需要注意的是,上述三种程序结构不是独立存在的,而是相互融合在一起的,它们之间可以相互交织相互嵌套来完成一个功能的实现,如一个顺序结构可划分为多个不同的阶段,也可看作多个顺序结构的结合,同时每个阶段又可以根据不同的条件进行选择和循环等等。

3.程序进阶抽象:问题(算法)抽象

做任何事情都有一定的步骤。为解决一个问题而采取的方法和步骤,就称为算法。算法是一个基本的概念,但也是一门深奥的学问,小到如何输出九九乘法表,如何对一组数据进行排序,大到如何控制飞行器的姿态,如何让无人机避障等待。对于程序设计的初学者,涉及到的算法都很简单,一般不会成为学习的障碍,
问题抽象通常又称算法抽象。对于比较简单的问题,使用变量抽象就可以解决。但对于稍微复杂的问题,只有简单的变量抽象就远远不够了,需要进行问题(算法)抽象才能解决。这就涉及到基本的程序设计方法,如穷举法、递推法和迭代法(含递归程序设计),此处不一一介绍。
如高空坠球问题:皮球从某给定高度自由落下,触地后反弹到原高度的一半,再落下,再反弹,……,如此反复。问皮球在第n次落地时,在空中一共经过多少距离?第n次反弹的高度是多少?
使用变量抽象方法可以得到输入变量为给定高度和反弹次数,输出变量为皮球n次落地后经过的距离及之后的反弹高度。由于没有直接的公式可以使用,必须经过推导得到相应的公式才能计算。
可以使用递推法解决该问题,问题分析如下:
设置初始高度h,反弹次数n,皮球经过的距离d和最后的反弹高度h2(也可由初始高度递推得到)。
分析问题可得到第1次落地时,经过的距离为h1,之后每1次落地时反弹高度为之前的1/2,经过的距离为反弹高度的2倍(弹起高度和下落高度)。
问题抽象和算法描述如下:

  1. 设置初始高度h,反弹次数n,皮球经过的距离d //h经递推后也是反弹高度
  2. 设置临时循环变量i
  3. 输入初始高度h和反弹次数n
  4. 第1次落地时d=h,反弹高度h=h/2
  5. 从2到n循环
  6.     d=d+2*h
    
  7.     h=h/2
    
  8. 打印d和h

4.软件工程抽象:函数(模块或问题分解)抽象

对于比较复杂的问题,往往需要进行问题分解,即将1个大的问题,分解成多个规模和难度较小的问题,如果需要,可进行多层次分解,最后再整合分解出的小问题而得到原问题的解决方案。这也是个教学难点,很多学生即使在课程学习结束之后仍然不能掌握。
函数抽象着重功能抽象,往往将1个复杂问题分解成多个功能模块,迭代分解直至一个个可以实现的具体功能模块。
初学者面对的问题比较简单,很多问题可以不使用函数都可以解决,但函数设计和使用是程序设计必须解决的问题。
函数抽象首先要明确函数的功能,根据功能先确定函数名和函数结果,函数结果也是函数的类型和返回值,并将已知条件确定为函数参数。对于有多个结果要返回的函数,可通过将参数设置为指针或引用即可。
设计函数分成两步进行,即设计函数首部和函数体。设计函数首部时,可根据抽象的结果明确给出函数首部各内容,如通常包括函数类型,函数名称,函数参数等。函数名称通常采用英文单词或简写命名,函数结果的类型就是函数类型,函数参数就是已知条件。设计出函数首部后就可以采用上面问题抽象的办法来完成函数体设计,实现函数功能。
如设计一个求整数n的阶乘的函数。阶乘的英文单词为factorial,通常将函数名设计为fact,显而易见可将函数参数设置为整数n,函数结果即函数类型也为整数。则用C语言描述为:int fact(int n);
又如前面的高空落球问题,我们也可以通过设计函数进行程序设计。函数名可设计为FallBall,函数结果有两个,我们可以设置距离d为函数结果,另一个反弹高度可通过参数的引用或地址传递得到。则c语言描述为double FallBall(double *h, int n);
程序设计方法可分为自底向上和自顶向下程序设计法。
一般而言,程序不是直接从第一行开始写到最后一行结束,而是遵循两种常见的顺序之一:自顶向下和自底向上。自顶向下就是先写框架,再写细节,实际上就是先写“伪代码”,然后转化成实际的代码。我们可以充分利用“函数”这个工具,更好地贯彻这个方法,即先写主程序,包括对函数的调用,再实现函数本身。自底向上则相反,即先写函数,再写主程序。

5.面向对象抽象:类与接口抽象(自定义数据抽象)

面向对象技术以更接近人们看待事物的思维,将数据和操作看成一个整体,具有程序结构清晰、实现简单、可有效减少程序的维护工作量、代码重用率高、开发效率高等优点。面向对象技术(OO,主要有OOA、OOD、OOP等)是当前计算机软件开发的主流。
程序设计方法的发展经历了4代,结构化和面向对象是软件工程的程序设计方法中最本质的思想方法,结构化体现了抽象思维和复杂问题求解的基本原则,面向对象则深刻反映了客观世界由对象组成这一本质特点。各种程序设计方法的一个重要区别在于问题分解的出发点不同(因子),思维模式不同。计算机中数据结构和过程是密切相关的,结构化方法将数据结构和过程分开考虑,面向对象的方法组合数据和过程于对象之中。如Java一切皆对象/Python一切皆对象。
面向对象程序设计从所处理的数据入手,以数据为中心而不是以服务(功能)为中心来描述系统。把编程问题视为一个数据集合,数据相对于功能而言,具有更强的稳定性。
面向对象程序设计由于和结构化程序设计存在着很大差异,初学者往往不能很好地转换过来,也是一个教学难点。

结束语

经过上述五重抽象,可以大大有助于学生对程序设计的理解和掌握。但要真正掌握编程还是要通过大量编程实践。
计算机世界里的抽象无处不在。每一类技术都建立了一套抽象,针对所面临的问题提出一种一致的机制,然后遵从该机制来实现这一类问题的求解;在后期的学习和工作中,还有很多的抽象需要关注和学习,如开发框架是对不可变的过程抽象,将可变部分留给应用开发者根据具体问题域来定义和实现;又如设计模式是对软件设计中普遍存在(反复出现)的各种问题,经过抽象后所提出的解决方案。
软件开发和教学实践证明,抽象是一种强有力的程序设计工具。抽象实现了“关注点分离”的原则,将一件复杂而完整的应用系统分解成多个子系统,各司其责,更容易构建和维护;善于系统地使用抽象,在合适的抽象层次上思考问题,或许就真正掌握了编程之道。

说明

文章内容如有问题和错误,请联系我:lg997@126.com。引用请注明出处

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
图书目录 第Ⅰ部分 预备知识   第1章 ANSI C概述1   1.1 什么是C   1.2 C程序的结构   1.3 变量、值和类型   1.4 表达式   1.5 语句   1.6 函数   1.7 小结   1.8 复习题   1.9 编程练习   第2章 C的数据类型   2.1 枚举类型   2.2 数据和内存   2.3 指针   2.4 数组   2.5 指针和数组   2.6 记录   2.7 动态分配   2.8 小结   2.9 复习题   2.10 编程练习   第3章 库和接口   3.1 接口的概念   3.2 随机数字   3.3 字符串   3.4 标准的I/O库   3.5 其他ANSI库   3.6 小结   3.7 复习题   3.8 编程练习   第Ⅱ部分 递归和算法分析   第4章 递归入门   4.1 一个简单的递归示例   4.2 阶乘函数   4.3 费波那契函数   4.4 其他递归示例   4.5 以递归的方式思考   4.6 小结   4.7 复习题   4.8 编程练习   第5章 递归过程   5.1 汉诺塔   5.2 产生排列   5.3 递归在绘图中的应用   5.4 小结   5.5 复习题   5.6 编程练习   第6章 回溯算法   6.1 用递归回溯解决迷宫问题   6.2 回溯与游戏   6.3 小结   6.4 复习题   6.5 编程练习   第7章 算法分析   7.1 排序问题   7.2 计算复杂度   7.2.6 大O的正式定义   7.3 递归帮助   7.4 标准复杂度类型   7.5 快速排序算法   7.6 数学归纳法   7.7 小结   7.8 复习题   7.9 编程练习   第Ⅲ部分 数据抽象   第8章 抽象数据类型   ……   第9章 效率与ADT   第10章 线性结构   第11章 符号表   第Ⅳ部分 递归数据   第12章 递归链表   第13章 树   第14章 表达式树   第15章 集合   第16章 图   第17章 展望Java

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值