程序设计基础

第一章 引言

第1章 引言

1.1 从一个C语言程序开始
1.2 程序与程序设计语言
  1.2.1 程序与指令
  1.2.2 程序设计语言的功能
  1.2.3 程序设计语言的语法
  1.2.4 程序的编译与编程环境
1.3 C语言的发展与特点
1.4 如何实现问题求解
1.5 本章总结

本章要点

  • 什么是程序?程序设计语言包含哪些功能?
  • 程序设计语言在语法上包含哪些内容?
  • 结构化程序设计有哪些基本控制结构?
  • C语言有哪些特点?
  • C语言的基本框架如何?
  • 形成一个可运行的C语言程序需要经过哪些步骤?
  • 如何用流程图描述简单的算法?

1.1 从一个C语言程序开始

例1-1. 求阶乘问题。输入一个正整数$n$,输出$n!$

比如,输入4,输出24

1.1 从一个C语言程序开始

代码解读

  • 函数 (function): C程序由一个或多个函数组成,函数是完成特定任务的代码块。main是主函数,有且只有一个,函数factorial是我们自己定义的函数
  • 变量定义 (int n;): 在内存中预留一个名为"n"的空间,用于存放整数。
  • 函数声明 (int factorial(int n)): 提前告诉main函数,“后面有一个叫"factorial"的函数,它是这样用的”,避免“先使用后定义”的编译错误。
  • 输入 (scanf): 从键盘读取用户输入。&n表示读取到的值要存放到变量n的地址去。
  • 循环 (for loop): 重复执行一段代码。这里用于实现从1到n的连乘。

1.2 程序与程序设计语言

程序
人们为解决某种问题,用计算机可以识别的代码,编排的一系列加工步骤。程序的执行过程实际上是对程序所表达的数据进行处理的过程
程序设计语言
提供了一种表达数据与处理数据的功能,要求程序员按照语言的规范编程

1.2.1 程序与指令

指令
计算机的一个最基本的功能,如实现一次加法运算或实现一次大小的判别
计算机的指令系统
计算机所能实现的指令的集合
程序
为完成某个任务而编写的一系列计算机指令的有序组合

一份菜谱:

菜谱名 (程序名) -> 番茄炒蛋

指令1 -> 拿出两个鸡蛋

指令2 -> 将鸡蛋打入碗中并搅拌

...

1.2.1 程序与指令

例1-2. 编写程序,分别求和与乘积,其中指令定义如下:

虚拟计算机指令系统共定义7条指令

  • 指令1: Input X 将当前输入数据存储到内存的X单元
  • 指令2: Output X 将内存X单元的数据输出
  • 指令3: Add X Y Z 将内存X单元的数据与Y单元的数据相加,并将结果存储到Z单元,即X+Y→Z
  • 指令4: Sub X Y Z 将内存X单元的数据与Y单元的数据相减,并将结果存储到Z单元,即X-Y→Z
  • 指令5: BranchEq X Y P 比较X与Y,若相等则程序跳转到P处执行,否则继续执行下一条指令
  • 指令6: Jump Q 程序跳转到Q处执行
  • 指令7: Set X Y 将内存Y单元的值设为X单元的值,即X→Y

1.2.1 程序与指令

(1) 输入3个数A, B和C, 求A+B+C的结果

  • Input A; 输入第1个数据到存储单元A中
  • Input B; 输入第2个数据到存储单元B中
  • Input C; 输入第3个数据到存储单元C中
  • Add A B D; 将A, B相加并将结果存储到D中
  • Add C D D; 将C, D相加并将结果存储到D中
  • Output D; 输出D的结果

思考:如何求A+B-C?

1.2.1 程序与指令

(2) 输入A, 求A+A+A的结果

虚拟程序1:


Input A;
Add A A D;
Add A D D;
Output D;
                            

虚拟程序2:


Input A;
Set 0 Z;
Add Z A Z;
Add Z A Z;
Add Z A Z;
Output Z;
                            

1.2.1 程序与指令

(3) 输入2个数A和B,求A*B

A*B=A+A+...+A,相当于B个A相加


Input A;
Input B;
Set 0 Z;
Add Z A Z;
Add Z A Z;
...
Add Z A Z;
Output Z;
                        

