本文用于记录程序设计基本概念的相关知识点,参考2022版《全国计算机等级考试二级教程 - C语言程序设计》
学习目标与要求
- 了解程序设计的基本含义
- 了解算法的基本特点,学习算法的重要性
- 结构化程序设计
- 了解结构化程序设计的三种基本机构
- 掌握如何用一般流程图和 N - S 流程图表示三种基本结构
知识图谱
程序和程序设计
- 计算机:是一种具有内部存储能力、由程序自动控制的电子设备
- 计算机指令:能够被计算机识别并执行的二进制代码,规定了计算机能完成的某种操作,由操作码和操作数(地址码)组成
- 操作码:指出指令需要完成操作的类型或性质。例如,取数、加法、减法、输出等不同的操作具有不同的操作码
- 地址码:描述该指令的操作对象,或直接给出操作数,或指出操作数的存储器地址或寄存器地址(即寄存器名)。根据操作数的性质,可以分为源操作数和目的操作数,例如加法指令中,加数和被加数为源操作数,计算结果为目的操作数。在多数指令中,操作数一般为存放数据的地址
- 计算机指令寻址方式:指确定本条指令的数据地址以及下一条将要执行的指令地址,分为指令寻址和数据寻址两大类。操作数的真实地址称为有效地址(effective address,EA),由寻址方式和形式地址共同决定
- 计算机指令系统:某种计算机的所有指令的集合,包括数据传送指令、数据处理指令、程序控制指令、输入/输出指令、其他指令
- 计算机执行指令过程:取指令 -> 分析指令 -> 执行指令 -> 修改程序计数器 -> 取指令
- 程序:解决实际问题的计算机指令的集合
- 高级语言:接近人们习惯的自然语言和数学语言的程序设计语言,使学习和操作更加方便。例如,visual Basic、C++、Java、C等
- 机器语言:面向机器的、被计算机接受和处理的、由 0 和 1 的代码构成的二进制指令或数据
- 编译程序:把源程序转换成目标程序的软件,实现将用户按规定语法写出的语句一一翻译成二进制的机器指令
- 源程序:由高级语言编写的程序
- 目标程序:由二级制代码表示的程序
- C程序编译:把C源程序(.C)经过编译生成目标程序(.OBJ),使用"连接程序"把 目标程序与C提供的各种库函数连接起来生成可执行文件(.EXE)
- 在操作系统环境下,点击或输入可执行文件的名字即可运行,不必携带后缀.EXE
- 程序设计步骤:确定数据结构 -> 确定算法 -> 编码 -> 调试程序 -> 整理文档
- 确定数据结构:根据任务书提出的要求、指定的输入数据和输出结果,确定存储数据的数据结构
- 确定算法:针对存放数据的数据结构来确定解决问题、完成任务的步骤
- 编码:根据确定的数据结构和算法,使用选定的计算机语言编写程序代码,输入到计算机并保存在磁盘上
- 调试程序:清除由于疏忽而引起的语法错误或逻辑错误;用各种可能的输入数据对程序进行测试,使之对各种合理的数据都能得到正确的结果,对不合理的数据能进行适当的处理
- 整理并写出文档资料
算法
- 算法:指解题方案的准确而完整的描述
- 算法特性:确定性、可行性、有穷性、有零个或多个输入、有一个或多个输出
- 有穷性:一个算法包含的操作步骤应该是有限的,且每一个步骤都在合理时间内完成
- 确定性:算法的每一条指令必须有确切的含义,不能有二义性,对于相同的输入必能得出相同执行结果
- 可行性:算法中指定的操作,都可以通过已经验证过可以实现的基本运算执行有限次后实现
- 有零个或多个输入:算法是用来处理数据对象,在多数情况下数据对象需要通过输入来得到
- 有一个或多个输出:算法目的是为了求"解","解"只有通过输出才能得到
- 算法设计基本方法:列举、归纳、递推、递归、减半递推、回溯
- 列举:根据提出的问题,列举所有可能的情况,并用问题中给定的条件检验哪些是需要的,哪些是不需要的
- 适用方向:解决"是否存在"或"有多少种可能"等类型问题,例如,求解不定方程
- 优化算法:在设计列举算法时,对实际问题进行详细的分析,将与问题有关的知识条理化、完备化、系统化,从中找出规律;或对所有可能的情况进行分类,引出一些有用的信息,是可以大大减少列举量的
- 归纳:通过列举少量的特殊情况,经过分析,最后找出一般的关系。归纳法比列举法更能反映问题的本质,可以解决列举量为无限的问题
- 递推:从已知的、或是分析与简化而确定的,初始条件出发,逐次推出所要求的各中间结果和最后结果。递推本质上是归纳法
- 适用方向:常用于数值计算,但必须要注意数值计算的稳定性问题
- 递归:将复杂问题逐层分解,归结为一些简单的问题,然后解决简单的问题后,再沿着原来分解的逆过程逐步进行综合。递归的基础也是归纳
- 减半递推:实际问题的复杂程度往往与问题的规模有着密切的联系,因此利用分治法解决这类实际问题是有效的,分治法就是对问题分而治之,工程上常用的分治法是减半递推技术。"减半"是指将问题的规模减半,而问题的性质不变,"递推"是指重复"减半"的过程
- 回溯法:通过对问题的分析,找出一个解决问题的线索,然后沿着这个线索逐步试探,对于每一步的试探,若试探成功,就得到问题的解,若试探失败,就逐步回退,换别的思路在进行试探,这种方法称为回溯法
- 适用方向:处理具备以下特点的实际问题,很难归纳出一组简单的递推公式或直观的求解步骤,且不能进行无限的列举。回溯法在处理复杂的数据结构方面有着广泛应用
- 列举:根据提出的问题,列举所有可能的情况,并用问题中给定的条件检验哪些是需要的,哪些是不需要的
- 算法复杂度:时间复杂度、空间复杂度
- 时间复杂度:指执行算法所需要的计算工作量。用算法在执行过程中所需基本运算的执行次数来度量算法工作量。例如,在考虑两个矩阵相乘时,可以将两个实数之间的乘法运算作为基本运算,而对所用的加法运算忽略不计
- 空间复杂度:是指执行算法所需的内存空间。包括算法程序所占的存储空间、输入的初始数据所占的存储空间、算法执行过程中所需要的额外空间
- 算法描述方式:常用描述方式是伪代码、流程图
- 伪代码:是一种近似于高级语言但又不受语法约束的一种语言描述方式
- 流程图:一般流程图、 N-S 流程图
- 一般流程图:由以下几种基本图形构成
- advantage:形象直观、简单方便
- disadvantage:对流程线的走向没有任何限制,可以任意转向;在描述复杂的算法时所占篇幅较多;费时费力且不易阅读
- N - S 流程图:算法的每一步都用一个矩形框来描述,把一个个矩形框按执行的次序连接起来就是一个完整的算法描述。相比一般流程图,完全去掉了流程线
结构化程序设计
- 程序设计风格:指编写程序时所表现出的特点、习惯和逻辑思路。程序设计风格应该强调简明清晰,易读易懂,程序必须是可以理解的,即"清晰第一,效率第二"是当今主导的程序设计风格
- 重要性:程序设计风格会深刻的影响软件的质量和可维护性。良好的程序设计风格可以使程序结构清晰合理,使程序代码易于阅读、跟踪,便于测试和维护程序
- 良好的程序设计风格考虑因素:源程序文档化、数据说明的方法、语句的结构、输入和输出
- 源程序文档化:符号名的命名、程序注释、视觉组织
- 符号名的命名:符号名的命名应具有一定的实际含义,以便于对程序功能的理解
- 程序注释:一般分为序言性注释和功能性注释。序言性注释通常位于每个程序的开头部分,给出程序的整体说明,主要描述内容可以包括程序标题、程序功能说明、主要算法、接口说明、程序位置、开发简历、程序设计者、复审者、复审日期、修改日期等。功能性注释的位置一般嵌在源程序体之中,主要描述其后的语句或程序做什么
- 视觉组织:为使程序的结构一目了然,可以在程序中利用空格、空行、缩进等技巧使程序层次清晰
- 数据说明的方法:在编写程序时,需要注意数据说明的风格,以便使程序中的数据说明更易于理解和维护
- 数据说明的次序规范化:鉴于程序理解、阅读和维护的需要,使数据说明次序固定,可以使数据的属性容易查找,也有利于测试、排错和维护
- 说明语句中变量安排有序化:当一个说明语句说明多个变量时,变量按照字母顺序排列为好
- 使用注释来说明复杂数据的结构
- 语句的结构:程序应该简单易懂,语句构造应该简单直接,不应该为提高效率而把语句复杂化
- 在一行内只写一条语句
- 程序编写应优先考虑清晰性
- 除非对效率有特殊要求,程序编写要做到清晰第一,效率第二
- 首先要保证程序正确,然后才要求提高速度
- 避免使用临时变量而使程序的可读性下降
- 避免不必要的转移
- 尽可能使用库函数
- 避免采用复杂的条件语句
- 尽量减少使用"否定"条件的条件语句
- 数据结构要有利于程序的简化
- 要模块化,使模块功能尽可能单一化
- 利用信息隐蔽,确保每一个模块的独立性
- 从数据出发去构造程序
- 不要修补不好的程序,要重新编写
- 输入和输出:输入和输出信息是用户直接关心的,输入和输出方式和格式应尽可能方便用户的使用,因为系统能否被用户接受,往往取决于输入和输出的风格。无论是批处理的输入和输出方式,还是交互式的输入和输出方式,在设计和编程时应都应该考虑如下原则
- 对所有的输入数据都要检验数据的合法性
- 检查输入项的各项重要组合的合理性
- 输入格式要简单,以使得输入的步骤和操作尽可能简单
- 输入数据时,应允许使用自由格式
- 应允许默认值
- 输入一批数据时,最好使用输入结束标志
- 在以交互式输入/输出方式进行输入时,要在屏幕上使用提示符明确提示输入的请求,同时在数据输入过程中和输入结束时,应在屏幕上给出状态信息
- 当程序设计语言对输入格式有严格要求时,应保持输入格式与输入语句的一致性;给所有的输出加注释,并设计输出报表格式
- 源程序文档化:符号名的命名、程序注释、视觉组织
- 程序设计方法:主要包括结构化程序设计、面向对象的程序设计
- 结构化程序设计(structured programming):结构化程序设计方法引入了工程思想、结构化思想,使大型软件的开发和编程都得到了极大的改善,可以使程序结构良好、易读、易理解、易维护
- 结构化程序设计原则:自顶向下、逐步求精、模块化、限制使用goto语句
- 自顶向下:程序设计时,应先考虑主体,后考虑细节;先考虑全局目标,后考虑局部目标。不要一开始就追求众多的细节,先从最上层总目标开始设计,逐步使问题具体化
- 逐步求精:对复杂问题,应设计一些子目标做过渡,逐步细化
- 模块化:一个复杂问题,肯定是由若干稍简单的问题构成。模块化是把程序要解决的总目标分解为分目标,再进一步分解为具体的小目标,把每一个小目标称为一个模块
- 限制使用goto语句
- 滥用goto语句确实有害,应尽量避免
- 完全避免使用goto语句也并非是个明智的方法,有些地方使用goto语句,会使程序流程更清楚、效率更高
- 争论的焦点不应该放在是否取消goto语句,而应放在用什么样的程序结构上
- 结构化程序的基本结构
- 顺序结构:是一种简单的设计程序,它是最基本、最常用的结构,就是按照程序语句行的自然顺序,一条语句一条语句地执行程序。例如,C中的赋值语句、输入、输出语句都可构成顺序结构
- 选择结构:又称为分支结构,它包括简单选择和多分支选择结构,这种结构可以根据设定的条件,判断应该选择哪一条分支来执行相应的语句序列。例如C中的if语句、switch语句
- 循环结构:循环结构给定的条件,判断是否需要重复执行某一相同的类或类似的程序段,利用循环结构可简化大量的程序行
- 当型循环结构:先判断后执行循环体,当指定的条件满足(成立)时,就执行循环体,否则就不执行
- 直到型循环结构:先执行循环体后判断,执行循环体直到指定的条件满足(成立)时就不再执行循环体
- 当型循环结构:先判断后执行循环体,当指定的条件满足(成立)时,就执行循环体,否则就不执行
- 顺序结构:是一种简单的设计程序,它是最基本、最常用的结构,就是按照程序语句行的自然顺序,一条语句一条语句地执行程序。例如,C中的赋值语句、输入、输出语句都可构成顺序结构
- 结构化程序设计方法设计的程序的优点:程序易于理解、使用和维护;提高了编程工作的效率,降低了软件开发的成本
- 结构化程序设计原则和方法的应用
- 使用程序设计语言中的顺序、选择、循环等有限的控制结构表示程序的控制逻辑
- 选用的控制结构只准许有一个入口和一个出口
- 程序语句组成容易识别的块,每块只有一个入口和一个出口
- 复杂结构应该用嵌套的基本控制结构进行组合嵌套来实现
- 语言中所没有的控制结构,应该采用前后一致的方法来模拟
- 严格控制goto语句的使用
- 用一个非结构化的程序设计语言去实现一个结构化的构造
- 若不使用goto语句会使功能模糊
- 在某种可以改善而不是损害程序可读性的情况下
模块化基本结构
- 模块化方法:把一个复杂任务分解为若干个子任务,每个子任务又分成很多个小子任务,每个小子任务只完成一项简单的功能,在程序设计时用一个个小模块来实现这些功能,每个程序设计人员完成一个或多个小模块,这样的程序设计方法称为模块化方法,有一个个功能模块构成的程序结构为模块化结构
- C语言的结构化与模块化体现
- C语言是一种结构化程序设计语言,提供了三种基本结构的语句
- 提供了定义"函数"的功能,在C语言中没有子程序的概念,它提供的函数可以完成子程序的所有功能
- C语言允许对函数进行单独的编译,从而可以实现模块化
- C语言提供了丰富的数据类型
习题
- 1. 在VC环境中用 RUN 命令运行一个 C 程序时,这时所运行的程序的后缀是什么?
- 2. C语言源程序文件名的后缀是什么?经过编译后,生成文件后缀是什么?经过连接后,生成文件的后缀是什么?
- 3. 结构化程序由哪三种基本结构组成?
- 4. 先后输入若干个整数,要求打印出其中最大的数,当当、输入的数小于0时结束。如何用 N - S 流程图表示算法?