这样的思路可行否?关键在哪里?如何改进?

1.2.1 程序与指令

(续)(3) 输入2个数A和B,求A*B

A*B=A+A+...+A,相当于B个A相加

  • 分别输入两个数到A,B两个变量中
  • 设X=0, Z=0
  • 当X不等于B时,重复做以下操作:
    Z=Z+A;
    X=X+1;
  • 输出Z

Input A;
Input B;
Set 0 X;
Set 0 Z;
BranchEq X B 9;
Add Z A Z;
Add 1 X X;
Jump 5;
Output Z;
                            

思考:如何求(A+B)*C?

1.2.2 程序设计语言的功能

  • 数据表达:表达所要处理的类型
  • 流程控制:表达数据处理的流程
  • 输入与输出:表达数据的输入与输出
  • 模块化:将代码组织成独立的模块

数据表达

数据表达
将数据抽象为若干类型
数据类型
对某些具有共同特征的数据集合的总称
  • 代表的数据(数据类型的定义域)
  • 在这些数据上要做些什么(即操作或称运算),例如
    • 包含的整数,{...,-2,-1,0,1,2,...}
    • 作用在整数上的运算:+, -, *, /等

数据表达

  • C语言提供的数据类型
    • 基本数据类型:程序设计语言事先定义好,供程序员直接使用,如整型、实型(浮点型)、字符型等
    • 构造类型:由程序员构造,如数组、结构、文件、指针等
  • 各种数据类型的常量与变量形式
    • 常量:常数
    • 变量

流程控制

结构化程序设计方法

  • 将复杂程序划分为若干个相对独立的模块
  • 模块,即一条语句(Statement),一段程序或一个函数(子程序)等
  • 单入口、单出口

流程控制

任何程序都可以将模块通过三种基本控制结构进行组合来实现

顺序结构
分支结构
循环结构

流程控制

  • 语句级控制:包含3种基本控制结构
    • 顺序控制结构,按语句顺序执行
    • 分支控制结构(选择结构),根据不同的条件选择所要执行的模块
    • 循环控制结构,重复执行某个模块
  • 单位级控制:函数的定义与调用
    • 处理复杂问题时,将程序分为若干个相对独立的子程序(函数)

1.2.3 程序设计语言的语法

程序必须符合的“语法规则”,规定了代码该怎么写

  • 源程序(源代码)是一个字符序列,这些字符序列按顺序组成了一系列”单词",“单词”的组合就形成了语言有意义的语法单位
  • 一些简单语法单位的组合又形成了更复杂的语法单位,最后一系列语法单位组合成了程序

C语言的主要“单词”

  • 标识符,在程序中定义的变量名、数据类型名、函数名以及符号常量名等。C语言规定,标识符必须由字母、数字及下划线组成,且第一个字符必须是字母下划线。如”factorial", "n"等,一般用有意义的英语单词
  • 保留字(关键字),C语言规定的、具有特定含义、有专门用途的标识符,如“int", "for", "return"等
  • 常量,常量是有数据类型的,如123为整型、12.34为浮点型
  • 运算符,代表对各种数据类型实际数据对象的运算,如:+(加), -(减), *(乘), /(除), %(求余), >(大于)等
  • 分隔符,用于表示代码结构,对语句或模块进行分割的符号,如“{}", "()", ";"等
  • 注释,对程序的解释,编译器会忽略

C语言的主要语法单位

  • 表达式,运算符与运算对象组合形成表达式,如2+3*4
  • 变量定义,变量有数据类型,在定义变量时需要说明相应变量的类型,如int n;
  • 语句,语句是程序最基本的执行单位,程序的功能是通过对一系列语句的执行实现
  • 函数的定义与调用

1.2.4 程序的编译与编程环境

  • 程序的编译,即通过编译器将程序(源代码)转变为计算机能够直接理解的指令序列
    • 编译器的功能是,对源程序进行词法分析、语法与语义分析,生成可执行的代码,并能在编译过程中指出程序中存在的语法错误
  • 编程环境,包括编辑程序(Edit),编译(Compile),调试(Debug)等工具和过程
  • 掌握程序设计语言,即能够根据语言的语法,用语言表达数据、实现程序的控制,并会使用编程环境

C语言编译过程

  • 编译命令
    • gcc -c test.c
    • gcc test.o -o test
    • gcc -o test test.c
    • gcc -Wall -save-temps test.c –o test
  • 各中间步骤和中间文件
    • 预处理(Preprocessor) test.i, 去除注释,扩展宏定义、头文件,进行条件编译
    • 编译(Compiler) test.s, 语法检查,生成汇编代码
    • 汇编(Assembler) test.o, 汇编成机器代码,生成目标文件
    • 连接(Linker) test.exe, 将目标文件与库函数(静态库和动态库)连接,生成可执行文件

1.3 C语言的发展历史与特点

C语言的诞生

  • 时间: 1972年
  • 地点: 贝尔实验室 (Bell Labs)
  • 人物: 丹尼斯·里奇 (Dennis Ritchie,1941--2011)
  • 事件: 为开发UNIX操作系统,在B语言基础上设计并实现

1.3 C语言的发展历史与特点

K&R

  • 时间: 1978年
  • 人物:布萊恩·克尼汉(Brian Wilson Kernighan, 1942--)和丹尼斯·里奇 (Dennis Ritchie,1941--2011)
  • 事件: 合著的《The C Programming Language》是各种C语言版本的基础,称为旧标准C语言

1.3 C语言的发展历史与特点

ANSI C

  • 时间: 1983年
  • 组织:美国国家标准化协会(ANSI)
  • 事件:制定了新的C语言标准,称ANSI C

C语言的特点

  • 结构化语言: 代码以函数为单位组织,逻辑清晰
  • 高效: 执行速度快,接近汇编语言
  • 可移植: 一次编写,只需少量修改即可在不同平台上编译运行
  • 强大灵活: 包含指针,可以直接对内存进行操作
  • 丰富的库函数: 提供了大量可以直接使用的标准函数

1.4 实现问题求解

问题:求1-100之间所有偶数的和

问题分析与算法分析

  • 思路确定算法
  • 算法:一组明确的解决问题的步骤,它产生结果并能在有限的时间内终止
  • 算法的描述:自然语言;伪代码;流程图,即算法的图形表示

思路和算法

  • 明确问题:求在一定范围内(1-100),满足一定条件(偶数)的若干整数的和,求累加和
  • 思路设置一个变量sum,其初始值为0,然后在1-100的数(i)中寻找偶数,将它们一个一个累加到sum
    • 一步累加:sum=sum+i;
    • 重复累加,用循环语句实现,在循环过程中,
      • 用分支控制,判断i是不是偶数,用分支控制语句实现
      • 用i值的变化,对循环次数进行控制

算法描述

编辑程序

用代码编辑器编写生成程序的源文件,C语言源文件的后缀为.c

程序编译连接

  • 编辑程序后,用该语言的编译程序对其进行编译,生成二进制代码表示的目标程序(.obj),与编程环境提供的库函数进行连接(link)形成可执行的程序(.exe)
  • 编译程序会指出源程序中的语法错误

运行与调试

  • 经过编辑、编译、连接、生成可执行文件后,就可以在编程环境或操作系统环境中运行程序
  • 如果程序运行产生的结果不是你想要的结果,表明程序有语义错误(逻辑错误)
    • 需要会区分语法错误逻辑错误
  • 调试,即在程序中查找错误并修正错误的过程,调试的方法可有
    • 设置断点
    • 单步跟踪
  • 调试是一个需要耐心和经验的工作,也是程序设计最基本的因素之一

C语言程序编译、连接、运行调试步骤示意

本章要点总结

  • 程序: 为解决问题而设计的一系列指令。
  • C程序框架: 由一个或多个函数组成,必须有`main`主函数。
  • C语言特点: 高效、可移植、强大、结构化。
  • 编译步骤: 预处理 -> 编译 -> 汇编 -> 链接。
  • 结构化控制: 主要包括顺序、选择(if)、循环(for, while)。
  • 问题求解: 核心是先设计算法(如用流程图),再编写代码。

课后作业

问题: 编写一个C程序,计算从1到n的之间的奇数之和。

(例如: 输入 100, 输出 2500)


要求:

  1. 先在纸上画出解决这个问题的流程图。
  2. 根据流程图编写C语言代码并成功运行。
  3. 提交流程图的照片和代码截图。