read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web...

308
目录 C 语言教程 目录 1 计算机软件基础知识 -------------------------------------------8 2 Turbo C2.0 --------------------------------------------------47 3 章 程序设计基础 ------------------------------------------------54 4 C 语言概述 ---------------------------------------------------71 5 章 基本数据类型和表达式 ----------------------------------------78 6 章 简单的 C 语言程序设计 ----------------------------------------95 7 章 分支结构 ---------------------------------------------------109 8 章 循环控制 ---------------------------------------------------120 9 章 函数与变量类型 ---------------------------------------------135 10 章 数组 ------------------------------------------------------168 11 章 指针 ------------------------------------------------------182 12 章 结构体与共用体 -------------------------------------------220 13 章 文件 ------------------------------------------------------245 14 章 常见错误分析和程序调试 ------------------------------------258 附录 1 ASCII 码表 --------------------------------------------------268 附录 2 Turbo C 常用库函数 ------------------------------------------269 附录 3 C 语言中的关键宇 --------------------------------------------276 附录 4 运算符和结合性 ----------------------------------------------277 1

Transcript of read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web...

Page 1: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

目录

C 语言教程目录

第 1 章 计算机软件基础知识 -------------------------------------------8第 2 章 Turbo C2.0 --------------------------------------------------47

第 3 章 程序设计基础 ------------------------------------------------54

第 4 章 C 语言概述 ---------------------------------------------------71

第 5 章 基本数据类型和表达式 ----------------------------------------78

第 6 章 简单的 C 语言程序设计 ----------------------------------------95

第 7 章 分支结构 ---------------------------------------------------109

第 8 章 循环控制 ---------------------------------------------------120

第 9 章 函数与变量类型 ---------------------------------------------135

第 10 章 数组 ------------------------------------------------------168

第 11 章 指针 ------------------------------------------------------182

第 12 章 结构体与共用体 -------------------------------------------220

第 13 章 文件 ------------------------------------------------------245

第 14 章 常见错误分析和程序调试 ------------------------------------258

附录 1 ASCII 码表 --------------------------------------------------268

附录 2 Turbo C 常用库函数 ------------------------------------------269

附录 3 C 语言中的关键宇 --------------------------------------------276

附录 4 运算符和结合性 ----------------------------------------------277

1

Page 2: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

目录

附录 5 部分参考答案 --------- --------------------------------------279http://jszx.qdu.edu.cn/CWeb/book.htm

第 1 章 计算机软件基础知识 -----------------------------------------------81.1 数据结构与算法1.2 计算机软件设计基础1.3 计算机软件工程基础1.4 数据库设计基础1.5 本章小结1.6 练习题第 2 章 Turbo C2.0 集成环境简介 -------------------------------------472.1 Turbo C2.0 界面详解

2.1.1 Turbo C2.0 菜单详解2.1.2 Turbo C2.0 的配置文件

2.2 Turbo C 2.0 使用实例2.3 本章小结2.4 练习题

第 3 章 程序设计基础 -------------------------------------543.1 概述

3.1.1 程序设计中的三个主要问题3.1.2 问题分析与算法3.1.3 算法描述工具3.1.4 数据结构3.1.5 程序编码调试运行

3.2 程序设计方法3.2.1 结构化程序设计方法3.2.2 模块化程序设计方法3.2.3 逐步细化的设计方法3.2.4 结构化程序的三种基本结构

3.3 计算机语言概述3.3.1 机器语言3.3.2 汇编语言

2

Page 3: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

目录

3.3.3 高级语言3.4 例题详解3.5 本章小结3.6 练习题第 4 章 C 语言概述 ----------------------------------------714.1 C 语言的发展过程4.2 C 语言的特点4.3 C 源程序的结构4.5 C 语言的上机步骤4.6 例题详解4.7 本章小结4.8 练习题第 5 章 基本数据类型和表达式 --------------------------------------------785.1 标识符和变量

5.1.1 标识符5.1.2 变量

5.2 基本数据类型5.3.1 整型常量5.3.2 实型常量5.3.3 单字符常量5.3.4 字符串常量5.3.5 符号常量

5.4 表达式5.4.1 算术运算符5.4.2 关系运算符5.4.3 逻辑运算符5.4.4 自增自减运算符5.4.5 赋值运算符5.4.6 逗号运算符及表达式5.4.7 条件运算符5.4.8 位运算符

5.5 数据类型的转换5.6 运算符的优先级和结合性5.7 赋值语句5.8 例题详解5.9 本章小结5.10 练习题第 6 章 简单的 C 语言程序设计 --------------------------------------------956.1 语句概述

6.1.1 控制语句6.1.2 函数调用语句

3

Page 4: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

目录

6.1.3 表达式语句6.1.4 空语句

6.2 数据输出6.2.1 字符输出函数 putchar6.2.2 格式输出函数 printf

6.3 数据输入6.3.1 字符输入函数 getchar()6.3.2 格式输入函数 scanf

6.4 例题详解6.5 本章小结6.6 练习题第 7 章 分支结构 -------------------------------------------------------------109

7.1 分支程序设计7.1.1 if 语句7.1.2 if 语句嵌套7.1.3 条件运算符的作用

7.2 Switch 语句7.3 goto 语句7.4 例题详解7.5 本章小结7.6 练习题第 8 章 循环控制 -------------------------------------------------------------120

8.1 while 语句8.2 do-while 语句8.3 for 语句

8.3.1 for 语句的一般格式8.3.2 条件表达式缺省的 for 语句8.3.3 条件表达式中包含逗号运算符的 for 语句

8.4 三种循环语句的比较8.5 break 语句和 continue 语句

4

Page 5: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

目录

8.5.1 break 语句8.5.2 Continue 语句

8.6 例题详解8.7 本章小结8.8 练习题第 9 章 函数与变量类型 ----------------------------------------------------135

9.1 函数9.1.1 概述9.1.2 函数定义的一般形式9.1.3 有关函数的说明9.1.4 函数的调用形式9.1.5 函数的递归调用9.1.6 库函数简介

9.2 变量类型9.2.1 自动型变量(局部变量)9.2.2 外部型变量(全局变量)9.2.3 静态型变量9.2.4 寄存器变量

9.3 变量初始化9.4 编译预处理器

9.4.1 宏定义9.4.2 文件包含9.4.3 条件编译

9.5 例题详解9.6 本章小结9.7 练习题

第 10 章 数 组 -------------------------------------------------------------16810.1 一维数组10.2 二维数组10.3 字符数组和字符串

10.3.1 字符数组的定义和初始化10.3.2 字符串和字符串结束标志

5

Page 6: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

目录

10.3.3 字符数组的输入和输出10.3.4 字符串处理函数

10.4 例题详解10.6 练习题

第 11 章 指 针 -------------------------------------------------------------182

11.1 指针的概念11.2 指针和指针变量

11.2.1 指针变量定义11.2.2 指针变量引用

11.3 数组和指针11.3.1 通过指针访问数组元素11.3.2 数组作为函数参数11.3.3 指向多维数组的指针和指针变量

11.4 字符串和指针11.4.1 字符串的表达形式11.4.2 字符串指针作函数参数

11.5 函数与指针11.5.1 指针函数11.5.2 函数指针

11.6 指针数组和指向指针的指针11.6.1 指针数组11.6.2 指向指针的指针

11.7 Turbo C 的内存分配函数11.8 本章小结11.9 练习题

第 12 章 结构体与共用体 ----------------------------------------------220

12.1 结构体的定义及其变量的初始化12.1.1 结构体定义12.1.2 结构体变量的初始化12.2 结构体类型变量的引用

6

Page 7: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

目录

12.3 结构体数组12.3.1 定义12.3.2 结构体数组初始化12.3.3 应用举例

12.4 指针和结构体12.4.1 指向结构体变量的指针12.4.2 指向结构体数组的指针12.4.3 结构指针参数

12.5 用指针处理链表12.5.1 链表12.5.2 建立链表12.5.3 链表输出12.5.4 对链表中的元素进行删除12.5.5 对链表插入结点12.5.6 主函数

12.6 共用体(联合)12.6.1 概念12.6.2 引用方式12.6.3 共用体的特点

12.7 枚举12.8 用 typedef 定义类型12.9 例题详解12.10 本章小结12.11 练习题

第 13 章 文件 ----------------------------------------------------------------245

13.1 文件概述13.2 文件的处理

13.2.1 文件指针13.2.2 文件的打开和关闭13.2.3 文件的读和写

13.3 例题详解7

Page 8: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

目录

13.4 本章小结13.5 练习题

第 14 章 常见错误分析和程序调试 -------------------------------------25814.1 常见错误分析

14.1.1 遗漏分号或分号位置错误14.1.2 路径表示的错误14.1.3 混淆赋值号(=)与比较符(==)14.1.4 遗漏花括号14.1.5 括号不配对14.1.6 大小写字母的区别14.1.7 忘记定义变量14.1.8 错误使用指针14.1.9 开头语句中忘记中断语句 break14.1.10 混淆字符和字符串的表示形式14.1.11 自加(++)和自减(一一)错误14.1.12 地址传送失败14.1.13 数组及数组下标14.1.14 int 型数据的数值范围14.1.15 函数的使用14.1.16 混淆数组名及指针变量区别14.1.17 混淆结构体类型和结构体变量区别14.1.18 使用文件时忘记打开文件或打开文件方式不对

14.2 错误的检出与分离14.3 程序调试附录 1 ASCII 码表 ------------------------------------------------268

附录 2 Turbo C 常用库函数 ----------------------------------------269

附录 3 C 语言中的关键宇 -------------------------------------------276

附录 4 运算符和结合性 ---------------------------------------------277

附录 5 部分参考答案 -----------------------------------------------279

8

Page 9: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

目录

9

Page 10: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

http://jszx.qdu.edu.cn/CWeb/book.htm

1.1 数据结构与算法1.2 计算机软件设计基础1.3 计算机软件工程基础1.4 数据库设计基础1.5 本章小结1.6 练习题

第 1 章 计算机软件基础知识1.1 数据结构与算法

借助于计算机解决问题,首先需要了解所处理对象的性质和特点即所操作对象的数据结构,然后再设计解决问题的方法和步骤即设计一个合理的算法,即通常所说的“程序=数据结构+算法”。1.1.1 算法的基本概念

“算法”(Algorithm)一词最早来自公元 9世纪波斯数学家比阿勒·霍瓦里松的一本影响深远的著作《代数对话录》。20世纪的英国数学家图灵提出了著名的图灵论点,并抽象出了一台机器,这台机器被我们称之为图灵机。图灵的思想对算法的发展起到了重要的作用。一般来说,算法是指完成一个任务或解决一个问题所需要的具体步骤和方法的描述。在这里我们说的算法是指计算机能执行的算法。1.算法分类

计算机算法可分为两大类,一类是数值运算算法,另一类是非数值运算算法。数值运算算法主要是求数值解,如求方程的解、求函数的定积分等,非数值运算的范围则非常广泛,如人事管理、图书检索等。2.算法特征

一个科学的算法必须具备以下特征:(1)有穷性:一个算法必须保证执行有限步之后结束,而不能是无限的。这是显而易见的。更进一步说,有穷性是指在合理的范围内结束运算,如果一个算法需计算机执行几百年或更长时间才结束,这显然是不合理的。

10

Page 11: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

(2)确定性:算法的每一步骤必须有确切的定义而不能模棱两可,算法中不能出现诸如“一个比较大的数”等模糊描述。(3)有零个或多个输入(4)有一个或多个输出。算法的目的是为了解决问题,一个没有输出的算法是不能解决任何问题因而它是没有意义的.

(5)有效性。算法中的每一个步骤都都应当能有效地执行,并得到确定的结果。例如,若 n=0则执行 m/n是无法有效执行的。

3.算法表示一个计算机算法可以用自然语言、流程图、N-S图等来表示。4.算法分析

算法分析的任务是对设计出的每一个具体的算法,利用数学工具,讨论各种复杂度,以探讨某种具体算法适用于哪类问题,或某类问题宜采用哪种算法。

算法的复杂度分时间复杂度和空间复杂度。    .时间复杂度:在运行算法时所耗费的时间为 f(n)(即 n 的函数)。   .空间复杂度:实现算法所占用的空间为 g(n)(也为 n 的函数)。    称O(f(n))和 O(g(n))为该算法的复杂度。

1.1.2 数据结构的定义数据结构是计算机科学与技术领域上广泛被使用的术语。尽管它至今还未有一个被一

致公认的定义,但其内容是大家一致公认的。它用来反映一个数据的内部构成,即一个数据由那些成分数据构成,以什么方式构成,呈什么结构。数据结构有逻辑上的数据结构和物理上的数据结构之分。逻辑上的数据结构反映成分数据之间的逻辑关系,而物理上的数据结构反映成分数据在计算机内部的存储安排。数据结构是数据存在的形式。

数据结构是信息的一种组织方式,其目的是为了提高算法的效率,它通常与一组算法的集合相对应,通过这组算法集合可以对数据结构中的数据进行某种操作。 一般数据结构可采用下面两类主要的存储方式,大多数数据结构的存储表示都采用其中的一类方式,或两类方式的结合。1. 顺序存储结构这种存储方式的主要用于线性数据结构,它把逻辑上相邻的数据元素存储在物理上相邻的存储单元内,结点之间的关系由存储单元的邻接关系来实现。

11

Page 12: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

顺序存储结构的主要特点是:(1)结点中只有自身信息域,没有连接信息域,因此存储密度大,存储空间利用率高;(2)可以通过计算直接确定数据结构中第 i个结点的存储地址 Li,计算公式为 Li=L0+(i-1)*m,其中 L0 为第一个结点的存储地址,m 为每个结点所占用的存储单元个数;(3)插入、删除运算不便,会引起大量结点的移动。

2. 链式存储结构链式存储结构就是在每个结点中至少包括一个指针域,用指针来体现数据元素之间逻辑上的联系。这种存储结构可把逻辑上相邻的两个元素存放在物理上不相邻的存储单元中;还可以在线性编址的计算机存储器中表示结点之间的非线性联系。 链式存储结构的主要特点是:(1)结点中除自身外,还有表示连接信息的指针域,因此比顺序结构的存储密度小,存储空间利用率低;(2)逻辑上相邻的结点物理上不必邻接,可用于线性表、树、图等多种逻辑结构的存储表示;(3)插入、删除操作灵活方便,不必移动结点,只要改变结点中的指针即可。

除上述两种主要存储方式外,散列法也是在线性表和集合的存储表示中常用的一种存储方式。

1.1.3 线性表结构1.线性表的定义线性表(Linear List)是最常用并且最简单的一种数据结构。它是由 n(n≥0)个数

据元素(结点)a1,a2,…,an 组成的有限序列。     ① 数据元素的个数 n 定义为表的长度(n=0 时称为空表)。     ② 将非空的线性表(n>0)记作:(a1,a2,…,an)     ③ 数据元素 ai(1≤i≤n)只是个抽象符号,其具体含义在不同情况下可以不同。在一些比较复杂的线性表中,一个数据元素可以由若干个数据项组成。在这种情况下,

一般把数据元素称为记录,含有大量记录的线性表也称为文件。  例 1英文字母表(A,B,…,Z)是线性表,表中每个字母是一个数据元素

(结点)  例 2 一副扑克牌的点数(2,3,…,10,J,Q,K,A)也是一个线性表,其中数据元素是每张牌的点数

2.线性表的存储线性表可采用顺序方式存储和链式方式存储。在各种高级语言中的一维数组就是用顺

序方式存储的线性表,因此也常用一维数组来称呼顺序表。下面主要讨论的线性表对象是指顺序表。

12

Page 13: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

3.线性表的基本操作线性表是一种相当灵活的数据结构,不仅对它的数据元素可以查找访问,它的长度也

可以根据需要增大或缩小,即可对线性表进行插入和删除数据元素运算。常见的线性表的基本运算(1) InitList(L) 构造一个空的线性表 L,即表的初始化。(2) ListLength(L)   求线性表 L 中的结点个数,即求表长。(3) GetNode(L,i)

取线性表 L 中的第 i 个结点,这里要求 1≤i≤ListLength(L)(4) LocateNode(L,x)

     在 L 中查找值为 x 的结点,并返回该结点在 L 中的位置。若 L 中有多个结点的值和 x 相同,则返回首次找到的结点位置;若 L 中没有结点的值为 x ,则返回一个特殊值表示查找失败。

(5) InsertList(L,x,i)     在线性表 L 的第 i 个位置上插入一个值为 x 的新结点,使得原编号为

i,i+1,…,n 的结点变为编号为 i+1,i+2,…,n+1 的结点。这里 1≤i≤n+1,而 n是原表 L 的长度。插入后,表 L 的长度加 1。

(6) DeleteList(L,i)      删除线性表 L 的第 i 个结点,使得原编号为 i+1,i+2,…,n 的结点变成编

号为 i,i+1,…,n-1 的结点。这里 1≤i≤n,而 n是原表 L 的长度。删除后表 L 的长度减1。具体程序实现可参考本书C 语言相关章节。1.1.4栈与队列结构1.栈与队列的定义栈是一种限定仅在表的一端进行插入与删除操作的线性表。允许进行插入与删除操作的这一端称为栈顶,而另一端称为栈底,不含元素的空表称为空栈,插入与删除分别称进栈与出栈。由于插入与删除只能在同一端进行,所以较先进入栈的元素,在进行出栈操作时,要比较后才能出栈。特别是,最先进栈者,最后才能出栈,而最晚进栈者,必最先出栈。因此,

13

Page 14: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

栈也称作后进先出(Last In First Out)的线性表,简称 LIFO 表。其示意图如图 1-1所示:

图 1-1栈结构队列是一种先进先出的线性表。它只允许在表的一端进行插入,而在另一端进行删除元素。允许插入的一端称队尾,允许删除的一端称队头。插入与删除分别称为入队与出队。队列示意图如图 1-2:

──────────────

出队 ←a1 a2 …… an-1  ←an 进队──────────────

队头           队尾图 1-2队列

2.栈与队列的存储栈的存储结构

栈既然是一种线性表,所以线性表的顺序存储和链接存储结构同样适用于栈。 (1) 栈的顺序存储结构 栈的顺序存储结构同样需要使用一个数组和一个整型变量来实现,利用数组来顺序存储栈中 的所有 元 素,利用 整 型 变 量来存储栈顶元 素 的 下 标 位 置。假定栈数 组 用stack[StackMaxSize]表示,指示栈顶位置的整型变量用 top 表示,则元素类型为ElemType 的栈的顺序存储类型可定义为: ElemType stack[StackMaxSize]; int top; 其中,StackMaxSize 为一个整型全局常量,需事先通过 const 语句定义,由它确定顺序栈(即顺序存储的栈)的最大深度,又称为长度,即栈最多能够存储的元素个数;由于 top 用来指示栈顶元素的位置,所以把它称为栈顶指针。 栈的顺序存储结构同样可以定义在一个记录类型中,假定该记录类型用 Stack 表示,

入栈

Top栈顶

Bottom栈底

出栈

14

Page 15: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

则定义为: struct Stack { ElemType stack[StackMaxSize]; int top; }; 如图 1-3所示:在顺序存储的栈中,top 的值为-1 表示栈空,每次向栈中压入一个元素时,首先使 top 增 1,用以指示新的栈顶位置,然后再把元素赋值到这个位置上,每次从栈中弹出一个元素时,首先取出栈顶元素,然后使 top 减 1,指示前一个元素成为新的栈顶元素。由此可知,对顺序栈的插入和删除运算相当于是在顺序表(即顺序存储的线性表)的表尾进行的,其时间复杂度为 O(1)。

图 1-3栈的存储结构栈也可以采用链式方式存储。(2)队列的存储结构队列的存储结构同线性表和栈一样,既可以采用顺序结构,也可以采用链接结构。(1) 队列的顺序存储结构 队列的顺序存储结构需要使用一个数组和两个整型变量来实现,利用数组来顺序存储队列中的所有元素,利用两个整型变量来分别存储队首元素和队尾元素的下标位置,分别称它们为队首指针和队尾指针。假定存储队列的数组用 queue[QueueMaxSize]表示,队首和队尾指针分别用 front 和 rear 表示,则元素类型为 ElemType 的队列的顺序存储类型可定义为:

ElemType queue[QueueMaxSize]; int front, rear;

其中 QueueMaxSize 为一个整型全局常量,需事先通过 const 语句定义,由它确定顺序队列(即顺序存储的队列)的最大长度,即最多能够存储的元素个数。当然,队列的顺序存储空间也可以采用动态分配,此时用于决定最大长度的量可以为全局常量,也可以为全局或局部变量。如在一个函数的函数体中使用下面语句能够为一个队列分配长度为 n的数组空间,该数组名仍用 queue 表示。

ElemType* queue=new ElemType[n]; 队列的顺序存储类型同样可以用一个记录类型来表示,假定记录类型名为 Queue,则该类型定义为: struct Queue {

ElemType queue[QueueMaxSize];

15

Page 16: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

int front, rear; }; 假定一个队列的当前状态如图 1-4(a)所示,此时已经有 a,b,c 三个元素相继出栈(为了同队列中的元素相区别,把它们分别括了起来),队首指针 front 的值为 3,指向的队首元素为 d,队尾指针的值为 7,指向的队尾元素为 h;若接着插入一个新元素 i,则队列的当前状态如图 1-4(b)所示;若再接着删除一个元素,则变为图 1-4(c)所示。

图 1-4顺序存储队列的插入与删除每次向队列插入一个元素,需要首先使队首指针后移一个位置,然后再向这个位置写入新元素。当队尾指针指向数组空间的最后一个位置 QueueMaxSize-1 时,若队首元素的前面仍存在空闲的位置,则表明队列未占满整个数组空间,下一个存储位置应是下标为 0的空闲位置,因此,首先要使队尾指针指向下标为 0 的位置,然后再向该位置写入新元素。通过语句 rear=(rear+1)%QueueMaxSize可使存储队列的整个数组空间变为首尾相接的一个环(称此为循环队列),当 rear 指向最后一个存储位置时,下一个所求的位置自动为数组空间的开始位置(即下标为 0 的位置)。 同对线性表和栈的插入一样,每次在进行队列插入前,也要判断队列是否已满(即数组空间是否已被用完),若是则停止插入,终止程序运行,否则可向队列中插入新元素。若队尾指针的下一个位置(采用(rear+1)%QueueMaxSize 计算出来)恰是队首指针front 所 指 的 位 置 , 则 表 明 队 列 已 满 , 可 知 判 断 队 满 的 条 件 是(rear+1)%QueueMaxSize==front。从另一方面看,若队首指针和队尾指针已经指向了同一个位置,则表明队列中只有一个元素,当删除该元素后,队列为空,队尾指针不变,而队首指针指向了下一个位置,此时队尾指针的下一个位置正好也是队首指针所指的位置,由此可知,当条件(rear+1)%QueueMaxSize==front成立时,可能是队满的情况,也可能是队空的情况。为了区别这两种情况,可设置一个标记,当进行插入操作后,置该标记为 1,当进行删除操作后,置该标记为 0。在标记为 1 的情况下,上述条件成立则表明队列已满,在标记为 0 的情况下,上述条件成立则表明队列为空。为了省去设置一个标记

16

Page 17: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

的麻烦,通常采用的处理方法是:让 front 指针不是指向队首元素的位置,而是指向它的前一个位置,当上述条件成立时队列必然为满,当队首指针等于队尾指针时队列为空,此时整个数组空间只能利用 QueueMaxSize-1 个存储位置,而不是 QueueMaxSize 个存储位置。(2) 队列的链接存储结构 队列的链接存储结构也是通过由结点构成的单链表实现的,此时只允许在单链表的表头进行删除和在单链表的表尾进行插入,因此它需要使用两个指针:队首指针 front 和队尾指针 rear。用 front 指向队首(即表头)结点的存储位置,用 rear 指向队尾(即表尾)结点的存储位置。用于存储队列的单链表简称链接队列或链队。假定链队中的结点类型仍采用第二章定义的 LNode 结点类型,那么队首和队尾指针为 LNode*指针类型。若把一个链队的队首指针和队尾指针定义在一个记录类型中,并假定该记录类型用标识符LinkQueue 表示,则定义如下: struct LinkQueue {

LNode* front; LNode* rear;

}; 其中 LNode 结点类型重写如下: struct LNode {

ElemType data; LNode* next;

};

图 1-5 链队的插入和删除操作示意图 设一个队列为(a,b,c),则对应的链接存储结构如图 1-5(a)所示,当向该链队插入一个元素 d后,对应如图 4-12(b)所示,当接着从中删除队首元素 a后,对应如图 1-5(c)所示。 对链队的插入和删除操作同样不需要比较和移动元素,只需要修改个别相关指针和进行结点的动态分配或回收操作,所以其时间复杂度为 O(1)。另外,使用链队不存在队满的问题,因为它使用的结点是动态分配的,只要内存中动态存储区仍有可用空间,就可以得到一个新结点,使之插入到链队中;链队也可能为空,此时 front 和 rear 指针均为空。3.常见的栈与队列的基本操作

17

Page 18: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

栈:(1) 1)    InitStack(a); //把栈 a 置空

(2) Push(a,35); //元素 35 进栈(3) int x=48; Push(a,x); //48 进栈(4) Push(a,x/2); //x 除以 2 的值 24 进栈(5) x=Pop(a); //栈顶元素 24退栈并赋给 x(6) x=Peek(a); //读取栈顶元素 48并赋给 x(7) Pop(a); //栈顶元素 48退栈

(8) StackEmpty(a); //因栈非空,应返回 0 (9) cout<<Pop(a)<<endl; //栈顶元素 35退栈并输出

(10) x=StackEmpty(a); //因栈为空,应返回 1,然后赋给 x队列: (1) InitQueue(q); //把队列置空

(2) QInsert(q,20); //元素 20 进队 (3) int x=5; QInsert(q,10*x); //元素 10*x 的值 50 进队 (4) cout<<QFront(q)<<endl; //输出队首元素 20 (5) QDelete(q); //删除队首元素 20 (6) cout<<(x=QDelete(q))<<endl;

//删除队首元素 50,把它赋给 x同时输出 (7) x=QueueEmpty(q); //因队列为空,返回 1并赋给 x (8) while(!QueueEmpty(q)) cout<<QDelete(q)<<” ”; //依次输出队

//列 q 中的所有元素,因 q已经为空,所以不会得到任何输出 注:cout 为 c++用法。

1.1. 5线性单链表、双向链表与循环链表结构链接方式存储的线性表简称为链表(Linked List)。单向链表是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始。单向链表的数据结构可以分为两部分:数据域和指针域,数据域存储数据,指针域指向下一个储存节点的地址。它的结构使用伪代码(C 语言)可以表达成:typedef struct _tagLNode{ ElemType data; struct LNode *next;}LNode;其结构如图 1-6所示:

18

Page 19: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

图 1-6 单链表结构双链表中有两条方向不同的链,即每个结点中除 next域存放后继结点地址外,还增

加一个指向其直接前趋的指针域 prior。其结点如图 1-7所示:其方向也有两种选择。

图 1-7双链表结点

循环链表是一种首尾相接的链表。在单链表中,将终端结点的指针域NULL改为指向表头结点或开始结点即可。如图 1-8所示:

图 1-8 单循环链表循环链表的特点是无须增加存储量,仅对表的链接方式稍作改变,即可使得表处理更加方便灵活。1.1.6树与二叉树结构树型结构是一种非线性结构,树和二叉树是最常用的树形结构。1. 树的定义

树是一个或多个结点组成的有限集合 T,有一个特定的结点称为根,其余的结点分为 m≥0 个不相交的集合 T1,T2,…,Tm。每个集合又是一棵树,被称为这个根的子树。如图 0000所示为一棵树。树形结构常用的术语有:双亲、子女:结点的各子树的根称作该结点的子女;相应地该结点的称作其子女的

双亲。兄弟:具有相同双亲的结点互为兄弟。结点的度:一个结点的子树的个数。树叶:度为 0 的结点。分支结点:度不为 0 的结点。结点的层数:根结点的层数为 0,其它任何结点的层数等于它的双亲结点的层数加

1。2. 二叉树结构

二叉树是每个结点最多有两个子结点的有序树。通常子结点被称作“左孩子”和“右孩子”。如图 1-9所示为一个简单的二叉树:

19

Page 20: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

图 1-9 二叉树结构二叉树可采用链式结构存储也可采用数组来存储。如果是完全二叉树,用数组方法

不会浪费空间。用这种紧凑排列,如果一个结点的索引为 i,它的子结点能在索引 2i+1和 2i+2找到,并且它的父节点(如果有)能在索引 floor((i-1)/2)找到(假设根节点的索引为 0)。这种方法更有利于紧凑存储和更好的访问的局部性,特别是在前序遍历中。然而,它需要连续的存储空间,这样在存储高度为 h 的 n 个结点组成的树时将会浪费很多空间。如图 1-10所示:

图 1-10 用数组存储二叉树二叉树的访问可采用前序、中序和后序遍历的方法。如图 00 所示的二叉树中其三种

方法遍历的次序分别为:前序遍历的结果:2, 7, 2, 6, 5, 11, 5, 9, 4 后序遍历的结果:2, 5, 11, 6, 7, 4, 9, 5, 2 中序遍历的结果:2, 7, 5, 6, 11, 2, 5, 4, 9

1.1.7 顺序查找与二分查找查找是数据结构中常用的一种基本运算。查找就是在数据结构中找出满足某种条件的

结点。给出的条件可以是关键码字段的值,也可以是非关键码字段值。在此只讨论基于关键码值的查找。若从数据结构中找到了满足条件的结点,则称查找成功,否则查找失败。衡量一个查找算法的主要标准是查找过程中对关键码进行的平均比较次数,或称检索长度,以n 的函数的形式表示,n是数据结构中的结点个数。

1.顺序查找顺序查找是线性表的最简单的查找方法。其思想是:从表的一端开始,顺序扫描线性

表,依次将扫描到的结点关键宇和给定值 K相比较。若当前扫描到的结点关键字与 K相等,则查找成功;若扫描结束后,仍未找到关键字等于 K 的结点,则查找失败。 顺序查找方法既适用于线性表的顺序存储结构,也适用于线性表的链式存储结构

(使用单链表作存储结构时,扫描必须从第一个结点开始)。下面以基于顺序结构的线性表为例,给出顺序查找算法:

20

Page 21: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

typedef struct{

KeyType key; InfoType otherinfo; //此类型依赖于应用 }NodeType; typedef NodeType SeqList[n+1]; //0 号单元用作哨兵

int SeqSearch(Seqlist R,KeyType K)

{ //在顺序表 R[1..n]中顺序查找关键字为 K 的结点, //成功时返回找到的结点位置,失败时返回 0

int i; R[0].key=K; //设置哨兵 for(i=n;R[i].key!=K;i--); //从表后往前找 return i; //若 i 为 0,表示查找失败,否则R[i]是要找的结点

} //SeqSearch

顺序查找的优点是:算法简单,且对表的结构无任何要求,无论是用向量还是用链表来存放结点,也无论结点之间是否按关键字有序,它都同样适用。其缺点是:查找效率低,因此,当 n 较大时不宜采用顺序查找。

2.二分查找二分查找又称折半查找,它是一种效率较高的查找方法。 二分查找要求:线性表是

有序表,即表中结点按关键字有序,并且要用向量作为表的存储结构。不妨设有序表是递增有序的。

二分查找的基本思想是:(设 R[low..high]是当前的查找区间) (1)首先确定该区间的中点位置:mid=(low+high)/2

 (2)然后将待查的 K 值与 R[mid].key 比较:若相等,则查找成功并返回此位置,否则须确定新的查找区间,继续二分查找,具体方法如下:

21

Page 22: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

     ①若R[mid].key>K,则由表的有序性可知 R[mid..n].keys均大于 K,因此若表中存在关键字等于 K 的结点,则该结点必定是在位置 mid左边的子表 R[1..mid-1]中,故新的查找区间是左子表 R[1..mid-1]。

     ②类似地,若R[mid].key<K,则要查找的 K必在mid 的右子表R[mid+1..n]中,即新的查找区间是右子表 R[mid+1..n]。下一次查找是针对新的查找区间进行的。

     因此,从初始的查找区间R[1..n]开始,每经过一次与当前查找区间的中点位置上的结点关键字的比较,就可确定查找是否成功,不成功则当前的查找区间就缩小一半。这一过程重复直至找到关键字为 K 的结点,或者直至当前的查找区间为空(即查找失败)时为止。二分查找算法:

    int BinSearch(SeqList R,KeyType K)

      { //在有序表 R[1..n]中进行二分查找,成功时返回结点的位置,失败时返回零        int low=1,high=n,mid; //置当前查找区间上、下界的初值        while(low<=high){ //当前查找区间R[low..high]非空          mid=(low+high)/2;          if(R[mid].key==K) return mid; //查找成功返回          if(R[mid].kdy>K)

             high=mid-1; //继续在R[low..mid-1]中查找          else

             low=mid+1; //继续在R[mid+1..high]中查找         }

        return 0; //当 low>high 时表示查找区间为空,查找失败       } //BinSeareh  二分查找算法亦很容易给出其递归程序二分法查找的优点是:平均检索长度小,为[log2n]。粗略地可以这样认为,每经

过一次键码比较,则查找的范围缩小一半,因此经过[log2n]次比较就可以完成过程。二分法查找的缺点是:排序线性表需花费时间,顺序方式存储插入、删除不方便。

1.2 计算机软件设计基础1.2.1 程序设计方法与风格1. 程序设计方法

22

Page 23: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

程序设计是一种技术,需要相应的理论、技术、方法和工具来支持。就程序设计技术的发展而言,主要经过了:经验式程序设计、结构化程序设计、面向对象的程序设计。后者是目前广为流行的技术。经验式程序设计:是一种"工艺性","技艺性"的方法。没有固定的方法和技术,因人

而异。因此,程序设计过程和质量取决于程序设计者本身的个人经验。程序设计员好比是一个"艺人","工匠"。

结构化程序设计:经验式程序设计的结果是,程序质量差,维护(修改,扩充,移植)困难,特别不宜向别人"移交"。为此,七十年代初提出了"结构化程序设计"的思想和方法。这种方法的原则是:

分解原则。把一个复杂的程序功能划分成若干子功能,使每一个子功能能独立设计,并且使程序的复杂性得到简化。如果子功能仍然比较复杂,则再对其进行进一步分划,使成为更小的子功能。每一个子功能便称为一个"功能模块"。

2. 程序设计风格程序设计中一个十分重要而又容易被忽视的问题是程序设计风格。为了使编写

的程序易于被他人看懂而又容易修改,在编写程序时必须遵守一些规则,这就是程序设计风格的要求。 从工程的角度来看待这个问题是很容易理解的,如图纸是许多工程设计的重要表达工具,如果设想,有的建筑图、机械图不能按统一的规范作图,就会发生除设计者外,别人很难看懂的情况,这时图纸完全失去了它的作用,在工程中这种情况当然不允许发生。同样在计算机中,程序的作用也非常类似。我们希望程序的编写和设计者不仅要严格遵循所用程序设计语言的语法规定,写出语法上没有错误的程序,同时还希望也遵循某些程序设计风格的要求,写出易读、易懂的程序来。下面从几个方面讨论体现程序设计风格的问题:(1) 源程序文件

1) 符号名的命名,它包括变量名,标号名,模块名,子程序名等的命名.虽然命名有很大的任意性,完全由设计者决定,但不主张用 A,B,C,A1,C3等.而是希望从易于识别和理解的要求出发,最好选用一些有实际意义的标识符,如变量名采用 AVERAGE,TOTAL等,标号采用 START,INITIALIZE等.在限制符 号 名 字 符 个 数 的情况下也应采用 上 述 有意义 标 识 符 的词头如AVER,INITI 等.

2) 程序中的注释行.夹在源程序中的注释行能帮助读者理解程序,绝非可有可无.大多数程序设计语言允许使用自然语言来写注释行,这就给阅读程序带来很大方便,成为源程序文件必不可少的一部分.一些正规的程序文本注释行占整个程序文件的三分之一或者更多.

特别是程序开头的序言性注释,有些软件开发部门当作必须遵循的规范,作了严格的规定.其中有些项目必须逐一列出。例如,有关的项目有程序标题 引用的子程序目的、功能 相关的数据说明调用形式、参数含意 作者输入数据 审查者输出数据 日期

23

Page 24: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

3)空行和缩格。自然的程序段用空行隔开,可以使程序清晰易读。缩格是为了避免所有的代码行都从某一列开始,不分层次。它按照程序中的逻辑关系,在不同的代码行的开头字符位置上作到错落有序,层次分明。

(2) 数据说明数据说明在每个程序中都会用到,但若从便于阅读、便于维护的要求考虑,最好使数据说明规范化。例如,规定说明次序为:简单变量说明,公用数据块说明,数组说明,文件说明。在每个说明中,多个符号名最好按字典顺序排列,以利于查找、加快测试和纠错。

(3) 语句结构程序的清晰性是最重要的目标,语句应写得简明、直接,不要一行多句,不要用否定的逻辑条件,不要在语句中使用一些不必要的技巧以防止给后来的工作带来麻烦,复杂的表达式要用括号表示运算的优先次序,以防造成误解。不要只求执行速度,而忽略了程序的简明、清晰性。需知,牺牲了程序的简明性和清晰性,实际上就是牺牲了程序的可靠性和正确性。这些原则都是以实践中的教训为依据的。另外还应注意要尽可能利用库中现成函数;少用临时变量;若使用的逻辑表达式不够直观,难于理解,应先对其进行变换;避免用浮点数比较相等;利用 IF…ELSEIF…ELSEIF…ELSE…ENDIF 结构来实现多路分支等。

(4) 输入和输出输入和输出是与用户使用直接相关的,输入、输出方式和格式应尽可能方便用户,避免因设计不当给使用带来麻烦。例如,在一个程序中输入格式尽可能统一;如果可能采用自由格式,不以计数的办法,而应以文件尾或其它特定标志来结束输入;在程序的注释行中给出输出数据的格式说明等。以交互式输入为例,应使输入步骤和操作尽可能简单,最好有提示。要能根据用户的不同类型、特点和不同的要求,设计输入方案。输入数据的格式也力求简单,并应有完备的出错检查和出错恢复措施。采用菜单方式也许对初学者更加方便,但对熟练的专家就可能感到厌烦。命令方式如果设计得当可能会被广泛接受,近年来人们对用户和系统的交互对话给予了很大注意,各种图幅和图形用户接口越来越普遍,其最终的目的是让用户更加方便。(5) 其它程序技巧除以上几点外,还需注意:避免使用过于相似的变量名,变量名中尽量不含数字;同一变量名不要具有多种意义;显式说明所有变量;注意浮点运算的误差;注意整数运算的特点;避免不必要的 GOTO 语句;GOTO 语句不要相互交叉;尽量少用语句标号等。

1.2.2 结构化程序设计结构化程序设计的概念首先是从编写程序中使用的无条件转移语句 goto 引起的,goto

语句的使用使得程序员编程技巧得到充分的发挥。但是大量使用 goto 语句会使程序不规范、可读性差、非常难修改。在程序的规模和复杂性越来越大的今天,程序的不规范、可读性差和难于修改形成了人们常说的“软件危机”。1966年 C.Bohm提出了在程序的构成上只使用顺序、条件、循环三种结构组成的编程方式。这就是当今所说结构化程序设计。一个结构化程序就是用高级语言表示的结构化算法。用三种基本结构组成的程序必然是结构化的程序,这种程序便于编写、阅读、修改和维护。这就减少了程序出错的机会,提高了程序的

24

Page 25: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

可靠性,保证了程序的质量。 结构化程序设计强调程序设计风格和程序结构的规范化,提倡清晰的结构。怎样才能得到一个结构化的程序呢?如果我们面临一个复杂的问题,是难以一下子写出一个层次分明、结构清晰、算法正确的程序的。结构化程序设计方法的基本思路是,把一个复 杂问题的求解过程分阶段进行,每个阶段处理的问题都控制在人们容易理解和处理的范围内。 具体说,采取以下方法保证得到结构化的程序。

(1)自顶向下;(2)逐步细化;(3)模块化设计;(4)结构化编码。结构化程序设计要求人们尽量避免使用 goto 语句,在不得不使用时应十分谨慎,不

能跳得很远,只限于一个结构内部跳,不能从一个结构跳到另一结构。描述算法流程的 NS图是结构化程序设计的最好工具。用户在进行算法描述时使用 NS

图可使程序设计必定符合结构化程序的设计方法。1.模块化程序设计方法

一个系统的设计,由多个具有单一功能、易于理解的多个模块组成。这就是模块化程宇设计方法。按什么原则划分模块?如何组织各模块之间的联系?有以下几条规则。

(1)按操作功能划分模块要求各模块功能尽量单一,各模块之间联系尽量的少,所编程序可读性和可理解性好,

当修改某一功能时只涉及一个模块。(2)按层次结构组织模块上层模块只实现对下层模块的调用,因此,只指出“做什么”,下层(即最低层)模

块才实现“如何做”,对“如何做”作精确描述,按具体任务进行算法分析,算法实现。组成独立模块,给上层调用。2.逐步细化的设计方法

逐步细化的设计方法是“自顶向下,逐步细化”的基本方法。采用此方法可以将一个复杂的问题分解成多层次的模块结构。直到把一个模块功能逐步细化为一系列的处理步骤,甚至于高级语言的一个语句或一条指令。采用逐步细化的优点是:① 符合人们解决复杂问题的普遍规律,可以显著提高程序设计的效率。② 先全局后局部、先整体后细节、先抽象后具体的逐步细化过程设计出来的程序具有

清晰的层次结构,容易阅读和理解。3.结构化程序的三种基本结构顺序结构、选择(分支)结构及循环结构称为程序设计的基本结构,由它们组成的程

序称为结构化程序。一个结构化程序具有易读性好、可靠性高、便于维护和易于移植等优点。任何一个结构化程序只能由以下三种基本结构组成:1.顺序结构顺序结构是最简单、最基本的程序结构。在这种结构中,程序的各块是按其书写顺序

依次执行的,如图 1-11所示。执行完A 块操作后,再执行 B 块操作。这里所说的每一块可以由一条或若干条不产生控制转移的语句组成。

A 块

B 块

入口

出口

A 块 B 块

入口

出口

条件

假 真

25

Page 26: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

图 1-11 顺序结构 图 1-12 选择结构2.选择结构选择结构又称分支结构,在这种结构中通过对给定条件的判断,来选择一个分支执行,

如图 1-12所示。当条件为“真”时,执行 A 块操作;当条件为“假”时,执行 B 块操作。无论何种图形,A、B两块操作不能同时执行。

3.循环结构循环是指在给定的条件下,重复执行某段程序,直到条件不满足为止。循环结构又分

为下两种形式: 入口 入口

真 真 假 假 出口 出口图 1-13 当型循环结构 图 1-14 直到型循环结构

(1)当型(WHILE 型)循环这种循环结构的执行过程是先判断条件,若条件为“真”时,重复执行某段程序直到

条件为“假”时结束,如图 1-13所示。由于是先判断条件,所以当一开始条件就为假时,则A 块操作将一次也不被执行。

(2)直到型(UNTIL 型)循环这种循环结构的执行过程是先执行某段程序,然后再判断条件,当条件为“真”时,

重复执行这段程序,直到条件为“假”时结束,如图 1-14所示。由于是先执行 A 块操作,然后再判断条件,所以无论一开始条件是否满足,A 块操作都至少被执行一次。

上述三种基本结构可以看出,它们都具有以下特点:(1)每种基本结构只能有一个人口和一个出口;(2)没有死语句,即程序中所有的语句都有被执行的机会;(3)不包含死循环(无限止的循环)。使用这三种基本结构可以组合成各种复杂的程序结构,并且具有自上而下设计的功能。

单一的顺序结构只适用于很简单的问题,大多数实际问题的处理都包含了选择结构或循环结构。如在 FORTRAN 77 中,用逻辑 IF 语句和块 IF 语句来实现选择结构。

1.2.3 面向对象的程序设计方法简介

条件

A 块条件

A 块

26

Page 27: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

面向对象的程序设计方法是程序设计技术的最新技术,也是程序设计技术的重发展。面向对象技术的实质是:把程序要处理的任务分解成若干"对象",对每一个对象进行程序设计,再将相关对象组合在一起构成程序。  所谓"对象"是一个能独立存在的"事实",如日常生活中的"学生","课

程","书","读者","汽车","建筑物",软件中的"窗口","按钮"等等都是对象的例子。  每一个都有自己的"属性"和"行为"。对象的"属性"描述对象的静态特征,或说属

性表示对象的特征。如"读者"对象都拥有"姓名","班级","专业"等属性。它们是一些关于对象的"数据"。不同的对象有不同的属性。如一个读者叫"黎 明"、"00 级一班","信息管理和信息系统"专业;而另一个读者叫"晓 军","00 级二班","图书馆专业";……等等。一个对象的属性可能始终不变,也可能随时间的推移而变化,如"00 级一班"变成"00 级二班"。  对象的"行为"描述对象的动态特征,即对象的"活动"。对象的行为包括:"方

法"和"事件"两种形式。"方法"是对象本身所具有的"处理过程",或为达到某些目的所进行的处理,如读者有"借书","还书"两个处理,达到借书和还书的目的。而"事件"是外界对对象所产生的"激励",或对象能认知的某种状态的改变。如读者接到催书通知单时产生的"刺激",即他有能力、也知道如何处理它。事件是"驱动"对象活动的激发因素;称为"事件驱动",是面向对象程序方法与传统的程序方法的重要差别。传统的程序是一行一行地执行;而面向对象的程序是当"事件"发生(出现)时才执行;否则整个程序就处?quot;停滞"状态。事件出现时,程序响应该事件,并作出处理,称为"事件处理"。事件处理是一个(程序)过程。因此,在面向对象的程序设计方法下,重点是编写"事件处理"程序。  把同类对象的集合称为"类"(Class);或者说"类"是对象的定义,亦可以说类

是对象的"模型";而对象则是"类"的一个"实例"。例如,一个窗口是一个对象,安置在窗口中的"输入框"、"按钮"等也是对象。假定我们要设计一个摇奖程序(见图 6. 11)。它由一个独立的窗口展现。窗口里安置一个 5 位数的奖面显示随机产生的数。再安置三个"按钮":一个是"福彩/停止",另一个是"体彩/停?quot;,第三个是"退出"。当按"福彩"时,则不断地翻转显示随机数,该按钮显示为"停止",按"停止"时,则停止翻转,显示最后的一个随机数,按钮又显示为"福彩"。按"退出"时,结束程序执行,并退出。

图 1-15 面向对象设计实例27

Page 28: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

 类具有继承性、多态性、封装性和抽象性等特点。继承性使可以从一个类继承另一个类,前者称"父类",后者称"子类"。子类延用父类的特征,子类随父类的改变而相应地改变,即继承父类的新特征;体现了面向对象的程序设计的共享机制。多态性使相关联的类可以包含同名的方法,使相同的操作作用于多种类型的对象上,但获得不同的结果。这增强了系统的灵活性,可维护性和可扩充性。封状性使对象包含并隐藏对象的所有信息,如内部数据和处理代码。封装使操作对象的内部复杂性与应用程序的其他部分分隔开来,使软件具有很好的模块性。各模块具有明显的范围和边界,实现了模块内的高内聚性和模块间的低耦合性。抽象性是指提取了一个类,或一个对象的与众不同的特征,而不对该类或对象的的所有信息进行处理。例如对一系列表的定位按钮,可以将它作为一个整体,而不关心其中的单个组件,以及它们相互间如何作用。  由于面向对象方法的诸多优越性,相应地出现了面向对象的程序设计语言,面向

对象的问题分析方法,面向对象的系统设计方法等等。因此,现在了解、学习、运用和进一步研究面向对象技术显得十分有意义和极为重要。

1.3 计算机软件工程基础1.3.1 软件工程概念所谓软件工程是指采用工程的概念、原理、技术和方法来开发与维护软件,把经

过时间考验而证明正确的管理技术和当前能够得到的最好的技术方法结合起来,以达到高效率开发软件的目的。

1.3.2 结构化分析方法在确定软件开发项目后,即可着手开发工作,此时不应急于进行软件设计,而应首先

搞清楚用户的需求,也就是真正理解所要设计的软件应具有哪些功能和特性,或者说将要让它干什么事。这看起来似乎很简单,然而事实表明,这步工作并不是很容易,为了确切了解用户的需求,必须掌握需求分析的工具,并在用户参与下,才能达到真正理解用户需求的目的。结构化分析(Structured Analysis)方法简称 SA 方法是一种常见的需求分析方法,近年来得到了广泛的应用,它适合于开发数据处理类型软件的需求分析尤其是企事业单位中有关数据管理类型的应用软件的开发。这一方法的优点是比较简明、易于掌握。此外,在进入设计阶段后还能和结构化方法相衔接,可取得良好的设计效果。结构化分析方法利用图形表达需求,避免了文字叙述常有的不够直观以及冗长、重复、难于阅读和修改等缺点,从而得到具有明显优越性的所谓结构化需求说明书。结构化分析方法使用的工具主要有:数据流程图,数据词典,结构化语言,判定表和判定树。

1. 数据流程图数据流程图也称数据流图,它是以图形的方式表达数据处理系统中信息的变换和传递过程,作为一种描述手段,它可以模拟手工的、自动的以及两者兼有的混合数据处理过程。在此我们以一个银行取款为例,画出取款过程中的数据加工过程各项活动的数据流程图,如图 1-16所示:

储户

核查

付款

登录 计时器 28

Page 29: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

图 1-16取款数据流图一般在数据流程图中可能出现下列四种基本符号:(1) 数据流. 它是具有名字且有流向的数据,在数据流程图中用标有名字的箭头表

示,如取款单,取款信息等.(2) 加工. 表示数据所进行的加工或变换,图中以标有名字的圆圈代表加工.指向加

工的数据流是该加工的输入数据,离开加工的数据流是该加工的输出数据.在图 1.3 中如核查,登录等.

(3) 文件.它是数据的暂存处,可对文件进行必要的存取,在图中以标有名字的短粗线表示,如帐卡,存折。对文件的存取分别以指向或离开文件粗线的箭头表示。由于文件的内容能顾名思义,因而对其进行存取的箭头即使无名也不会造成误解。

(4) 数据源及数据终点。表明数据处理过程的数据来源及数据去向的标志称为数据源及数据终点。在数据流程图中均以命名的方框来表示,如储户、计时器。

为了表达数据处理问题的数据加工过程,只用一个数据流程图是不够的。稍为复杂一些的实际问题,以数据流表示,其中由于数据流加工太多,使人很容易产生混淆,此时采用层次结构的数据流图则能很好解决这一问题。如可以把图 1.3 的数据流图按照层次结构对系统进行逐步分解,即可很清楚很容易地表达各理解整个系统。

2. 数据字典数据字典是结构化分析方法的另一个有力工具,它对数据流程图中出现的所有数据元素给出逻辑定义。有了数据字典,使数据流程图上的数据流、加工和文件得到确切的解释,这些数据元素的定义通常用定义式的形式给出。视所考虑问题的大小,整个数据处理系统的数据字典可能有几十、几百、甚至于几千个定义式。在图1.3 的流程图中,以数据元素“存折”为例,它在数据字典的定义式为:

存折=帐号+储户名+{存取行}这个定义式表明,数据元素“存折”由三部分组成,前两项的含义是明显的,无需解释。第三项则需进一步解释:

存取行=日期+存入额+支出额+余额+经手人和层次数据流程图的概念类似,一个数据字典的定义式不宜包含过多的项。可以采用逐级定义的方法,使得一些复杂的数据元素自顶向下多层定义,直到最后给出无需定义的基本数据元素。数据字典的建立和维护是一个细致而又复杂的工作,大的数据处理系统在数据字典上投入的工作量也是相当多的。在以人工的方法建立和维护数据字典时常常利用卡片记载数据定义,当这种方法的效率不能满足要求时,一般都采用计算机进行数据字典的自动管理,其功能有数据定义的修改、补充、查询、自身的一致性检查和与数据流程图的一致性检查。

3. 结构化语言使用自然语言对数据处理过程作文字的描述毕竟不够清晰和严格。为了更精确地表达数据处理过程,更加简明地在软件需求规格说明书中描述软件的需求,有必要对自然语言加以限制。如在描述需求的语句中只允许使用确切的动词和名词,规定少量的关键字以及为表达层次关系,书写时对某些行给出向右的缩格等,这样的限制同时也使可读性和可维护性得到明显的改善。结构化的语言如类 pascal 语言等。

29

Page 30: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

4. 判定表判定表能够把在何条件下,数据处理系统应完成哪些工作表达得十分清楚。这种以表格形式给出的数据加工说明,比上述文字叙述形式更简明、直观。判定表中左上部给出的是不同的条件,左下部各行则表示在不同条件下相应要作的处理,以下以录取学生数据处理为例,给出它的判定表如下:

1 2 3 4

条件

成绩在录取分数线以上 是 是 否 否体检结果合格 是 否 是 否

动作

录取 满足转下一志愿学校 满足 满足不录取 满足

使用判定表能把具有复杂逻辑关系的所有可能条件及其相应的动作都考虑得很完全。所有条件的组合情况都被列出,这样就不会造成因个别情况遗漏而出现差错。

5. 判定树判定树比判定表更加直观,用它来描述具有多个条件的数据加工更容易被用户接受。树状的分枝表示着多种不同的条件。上面录取新生的例子可以表示成如下判定树:

体检合格------录取已达录取分数线

体检不合格-----转下一志愿学校新生录取系统

体检合格----转下一志愿学校未达录取分数线

体检不合格-----不录取

1.3.3 结构化设计方法当需求分析结束后,进入设计阶段,通常把设计阶段分成两步,总体设计和详细

设计,总体设计阶段着重解决实现需求的程序模块设计问题,详细设计则要决定每个模块的内部处理过程,即具体算法。结构化设计方法是一种常见的设计方法。它从整个程序的结构出发,突出程序模块,利用程序结构图表达程序模块之间的关系。由于数据流程图和程序结构图之间有着一定的联系,结构化设计可以和需求分析所采用的结构化分析方法很好地衔接。使用结构化方法的关键是恰当地划分模块,采用试探方法处理好模块内部以及模块之间的联系问题,从而可以逐步达到较好的设计效果。

1.1.3.4 软件测试方法

软件测试就是用各种常规或者非常规的手段来试图发现软件中的错误的过程。测试在软件生存期中占有重要地位,不仅因测试阶段占用的时间、花费的人力和成本占软件开发的比重很大,而且它直接影响软件的质量。1. 测试的目的软件开发工作在测试以前已经历了制定计划、需求分析、设计和编码等许多阶段。由于人们的思维不可能绝对周密,因而不可能不发生任何差错,由于在大中型软件开发项目中,系统内各部分之间、各种数据之间、各种人员之间有着复杂的关系,因而目前所采用的开发

30

Page 31: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

方法不可能完全避免发生差错。测试阶段的任务就是发现软件中隐藏的各种差错。3. 测试用例设计

测试最典型的做法是,选取一些测试数据,运行被测程序,检验运行结果,其中选取测试数据是整个测试工作的关键。应设法利用有限的人力物力,最有效地发现隐藏的差错。有两种不同的方法测试数据:黑盒方法和白盒方法。黑盒方法又称为功能测试方法,按这一方法进行测试时,程序被看作不能打开的黑盒,在完全不考虑程序内部结构的情况下,依靠程序的规格说明书,从可能的输入条件和输出条件中确定测试数据,也就是根据程序的功能或程序的外部特性设计测试数据。白盒测试又称结构测试或逻辑驱动测试,这种测试允许测试者检查程序的内部结构,程序的内部结构对测试者是已知的,测试者完全不考虑程序的功能,而是根据程序的内部结构设计测试数据。

4. 测试步骤1) 单元测试:也称之为模块测试,是针对各个程序单元或模块单独进行的测试。单

元测试一般和程序编写结合起来,由程序员分工进行,并且多个模块可以平行地展开。它着重发现和解决程序编写中产生的差错,比较重视重视对程序结构的检验。单元测试是整个测试工作的基础。

2)集成测试:是把已经通过单元测试的模块连接起来,着重检验模块间的接口以及软件设计中的一些问题,通常使用功能测试方法。

3)验收测试验收测试是为了确认已开发的软件能否满足验收标准,是否合格,客户决定是否接受的正式测试过程。需求是否达到,特别是功能是否达到是最主要的检验目标,验收测试是对软件质量的全面考核,验收测试以前应制定验收标准和验收计划。验收测试一般由客户主持。

1.3.5 程序调试程序调试可分为人工检查、语法检查和逻辑检查三个部分。人工检查主要是通过人主动读程序而发现一些错误,语法检查主要可以通过编译器来

发现程序中的语法错误,逻辑检查则需要使用调试工具及采用合理的方法来进行。一般各个软件开发平台都会提供相应的调试工具。

1.4 数据库设计基础1.4.1 数据库的基本概念数据处理是计算机应用的重要领域之一。而在数据处理中,除数据计算外,对于庞大数

据的有效管理是一个更重要、更复杂的问题。数据管理:是指数据的收集、整理、组织、存储、维护、检索、传送等操作,这些操作组成数据处理的基本环节且为任何数据处理必不可少的共有部分。数据管理技术的优劣直接影响数据处理的效率。而数据管理技术的发展与计算机硬件、软件和计算机应用的范围有密切联系。以计算机为基础的数据处理发展到目前大致经历了三个阶段:人工管理阶段、文件系统阶段和数据库阶段。

1.1.1、人工管理阶段(20世纪 50年代中期以前) 特点:1)数据不保存在计算机系统中。2)没有专门的软件负责管理数据。每个应用程序要负责自己数据的组织与管理,包

括存储结构、存取方法、输入、输出方式。程序中的数据存取子程序随着存储结构的变化而变化,因此程序与数据不具有独立性。即存储结构改变时程序必须改变。

1)只有程序的概念而没有文件的概念。数据的组织方式必须由程序员自行安排。2)数据面向应用。即一组数据对应一应用程序。

31

Page 32: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

3)此时无直接存取存储设备(磁鼓、磁盘等),只有顺序存取存储设备(磁带)。4)基本上也没有操作系统等系统软件。5)处理方式基本为批处理方式。1.1.2、文件管理阶段(20世纪 50年代中期以后至 60年代中期) 计算机不仅应用于科学计算,同时也渗入信息管理领域。数据处理的量大大增加。数

据存储、检索与维护成为迫切需要。软件方面已经有了操作系统、高级语言等;硬件方面出现了直接存取存储设备(磁鼓、磁盘等);处理方式不仅有批处理也出现了联机实时处理。操作系统中有了文件管理系统专门进行数据组织与管理工作。此时的特点是:

1)数据可以长期保存在磁盘上。2)数据的逻辑结构与物理结构有了区别。实现了数据文件的按名存取。即实现了程序

与数据的“设备独立性”3)文件组织呈现多样化。如有了索引文件、链接文件和散列文件等。但文件之间相互

独立而无联系。数据间的联系要由程序去构造。4)数据已经不再仅仅属于特定的程序,一定程度上可以重复使用。但文件结构的设

计基本还是面向特定的应用,而程序也是基本特定的数据结构和存取方法。因此程序与数据之间的依赖关系还没有得到根本改变。

文件系统的不足之处:A、 数据冗余性(redundancy)冗余的概念:同一个数据在同一个计算机系统中被不适当地存储一次以上这种现象称

之为数据的冗余。数据的冗余会带来一系列问题。浪费了存储空间;不容易维护;会产生数据的不一致

性。B、 数据不一致性(inconsistency)C、 数据联系弱(poor data relationship)(指文件之间相互独立,缺乏联系造成的。1.1.3、数据库阶段(20世纪 60年代后期开始)客观条件:数据管理规模一再扩大,数据量急剧增加,生产发展的需要。磁盘技术取

得重要进展是物质基础。三大标志事件:1)1968年,美国 IBM公司推出层次模型系统 IMS。2)1969年,美国数据系统语言协会(CODASYL)的数据库任务组(DBTG)发表

了关于网状模型的 DBTG报告(1971年通过)。3)1970年,美国 IBM公司高级研究员 E。F。Codd 发表一系列关系模型的论文奠定了

关系数据库的理论基础。基于数据库技术的数据管理的基本特点:A、 采用复杂的数据模型表示数据结构;面向数据本身,而不再仅仅是面向应用。降

低数据的冗余度;提高了数据的共享性;B、 有较高的数据独立性(data independency)三级结构:用户逻辑结构、全局逻辑结构和物理结构。两种独立性:逻辑独立性与物理独立性。C、 数据库系统为用户提供了方便的用户接口D、 系统提供四种数据控制功能:数据库的恢复,并发控制,数据完整性与数据安全

性以保证数据库中的数据始终是完整的、正确的和可靠的。E、 数据操作不再仅仅以记录为单位,也可以进行以数据项为单位的操作。增加了系

统的灵活性。1.2、数据描述

32

Page 33: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

1.2.1、数据描述的三个领域1)现实世界2)信息世界实体(entity)需要对之记录数据的对象。可以是具体的事物,也可以是抽象的行为。实体集(entity set)性质相同的实体的集合。属性(attribute)实体某个特性实体标识符(identifier)能够唯一标识一个实体最小属性集合。3)机器世界(数据世界)字段(field)或者数据项(data item)对应于信息世界中的属性。记录(record)是字段的有序集合对应于信息世界的实体。文件(file)同类型记录的集合。对应于信息世界的实体集。关键字(key)能够唯一标识一条记录的最小字段集合。关于“型”(type)与“值”(occurrence)的区别与联系。型是概念的内涵,而是概念的外延。型是值的抽象表示;而值是型的一次具体体现。数据描述的两种形式:物理描述与逻辑描述。数据管理软件的功能就是在这两种不同的描述之间进行转换或者称为映象。 1.2.2、物理存储介质的层次及数据描述1)物理存储介质的层次:基本存储器(cache and main memory即高速缓冲存储器与主存储器)辅助存储器(flash memory and magnetic disk 即快闪存与磁盘存储器)第三级存储器指光存储设备(optical storage)包括 CD-ROM 和一写多读光盘(WORM)等等。磁带(tape storage)它只是顺序存储设备。其每盘存储容量已达 5GB等等。2)物理存储设备中的数据描述 位(bit); 字节(byte); 字(word)也称字长。一般由若干个字节组成。因机器而

异。 块(block)又称物理块或者物理记录。一般它内外交换的单位。通常为 256-4096 个字

节不等。 桶(bucket)它是外存储器的逻辑单位。一般它可以包括一个或者多个不连续的

物理块。 卷(volume)通常它指一台输入输出设备所能够装载的全部有用信息。例如:磁

带机的一盘磁带或者磁盘机的一个磁盘组等等。 1.2.3、数据联系的描述从客观世界事物之间的联系出发可以将数据之间的联系区分为以下情况:1)实体内部各属性之间的联系。2)实体之间的联系:实体之间的联系又可以区分为同一个实体集内部各实体之间的联

系。不同实体集中的实体之间的联系。这些联系都是建立在语义基础之上的,而不是由数理规律所能够推理或者定义的。在不同实体集的实体之间的联系可以分为:

一对一;一对多;多对多。简而言之,数据库”就是为了实现一定的目的按某种规则组织起来的“数据”的“集

合”。它由一个称为数据库管理系统的软件进行管理。数据的存取方式独立于使用它的应用程序。

数据库具有如下主要特征:

33

Page 34: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

l 数据共享

2 数据具有最小冗余度

3 数据的完整性

4 数据的安全性

5 数据的独立性数据库管理系统:数据库为了保证存储在其中的数据的安全和一致,必须有一组软件

来完成相应的管理任务,这组软件就是数据库管理系统,简称 DBMS,DBMS随系统的不同而不同,但是一般来说,它应该包括以下几方面的内容:   数据库描述功能:定义数据库的全局逻辑结构,局部逻辑结构和其他各种数据库

对象;   数据库管理功能:包括系统配置与管理,数据存取与更新管理,数据完整性管理

和数据安全性管理;   数据库的查询和操纵功能:该功能包括数据库检索和修改;   数据库维护功能:包括数据引入引出管理,数据库结构维护,数据恢复功能和性

能监测。   为了提高数据库系统的开发效率,现代数据库系统除了 DBMS之外,还提供了

各种支持应用开发的工具。1.4.2 数据模型数据模型是数据库中数据组织的结构和形式,它反映了客观世界中各种事物之间的联

系。 模型是现实的抽象。在数据库技术中我们使用模型的概念描述数据库的结构与语义,对现实世界进行抽象。表示实体与实体之间的联系的模型称为数据模型(data model)。

独立于计算机系统与数据库管理系统的数据模型称为概念模型。它是对现实世界的第一级抽象。(信息系统分析时用于描述业务数据之间的联系。它简单、清晰容易为用户所理解。(E-R 模型就是一种)。

直接面向数据库的逻辑结构,是现实世界第二级抽象。又称为“结构数据模型”最常见的有:层次、网状、关系与面向对象模型。它们具有严格的形式化定义,以便于在计算机系统中实现。现在关系结构数据模型已经发展相当成熟,而面向对象的数据结构模型也在飞速发展中。以下简要介绍几种数据结构模型:非关系数据模型 数据库按数据模型来分,可分为层次数据库,网状数据库和关系数据库,层次和网状数

据库,又称为"非关系数据库". 现实世界中客观存在并可以相互区分的事物可将其称为"实体(Entity)".实体可以是具

体的人,事物,也可以是抽象的概念或联 系,如学生的一次选课或退课,学生与学校的对应关系等,都可以认为是实体.

在非关系模型中,实体用记录表示,记录由若干数据项组成.记录名和组成记录的数据项名的集合用来抽象和刻画同类记录,称为 记录型,如:学生记录(学号,姓名,班级,年龄,政治面貌)就是一个记录型.而(9801338,张立,9801,21,共青团员)是这个记录型的 一个值.

    现实世界实体型之间的联系在非关系模型中转换成记录之间的两两联系.若对于记录型 A 中的每一个值,记录型 B 中至多有一个值 与之联系,反之亦同,则称记录型 A 与记录

34

Page 35: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

型 B之间是一对一的联系.如学校是一个记录型,每个学校只有一个校长,而每个校长只能 在一个学校任职,则学校和校长两个记录型之间是一对一的联系.

    若对于记录型 A 中的每个值,记录型 B 中可以有 N 个值(N>1)与之联系,反之,若记录型 B 中的每个值,记录型 A 中至多有一个值与之联 系,则称记录型 A 与记录型 B之间是一对多的联系.如学校是一个记录型,学生是一个记录型,每个学校可以接收多个学生,而一个学 生只能在一个学校(一般而言)就读,则学校和学生两个记录型之间是一对多的联系.

    类似的可以定义"多对多的联系",如学生与课程之间的联系就是一种多对多的联系 .即一个学生可以选修多门课程,一门课程也可 以被多个学生选修,无论关系模型或.但是非关系模型均不支持多对多联系,只支持基本层次联系,即一对一和一对多联系,但多对 多联系可以转化为两个一对联系.

    下面介绍非关系模型中的层次模型和网状模型的基本概念: 层次模型:层次模型是以 "一对多"的基本联系为主体构造成的数据模型;是一

种"树"结构,如在图 1-17 中,A,B,C,D 为"结点",表示实体集合,是对实体的"定义";a1,a2,…b1,b2,…c1,c2,…d1,d2,…表示实体,是实体集合定义下的"值"。清晰可见,层次模型的"型"和"值"的构造都是基于"一对多"基本联系的定义。

图 1-17层次模型    层次数据库采用层次模型作为数据的组织方式.历史上最典型层次模型的数据库管

理系统是 IMS,它是信息管理系统的英文缩写,在 1986年由 IBM公司推出.

    层次模型对具有一对多的层次联系的部门描述得非常自然,直观,容易理解,如现实世界中的家庭和组织机构关系等都是自然的层次结 构,即树状结构的例子.若采用层次模型来组织数据,查询数据也很简便,无须设计特别的算法,因为查询路径是唯一的.但是,它毕竟是 一种十分简单的模型,它无法描述事物间复杂的联系,描述能力较弱,故适用面受到限制.

网状模型 网状模型是以 "多对多"的基本联系为主体构造成的数据模型;是一种"网络"结构,如

在图 1-18 中,教师(T),学生(S),课程(C)为"结点",表示实体集合,是对实体的"定义";t1,t2,…s1,s2,…c1,c2,…表示实体,是实体集合定义下的"值"。清晰可见,层次模型的"型"和"值"的构造都是基于"多对多"基本联系的定义。

35

Page 36: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

图 1-18网状模型    网状数 据 库采用网状模 型 作 为 数 据 的 组织方 式 .网状数 据 库 的典型代表是

CODASYL 系统,这是 20世纪 70年代数据系统语言研究会 CODASYL(Conference On Data Systems Language)下属的数据库任务组(DataBase Task Group,缩写为 DBTG)提出的一个系统方案,所 以又称为 DBTG报告,但它并不是一种具体的数据库管理系统 ,而有很多网状数据库管理系统的设计是遵守DBTG报告的.

    相比于层次模型,网状模型可适用于描述较为复杂的现实世界.但是,由于到达一个结点的路径有多条,因此应用开发者必须选择相对较优的路径来进行搜索以提高查询效率,这对应用开发人员的要求是较高的.

    据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.

基于网状数据类型的数据库管理系统的运行,使数据库技术日益广泛地应用到企业管理, 交通运输,情报检索,军事指挥,政府管理.辅助决策等各个方面,为数据库技术的发展和应用奠定基础,并成为实现和优化信息系统的基本技术.了解层次,网状数据库技术的发展,对了解数据库基本概念,技术的基本内涵,对进一步掌握数据库技术发展都是有益的。但随着 对现实世界中复杂事物的描述的需求和数据库技术的应用,也暴露了基于层次,网状模型的DBMS 存在着各自的缺点:

① 结构比较复杂,而且随着应用规模的扩大,数据库的结构就变的越来越复杂,不利于最终用户掌握;

②操作比较复杂,编写应用程序时用户必须选择适当的对数据的存去路径,因此必须了解系统结构的细节,加重编写应用程序的负担.

36

Page 37: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

尽管如此,在特定应用领域内,传统的数据库产品仍然有其用户,如 IBM公司的 IMS至今仍然有其固定的用户,且产品仍在不断地发展.

2. 关系模型 关系模型是数据库中所讨论的模型中最重要的模型.自 20世纪 80年代以来,计算机厂商推出的数据库管理系统的产品几乎都是支持关系模型的.为了便于理解,这里主要讨论按照用户观点所应了解的关系模型.在用户看来,关系模型中数据的逻辑结构(即数据结构)就是一张 二维表.现在以学生登记表基本信息表为例,介绍关系模型中的一些基本概念和过程.

i. 关系模型的数据结构:关系模型的数据结构单一,是一种二维表格结构,如图 1-

19所示.

图 1-19 关系数据模型的数据结构示例

关系模型的基本术语:

① 关系模型:用二维表结构来表示实体及实体间联系的模型称为关系模型 (Relational Mondel).

②属性和值域:在二维表中的列(字段,数据项)称为属性(Attribute);列值称为属性值;属

37

Page 38: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

性值的取值范围称为值域(Domain).

③ 关系模型:在二维表中,行定义(记录的型)称为关系模式。

④ 元组(Tuple)与关系:关系在二维表中的行(记录的值),称为元组;元组的集合称为关系;关系模式和关系常常称为关系。

⑤ 关键字(Key)或码:在关系的诸多属性中,能够用来唯一表示远祖的属性(或属性组合)称为关键字或码.即关系中的元组由关键子的值 来唯一确定。

关键字是一个术语概念。一个关系的关键字是什么是没有办法从数学上证明的。同时,

关键字的唯一性不是只对关系的当前元组构成来 的。对图 1-19 学生关系和系关系,关键字分别是学号和系号.学生关系中一般姓名不能做为关键字,尽管当前该关系中没有两个记录有 相同的姓名。但不能保证在将来的任何时候不会有同名的学会上进入同一学系。

    在一个关系中,关键字的值不能为空,即关键字的值为空的元组在关系中是不允许存在的。但在一些桌面型的系统中,如 xBase 系列却没 有这种限制。

    有些关系中的关键字是由单个属性组成的,还有一些关系的关键字常常是由若干个属性的组合而构成的,即这种关系中的元组不能由任何 一个属性唯一表示,必须由多个属性的组合才能唯一表示。如考试成绩关系:考试成绩(学号,考试时间,考试科目,姓名,性别,成绩, 系号),它的关键字由(学号,考试日期,考试科目)属性的组合构成.

⑥候选关键字(Candidate Key)或候选码:如果在一个关系中,存在多个属性或属性组合都能用来唯一表示该关系的元组,这些属性或属性组合都称为该关系的候选关键字或候选码.

⑦ 主关键字(Primary Key)或主码:在一个关系的若干个侯选关键字中指定作为关键字的属性或属性组合称为该关系的主关键字或主码.如 在考试成绩关系中,当姓名字段的值在每次考试中都是唯一的话,则(学号,考试日期,考试科目)和(姓名,考试日期,考试科目)是该关系的两个侯选关键字,选择(学号,考试日期,考试科目)作为该关系的主关键字.

⑧非主属性(Non Primary Attribute)或非码属性:关系中不组成码的属性均为非主属性或非码属性.

⑨ 外部关键字(Foreign Key)或外键当关系中的某个属性或属性组合随不是该关系的关键字或只是关键字的一部分,但却是另一个关系的关键 字知,称该属性或属性组合为这个关系的外部关键字或外键.例如,对图 1-19 中的学生关系,系号不是关键字,但系号是系关系的关键字,所以系 号是学生关系的外部关键字或外键.

38

Page 39: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

⑩ 主表与从表:主表和从表是指以外键相关连的两个表,以外键作为主键的表称为主表;外键所在的表称为从表.如图 1-19 中的学生关系对外 键"系号"而言,它是从表;而系关系是主表.关系模式是稳定的,而关系是随时间不断变化的,因为数据库中的数据在不断更新.

数据模型要素     如果抽象出数据模型共性,并加以归纳,数据模型可严格定义成一组概念的集合,这些概念精确描述了系统的静态特性,动态特性和完整性约束条件.数据模型的这些 概念,通常由数据结构,数据操作和完整性约束三部分组成.

1. 数据结构 数据结构是所研究的对象的类型的集合,这些对象是数据库的组成成分.

一般可以分为两类:一类是与数据类型,内容有关的对象,如网状模型中的数据项,记录,对应于现实应用环境中的数据项,记录;关系模型中的关系等;另一类哦是与数据之间联系有关的对象.

在数据库系统中通常按照数据结构的类型来命名数据模型,如层次结构,

网转结构和关系结构的模型分别命名为层次模型,网状模型和关系模型.

2. 数据操作    数据操作是指对数据模型中各种对象型的实例,如关系模型中的关系的值所允许表行的所有操作,即操作的集合,包括操作及有关的操作规则.数据库 中主要有检索和更新(包括插入,删除,修改)两大类操作.数据模型要定义这些操作的确切含义,操作符号,操作规则,如操作有优先级别以及实现操作的语言.

数据结构是对系统静态性的描述,数据操作是对系统动态的特性的描述.

3. 数据的完整性约束条件

39

Page 40: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

     根据的完整性约束条件是完整性规则的集合.完整性规则是给定的数据模型中数据极其联系所具有的约束和依存规则.这些规则用来限定基于数据模型的数据库的状态及状态的变化,以保证数据库中数据的正确,有效和相容.

1.4.3 关系代数运算

关系数据库所使用关系语言的特点是高度非过程化,即用户只需说明"做什么"而不必说明"怎么做".拥护不必请求数据库管理员为其建立特殊的存取路径,存取路径的选择是由DBMS 自动完成的.这也是关系数据库的主要优点之一.

早期,关系操作有两种表示方式:关系代数与关系演算.理论上,关系代数和关系演算被证明是完全等价的.

关系代数通过对关系的运算来表达查询,其操作对象是关系,操作结果亦为关系.关系代数的运算可分为两类.下面通过关系代数来说明关系操作是如何实现的.

(1)传统的集合操作:传统的集合操作包括并,交,差,广义笛卡儿积等.这类操作将关系看作元组的集合.其操作是从关系的水平方向,即是对关系的行来进行的.

设关系 R 和关系 S 具有相同数目的属性列(n列属性),并且相应的属性取自同一个域,

则可定义以下四种集合运算:

①并(Union):关系 R 与关系 S 的并,它是属于 R 或属于 S 的欲组组成的集合,结果为n列属性的关系.

②交(Intersection):关系 R 与关系 S 的交,它是既属于 R又属于 S 的元组组成的集合,结果为 n列属性的关系.

③差(Difference):关系 R 与关系 S 的差,它是属于 R而不属于 S 的元组组成的集合,

结果为 n列属性的关系.

④广义笛卡儿积(Extended cartesian product):关系 R(假设为 n列)和关系 S(假设为 m列)的广义笛卡儿积是一个(n+m)列元组的集合,每一个元组的前 n列是来自关系

40

Page 41: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

R 的一个元组,后m列是来自关系 S 的一个元组.若R 有 K1 个元组,S 有 K2 个元组,则关系R 和关系 S 的广义笛卡儿积有 K1*K2 个元组.

    图 1-20 中(a),(b)分别是具有三个属性列的关系 R,S,(c)为关系 R 和 S 的并,(d)为关系 R 与 S 的交,(e)为关系 R 与 S 的差,(f)为关系 R 与 S 的广义笛卡儿积.

(2)专门的关系操作:包括选择,投影,连接等.这类操作不仅涉及行,而且也涉及列.

①选择(Selection):选择操作是指在关系中选择满足某些条件的元组.例如,要在学生基本信息中找出年龄为 24岁的所有学生数据,就可以对学生基本信息表做选择操作,条件是年龄为 24岁.

②投影(Projection):投影操作是在关系中选择某些属性列.例如,要找出所有老师的姓名,

电话,则可以对教师基本信息表做投影操作,将表数据投影到教师名和电话列.

③连接(Jion):连接操作是从两个关系的笛卡儿积中,选取属性间满足一定条件的元组.例如,

对图 1-20 中关系 R 和 S做连接操作,连接条件是 S.B=R.B,即在图 1-20(f)所示的两个关系的笛卡儿积中选取 S.B=R.B 的元组,得到的结果关系如图 1-20(g).连接条件中的属性称为连接属性,两个关系中的连接属性应该是可比的,即是同一类的数据类型,如:都是数字型或都是字符型.连接条件中的算符为算术比较运算符,当此算符取"="时,为等值连接.图1-20(g)则是关系 R 和 S做等值连接后得到的结果关系.若等值连接中连接属性为相同属性(或属性组),且在结果关系中去掉重复组,则此等值连接为自然连接.如图 1-20(h)即是关系 R 和 S做自然连接得到的结果关系,其连接条件为 S.B=R.B.自然连接是最常用的连接操作.

41

Page 42: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

图 1-20集合运算示例

    由此可见,关系操作的特点是集合操作,即操作的对象是元组的集合----关系,而操作的结果也是元组的集合——关系。

1.4.4 数据库设计方法和步骤一、数据库设计过程数据库技术是信息资源管理最有效的手段。数据库设计是指对于一个给定的应用环境,

构造最优的数据库模式,建立数据库及其应用系统,有效存储数据,满足用户信息要求和处理要求。

数据库设计中需求分析阶段综合各个用户的应用需求(现实世界的需求),在概念设计阶段形成独立于机器特点、独立于各个 DBMS产品的概念模式(信息世界模型),用 E-R图来描述。在逻辑设计阶段将 E-R图转换成具体的数据库产品支持的数据模型如关系模型,形成数据库逻辑模式。然后根据用户处理的要求,安全性的考虑,在基本表的基础上再建立必要的视图(VIEW)形成数据的外模式。在物理设计阶段根据 DBMS 特点和处理的需要,进行物理存储安排,设计索引,形成数据库内模式。

1. 需求分析阶段 需求收集和分析,结果得到数据字典描述的数据需求(和数据流图描述的处理需求)。

需求分析的重点是调查、收集与分析用户在数据管理中的信息要求、处理要求、安全性与完整性要求。需求分析的方法:调查组织机构情况、调查各部门的业务活动情况、协助用户明确对

42

Page 43: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

新系统的各种要求、确定新系统的边界。

常用的调查方法有: 跟班作业、开调查会、请专人介绍、询问、设计调查表请用户填写、查阅记录。

分析和表达用户需求的方法主要包括自顶向下和自底向上两类方法。自顶向下的结构化分析方法(Structured Analysis,简称 SA 方法)从最上层的系统组织机构入手,采用逐层分解的方式分析系统,并把每一层用数据流图和数据字典描述。

数据流图表达了数据和处理过程的关系。系统中的数据则借助数据字典( Data Dictionary,简称DD)来描述。

数据字典是各类数据描述的集合,它是关于数据库中数据的描述,即元数据,而不是数据本身。数据字典通常包括数据项、数据结构、数据流、数据存储和处理过程五个部分(至少应该包含每个字段的数据类型和在每个表内的主外键)。

数据项描述={数据项名,数据项含义说明,别名,数据类型,长度,

         取值范围,取值含义,与其他数据项的逻辑关系}

数据结构描述={数据结构名,含义说明,组成:{数据项或数据结构}}

数据流描述={数据流名,说明,数据流来源,数据流去向,

         组成:{数据结构},平均流量,高峰期流量}

数据存储描述={数据存储名,说明,编号,流入的数据流,流出的数据流,           组成:{数据结构},数据量,存取方式}

处理过程描述={处理过程名,说明,输入:{数据流},输出:{数据流},

          处理:{简要说明}}

2. 概念结构设计阶段 通过对用户需求进行综合、归纳与抽象,形成一个独立于具体 DBMS 的概念模型,可

以用 E-R图表示。

概念模型用于信息世界的建模。概念模型不依赖于某一个 DBMS 支持的数据模型。概念模型可以转换为计算机上某一 DBMS 支持的特定数据模型。

概念模型特点:(1) 具有较强的语义表达能力,能够方便、直接地表达应用中的各种语义知识。

(2) 应该简单、清晰、易于用户理解,是用户与数据库设计人员之间进行交流的语言。概念模型设计的一种常用方法为 IDEF1X 方法,它就是把实体-联系方法应用到语义

数据模型中的一种语义模型化技术,用于建立系统信息模型。

43

Page 44: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

使用 IDEF1X 方法创建 E-R 模型的步骤如下所示:

2.1 第零步——初始化工程这个阶段的任务是从目的描述和范围描述开始,确定建模目标,开发建模计划,组织

建模队伍,收集源材料,制定约束和规范。收集源材料是这阶段的重点。通过调查和观察结果,业务流程,原有系统的输入输出,各种报表,收集原始数据,形成了基本数据资料表。

2.2 第一步——定义实体实体集成员都有一个共同的特征和属性集,可以从收集的源材料——基本数据资料表

中直接或间接标识出大部分实体。根据源材料名字表中表示物的术语以及具有“代码”结尾的术语,如客户代码、代理商代码、产品代码等将其名词部分代表的实体标识出来,从而初步找出潜在的实体,形成初步实体表。

2.3 第二步——定义联系IDEF1X 模型中只允许二元联系,n 元联系必须定义为 n 个二元联系。根据实际的业务

需求和规则,使用实体联系矩阵来标识实体间的二元关系,然后根据实际情况确定出连接关系的势、关系名和说明,确定关系类型,是标识关系、非标识关系(强制的或可选的)还是非确定关系、分类关系。如果子实体的每个实例都需要通过和父实体的关系来标识,则为标识关系,否则为非标识关系。非标识关系中,如果每个子实体的实例都与而且只与一个父实体关联,则为强制的,否则为非强制的。如果父实体与子实体代表的是同一现实对象,那么它们为分类关系。

2.4 第三步——定义码通过引入交叉实体除去上一阶段产生的非确定关系,然后从非交叉实体和独立实体开

始标识侯选码属性,以便唯一识别每个实体的实例,再从侯选码中确定主码。为了确定主码和关系的有效性,通过非空规则和非多值规则来保证,即一个实体实例的一个属性不能是空值,也不能在同一个时刻有一个以上的值。找出误认的确定关系,将实体进一步分解,最后构造出 IDEF1X 模型的键基视图(KB图)。

2.5 第四步——定义属性从源数据表中抽取说明性的名词开发出属性表,确定属性的所有者。定义非主码属性,

检查属性的非空及非多值规则。此外,还要检查完全依赖函数规则和非传递依赖规则,保证一个非主码属性必须依赖于主码、整个主码、仅仅是主码。以此得到了至少符合关系理论第三范式的改进的 IDEF1X 模型的全属性视图。

2.6 第五步——定义其他对象和规则 定义属性的数据类型、长度、精度、非空、缺省值、约束规则等。定义触发器、存储过

程、视图、角色、同义词、序列等对象信息。3. 逻辑结构设计阶段

44

Page 45: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

将概念结构转换为某个 DBMS所支持的数据模型(例如关系模型),并对其进行优化。设计逻辑结构应该选择最适于描述与表达相应概念结构的数据模型,然后选择最合适的 DBMS。将 E-R图转换为关系模型实际上就是要将实体、实体的属性和实体之间的联系转化为

关系模式,这种转换一般遵循如下原则:

1)一个实体型转换为一个关系模式。实体的属性就是关系的属性。实体的码就是关系的码。

2)一个 m:n 联系转换为一个关系模式。与该联系相连的各实体的码以及联系本身的属性均转换为关系的属性。而关系的码为各实体码的组合。

3)一个 1:n 联系可以转换为一个独立的关系模式,也可以与 n端对应的关系模式合并。如果转换为一个独立的关系模式,则与该联系相连的各实体的码以及联系本身的属性均转换为关系的属性,而关系的码为 n端实体的码。

4)一个 1:1 联系可以转换为一个独立的关系模式,也可以与任意一端对应的关系模式合并。

5)三个或三个以上实体间的一个多元联系转换为一个关系模式。与该多元联系相连的各实体的码以及联系本身的属性均转换为关系的属性。而关系的码为各实体码的组合。

6)同一实体集的实体间的联系,即自联系,也可按上述 1:1、1:n 和 m:n 三种情况分别处理。

7)具有相同码的关系模式可合并。

为了进一步提高数据库应用系统的性能,通常以规范化理论为指导,还应该适当地修改、调整数据模型的结构,这就是数据模型的优化。确定数据依赖。消除冗余的联系。确定各关系模式分别属于第几范式。确定是否要对它们进行合并或分解。一般来说将关系分解为 3NF 的标准,即:

表内的每一个值都只能被表达一次。· 表内的每一行都应该被唯一的标识(有唯一键)。表内不应该存储依赖于其他键的非键信息。

4. 数据库物理设计阶段 为逻辑数据模型选取一个最适合应用环境的物理结构(包括存储结构和存取方法)。

根据 DBMS 特点和处理的需要,进行物理存储安排,设计索引,形成数据库内模式。5. 数据库实施阶段 运用 DBMS提供的数据语言(例如 SQL)及其宿主语言(例如 C),根据逻辑设计

和物理设计的结果建立数据库,编制与调试应用程序,组织数据入库,并进行试运行。数据库实施主要包括以下工作:用 DDL 定义数据库结构、组织数据入库 、编制与调试应用程序、数据库试运行

45

Page 46: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

6. 数据库运行和维护阶段 数据库应用系统经过试运行后即可投入正式运行。在数据库系统运行过程中必须不断

地对其进行评价、调整与修改。包括:数据库的转储和恢复、数据库的安全性、完整性控制、数据库性能的监督、分析和改进、数据库的重组织和重构造。

建模工具的使用为加快数据库设计速度,目前有很多数据库辅助工具(CASE 工具),如 Rational公

司的 Rational Rose,CA公司的 Erwin 和 Bpwin,Sybase公司的 PowerDesigner以及 Oracle公司的 Oracle Designer等。

ERwin 主要用来建立数据库的概念模型和物理模型。它能用图形化的方式,描述出实体、联系及实体的属性。ERwin 支持 IDEF1X 方法。通过使用 ERwin 建模工具自动生成、更改和分析 IDEF1X 模型,不仅能得到优秀的业务功能和数据需求模型,而且可以实现从IDEF1X 模型到数据库物理设计的转变。ERwin 工具绘制的模型对应于逻辑模型和物理模型两种。在逻辑模型中,IDEF1X 工具箱可以方便地用图形化的方式构建和绘制实体联系及实体的属性。在物理模型中,ERwin可以定义对应的表、列,并可针对各种数据库管理系统自动转换为适当的类型。

设计人员可根据需要选用相应的数据库设计建模工具。例如需求分析完成之后,设计人员可以使用 Erwin画 ER图,将 ER图转换为关系数据模型,生成数据库结构;画数据流图,生成应用程序。

二、数据库设计技巧1. 设计数据库之前(需求分析阶段)1) 理解客户需求,询问用户如何看待未来需求变化。让客户解释其需求,而且随着开

发的继续,还要经常询问客户保证其需求仍然在开发的目的之中。2) 了解企业业务可以在以后的开发阶段节约大量的时间。3) 重视输入输出。在定义数据库表和字段需求(输入)时,首先应检查现有的或者已经设计出的报表、

查询和视图(输出)以决定为了支持这些输出哪些是必要的表和字段。举例:假如客户需要一个报表按照邮政编码排序、分段和求和,你要保证其中包括了

单独的邮政编码字段而不要把邮政编码糅进地址字段里。4) 创建数据字典和 ER 图表ER 图表和数据字典可以让任何了解数据库的人都明确如何从数据库中获得数据。ER

图对表明表之间关系很有用,而数据字典则说明了每个字段的用途以及任何可能存在的别名。对 SQL 表达式的文档化来说这是完全必要的。

46

Page 47: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

5) 定义标准的对象命名规范数据库各种对象的命名必须规范。2. 表和字段的设计(数据库逻辑设计)表设计原则1) 标准化和规范化数据的标准化有助于消除数据库中的数据冗余。标准化有好几种形式,但 Third

Normal Form(3NF)通常被认为在性能、扩展性和数据完整性方面达到了最好平衡。简单来说,遵守 3NF 标准的数据库的表设计原则是:“One Fact in One Place”即某个表只包括其本身基本的属性,当不是它们本身所具有的属性时需进行分解。表之间的关系通过外键相连接。它具有以下特点:有一组表专门存放通过键连接起来的关联数据。

举例:某个存放客户及其有关定单的 3NF 数据库就可能有两个表:Customer 和Order。Order 表不包含定单关联客户的任何信息,但表内会存放一个键值,该键指向Customer 表里包含该客户信息的那一行。事实上,为了效率的缘故,对表不进行标准化有时也是必要的。2) 数据驱动采用数据驱动而非硬编码的方式,许多策略变更和维护都会方便得多,大大增强系统

的灵活性和扩展性。举例,假如用户界面要访问外部数据源(文件、XML 文档、其他数据库等),不妨把

相应的连接和路径信息存储在用户界面支持表里。还有,如果用户界面执行工作流之类的任务(发送邮件、打印信笺、修改记录状态等),那么产生工作流的数据也可以存放在数据库里。角色权限管理也可以通过数据驱动来完成。事实上,如果过程是数据驱动的,你就可以把相当大的责任推给用户,由用户来维护自己的工作流过程。

3) 考虑各种变化在设计数据库的时候考虑到哪些数据字段将来可能会发生变更。举例,姓氏就是如此(注意是西方人的姓氏,比如女性结婚后从夫姓等)。所以,在

建立系统存储客户信息时,在单独的一个数据表里存储姓氏字段,而且还附加起始日和终止日等字段,这样就可以跟踪这一数据条目的变化。

字段设计原则4) 每个表中都应该添加的 3 个有用的字段· dRecordCreationDate,在 VB 下默认是 Now(),而在 SQL Server 下默认为

GETDATE()

47

Page 48: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

· sRecordCreator,在 SQL Server 下默认为 NOT NULL DEFAULT USER

· nRecordVersion,记录的版本标记;有助于准确说明记录中出现 null 数据或者丢失数据的原因

5) 对地址和电话采用多个字段描 述街道地 址就短短一 行 记 录是不够的。 Address_Line1、Address_Line2 和

Address_Line3 可以提供更大的灵活性。还有,电话号码和邮件地址最好拥有自己的数据表,其间具有自身的类型和标记类别。

6) 使用角色实体定义属于某类别的列在需要对属于特定类别或者具有特定角色的事物做定义时,可以用角色实体来创建特

定的时间关联关系,从而可以实现自我文档化。举例:用 PERSON 实体和 PERSON_TYPE 实体来描述人员。比方说,当 John Smith,

Engineer 提升为 John Smith, Director 乃至最后爬到 John Smith, CIO 的高位,而所有你要做的不过是改变两个表 PERSON 和 PERSON_TYPE 之间关系的键值,同时增加一个日期/时间字段来知道变化是何时发生的。这样,你的 PERSON_TYPE 表就包含了所有 PERSON 的可能类型,比如Associate、Engineer、Director、CIO 或者 CEO 等。还有个替代办法就是改变 PERSON 记录来反映新头衔的变化,不过这样一来在时间上无法跟踪个人所处位置的具体时间。

7) 选择数字类型和文本类型尽量充足在 SQL 中使用 smallint 和 tinyint 类型要特别小心。比如,假如想看看月销售总额,总

额字段类型是 smallint,那么,如果总额超过了$32,767 就不能进行计算操作了。而 ID 类型的文本字段,比如客户 ID 或定单号等等都应该设置得比一般想象更大。假

设客户 ID 为 10 位数长。那你应该把数据库表字段的长度设为 12 或者 13 个字符长。但这额外占据的空间却无需将来重构整个数据库就可以实现数据库规模的增长了。

8) 增加删除标记字段在表中包含一个“删除标记”字段,这样就可以把行标记为删除。在关系数据库里不

要单独删除某一行;最好采用清除数据程序而且要仔细维护索引整体性。

3. 选择键和索引(数据库逻辑设计)键选择原则:1) 键设计 4 原则· 为关联字段创建外键。· 所有的键都必须唯一。· 避免使用复合键。

48

Page 49: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

· 外键总是关联唯一的键字段。2) 使用系统生成的主键设计数据库的时候采用系统生成的键作为主键,那么实际控制了数据库的索引完整性。

这样,数据库和非人工机制就有效地控制了对存储数据中每一行的访问。采用系统生成键作为主键还有一个优点:当拥有一致的键结构时,找到逻辑缺陷很容易。

3) 不要用用户的键(不让主键具有可更新性)

在确定采用什么字段作为表的键的时候,可一定要小心用户将要编辑的字段。通常的情况下不要选择用户可编辑的字段作为键。

4) 可选键有时可做主键把可选键进一步用做主键,可以拥有建立强大索引的能力。

索引使用原则:索引是从数据库中获取数据的最高效方式之一。95%的数据库性能问题都可以采用索

引技术得到解决。1) 逻辑主键使用唯一的成组索引,对系统键(作为存储过程)采用唯一的非成组索

引,对任何外键列采用非成组索引。考虑数据库的空间有多大,表如何进行访问,还有这些访问是否主要用作读写。

2) 大多数数据库都索引自动创建的主键字段,但是可别忘了索引外键,它们也是经常使用的键,比如运行查询显示主表和所有关联表的某条记录就用得上。

3) 不要索引 memo/note 字段,不要索引大型字段(有很多字符),这样作会让索引占用太多的存储空间。

4) 不要索引常用的小型表不要为小型数据表设置任何键,假如它们经常有插入和删除操作就更别这样作了。对

这些插入和删除操作的索引维护可能比扫描表空间消耗更多的时间。

4. 数据完整性设计(数据库逻辑设计)1) 完整性实现机制:实体完整性:主键参照完整性:父表中删除数据:级联删除;受限删除;置空值

49

Page 50: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

父表中插入数据:受限插入;递归插入父表中更新数据:级联更新;受限更新;置空值DBMS 对参照完整性可以有两种方法实现:外键实现机制(约束规则)和触发器实

现机制用户定义完整性: NOT NULL;CHECK;触发器2) 用约束而非商务规则强制数据完整性采用数据库系统实现数据的完整性。这不但包括通过标准化实现的完整性而且还包括

数据的功能性。在写数据的时候还可以增加触发器来保证数据的正确性。不要依赖于商务层保证数据完整性;它不能保证表之间(外键)的完整性所以不能强加于其他完整性规则之上。

3) 强制指示完整性在有害数据进入数据库之前将其剔除。激活数据库系统的指示完整性特性。这样可以

保持数据的清洁而能迫使开发人员投入更多的时间处理错误条件。4) 使用查找控制数据完整性控制数据完整性的最佳方式就是限制用户的选择。只要有可能都应该提供给用户一个

清晰的价值列表供其选择。这样将减少键入代码的错误和误解同时提供数据的一致性。某些公共数据特别适合查找:国家代码、状态代码等。

5) 采用视图为了在数据库和应用程序代码之间提供另一层抽象,可以为应用程序建立专门的视图

而不必非要应用程序直接访问数据表。这样做还等于在处理数据库变更时给你提供了更多的自由。

5. 其他设计技巧1) 避免使用触发器触发器的功能通常可以用其他方式实现。在调试程序时触发器可能成为干扰。假如你

确实需要采用触发器,你最好集中对它文档化。2) 使用常用英语(或者其他任何语言)而不要使用编码在创建下拉菜单、列表、报表时最好按照英语名排序。假如需要编码,可以在编码旁附

上用户知道的英语。3) 保存常用信息让一个表专门存放一般数据库信息非常有用。在这个表里存放数据库当前版本、最近

50

Page 51: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

检查/修复(对 Access)、关联设计文档的名称、客户等信息。这样可以实现一种简单机制跟踪数据库,当客户抱怨他们的数据库没有达到希望的要求而与你联系时,这样做对非客户机/服务器环境特别有用。

4) 包含版本机制在数据库中引入版本控制机制来确定使用中的数据库的版本。时间一长,用户的需求

总是会改变的。最终可能会要求修改数据库结构。把版本信息直接存放到数据库中更为方便。

5) 编制文档对所有的快捷方式、命名规范、限制和函数都要编制文档。采用给表、列、触发器等加注释的数据库工具。对开发、支持和跟踪修改非常有用。对数据库文档化,或者在数据库自身的内部或者单独建立文档。这样,当过了一年多

时间后再回过头来做第 2 个版本,犯错的机会将大大减少。6) 测试、测试、反复测试建立或者修订数据库之后,必须用用户新输入的数据测试数据字段。最重要的是,让

用户进行测试并且同用户一道保证选择的数据类型满足商业要求。测试需要在把新数据库投入实际服务之前完成。

7) 检查设计在开发期间检查数据库设计的常用技术是通过其所支持的应用程序原型检查数据库。

换句话说,针对每一种最终表达数据的原型应用,保证你检查了数据模型并且查看如何取出数据。

1.5 本章小结本章介绍了计算机软件的一些基本常识。初步介绍了数据结构与算法、软件工程、程序

设计基础以及数据库等基本概念。其中的内容面比较广泛,在此仅为计算机程序设计的学习打一个基础,读者如想更深入、详细了解本章所涉及内容可参考相关专业资料。

1.6 练习题1.什么是算法?算法有何特征?2.简述线性表结构的特点,其存贮结构可采用何种方式?3.二叉树可采用哪几种形式遍历?4.什么叫结构化程序设计?5.简述数据库设计方法和步骤。

51

Page 52: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

第 2 章 Turbo C2.0 集成环境简介2.1 Turbo C2.0 界面详解

2.1.1 Turbo C2.0 菜单详解2.1.2 Turbo C2.0 的配置文件

2.2 Turbo C 2.0 使用实例2.3 本章小结2.4 练习题

第 2 章 Turbo C2.0 集成环境简介2.1 Turbo C2.0 界面详解

启动 Turbo C2.0后其界面如图 2.1所示

52

Page 53: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

图 2-1 Turbo C2.0 界面2.1.1 Turbo C2.0 菜单详解在如图 2.1所示界面中各菜单功能如下:

一、File(文件) 菜单按 Alt+F可进入 File 菜单,该菜单包括以下内容:.Load(加载)装入一个文件,可用类似DOS 的通配符(如*.C)来进行列表选择。也可装入其它扩展名的文件,只要给出文件名(或只给路径)即可。该项的热键为 F3,即只要在主菜单中按 F3即可进入该项,而不需要先进入 File 菜单再选此项。.Pick(选择)将最近装入编辑窗口的 8 个文件列成一个表让用户选择, 选择后将该程序装入编辑区,并将光标置在上次修改过的地方。其热健为 Alt-

F3。. New(新文件)说明文件是新的,缺省文件名为 NONAME.C, 存盘时可改名。.Save(存盘)将编辑区中的文件存盘,若文件名是NONAME.C 时, 将询问是否更改文件名,其热键为F2。.Write to(存盘)可由用户给出文件名将编辑区中的文件存盘, 若该文件已存在, 则询问要不要覆盖。.Directory(目录)显示目录及目录中的文件,并可由用户选择。.Change dir(改变目录)显示当前目录, 用户可以改变显示的目录。.Os shell(暂时退出)暂时退出 Turbo C 2.0

到DOS提示符下,此时可以运行 DOS 命令,若想回到 Turbo C 2.0 中,只要在DOS状态下键入 EXIT即可。.Quit(退出)退出 Turbo C 2.0,返回到DOS操作系统中,其热键为 Alt+X。 说明:以上各项可用光标键移动色棒进行选择,回车则执行。也可用每一项的第一个大写字母直接选择。 若要退到主菜单或从它的下一级菜单列表框退回均可用 Esc 键, Turbo C 2.0

所有菜单均采用这种方法进行操作, 以下不再说明。    二、Edit(编辑) 菜单按 Alt+E可进入编辑菜单,若再回车,则光标出现在编辑窗口,此时

用户可以进行文本编辑。编辑方法基本与 wordstar相同,可用 F1 键获得有关编辑方法的帮

53

Page 54: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

助信息。与编辑有关的功能键如下: F1 获得 Turbo C 2.0 编辑命令的帮助信息 F5 扩大编辑窗口到整个屏幕 F6  在编辑窗口与信息窗口之间进行切换 F10从编辑窗口转到主菜单编辑命令简介:PageUp 向前翻页 PageDn 向后翻页Home 将光标移到所在行的开始 End  将光标移到所在行的结尾Ctrl+Y   删除光标所在的一行 Ctrl+T 删除光标所在处的一个词Ctrl+KB 设置块开始 Ctrl+KK 设置块结尾Ctrl+KV 块移动 Ctrl+KC 块拷贝Ctrl+KY 块删除Ctrl+KR 读文件 Ctrl+KW 存文件 Ctrl+KP  块文件打印Ctrl+F1如果光标所在处为 Turbo C

2.0 库函数,则获得有关该函数的帮助 信息Ctrl+Q[ 查找 Turbo C 2.0双界符的后匹配符Ctrl+Q] 查找 Turbo C 2.0双界符的前匹配符 说明:1. Turbo C 2.0 的双界符包括以下几种符号:花括符{和}尖括符<和>圆括符(和)方括符[和]注释符 /*和*/双引号"单引号 '2. Turbo C

2.0在编辑文件时还有一种功能,就是能够自动缩进,即光标定位和上一个非空字符对齐。在编辑窗口中 Ctrl+OL 为自动缩进开关的控制键。    三、Run(运行)菜单按 Alt+R可进入 Run 菜单,该菜单有以下各项:.Run(运行程序)运行由Project/Project name项指定的文件名或当前编辑区的文件。如果对上次编译后的源代码未做过修改, 则直接运行到下一个断点(没有断点则运行到结束)。否则先进行编译、连接后才运行,其热键为 Ctrl+F9。.Program reset(程序重启)中止当前的调试, 释放分给程序的空间,其热键为 Ctrl+F2。.Go to cursor(运行到光标处)调试程序时使用,选择该项可使程序运行到光标所在行。光标所在行必须为 一条可执行语句,否则提示错误。其热键为 F4。.Trace

into(跟踪进入)在执行一条调用其它用户定义的子函数时,若用 Trace into项,则执行长条将跟踪到该子函数内部去执行,其热键为 F7。.Step over(单步执行)执行当前函数的下一条语句,即使用户函数调用,执行长条也不会跟踪进函数内部,其热键为 F8。.User screen(用户屏幕)显示程序运行时在屏幕上显示的结果。其热键为 Alt+F5。四、Compile(编译)菜单按 Alt+C可进入 Compile 菜单,该菜单有以下几个内容:Compile

to OBJ(编译生成目标码)将一个 C 源文件编译生成.OBJ 目标文件,同时显示生成的文件名。其热键为 Alt+F9。.Make EXE file(生成执行文件)此命令生成一个.EXE 的文件, 并显示生成的. EXE 文件名。其中. EXE 文件名是下面几项之一。1. 由 Project/Project name 说明的项目文件名。2. 若没有项目文件名, 则由 Primary Cfile 说明的源文件。3. 若以上两项都没有文件名, 则为当前窗口的文件名。.LinkEXE file(连接生成执行文件)把当前.OBJ 文件及库文件连接在一起生成.EXE 文件。.Build all(建立所有文件)重新编译项目里的所有文件,并进行

54

Page 55: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

装配生成.EXE 文件。该命令不作过时检查(上面的几条命令要作过时检查,即如果目前项目里源文件的日期和时间与目标文件相同或更早,则拒绝对源文件进行编译)。.Primary C

file(主 C 文件)当在该项中指定了主文件后,在以后的编译中,如没有项目文件名则编译此项中规定的主 C 文件,如果编译中有错误,则将此文件调入编辑窗口,不管目前窗口中是不是主C 文件。. Get info(获得有关当前路径、源文件名、源文件字节大小、编译中的错误数目、可用空间等信息。

    五、Project(项目) 菜单按 Alt+P可进入 Project 菜单, 该菜单包括以下内容:.Project

name(项目名) 项目名具有.PRJ 的扩展名,其中包括将要编译、连接的文件名。例如有一个程序由 file1.c, file2.c,file3.c 组成,要将这 3 个文件编译装配成一个 file.exe 的执行文件,可以先建立一个 file.prj 的项目文件,其内容如下:file1.c file2.c file3.c此时将 file.prj放入Project name项中,以后进行编译时将自动对项目文件中规定的三个源文件分别进行编译。然后连接成 file.exe 文件。如果其中有些文件已经编译成.OBJ 文件,而又没有修改过,可直接写上.OBJ扩展名。此时将不再编译而只进行连接。例如:file1.obj    file2.c    file3.c将不对file1.c 进行编译,而直接连接。说明:   当项目文件中的每个文件无扩展名时, 均按源文件对待,另外,其中的文件也可以是库文件, 但必须写上扩展名.LIB。.Break make on(中止编译)

由用户选择否在有 Warining(警告) 、Errors(错误)、Fatal Errors( 致命错误)时或 Link(连接)

之前退出 Make 编译。. Auto dependencies(自动依赖)当开关置为 on,编译时将检查源文件与对的.OBJ 文件日期和时间,否则不进行检查。.Clear project(清除项目文件)

清 Project/Project name 中的项目文件名。.Remove messages(删除信息)把错误信息从信息窗口中清除掉。

    六、Options(选择菜单)按 Alt+O可进入 Options 菜单,该菜单对初学者来说要谨慎使用。.Compiler(编译器)本项选择又有许多子菜单,可以让用户选择硬件配置、存储模型、调试技术、代码优化、对话信息控制和宏定义。这些子菜单如下:Model 共有 Tiny, small,

medium, compact, large, huge 六种不同模式可由同户选择。Define 打开一个宏定义框,同户可输入宏定义。多重定义可同分号,赋值可用等号。

Code generation它又有许多任选项,这些任选项告诉编译器产生什么样的目标代码 。Calling convention 可选择C 或 Pascal 方式传递参数。 Instruction set  可选择 8088/8086

或 80186/80286 指令系列。Floating point可选择仿真浮点、数学协处理器浮点或无浮点运

55

Page 56: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

算。Default char type 规定 char 的类型。Alignonent规定地址对准原则。 Merge duplicate

strings 作优化用,  将重复的字符串合并在一起。Standard stack frame 产生一个标准的栈结构。 Test stack overflow 产生一段程序运行时检测堆栈溢出的代码。Line number

在.OBJ 文件中放进行号以供调试时用。OBJ debug information 在.OBJ 文件中产生调试信息。Optimization    Optimize for 选择是对程序小型化还是对程序速度进行优 化处理。 Use register variable 用来选择是否允许使用寄存器变量。 Register optimization 尽可能使用寄存器变量以减少过多的取数操作。 Jump optimization 通过去除多余的跳转和调整循环与开关语句 的办法,压缩代码。Source    Indentifier length 说明标识符有效字符的个数,默认为 32 个。

    Nested comments 是否允许嵌套注释。 ANSI keywords only 是只允许 ANSI 关键字还是也允许 Turbo C    2.0 关键字 Error    Error stop after 多少个错误时停止编译,默认为 25 个。

  Warning stop after 多少个警告错误时停止编译,  默认为 100 个。 Display warning   

Portability warning 移植性警告错误。 ANSI Violations 侵犯了 ANSI 关键字的警告错误 。 Common error 常见的警告错误。

    Less common error 少见的警告错误。 Names 用于改变段 (segment) 、 组(group)和类

    (class)的名字,默认值为 CODE,DATA,BSS。    .Linker(连接器)本菜单设置有关连接的选择项,它有以下内容:Map file menu选择是

否产生.MAP 文件。Initialize segments 是否在连接时初始化没有初始化的段。Devault

libraries 是否在连接其它编译程序产生的目标文件时去寻    找其缺省库。 Graphics  library  是否连接 graphics 库中的函数。 Warnduplicate

symbols 当有重复符号时产生警告信息。Stack warinig 是否让连接程序产生No stack 的警告信息。Case-sensitive link 是否区分大、小写字。

    .Environment(环境)本菜单规定是否对某些文件自动存盘及制表键和屏幕大小的设置 Message tracking

    Current file 跟踪在编辑窗口中的文件错误。    All files 跟踪所有文件错误。

56

Page 57: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

    Off 不跟踪。 Keep message 编译前是否清除 Message窗口中的信息。 Config

auto save 选 on 时,在Run,Shell 或退出集成开发环境之前,    如果 Turbo C 2.0 的配置被改过,则所做的改动 将存入配置文件中。 选 off 时不存。Edit auto save 是否在Run 或Shell之前,自动存储编辑的源文件。Backup file 是否在源文件存盘时产生后备文件 (.BAK

文件) 。Tab size 设置制表键大小,默认为 8。Zoomed windows 将现行活动窗口放大到整个屏幕,其热键为 F5。Screen size 设置屏幕文本大小。

    . Directories(路径) 规定编译、连接所需文件的路径, 有下列各项:Include directories

包含文件的路径,多个子目录用";"分开。Library directories 库文件路径,多个子目录用";"分开。Output directoried 输出文件(.OBJ,.EXE,.MAP 文件)的目

录。Turbo C directoried Turbo C 所在的目录。Pick file name 定义加载的 pick 文件名,如不定义则从 current    pick file 中取。

    .Arguments(命令行参数)允许用户使用命令行参数。

    . Save options(存储配置)保存所有选择的编译、连接、调试和项目到配置文件中,缺省的配置文件为 TCCONFIG.TC。

    . Retrive options装入一个配置文件到 TC 中,TC将使用该文件的选择项。    七、Debug(调试) 菜单按 Alt+D可选择Debug 菜单,该菜单主要用于查错,它包括以下

内容:Evaluate    Expression 要计算结果的表达式。 Result 显示表达式的计算结果。 New value 赋给新值。 Call stack 该项不可接触。而在 Turbo C debuger 时用于检 查堆栈情况。Find function 在运行 Turbo C debugger 时用于显示规定的函数。Refresh display 如果编辑窗口偶然被用户窗口重写了可用此恢复编辑窗口的内容。

    八、Break/watch(断点及监视表达式)按 Alt+B可进入 Break/watch 菜单,该菜单有以下内容:Add watch 向监视窗口插入一监视表达式。Delete watch 从监视窗口中删除当前的监视表达式。 Edit  watch   在监视窗口中编辑一个监视表达式。Remove all watches 从监视窗口中删除所有的监视表达式。Toggle breakpoint 对光标所在的行设置或清除断点。

Clear all breakpoints  清除所有断点。 View next breakpoint 将光标移动到下一个断点处。

57

Page 58: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

2.1.2 Turbo C2.0 的配置文件    所谓配置文件是包含 Turbo C 2.0 有关信息的文件,其中存有编译、连接的选择和路径等信息。可以用下述方法建立 Turbo C 2.0 的配置: 1. 建立用户自命名的配置文件可以从Options 菜单中选择Options/Save options命令,将当前集成开发环境的所有配置存入一个由用户命名的配置文件中。下次启动 TC 时只要在 DOS 下键入:tc/c<用户命名的配置文件名>就会按这个配置文件中的内容作为 Turbo C 2.0 的选择。2. 若设置 Options/Environment/Config auto save 为 on,则退出集成开发环境时,当前的设置会自动存放到 Turbo C 2.0 配置文件 TCCONFIG.TC 中。Turbo C 在启动时会自动寻找这个配置文件。3. 用 TCINST 设置 Turbo C 的有关配置,并将结果存入 TC.EXE 中。Turbo C 在启动时,若没有找到配置文件,则取 TC.EXE 中的缺省值。

2.2 Turbo C 2.0 使用实例使用 Turbo C2.0 编写程序一般可按如下步骤进行: (以下以在屏幕上

打印”我爱中国”为例)1. 编辑程序: 在如图 2-1所示的界面上输入 C 源程序如图 2-2所示:

图 2-2 编辑源程序2. 编译程序:在如图 2-2 中按下编译快捷键”ALT+F9”如果程序无语法错误,则会出现如图 2-3所示界面,:

58

Page 59: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

图 2-3 编译无语法错误此时若检查程序无逻辑错误则可运行程序.否则将出现如图 2-4 的界面.此时需返回到图 2-2 界面中重新修正程序直至无语法错误为止.再运行程序.

图 2-4 编译语法错误3. 连接运行程序:在如图 2-3 界面中按下快捷键“CTRL+F9”即可运行程序。按下快捷键“ALT+F5”即可看到程序运行结果如图 2-5所示。如果根据程序运行结果发现程序有逻辑错误则需继续返回步骤 1。

(注:以上步骤均可用菜单实现。)

59

Page 60: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 1 章 计算机软件基础知识

图 2-5 运行结果2.3 本章小结

Turbo C2.0是非常经典的集编辑,编译,链接,执行一体的 C 语言处理产品,本章详细介绍了 Turbo C2.0集成环境的基本功能,并举例说明了 Turbo C2.0 的基本用法,Turbo C2.0 具有强大的调试程序功能,其各个功能的使用,读者可在今后在掌握了C 语言的语法和各种基本算法的基础上在实践中逐步积累经验,

熟悉它的使用.2.4 练习题

1.使用 turbo C2.0 的菜单功能将打印“我爱中国”的程序重新编译、运行。2.设计一个适合读者自己的 Turbo C 配置文件,并在使用 Turbo C 时使之发生作用。

60

Page 61: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

第 3 章 程序设计基础3.1 概述

3.1.1 程序设计中的三个主要问题3.1.2 问题分析与算法3.1.3 算法描述工具3.1.4 数据结构3.1.5 程序编码调试运行

3.2 程序设计方法3.2.1 结构化程序设计方法3.2.2 模块化程序设计方法3.2.3 逐步细化的设计方法3.2.4 结构化程序的三种基本结构

3.3 计算机语言概述3.3.1 机器语言3.3.2 汇编语言3.3.3 高级语言

3.4 例题详解3.5 本章小结3.6 练习题

 第 3 章 程序设计基础 

3.1 概述 不管用计算机求解大问题还是小问题,都要把所求的问题转化成计算机能识别的语言

程序,即进行程序设计。如何进行程序设计,如何编制一个正确的或较好的程序,这就要讨论程序设计的原则和方法。

例 3-1 程序设计的例子已知某班 30 个同学的英语成绩,请输出这个班英语最高分和平均分。分析该问题后知道,用计算机来求解它,要涉及到下面三个问题:(1)数据存放,分析后知道,用数组比较合适。这是数据结构问题。(2)数据比较。这是算法问题。(3)程序实现,涉及循环结构和选择结构程序。这是程序结构问题。解:用 max代表最高分,aver代表平均分。程序如下:

main(){ float cj[30];  float aver=0.,max=0.,sum=0.;  int i;  printf("input cj please:\n");  for(i=0;i++;i<30;)  { scanf("%f",&cj[i]);    if(max<cj[i])

max=cj[i];

Page 62: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

    sum=sum+cj[i];}

    aver=sum/30;  printf("aver=%f,max=%f\n",aver,max);}

 3.1.1 程序设计中的三个主要问题  通过程序设计方法的学习和实际练习,就能动手进行一般应用软件的设计。应用软件设计中有三个主要问题:功能设计,算法设计,结构设计。这三者之间既有联系又不能相互代替。

1.功能设计依据“解决什么样的问题,完成什么样的功能”,提出“面向计算机的、含意明确而

无歧义”的说明书。功能需求,一般是由用户提出的。这些需求未必合理和利于在计算机上实现。设计者分

析用户需求后,应使之“面向计算机且含意确切”。也就是说便于在计算机上实现。例如,用计算机做教务管理,要求具备“学生学籍管理,学生成绩管理,课程安排”

等功能。即要分析它的全局和细节,将各部分功能具体化,使之便于在计算机上实现它。一个“面向计算机的、含意明确而无歧义性”的说明书,将是算法设计和程序设计的依据。

2.算法设计算法设计在程序设计中占有特别重要的位置。如果对被求解的问题的算法模糊,则不

可能出求解它的正确程序。算法设计是提出实现软件功能的合适算法。算法应是正确有效的,并且用自然语言或

伪码描述算法。比如对一组学生成绩数据进行排序,在学生成绩管理中就涉及到这个问题,用选择排

序算法。算法为:(1)选取具有最小值的数组元素 s[k]。(2)将 s[1]和 s[k]交换。然后,对剩下的 n-1 个元素,n-2 个元素,…,重复此运算,直到剩下最后一项 s[n]。算法细化为:for(i=1;i<=n-1;i++)

1-1  求 s[i],s[i+1],…,s[n]中的最小值 s[k];1-2  把 s[i]和 s[k]互换;

其中第 1-1 步可进一步细化为:k是当前最小值元素序号 for(j=i+1;j<n;j++)

if(s[k]>s[j]) k=j;算法的再进一步细化,将容易转化为 FORTRAN 语言程序。3.结构设计结构设计就是选择适当的数据结构和程序结构实现算法。这和建筑一栋楼房时要进行

周密的结构设计相似。算法设计和结构设计之间有联系,但不能代替。例如对一组数据进行排序时,主要使用的是数组和循环结构程序。如果不使用数是采

用 n 个简单变量,则很难对它们进行排序。如果不用循环结构程序,则程序将要写得很长和难读。

Page 63: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

现在,结构设计已被提高到应有的位置上了。一个程序有较好的结构,则易读、易调试易维护和方便功能扩充,反之不然。

构筑一个结构化的程序,到底应熟悉哪些基本结构,后面 4.2节将有介绍。 3.1.2 问题分析与算法

 1.目标问题分析对目标问题的分析是程序设计的基础。只有对问题进行充分地分析、理解后,才能寻找

出正确的算法,有把握编制出高水平的程序,从而求得出正确的结果。问题的分析很复杂,程序员面对的是各种各样的问题,当然不同的问题就需要不同的解法。如何针对问题着手分析,一般来说应从下面的几个方面着手。

(1)从问题的性质方面:人面对的问题是各种各样,而对于不同性质的问题,使用的方法、工具一般是不同的。

例如:首先程序员应分析你面对的问题属于数值型数据的计算还是非数值型数据处理的问题。对于数值型数据的计算问题要考虑计算结果的精度,从而定义输入数据和中间结果的数据类型,以求获得一个合理的精度要求。对非数值型数据处理,则考虑输出结果与输入的关系,合理定义输入数据的数据类型,求得数据类型的统一。

(2)输入/输出:程序设计中分析问题常常通过从输出的要求回溯到输入或从输入数据分析一步一步到

输出。在这个分析过程中输入/输出的数据应从下面几个方面考虑。① 数据的类型,即数据设为整型、实型、字符型、双精度型等。② 输入/输出时数据定义格式。③由哪些设备完成数据输入/输出。(3)数学模型:通过分析问题的性质,输入/输出数据类型后,一般就要考虑数学模型的设计。寻找

一个适合于该问题的算法。2.算法的设计算法一般说来是在有限步骤内解决一个目标问题,有明确意义描述的步骤的集合。即

指对解题过程的准确而完整的描述。例如:要求一个圆的周长和面积就应知道求它们的公式:周长=2πR,面积=πR2。写出对这个问题的算法如下。

①从键盘输入的半径 R,π=3.1415926② 计算周长 Z=2*π*R③ 计算面积 S=π*R*R④显示 Z 和 S从上面例子中看到算法不同于一般公式,算法应具有以下一些基本特征。(1)可行性:描述对某一问题的算法,每一步必须都能实现。例如,求算术平方根中出现在实数范

围内对负数求平方根这样的算法描述,在除法运算中出现分母为零的情况等,在算法设计中就要避免,不允许出现。

(2)唯一性:算法是针对某一问题提出的解决本问题的操作步骤。每一步必须确定,不允许出现模

棱两可的解释,也不允许多义性,而是要给出针对此问题的唯一执行步骤。(3)有穷性:算法不允许无限制的进行计算,必须在一定的时间内完成。对于像数学中的无穷级数,

在算法描述中只能按实际要求取有限项。

Page 64: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

(4)明确数据源:一个算法是否有效,要根据提供的数据进行实际检测,获得输出结果是否满足设计要

求。这就要求数据的充分性,大量的实际数据和特殊数据才能验证算法的正确性和有效性。综上所述,算法是一个针对某一问题的一组严谨的运算顺序的规则,它的每一规则都

有明确的定义,并且都将在有限次的操作中终止。又因为算法是针对某一问题建立的,所以算法按其操作的数据对象常又分为:数值型求解算法和非数值型数据处理算法。

2.算法的类型 算法是为解决特定问题而设计的,而要解决的问题门类繁多,因此,算法也会呈现出

多样性与复杂性,但这并不妨碍对算法作一个大致的分类。对于计算机处理而言,算法根据其应用方向可以大概分为数值算法和非数值算法两种。

数值算法可以定义为“数学问题构造性解法的一个完备而确切的描述。并规定方法中仅允许加、减、乘、除等基本算术运算。数值算法常用于科学计算领域中。非数值算法则广泛应用在信息(数据)处理的场合。这类问题常常要对大量的数据进

行加工处理(搜集、转换、分类、组织、检索、存储、维护等),有时还要绘制数据分布曲线或印出报表,还可以根据加工后得到的信息寻找规律,进行预测。这些处理工作一般不涉及复杂的数学问题,但数据量大,数据的类型和结构也较复杂。

3.算法的基本结构一个算法是由“结构”和“原操作”两个部分构成的。最基本的结构有三种,它们是:

顺序结构、分支结构和循环结构。原操作包括:输入、输出、求一个表达式的值并赋给一个变量、比较二个变量等。

下面用图来分别描述一下三个基本结构。1.顺序结构这个结构是由若干个依次执行的处理块组成。图 4-1是包含二个处理块的序列,其中,

S1、S2 分别代表不同的处理块。顺序结构是任何一个算法都离不开的基本主体结构。

     

图 3-1  顺序结果示意图 

2.分支结构最基本的分支结构是二分支结构。它是根据某一逻辑条件是否成立而决定选择哪一个

分支上的处理块去执行,所以分支结构又称选择结构。图 4-2是分支结构示意图。分支结构总是以条件或情况的判断为起始点的,它是人脑思维判断活动的抽象。  

Page 65: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

        

图 3-2  分支结构示意图 3.循环结构循环结构是指在算法设计中,从某处开始有规律地反复执行某一处理块,该处理块称

为循环体。循环体执行多少次是由一个控制循环的条件决定的。当控制条件成立时,重复执行哟处理块。典型循环结构示意图如图 4-3所示。 

 

     

 

图 3-3  循环结构示意图  循环结构反映了人们在处理某一事件时,对不同数据执行同一操作的工作方式。这三个结构块中的每一个都具有一个人口和一个出口,而结构块中的每一处理块,如

上图中的 S、S1、S2,也都具有一个人口和一个出口。由这三种基本结构可以繁衍出无限多的勾来,可以表示任意一个复杂的算法。

 3.1.3 算法描述工具

Page 66: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

  程序设计的过程中,可以使用不同的算法描述工具确定解决问题的详细步骤。常用的描述工具有以下几种。

(1)自然语言自然语言指人类在日常生活、学习、工作中通用的语言,这种语言不需要设计者作专门

的学习和训练。但是使用自然语言作系统描述时要求用语简练,尽量减少语言修饰。例如用自然语言描述打印两数之和及求平均值的算法:

①从键盘读入两个数 A1 和 A2② 计算两数之和 S=A1+A2③求两数的平均值 V=S/2④ 打印和 S 与平均值(2)算法描述工具自然语言描述算法容易理解,一般适合于较小的程序设计,对于较大的程序设计工程

使用自然语言进行算法描述;会令人感到不直观,容易产生多义性,也增加了理解的难度。使用算法描述工具是改善程序设计环境、提高设计效率和质量的一条重要途径。常用算法描述工具有流程图、NS图、PAD图和 PDL 语言等。其中流程图和 NS图使用最广。

①流程图流程图是用图形来描述问题的处理过程的工具。流程图普遍用于复杂计算和工程设计

它能直观、灵活地表现条件、活动和转移。图 3-4 为国家标准规定的一些常用图符。例如用图3-4 的常用图符求解一元二次方程 ax2+bx+c=0 的算法描述如图 3-5所示。流程图把控制和执行顺序表达十分清晰,看起来也直观易懂。这就使得习惯用流程图

它有偏爱,不愿接受其它新的工具。而不得不指出流程图存在严重的缺陷,由于流程线方向任意,如使用不当,会使得计成为非结构化方式,影响程序设计质量。 

   

  

  

     

  

图 3-4  常用字符 

②NS图NS图是 1973年美国 I.Nassi 和 B.Shneiderman提出的一种新的符合结构化程序设计的

流程图。NS图有五种基本结构如图 3-6(a)所示。用 NS 的基本结构图描述的一元二次方程的算法,如图 3-6(b)所示,该算法描述写在一个框内,去掉了容易引起麻烦的流程线。

从NS流程图中看到,NS图强迫设计者按结构化的要求构造算法。它有助于培养良好的按结构化原则进行程序设计的习惯。NS图的缺点是由外框开始逐步向内画,可能图的整

起始框 

输入输出终止框 判断框 

注释框 

处理框 

流程线 

处理点 

流程线 

Page 67: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

个布局由于考虑不周,使内部矩形功能域太小,无法向内层扩展,在设计时用户应尽量给出余量。 

            

 

     

Page 68: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

   

   

图 3-5  一元二次方程流程图 

3.1.4 数据结构 1.设计数据结构.数据结构是计算机科学的重要基础,近年来已发展成一门专门的学科,其内容涉及到

计算机的硬件和软件,它是应用程序设计中必不可少的一项数据描述。(1)数据类型在低级语言时,机器语言和汇编语言是不区分数据类型的,只有高级语言才区分数据

数据类型。这种数据类型的区分,使得程序员能按实际问题的要求进行数据组织,有效用资源和实现算法。数据类型分原始与组合两大类型。原始数据类型:数值类型、逻辑类型、字符类型、指针类型。组合数据类型:由原始类型按某种方式组合构成。例如,数组类型、记录类型、文件类

型等。数据类型定义了一个运算的集合,不同的数据类型的数据参与不同运算方式。例如数

值型才可以参加算术运算;字符型只能进行字符串的连接,求字符串长度等运算;而逻辑型数据只能进行逻辑运算(与、或、非等)。 

循环(UNTIL) 

Page 69: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

      

             

   

图 3-6  NS流程图  数据类型还规定了该类型的数据定义域,例如,逻辑型数据的取值只能是“真”和“假”;字符型数据只能允许出现计算机中提供的字符集中元素组成;数值型数据在FORTRAN 77 中,整型的取值范围一般微机系统中为-32768~32767。

Page 70: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

(2)数据结构数据结构是研究如何合理地组织处理数据,通常涉及三个方面:

数据逻辑结构 数据物理结构

数据结构上实施的运算① 数据的逻辑结构在数据结构的研究中,常把数据称为一个结点(或原子)。各个结点之间的逻辑结构

是数据元素代表的客体之间的联系。数据结构分线性结构和非线性结构两种。线性结构的特点 仅有一个开始结点和一个终止结点,并且所有结点只有一个父结点和

一个子结点,开始结点只有一个子结点,终止结点只有一个父结点。例如计算机中的队列、堆栈、表格等。非线性结构的特点 有多于一个开始结点或终止结点,至少有一个结点有多于一个父或

子结点。如树型、图等。② 数据的物理结构数据的物理结构就是数据在计算机中的存储结构,数据的存储实现大致有以下四种方

式。顺序存储 将逻辑上相邻结点存储在物理上相邻的存储单元中。如图 4-7所示,逻辑上

线性结构为:K1→K2→K3→K4→K5→K6,顺序存放的存储单元为 4000~4005。顺序存储的特点是:没有连接信息域,只有信息本身,因此存储空间利用率高,但是插入,删除数据不方便。 

                     地址 4000                           4001                           4002                           4003                           4004                           4005 图 3-7顺序存储  链接方式:链接方式中每个结点由两部分组成:一部分存放信息;另一部分存放指指针用来指向该节点的父结点或子结点。链接

方式有线性链接和非线性链接两种,如图 3-8(a)与(b)所示。在线性链接的存储方式中,开始结点用一个指针“H”指向它,最后一个结点的指针为

空,用“NIL”表示。在非线性链接的二叉树物理存储方式中,每一个结点有两个指针域,左指针指向左边

的子结点,右指针指向它的右子结点。二叉树的根结点有一个专门指针“R”指向它。索引方式 通过结点在线性序列中的位置来确定结点的实际存储位置。散列方式 通过结点的值来确定结点的存储位置。后两种数据存储的物理结构一般用于系统软件的开发中。③在数据结构上实施的运算。常用于数据的运算有:插入 往数据结构中增加新的结点。

查询 查找满足条件的结点。更新 改变结点的部分或全部值。排序 按要求对结点进行排列。删除 删除指定结点。

  地址 4000

K1

K2

K3

K4

K5

K6

信息域 指针域K5 4007

K2 4004

   

K1 4001

K3 4006

   

K4 4000K5 NIL

Page 71: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

                     4001                     4002                     4003                     4004                     4005                     4006                     4007 (a)线性链接

 

         

二叉树 

                 地址 4000                       4001                       4002                       4003                       4004                       4005                       4006                       4007                       4008 (b)二叉树(非线性链接)

图 3-8  链接方式 3.1.5 程序编码调试运行

 1.编码

编码就是使用某种程序设计语言按设计出的算法流程描述,用语言中语句的实现,可称为程序设计的最终描述。例如用 C 语言编写程序求解当 n=4,k=6 时,求 bin(n,k)=n!/(k!*(n+k)!)的值。

main(){ int n,k;

n=4;k=6;

信息域 L 指针 R 指针K4 NIL NIL

K6 NIL NIL

     

K1 4006 4008

K5 NIL NIL

     

K2 4000 4004

     

K3 NIL 4001

Page 72: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

printf("bin(n,k)=%d\n",fac(n)/(fac(k)*fac(n+k)));} 

fac(m)/* 求m!*/int m;

{ int i,h;h=1;for(i=1;i<=m;++i)h=h*i;return(h);}

2.程序调试、测试和运行最后编制出来的语言程序还需要进行调试和测试,只有经过调试和测试的程序才能正

式运行。调试程序 从程序中存在的某些迹象开始,确定错误的位置,仔细研究这段代码以确定

问题的原因,并且设法改正错误。程序测试 通过大量的数据和一些特殊数据,尽可能多地发现错误。测试出来的错误由

程序员进行修改。测试与调试两项工作往往是交替地进行,直到程序中不再发现错误为止才能交付运行。 

3.2 程序设计方法  上一节讲述了程序设计的几个基本步骤的实现方法,本节将进一步讲解程序设计方法中需要考虑的因素。正确的程序设计方法直接影响程序的质量,尤其对大型的软件系统更重要。程序设计方法包括:结构化程序设计、模块化设计和逐步细化的设计方法。

 3.2.1 结构化程序设计方法

 结构化程序设计的概念首先是从编写程序中使用的无条件转移语句 goto 引起的,goto语句的使用使得程序员编程技巧得到充分的发挥。但是大量使用 goto 语句会使程序不规范、可读性差、非常难修改。在程序的规模和复杂性越来越大的今天,程序的不规范、可读性差和难于修改形成了人们常说的“软件危机”。1966年 C.Bohm提出了在程序的构成上只使用顺序、条件、循环三种结构组成的编程方式。这就是当今所说结构化程序设计。

结构化程序设计要求人们尽量避免使用 goto 语句,在不得不使用时应十分谨慎,不能跳得很远,只限于一个结构内部跳,不能从一个结构跳到另一结构。

描述算法流程的 NS图是结构化程序设计的最好工具。用户在进行算法描述时使用 NS图可使程序设计必定符合结构化程序的设计方法。 3.2.2 模块化程序设计方法  一个系统的设计,由多个具有单一功能、易于理解的多个模块组成。这就是模块化程宇设计方法。按什么原则划分模块?如何组织各模块之间的联系?有以下几条规则。

(1)按操作功能划分模块要求各模块功能尽量单一,各模块之间联系尽量的少,所编程序可读性和可理解性好,

当修改某一功能时只涉及一个模块。(2)按层次结构组织模块

Page 73: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

上层模块只实现对下层模块的调用,因此,只指出“做什么”,下层(即最低层)模块才实现“如何做”,对“如何做”作精确描述,按具体任务进行算法分析,算法实现。组成独立模块,给上层调用。

 3.2.3 逐步细化的设计方法  逐步细化的设计方法是“自顶向下,逐步细化”的基本方法。采用此方法可以将一个复杂的问题分解成多层次的模块结构。直到把一个模块功能逐步细化为一系列的处理步骤,甚至于高级语言的一个语句或一条指令。采用逐步细化的优点是:① 符合人们解决复杂问题的普遍规律,可以显著提高程序设计的效率。② 先全局后局部、先整体后细节、先抽象后具体的逐步细化过程设计出来的程序具有清

晰的层次结构,容易阅读和理解。 

3.2.4 结构化程序的三种基本结构  顺序结构、选择(分支)结构及循环结构称为程序设计的基本结构,由它们组成的程序称为结构化程序。一个结构化程序具有易读性好、可靠性高、便于维护和易于移植等优点。任何一个结构化程序只能由以下三种基本结构组成:1.顺序结构顺序结构是最简单、最基本的程序结构。在这种结构中,程序的各块是按其书写顺序依

次执行的,如图 3-9所示。执行完A 块操作后,再执行 B 块操作。这里所说的每一块可以由一条或若干条不产生控制转移的语句组成。

          

                   图 3-9  顺序结构 图 3-10  选择结构 

2.选择结构

Page 74: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

选择结构又称分支结构,在这种结构中通过对给定条件的判断,来选择一个分支执行,如图 3-10所示。当条件为“真”时,执行 A 块操作;当条件为“假”时,执行 B 块操作。无论何种图形,A、B两块操作不能同时执行。

3.循环结构循环是指在给定的条件下,重复执行某段程序,直到条件不满足为止。循环结构又分

为下两种形式:             入口 入口

    

                     真 真 

               假 假            出口 出口图 3-11  当型循环结构 图 3-12  直到型循环结构

  (1)当型(WHILE 型)循环这种循环结构的执行过程是先判断条件,若条件为“真”时,重复执行某段程序直到

条件为“假”时结束,如图 3-11所示。由于是先判断条件,所以当一开始条件就为假时,则A 块操作将一次也不被执行。

(2)直到型(UNTIL 型)循环这种循环结构的执行过程是先执行某段程序,然后再判断条件,当条件为“真”时,

重复执行这段程序,直到条件为“假”时结束,如图 3-12所示。由于是先执行 A 块操作,然后再判断条件,所以无论一开始条件是否满足,A 块操作都至少被执行一次。

上述三种基本结构可以看出,它们都具有以下特点:(1)每种基本结构只能有一个人口和一个出口;(2)没有死语句,即程序中所有的语句都有被执行的机会;(3)不包含死循环(无限止的循环)。使用这三种基本结构可以组合成各种复杂的程序结构,并且具有自上而下设计的功能。

单一的顺序结构只适用于很简单的问题,大多数实际问题的处理都包含了选择结构或循环结构。FORTRAN 77 中,用逻辑 IF 语句和块 IF 语句来实现选择结构。

 

4.3 计算机语言概述 

Page 75: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

程序设计语言是用户用来编写程序的语言,是人机之间交换信息的工具。程序设计语言一般分为三类:机器语言、汇编语言和高级语言。 3.3.1 机器语言

 机器语言是用机器指令编写的程序,计算机可以直接执行。程序中每一条机器指令都是以二进制编码的形式出现,每一台机器的指令集就是机器语言,因此机器语言与计算机一一对应,有多少种计算机就有多少种机器语言。针对一种机器编写的机器语言程序不能在另一种计算机上运行。由于机器语言是针对机器硬件编写程序的,所以它的执行效率高,能充分发挥计算机性能。但是,编写程序的难度大,常常需要计算机专业人员编写——一般人员不能进行编程。 3.3.2 汇编语言

 用助记符替代机器指令称为汇编指令,用汇编指令编写的程序称为汇编语言源程序。汇编语言的命令与机器语言指令一一对应,因此,汇编语言也与具体针对的计算机有关,一种机器上的汇编程序同样不能在另一种机器上运行。

汇编语言由于采用了人们比较容易记忆的助记符,相对于机器语言就直观得多,并且容易理解和记忆,但计算机不能直接识别,必须由针对某一种机器编写的“汇编程序”对汇编源程序进行解释,将其翻译成机器语言才能运行。这种翻译过程就称为“汇编”。 3.3.3 高级语言  机器语言和汇编语言一般称为低级语言,是面向机器的语言。开发这类语言比较困难,一般用户很难胜任这一工作。随着计算机的不断发展,计算机用户队伍的不断扩大,要使普通用户也能参与软件开发工作。从 20世纪 50年代就发展了面向问题的程序设计语言,这就是高级语言。

高级语言与计算机的硬件无关,其表达方式接近于人对问题的描述,容易为人接受和掌握。用高级语言编写程序比低级语言容易得多,编制出的程序通用性强,可移植性高,容易修改。

高级语言从 50年代发展到现在已有上百种之多,得到广泛应用的有十几种,几乎每一种高级语言都有它自身最适用的领域。表 3-1列出了常用高级语言的应用领域。  表 3-1  常用高级语言的应用领域。

语言名称 应用特点 应用领域BASIC 基础语言 教学和小型系统的开发FORTRAN 基础语言 科学工程计算PASCAL 结构化语言 教学和应用系统的开发COBOL 基础语言 商业和管理应用系统开发FOXBASE 专用语言 数据库管理系统C 结构化语言 中小型系统软件开发C++ 结构化语言 面向对象程序开发LISP 专用语言 人工智能PROLOG 专用语言 人工智能JAVA 结构化语言 应用程序开发

Page 76: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

  高级语言发展非常快,新的版本正在不断推出、例如数据库开发语言,适用于大、中型系统的网络数据库软件 SQL—Server、SYBASE、Oracle、Informix 和 DB2等。但必须指出,任何一种高级语言编写的程序(源程序)都要经过编译或解释程序翻译成机器语言后计算机才能运行。

程序设计的最终目标是在计算机上执行。选择什么样的高级语言进行程序设计,很难用一句话来论断,在实际选择时,通常在下列因素中作合理的折衷。

(1)应用范围计算机应用范围很广,涉及到社会的各个领域,一般选择在该领域具有优势的高级语

言。例如作科学计算多选用 FORTRAN;在数据处理中多选用 FoxBASE、FoxPro、SQL—Server等。

(2)算法和计算的复杂程度当某些目标需要特殊算法时,就需要选择某些可能提供这些特殊算法的软件包的语言。(3)数据结构的复杂性该语言应具有与处理问题相适应的数据结构。例如,数据处理项目需要文件或数据库;

系统软件则需要栈、队列、树等动态数据结构。要根据构造数据类型的能力选取合适的语言。(4)执行环境选择的语言必须在配置合适的机器上执行。(5)程序员的心理因素和对语言熟习程度程序员总是希望用简单、易学、使用方便的语言,因此程序员在新的语言面前往往采取

保守的态度。所以选择熟习的语言,可减轻程序员的心理障碍。 

3.4 例题详解 例 3-2 算法与数据结构在程序设计中具有重要作用,相互联系。算法按其操作的数据对

象又分为 。(A)逻辑算法和几何算法 (B)数值型数据的算法和非数值型数据的算法(C)递归算法和查找算法 (D)排序和代数算法解:程序设计过程中,针对问题设计算法。设计出的算法是对该问题求解的一组严谨

的运算步骤。这些运算步骤的处理对象是该问题的数据,数据分数值数据和非数值数据,对数据进行处理的算法也被分为数值型数据的算法(数值计算)和非数值型数据的算法(简单的数据处理)。

本题答案:B例 3-3 数据结构中研究的内容包括 、 和 。解:数据结构是研究数据在程序设计中计算机的操作对象以及它们之间关系和运算的

学科。其主要内容有:① 数据逻辑结构 从具体问题抽象出来的数据模型,如集合、树、图等。② 数据的物理结构 即数据存储结构,就是数据在计算机中存储的方式。⑧ 数据运算,对数据实行的运算,包括:插入、删除、修改、检索等。本题答案:数据逻辑结构 数据物理结构 数据运算例 3-4 通常程序设计涉及四个方面,这四个方面是 、 、 和 。解:初学计算机的人常常把程序设计理解为对一个问题的简单编程。即针对问题选择

—个合适的语言进行编程就可以了。其实程序设计涉及多方面的因素,需要设计问题的算法、考虑数据的结构、寻找合适的方法和使用各种描述工具。

本题答案:算法 数据结构 程序设计方法 设计工具

Page 77: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

 

3.5 本章小结  本章主要讲述程序设计的基础知识。对程序设计中的主要问题如问题分析与算法、数据结构以及程序的编码调试运行做了简要介绍,并介绍了算法描述工具。同时讲述了程序设计方法,使读者对结构化程序设计方法、模块化程序设计方法和逐步细化的设计方法有基本了解,并掌握结构化程序的三种基本结构。本章最后还简单介绍了计算机语言,通过学习读者应了解机器语言、汇编语言以及高级语言和常用高级语言的应用领域。  

3.6 练习题 3.6.1选择题

 1.结构化程序设计的目的是 。(A)提高程序的可读性 (B)提高程序运算精度(C)减少程序的长度 (D)提高程序运行速度2.计算机能直接运行的程序是 。(A)高级语言程序 (B)自然语言程序(C)机器语言程序 (D)汇编语言程序3.下列叙述中错误的是 。 (A)程序测试的目的是为了证明程序无错(B)对程序进行测试与调试后还不能保证程序无错(C)对程序进行测试是为了发现程序中的错(D)调试程序的目的是为了排除程序中的错误4.下列数据结构中,属于非线性结构的是 。(A)队列 (B)一维数组(C)栈 (D)树和图5.顺序存储结构中,逻辑上相邻的结点存储在物理上 的存储单元内。(A)随机 (B)空闲 (C)相同 (D)相邻6.在链式存储结构中,每一个结构包含 ,因此逻辑上相邻的结点,在物理上不一定

相邻。(A)指针 (B)地址 (C)标志 (D)编码 

3.6.2填空题 1.结构化程序设计包含的三种基本程序结构是 、 和 。2.结构化程序设计一般原则有 、 和单入口单出口。3.将汇编源程序翻译成机器指令的过程叫 。4.机器语言和汇编语言是面向机器硬件的语言,高级语言是面向 的程序设计语言,

它与机器硬件无关。5.所有高级语言共同的特点是不能被计算机直接执行,必须经过 或 成机器语言才

能执行。 

Page 78: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

Page 79: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 3 章 程序设计基础

Page 80: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 4 章 C 语言概述

第 4 章 C 语言概述4.1 C 语言的发展过程4.2 C 语言的特点4.3 C 源程序的结构4.5 C 语言的上机步骤4.6 例题详解4.7 本章小结4.8 练习题

 第 4 章 C 语言概述 

4.1 C 语言的发展过程 C 语言是 70年代初美国贝尔(Bell)实验室Dennis M.Ritchie(里奇)设计的一种程序

设计语言,正式发表于 1978年。它是在一种称为 B 语言的基础上进行重新设计的一种语言,由于是 B 语言的后继,故称为 C 语言。随着UNIX操作系统的广泛使用,C 语言也得到迅速的普及。1978年 Brian W.Kernighan 和 Dennis M.Ritchie(合称K&R)合著了影响深远的一书《The C Programming Language》,这本书所介绍的 C 语言成为后来广泛使用的 C 语言版本的基础,称为标准 C。

1983年美国国家标准化协会(ANSI)制定新的标准,称为 ANSI C,它比原来的标准C 有了很大的发展。目前广泛流行的各种版本 C 语言编译系统基本相同,但也有些区别。在微机上使用的有 Microsoft C、Turbo C、Quick C等,它们的不同版本也略有差异,读者可以通过参阅有关手册了解所用计算机系统 C 编译的特点和规定。

 

4.2 C 语言的特点 C 语言是一种通用的程序设计语言,它既不是“非常高级”的语言,也不是“低级”

语言,而通常称为“中级”语言。但这并不意味 C 语言功能差、难以使用,正是 C 语言的通用性和限制较少才使它得到广泛的应用。

C 语言具有如下特点:1.C 语言吸取了汇编语言的精华。汇编语言是一种面向机器的语言,尽管它的编程要

比高级语言麻烦得多,但目标程序质量高,运行快,所以仍旧有很强的生命力。(1)C 语言提供了对位、字节以及地址的操作,使程序可以直接对内存、指定寄存器进

行操作;(2)C 语言吸取了宏汇编技术中的一些灵活处理方式,提供宏代换#define 和文件蕴含

的预处理命令#include;(3)C 语言能方便地与汇编程序相连接,C 语言中引用汇编程序与引用函数一样方便。2.C 语言继承和发扬了高级语言的长处。(1)继承了 PASCAL 语言具有丰富数据类型的特点,具有完备的数据结构,并可以

用{  }把一串语句括起来作为复合句(分程序)来处理;(2)吸取了 FORTRAN 语言中模块结构的思想,C 语言中每个函数都是独立的,允许

单独进行编译。这有利于大程序的分工编程和调试工作;(3)允许递归调用,由于采用递归使有些算法的实现简明、清晰。

Page 81: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 4 章 C 语言概述

3.C 语言规模适中,语言简洁,编译生成的目标代码质量高,执行效率高,一般只比汇编程序生成的目标代码效率仅仅低 10%~20%,但 C 语言编程速度快,程序可读性好,易于调试和修改。

4.可移植性好,统计资料表明,C 编译程序的 80%以上是公共代码,因此稍加修改就能移植到各种不同的计算机上。

C 语言的优点很多,但也有不足之处。例如,运算符优先级太多不便记忆,有些与常规约定有所不同;数据类型转换比较灵活,类型检验能力弱,不够安全;编程自由度大,给不熟练的程序员带来一定困难。综上所述,C 语言把高级语言的基本结构与低级语言的高效实用性很好地结合起来,

不失为一个出色而有效的通用程序设计语言。 

4.3 C 源程序的结构  例 4-1/* This is the smallest C program */main(){

}这是一个最简单的 C 源程序,仅由一个主函数构成,且程序体为空,程序运行时无任何实际的执行动作。本程序的第一行是注释部分,注释内容用一对“/*”和“*/”括起来。注释往往表明程序员编程的意图和思想,便于程序员和用户理解程序的作用和功能。我们提倡大家在程序中多用注解。第二行是 C 语言的主函数首部,main是主函数名,这是一个特殊的函数,每个 C 语言程序都必须有一个且只能有一个主函数,它是 C 程序运行的起点 。main后的“( )”是函数的参数部分,可以为空,但括号不能省略,一定要有。第三、四行对应一对花括号“{  }”,表示函数体的开始和结束,“{  }”内语句的集合构成函数体,函数体允许为空。

例 4-2/* 打印字符串 */main(){printf("Hello!");

}这是一个完整的 C 语言,printf是一个标准的输出函数,括号内双引号括起来的是所带的参数,即要打印的内容,对应的输出设备是终端屏幕。上述程序运行后在屏幕上打印出字符串:

Hello!以上例子中,使用了 printf,它称为库函数,实现标准输出功能,在 C 语言中,函数分为两类,一类是系统本身提供的库函数(标准函数),编程时只要在需要的地方写上函数名,再加上参数就可以调用此函数。一般情况下要在主函数 main之前加上相应的蕴含函数库名,比如要调用数学库函数,应该在main之前加上"#include<math.H>"C 语言提供了十分丰富的库函数;另一类称为自定义函数,程序员可以根据需要自己设计一段程序来完成一个特定的功能,它相当于 Pascal 中的过程或函数,等价于一个子程序。

C 语言函数使用简单方便,执行效率高,在 C 程序设计中要养成良好的设计风格,即尽量用多个小函数或小程序来构成一个大程序,而每个小函数或小程序完成一个独立的功能。

例 4-3 现有两组数据,求每组数中的较大者,并求出两个较大者之中的较大者。main() /*主函数*/

Page 82: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 4 章 C 语言概述

{ int a1,b1,a2,b2,max1,max2,max;printf("input a1,b1,a2,b2 please:");scanf(“%d,%d,%d,%d”,&a1,&b1,&a2,&b2);max1=Max(a1,b1); /*调用函数 Max,将得到的值赋给max1*/max2=Max(a2,b2); /*调用函数 Max,将得到的值赋给max2*/max=Max(max1,max2); /*调用函数 Max,将得到的值赋给max*/printf(“max1=%d,max2=%d,max=%d\n”,max1,max2,max);}

int Max(x,y) /*定义函数 Max*/int x,y;{ int z;

if(x>y) z=x;else  z=y;return(z); /*返回 z 值*/

}这是一个求较大者的 Max(x,y)函数及调用它的主程序所构成的 C 程序,主程序中调用 Max(x,y)共三次,但每一次参数不同,即Max(a1,b1)、Max(a2,b2)和Max(max1,max2)。从上例可知,表示一个函数其形式是:

函数类型说明 函数名 (参数表) 参数说明

{变量说明语句部分}其中,函数名、圆括号和花括号是不可缺少的,通常函数可以分为两部分--函数说明部

分和函数体。(1)函数说明部分。函数类型说明定义函数返回值的数据类型(int、char、float等),

若不加说明,隐含为 int 型(整数型);函数名是以英文字母(大、小写)或者下划线开头,后跟英文字母或数字、下划线的序列。计算机只辨认前面 8 个字符,同时英文大小写有区别,例如 fac、FAC、Fac…是不同的函数,习惯上我们常使用英文小写字母;函数定义中参数(称为形式参数或形参)放在圆括号内,使用函数时采用实际参数(实参),进行形实结合,函数名后面可以没有参数,但圆括号不能省略。

(2)函数体。定义函数所要完成的功能,用“{”开始,“}”结束。函数中所用到的变量通常在“{”后进行说明,常用类型有 int、char 和 float等,函数功能由一系列语句组成,语句和语句之间用分号(;)隔开,最后一个语句末尾也有分号(这一点与 Pascal 语言不同)。

本例涉及到函数调用、实参、形参、数据类型等一系列概念,初学者不太理解可以不予深究,在后面章节都会涉及到,在此介绍这个例子,无非是使读者对 C 语言程序的组成有一个初步的了解。

 

4.4 基本的输入与输出 

C 语言中输入输出是以标准函数形式提供的,通常源程序开始包含有#include<stdio.H>这一行。C 语言中提供两个非常有用的格式化输入/输出函数,类似其他语言中的 Read 和Write 语句。

Page 83: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 4 章 C 语言概述

1.格式化输出函数的形式为:printf(控制字符串,参数 1,参数 2,…);

printf 的功能是按照控制字符串格式,将参数进行转换,然后在标准输出设备上输出。控制字符串中有两种字符,一种是普通字符将原样打出来,另一种是格式符,规定以

“%”开头紧跟格式字符,最常用的格式字符有:%d  将参数按十进制形式输出 %c  将参数看作单个字符输出%f  将参数按浮点数形式输出 %s  将参数以字符串输出(空格为终止符)例 4-4

…x1=1234;x2=5678;printf("x1=%d x2=%d\n",x1,x2);

…其中 x1=及 x2=和回车换行(\n)都是普通字符,应按原样输出,两个格式符%d依次说明 x1、x2 应按十进制整数形式输出,因此该程序输出为:

x1=1234  x2=5678    2.格式化输入函数 scanf,其格式类似于 printf:

scanf(控制字符串,参数 1,参数 2,…);scanf 函数实现从标准输入设备(通常指键盘)上按规定格式输入数值或字符,并将输

入内容存放在参数所指定的单元中。读者要特别注意参数的书写,在 printf 中参数是指要输出值的变量名,而 scanf 中参数

是要接受数据的变量地址!例 4-5

…scanf("%d %d",&x,&y);

…该语句表示从键盘输入两个十进制整数,分别送给变量 x 和 y,这&Lx、&y 表示变量x、y 的地址,输入的两个十进制数中间用空格隔开。

 

4.5 C 语言的上机步骤  这里介绍 Turbo C 运行 C 程序的步骤:

(1)先将 Turbo C装入硬盘的某个子目录(例 T(C)下,然后在子目录 TC 下键人tc↙(↙表示回车键)。

(2)启动后,屏幕顶部出现主菜单:FILE  EDIT  RUN  COMPLIER  PROJECT  OPTIONS  DEBUG可以用←和→键来移动光标,光标指到某一个命令后,接回车键(↙)开始执行此命

令,开始时光标指向“FILE”表示对文件进行输入和输出。(3)在“FILE”命令上按回车键,则在 FILE 下面出现一个子菜单(称为下拉菜单),

如图 5-l所示,它提供多种选择。可用↑或↓键选择。如果用↓键将光标移到“Load”或“New”处,再按回车键,表示要输入源程序,此时屏幕又出现一个小窗口,要求你指定文件名,例如,输入 f1.c↙。

Page 84: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 4 章 C 语言概述

Load    F3

Pick    Alt-F3

New

Save    F2

Write to

Directory

Change dir

OS shell

Quit    Alt-x

 如果原来不存在此文件名,则表示要建立一个新文件,

如果已存在此文件,则将此文件调入并显示在屏幕上,自动转入编辑(EDIT)状态。

(4)编辑源程序 f1.c,根据要求输人或修改源程序。(5)编译源程序,用功能键 F9就可以对源程序进行

编译和连接,并且屏幕上显示有无错误和有几个错误。当按任一键之后,屏幕显示源程序,光标停留在出错之处,并屏幕下部显示错误原因,可根据此信息修改源程序改正错误,再按下 F9 编译,反复进行直到不出现错误为止。

(6)按 F10 键,屏幕又出现主菜单,用→键使光标移 图 4-1 文件子菜单到 RUN,再按回车键,执行已编译好的程序,此时屏幕上会显示输出结果,如果程序需要输入数据,则应输入相应的数据,接着执行程序,输出结果。

(7)如果发现输出结果有错(称为运行错误)要重新修改源程序,可以再次按下F10,并用←键移光标到 EDIT 处,再按回车键。

(8)如果要想保存编辑好的源程序可用 FILE子菜单中的 Save命令(或直接按 F2键),如果想换个名称保存文件(原文件仍保持为编辑前状态),可用 Write to命令,这时系统会询问新文件的名字。

(9)用 FILE子菜单中 Quit命令可以退出 Turbo C,返回DOS 系统,也可直接用Alt+x 键(两键同时按下)来退出。

(10)退到DOS 系统后,可用 DOS命令 typen f1.c↙来显示源程序清单,如果在 Turbo C 环境下,利用 COMPLIER生成可执行文件 f1.exe,那么直接可用 f1↙来执行该程序。

有关使用 Turbo C 详细说明,请参见第二章。 

4.6 例题详解  例 4-6 C 语言程序的基本单位是 。

(A)程序行 (B)语句(C)函数 (D)字符分析:根据 C 语言规定,C 程序是由函数构成的,函数是 C 程序的基本单位。语句不

是 C 程序的基本单位,语句是最小的可执行单位,它仅表示实现某种功能的一个动作。函数有语句组成,是独立的程序单元。函数之间的关系是调用关系。在组成一个程序的多个函数中,有且仅有一个主函数。

本题答案:C

Page 85: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 4 章 C 语言概述

例 4-7 已知三边 a、b、c,求三角形面积。分析:本题输入条件是 a、b、c 三条边,可以在程序中设定值也可以由读者从键盘输入,

显然,后者更为灵活和方便。当然在输入三条边时要保证 a、b、c都是正数并且两边之和大于第三边,否则不可能构成三角形。三角形面积计算的数学公式是:

S=√s(s-(A)(s-(B)(s-(C)其中:s=(a+b+C)/2。同时,应确定数据类型,公式中 a、b、c、s 及 S都应该是浮点数(实数),可用 float来

说明。程序如下:

#include〈stdio.h〉 /* 〈stdio.h〉为输入输出库文件*/#include〈math.h〉 /* 〈math.h〉为数学计算库文件*/float s(float a,float b,float c); /* 这里定义 S()为求面积函数*/main() /*主函数*/

{ float a,b,c;printf("请输入三角形的边长:\n"); /* 提示字符串*/scanf('%f\n%f\n”,&d,&b,&c; /* 输入三条边长*/printf(”三角形面积为:%f\n”,mj(a,b,c); /* 调用 s*/}

mj(a,b,c){ float s;

s=(a+b+c)/2;return(sqrt(s *(s+a)*(s-b)*(s-c));/* sqrt是求开方的函数*/}说明:程序中第一个 printf显示一个汉字串,第二个 printf 除显示一个汉字串外,还输

出一个 mj 函数的调用值,由于要显示汉字,应该在汉字操作系统(例如UCDOS)下进行运行。

 例 4-8 编写一个程序输入 x、y、z 三个值,求出最大值。分析:求最小值是三个数两两进行比较,我们可以先把 x 赋给一个变量 max,然后再

把max 与 y 比较,把其中大的数送入 max,再把max 与 z 比较,把大的数送入 max,这样max 为 x、y、z 三个数中最大者,因此这里有一个条件,我们用 if…来表示。

x、y、z 三个值可由用户输入,比较后得到的 max 应该输出,x、y、z 三个数类型为实数类型(float)。

程序:#indude<stdio.h>main(){ float x,y,z,max;

printf("please input x,y,z:\n");scanf("%f,%f,%f,&x,&y,&z);max=x;if(max<y) max=y;if(max<z) max=z;printf("最大数为:%f",max);

}说明:条件语句 if(max<y)max=y;表示如果max 小于 y,那么把 y 赋给max(原先max 中为 x 的值,现在被 y所取代),max 中值不变,仍旧是 x 中的值。

Page 86: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 4 章 C 语言概述

scanf 语句中,格式符中有两个逗号(,),说明输入 x、y、z 三个数时应该用逗号(,)隔开。

运行:please input x,y,z:5.3,-2.47,-7.32最小数为-7.32000

 

4.7 本章小结  本章介绍了 C 语言的发展过程及它的特点,C 语言是一个普遍被采用的出色有效的程序设计语言。

本章举例说明了 C 源程序的基本结构,它有一个且只有一个主函数,并且可以有若干个子函数(自定义函数)组成。正因为计算机系统提供了丰富的库函数,才使我们可以方便地进行编程。

本章还初步介绍了两个基本输入输出(I/O)函数 printf 及 scanf,前者用来输出变量的值,后者用来输入数据到变量中,但特别要注意,scanf 语句中,变量以地址的形式(例&x、&y)来表示。

本章介绍了 Turbo C 环境下上机步骤,读者不妨试一试,可以把本章中提到的例子输入进去,然后进行编译和运行。

 

4.8 练习题 4.8.1选择题 

1.一个 C 语言程序是由 组成。(A)主程序 (B)子程序(C)函数 (D)过程2.一个 C 语言程序总是从 开始。(A)主过程 (B)主函数(C)子程序 (D)主程序3.在 C 语言中,如果下面的变量都是 int 型,则输出的结果是 。

sum=pad=5;pAd=sum++,pAd++,++pAd;printf(“%d\n”,pad);

(A)7                                                    (B)6(C)5                                                    (D)44.C 语言程序的三种基本结构是 。(A)顺序结构,选择结构,循环结构 (B)递归结构,转移结构,循环结构(C)嵌套结构,选择结构,循环结构 (D)转移结构,循环结构,嵌套结构

5.C 语言程序中的大小字母是 。(A)都不加区分 (B)变量不加区分(C)字符串不加区分 (D)字符串中加区分 

4.8.2填空题 1.一个 C 程序是由若干个函数构成的,其中必须有一个 函数。2.在 C 程序中,注释部分以 开始,以 结束。

Page 87: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 4 章 C 语言概述

3.在 C 语言中,一个函数一般有两部分组成,它们是 和 。4.在 C 语言中,一个函数的范围是以 开始,以 结束的。

Page 88: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

第 5 章 基本数据类型和表达式5.1 标识符和变量

5.1.1 标识符5.1.2 变量

5.2 基本数据类型5.3.1 整型常量5.3.2 实型常量5.3.3 单字符常量5.3.4 字符串常量5.3.5 符号常量

5.4 表达式5.4.1 算术运算符5.4.2 关系运算符5.4.3 逻辑运算符5.4.4 自增自减运算符5.4.5 赋值运算符5.4.6 逗号运算符及表达式5.4.7 条件运算符5.4.8 位运算符

5.5 数据类型的转换5.6 运算符的优先级和结合性5.7 赋值语句5.8 例题详解5.9 本章小结5.10 练习题

第 5 章 基本数据类型和表达式5.1 标识符和变量

5.1.1 标识符所谓标识符实际上是一个字符序列,常用它来标记常量、变量、数据类型、函数及程序

的名字等,在 C 语言中标识符必须符合以下规定:(1)以字母或下划线( )开头;(2)后跟由字母、数字、下划线组成的字符序列(也可以是空串);(3)大小写字母含义不同。例如Name 和 name是不同的标识符;(4)标识符书写时长度不限,但只有前八个字符有效,因此定义标识符时应注意前八

个字符不要相同。C 语言中的标识符可分为三类:(1)关键字(共 32 个)。关键字有专门的含义,不得赋予其他含义。C 语言中习惯使

Page 89: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

用小写字母,所以这些关键字也由小写字母构成:auto break case char const continue default do double enumelse extern float for goto if int long register return shortsigned sizeof static struct switch typedef union unsigned voidvolatile while(2)特定字(7 个)。特定字是具有特定含义的标识符,它们主要用在 C 语言的预处

理程序中,因此人们习惯上也把它们看成是关键字,不作一般标识符使用,它们是:define include under ifdef ifndef endif line(3)一般标识符。这是用户自定义的标识符,通常根据标志内容的含义用英文或汉语

拼音来表示,也可以按习惯符号来表示。下面是几个合法标识符的例子:

d dw name f 1 f 2 z11 area age而下面的字符串都是不合法的标识符:2x -xy name* no? a/b

5.1.2 变量

数据项在程序中不是常量就是变量。在程序执行过程中变量的值可以改变而常量的值不可以改变。变量就是一般标识符,用来存储各种类型的数据以及指向存储器内部单元的地址(指针)。所谓变量在使用之前必须加以说明,即说明变量的名称、类型、长度等信息。其格式是:

类型说明符 变量表;例如:int lower,upper,step;charc name[10];上述说明也可以写成:int lower;int upper;int step;char c;char name[10];后一种形式会使源程序冗长,但便于给每个变量说明增加注释,也便于修改。上面说

明的 lower、upper、step 为整数类型,c是字符类型,name是字符数组可存放 10 个字符。5.2 基本数据类型

数据类型是语言中一个重要的概念,它把一个语言所处理的对象按其性质不同分为不同的子集,对不同的类型规定不同的运算。

Turbo C 中规定的基本数据类型有四种: 整型 int

单精度 float基本类型 实型 float

双精度 double 字符型 char

表 5-1给出基本数据类型的长度和存储的值域。表 5-1 基本数据类型的长度和存储的值域(带*号为绝对值范围)

Page 90: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

类型 占字节长度(位) 值域char 1(8) 0~255

int 2(16) -32768~32767

float 4(32) *3.4E-38~3.4E+38

double 8(64) *1.7E-308~1.7E+308

此外,还有一些用于整型的限定词:short(短)、long(长)、signed(有符号)和unsigned(无符号),其中 signed经常省略。同时当 int前加上限定词后,int 本身也可省略,从表 5-2可知 signed int 和 short int是一样的。

表 5-2 带限定词后整数的长度和范围(带方括号部分可以省略)类型 占字节长度(位) 值域

short[int] 2(16) -32768~32767

int 2(16) -32768~32767

signed[int] 2(16) -32768~32767

long[int] 4(32) -2147483648~2147483647

unsigned[int] 2(16) 0~65535

unsigned long[int] 4(32) 0~4294967295

5.3 常量常量是 C 语言中使用的基本数据对象之一。其值在程序运行过程中是不允许改变的。常

量在程序中一般以其值本身来表示,也可以通过宏定义命令(#define 标识符 常量)来义。C 语言中的常量可分为算术常量和字符常量两部分,其类型如下:

十进制数整型常量 八进制数

算术常量 十六进制数 长整型数

常量 实型(浮点)常量 单字符常量

字符常量 字符串常量

5.3.1 整型常量C 语言中整型常量有四种形式。(1)十进制常数。一般占一个机器字长,是一个带正负号的常数,其值为-2n-1~2n-1-1

之间,n 为机器字的位数,例如 16 位机器中,其值范围为一 32768~十 32767。下列数都是合法的十进制常数:

-32678 0 3261 +123 -456(2)八进制数。C 语言中规定八进制数表示一律以零(0)开头,后面跟一串八进制数

字(0~7)表示,因此下列数都是合法的八进制数:0123 05 0100 03276

Page 91: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

它们分别等于十进制数的 83,5,64,1726。而下列数是十进制数:123 5 100 3276(3)十六进制数。C 语言中规定十六进制数是以OX 开头,后面跟一串十六进制数(0

~F 或 0~f)组成的串,例如:OxlO OxlB 0x2f 0x25它们分别是十进制的 16,27,47,37(这里 B代表 11,f代表 15)。

(4)长整数。长整数占两个机器字长,其值范围为-22n-1~22n-1-1。规定在上述三种进制的整数后加字母 1 或L来表示长整数常量,在 16 位机器中占用四个字节(32 位)空间。例如:

-30L 0371 -0xlfL都是长整数常量。5.3.2 实型常量

C 语言中实型常量可由整数、小数、指数三部分组成。前两部分之间用小数点隔开,后两部分依靠 E(或 e)来连接,E 或 e 表示 10 的幂,指数部分也可有正负号,它表示小数点的实际位置。

实数(浮点数)的组成规则:(1)上述三个部分可以缺省一个部分或两个部分,但整数部分和小数部分不能同时缺

省;(2)如果带有小数点,那么小数点两边至少有一边有数字;(3)如果带有 E(e),两边至少有一位数;(4)指数部分必须是整数。例如下列都是合法的实型常量:

3. 123.45 .002 52.48E3 1.2E-5 0.0而下列是非法的实型常数:

e3 3.0e e-9 . .e5 e

5.3.3 单字符常量单字符常量由一对单引号括起的单个字符构成,例如'A'、'2'、'?'、'#'均为

单字符常量,它占一个字节(8 位)。在计算机中 ASCII 码中还有一些非图形字符,C 语言中用转义序列来表示,例如:'\n' 表示换行(newline) '\f'走纸(form feed)'\t' 制表符(tab) '\\'反斜杠(backslash)'\o' 空白(null) '\ddd'位型(bit pattern)(1~3 位八进制)'\b' 退格(backspace) '\xdd'位型(1~2 位十六进制)'\r' 回车(CR)注意,转义字符'\n'中的 n已不代表字符'n'而表示换行。转义字符'\012'是'\

ddd'形式,其中 012是八进制字符串,代表 ASCII 表中编码为 10 的字符,即换行符,因此其功能与'\n'相同。5.3.4 字符串常量

C 语言中字符串常量是用双引号括起来的字符序列。双引号是字符串常量的边界,它本身不是字符串的一部分,例如:

Page 92: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

"this is a string" "How are you?" "a" "□"其中"a"是字符串常量,它和'a'不同,后者是字符常量。此外,如果在字符串中出现双引号,则前面应加上反斜杠将其转义(不作为边界看

待)。例如,要输出字符串:

He says:"What's your name?"应写成下列格式:

printf("He says:\"what's your name?\"");字符串可以看成一个数组,即字符数组,其说明及使用详见本书后面有关章节。

5.3.5 符号常量有时程序要多次使用一些常量,如果这些常量本身字符序列很长,会使工作很繁琐,

同时也难以查找和修改,有时为表达清楚常量的含义,也需要给它起个名字。C 语言提供一种宏定义命令对常量进行定义,其格式为:

#define 标识符 常量例如,在程序中想用 ONE代表 l,PAI代表 3.4159,TV代表字符串“television”,可

以用三个宏定义命令:#define ONE 1 ’#define PAl 3.14159#define TV"television"

说明:(1)符号常量与变量不同,程序中一旦定义后,不能再改变,也不能再赋值,为了区

别,习惯上符号常量用大写字母表示,变量用小写字母表示。(2)符号常量作用范围是从开始定义处直到程序结束,通常在程序中一开始就将定义

常量的宏命令集中放在程序的开始处,这种良好的习惯使程序结构规范,也便于对宏定义进行查找。

(3)常量定义允许嵌套,即可以引用已定义过的符号常量名。例如:#define PAI 3.14159/#define R 65.7#define AREA PAI*R*R(4)一个宏定义命令一行写不下,可以延续到下一行,但第一行结尾应加一个字符'

\'。例如:#define BIT"Beijing Institute Of\

Technology"5.4 表达式

表达式是计算机语言中的基本成分,用来计算一个值的式子,表达式一般由运算对象和运算符组成,运算对象包括常数、变量、函数及其他表达式等。

C 语言中提供的运算符十分丰富,除了在一般高级语言中所具有的算术运算符、关系运算符、逻辑运算符之外,还提供了位运算符、增减运算符等。 5.4.1 算术运算符

C 语言中允许有五种算术运算符,它们是+(加)、一(减)、*(乘)、/(除)和%

Page 93: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

(模)。说明:(1)对除法运算(/)规定两个整数相除时为整除,即舍去小数部分仅取整数部分。例

如:5/3=l, 5.0/3=1.666。

(2)求模运算(%)要求两个运算对象都是整数,其结果是整数除法的余数。例如:5%10=5,10%3=1,-10%3=一 1。

(3)算术运算符的优先级与一般数学运算相同,先乘除后加减,并且从左至右进行结合。例如:

10/5*3 结果是 6,而不是 10/(5*3)=0。5.4.2 关系运算符

C 语言规定了六个关系运算符:>(大于)、<(小于)、>=(大于等于)、<=(小于等于)、!=(不等)及==

(等于)关系运算的结果是逻辑值,C 语言中没有逻辑类型数据,因此用整数0代表“假”,整数 1代表“真”。

说明:(1)<、<=、>、>=的优先级相同,==和!=的优先级相同。前者运算优先级高于后者。(2)关系运算符优先级低于算术运算符。(3)表达式中连续使用多个运算符时要注意运算的优先级和结合性。例 5-1 若程序中已说明 int a=5,b=2,c=3;则求以下关系表达式的值:

a>b (成立,其运算结果为 1)a<=c (不成立,其运算结果为 0)a!=b (成立,其运算结果为 1)(a>c)==b (成立,其运算结果为 1)a-b!=c (不成立,其运算结果为 0)

说明:最后一题中,因为关系运算符优先级低于算术运算符,因此先计算。a-b 其值为 2,再计算 2!=c 不成立,因此其最终结果为 0。若变量 x 的取值范围为 0≤x≤10,不能写成“0<=x<=10”,因为这样做,先求“0<=

x”,结果为0或者 1,再作“<=l0”的判断其最终结果必定为 1,显然违背了原意,此时应该采用逻辑运算符进行连接,写成“0<=x&&x<=10”。5.4.3 逻辑运算符

C 语言中规定了三个逻辑运算符,它们是逻辑与(&&)、逻辑或(||和逻辑非(!),其中前两个是双目运算,后一个是单目运算。三者中“!”优先级最高,“&&”次之,“||”最低,尤其要注意,“!”优先级比任何算术运算都高,而“&&”及“||”的优先级低于所有关系运算。

表 5-3给出了逻辑运算真值表,式中 0 表示假,1 表示真,C 语言中把非 0 值也作为真来处理。

表 5-3 逻辑真值表a b !a !b a&&b a||b

0 0 1 1 0 0

Page 94: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

0 非 0 1 0 0 1

非 0 0 0 1 0 1

非 0 非 0 0 0 1 1

例 5-2 若 a=3,b=2,计算下面的值。!b (值为 0,因为 a 值为非 0即真)a&&b (值为 1,因为 a、b 值均为非 0)!a||b (值为 1)a||b (值为 1)4&&0||2 (值为 1)2>5&&2||3<4-!0 (值为 0)

因为关系运算优先级高于“&&”和“||”,因此先计算 2>5,其值为 0,再进行 0&&2 运算,其值为 0,接着根据逻辑次序先计算!0 其值为 1,计算 4-1=3,再计算 3<3 其值为 0。最后综合 0||0=0。从上例可知逻辑运算的对象不仅可以是 0,1,还可以是非 0 值,甚至是字符型、实型

等,但逻辑运算的结果必然为 0 或者 1。例如'c'&&'d'值为 1(因'c'和'd'的ASCII 值都不是0,按“真”处理)。

例 5-3 给出判定某一年 year是否为闰年的条件。分析:闰年是符合下面二者之一的年份:(1)能被 4 整除,但不能被 100 整除;

(2)能被 400 整除。判别年份 year能否被 4 整除,只要进行求模运算,即 year%4,若其值为 0,说明能被

4 整除。求解:

(year%4==0&&year%100!=0)||year%400==0当上述表达式值为 1(真)时 year 为闰年,否则不为闰年。

5.4.4 自增自减运算符自增“++”、自减“一一”都是单目运算符,其作用是使变量的值增 1 或减 1,可表

示为:++i;——i ++、一一在变量 i之前,为“前缀”形式i++;i 一一 十+、一一在变量 i之后,为“后缀”形式请特别注意,在表达式中前缀形式是先增减再使用,后缀形式是先使用再增减,因此

其意义不同。例 5-4 若 i=1,计算下列各式值。

x=++i 先计算 i=i+1(结果 i=2)再执行 x=I,因此最终结果为i=2,x=2。

x=i十+ 先执行 x=i(结果 x=1),再执行 x=x+1因此最终结果为i=2,x=1。

x=i++*i++ 先取 i 值进行乘法(*)运算,再两次对 x 加 1,因此结果为i=3,x=1。

x=++i*++i 先对 x两次加 1,再取 x 值相乘,因此结果为i=3,x=9。

使用 i++或++i 有不少容易混淆的地方,请读者注意以下几个问题:(1)自增、自减运算符只能用于变量而不能用于常量或表达式,例如 5十+,(a+

Page 95: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

b)++都是不允许的,本例中 5是常量不能改变值,a+b 值若为 8,那么增 1后为 9 存放到何处去呢?无变量供存放。

(2)++和一一的结合方向是“自右至左”而不是习惯上的“自左到右”,例如一 i++如果 i原值为 4,根据从左到右的结合,应求取(-i)++,表达式是不允许自增自减运算的,实际上根据“自右至左”的结合方向,是计算一(i++),因此表达式值是一4(不是一 5!)。

(3)在表达式中出现时要尤其小心。如 i 的原值是 3,那么(i++)+(i++)+(i十+)其值是多少呢?有人认为相当于 3+4+5即 12,事实上 Turbo C显示它为 9,实际上是先把三个 i取出来相加,然后再对 i 自加三次(i=6)再例如,i 的原值为 3,那么 k=(++i)+(++i)+(++i)值是多少呢?有人认

为 k=4+5+6=15,事实上 k=18。其原因是首先 i 三次自加,得到 i=6,然后求 k=6+6+6=18。

(4)i+++j是理解为(i++)+j还是 i+(++j)呢?在 C 语言中自左到右尽可能多地把若干字符组合一个运算符,因此其解释为前者而不是后者。

(5)printf("%d,%d",i,i++);若 i原值为 3,那么输出是多少呢?多数系统对函数参数的求值次序是从右向左,执行 i++时先输出 i 值再进行自加,当打印第一个参数时,其值已变为 4,因此该 printf 输出值不是“3,3”而是“4,3”。因此自增自减运算符往往会产生人们“想不到”的副作用,初学者要慎用。

5.4.5 赋值运算符1.C 语言中规定‘=’是赋值运算符,它把右边表达式内容赋于左边的变量,例如

“a=17”,其作用是把 17 赋给变量 a。2.如果赋值运算两侧类型不一致,但都是数值型或字符型时,赋值时自动进行类型的

转换。(1)将实型数(包括单、双精度)赋给整数变量时,舍弃小数部分,自动取整。例如:

a 为整型变量,执行“a=5+3.72”后 a 中值为 8。(2)将整数赋给实型变量时,数值不变,但以浮点形式存入变量中,例如,x 为 float

变量,执行“x=25”后,x=25.00000。3.复合赋值符在赋值符前加上其他运算符可以构成复合运算符,例如“十=”、“*=”…。例如:a+=5 等价于 a=a+5

x*=y+8 等价于 x=x*(y+8),注意圆括号不可少x%=5 等价于 x=x%5

4.赋值表达式赋值表达式形式是:

<变量><赋值运算符><表达式>因此“a=5”是一个赋值表达式。但要注意<表达式>本身也可以是赋值表达式。例如:a

=b=c=d=5,其结果是 a到 d 共四个变量值均被赋于 5,再例如,a=(b=l0)/(c=2),a 的值为 5。

赋值表达式还可以包含复合赋值运算符,例如,a+=a 一=a*a如果 a 的初值是 5,那么此表达式求解过程是:

(1)先进行 a 一=a*a 运算,相当于 a=a-a*a=5-5*5=一 20;(2)再进行 a+=一 20即 a=a十(一 20)=-20-20=-40。例 5-5 若 a 的原值为 12,计算 a+=a-=a*=a。

Page 96: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

解:(1)计算 a=a*a=144(2)计算 a=a-144=0(3)计算 a=a+0=0

因此其结果为0。5.4.6 逗号运算符及表达式

C 语言提供一种特殊的运算符叫逗号运算符。用它把两个表达式连接起来,例如 3+7,4+9 其一般形式是:

表达式 1,表达式 2其求解过程是先求解表达式 l,再求解表达式 2,而整个表达式值为表达式 2 的值。例如:

“3+7,4+9”值为 13“a=3*4,a+5”值为 17“(a=3*4,a*5),a+8”值为 20

注意,尽管执行 a*5,但 a 值未变,仍为 12。 逗号表达式扩展形式为:

表达式 1,表达式 2,…,表达式 n其值为表达式 n 的值。

逗号运算符是运算级别最低的运算符,因此下面两个式子中 x 值不一样:(1)x=(a=3,6*3) x 值为 18(2)x=a=3,6*a x 值为 3

5.4.7 条件运算符条件运算符“?:”是三目运算符,其一般形式为:

el ? e2 :e3这里 e1、e2、e3均是表达式,先计算 e1 的值,若非零则执行 e2,把 e2 值作为整个表达

式值;若 e1 为零,则执行 e3 的值,且把 e3 值作为整个表达式值。

例如:z=(a>b)?a:b。该赋值语句表明把 a 和 b 值大的一个赋予 z,其中(a>b)为e1,a 为 e2,b 为 e3。5.4.8 位运算符

C 语言的位运算是它有别于其他高级语言的特点之一,它是对变量的二进制位进行运算,共有六种运算符:

&(按位与) |(按位或) ^(按位异或)~(按位求反) 《(按位左移) 》(按位右移)其中求反(~)是单目运算符,其他都是双目运算符,位运算对象只能是整型(int)

或者字符型(char)数据。1.“按位与”运算(&)。参加运算的两个二进制数相应位都为 1,则该位结果值为

1,否则为0。即 0&0=0,0&1=0,1&0=0,1&1=1。例如:3&5并不等于 8,先把 3 和 5以补码表示,再按位运算。

3 的补码为 0000001l5 的补码为 00000101

Page 97: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

&: 00000001它是 1 的补码,因此 3&5=l。按位与运算有一些特殊的用途:(1)清零。若要把一个单元清零(即 8 位二进制都为0),则只要用0与该单元进行

按位与运算即可,即0&n=O(n 为任意二进制数)。(2)取一个数中某些指定位。例如:x(1 个字节)只想取其低 4 位,只需把它与

(OF)16(十六进制数)进行逻辑与即可。例:x 01011101(0F)16 00001111

&: 00001101其结果是 x 的低 4 位。

(3)保留特定位。例如:x=84=(01010100)2,想保留左面第 3、4、7 位的值,可以与一个数进行&运算,此数(n)的第 3、4、7 位为 1,其余各值为 0。即 n=(00110010)2=50。

x=84= 01010100n=50= 00110010

&: 00010000(等于十进制数 16)所以:84&50=162.按位或(|)运算。参加运算的两个二进制数相应位只要有一个是 1,则该结果为

1,否则为 0,即 0|0=0,0|1=1,1|0=1,1|1=1。例如:061|017,使八进制数 061 与 027 进行按位或运算。

(061)8=(00110001)2(027)8=(00010111)2

|: (00110111)2 (067)8因此 061|027=067 (均为八进制表示)。按位或常用以使原数的指定位置 1。3.按位异或运算(^)。异或运算是两个运算量的相应位相同,则结果为 o。相异则结

果为 1,即 0^0=0,0^1=1,1^0=1,1^1=0。异或运算常用以使某个数的某几位翻转。例如:a=015(八进制),要使其后四位翻转,只需要 a=a^017。

a: 00001101 ^017: 00001111 a: 00000010

(4)接位求反运算(~)。该运算为单目运算,求反是把对象(二进制数)接值取反。例如:

x=7y=~x=(00000111)=(11111000)

由于计算机中存放补码,因此其值的真值为一 8。请注意求反运算,单目减和逻辑非三者之间差别:

y=~x=~(7)=一 8y=-x=-7y=!x=0

(5)左移(《》和右移())运算符。左移、右移运算表达式为:

Page 98: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

x《n 或 x》n表达式把二进制的 x 全部向左或向右移动 n 位,左移时左边移出的高位舍弃,右边补

0;右移时,右边低位舍弃,对于无符号位数左边高位补0,对有符号位数,左边高位不变。例如:

a=14b=a《2=00001110《2=00111000 (b是十进制数 56,为 a 的 22倍)c=a 》2=00001110》2=00000011 (c是十进制数 3,为 a 的 2-2倍,有一定误差)

5.5 数据类型的转换C 语言允许进行整型、实型、字符型数据的混合运算,但在实际运算时,要将不同类型

数据转换成同一类型再进行运算,这种类型转换的一般规则是:(1)运算中将 char 类型转换为 int 型,float 型转换为 double 型。(2)低级类型服从高级类型并进行相应转换,数据类型识别由低到高的次序为:

char→int→unsigned→long→float→double(3)赋值运算中右边表达式值最终以左边变量的类型为准看齐,并进行相应变换。例 5-6

int a,b,c;float x;long d;double e;

…c=a+'a'+a*x-b/d+e

…上列赋值运算中,'a'转换为 ASCII 码整数 97,并与整数 a 值相加;在计算 a*x 时,由于 x 为 float 型先转换为 double 型,a是整型但为运算一致也能转变为 double 型。其运算结果也为 double 型;上两步求和,是把 a+'a'的整型值(int)先转化为 double 型,再进行求和;计算-b/d 其值为 long 型;再把以上几步结果和 e相加,类型为 double 型;赋于 c时,压缩 double 的小数部分变为 int 型,赋于 c。以上各步骤中的类型转换都是 C 编译系统自动完成,用户不必过问。除自动进行类型转换外,用户可以用强制类型运算符(type)(其中 type泛指某一数

据类型),它是单目运算符。例如:(double)a 将 n强制转换为 double 型(int)(a*b) 将 a*b 结果强制转换为 int 型(float)a*b 把 a 先强制转换为 float 型再与 b相乘

5.6 运算符的优先级和结合性与数学中的运算符类似,运算符都有确切的含义,有一定的形式,具有优先级和结合

性。例如四则运算中“先乘除后加减”,乘除为同级运算,通常从左向右进行结合。C 语言中运算符的优先级和结合性见表 5-4所示。例 5-7 已知 a=3,b=4,c=5,写出下列表达式计算结果。(1)a/b*c 结果为 0。因为/和*运算优先级相同,左→右结合,先计算

a/b 值为 0,再计算 0*c=0。(2)a%b*c 结果为 15。同样,%与*同级,从左到右执行。

Page 99: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

(3)a*c》2 *运算优先级大于位右移运算()),因此先求出 a*c 值为15,再右移二位,为十进制值 3。

(4)a&b&&c 按位与(&)优先级高于逻辑与(&&),先计算 a&b结果为 2,再进行 2&&5 其值为 1。

(5)a|b&c 先执行 b&c 结果为 4,再执行 a|4 其值为 7。(6)~(a~)3) 先计算括号,先对 a接位求反(101→010),再右移三位,

其位为0,然后再按位求反其值为一 1。表 5-4 C 语言运算符优先级和结合性

优先级 运算符 功能 适用范围 结合性15 ()

[].->

括号下标

存取成员存取成员

表达式数组

结构联合结构联合

→(左→右)

14 !~++――-&*

(type)sizeof

逻辑非接位求反

加 1

减 1

取负取地址取内容强制类型长度计算

逻辑运算字位自增自减算术指针指针

类型转换变量

←(自右向左)

13 *

/

%乘除

整数取模算术 →

12 +-

加减

算术 →

11 <<>>

位左移位右移

字位 →

10 <<=>>=

小于小于等于

大于大于等于

关系 →

9 ==!=

相等不等

关系 →

8 & 按位与 字位 →7 ^ 按位异或6 ∣ 按位或5 && 逻辑与 逻辑 →4 ‖ 逻辑或3 ?: 条件运算 条件 ←2 =

OP=运算且

赋值←

Page 100: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

OP可为*/%+

-<<>>^|

1 , 顺序求值 表达式 →说明:①大多数运算是从左向右结合,部分运算是从右向左结合。

② 有些运算符(例如指针)在后面章节介绍。5.7 赋值语句

C 语言中赋值语句是最基本、使用频率最高的语句之一,它是由具有赋值功能的表达式加上一个语句结束标志(分号)构成,其一般形式为:

V=e;其中,=为赋值运算符,V为广义的变量,初学C语言时可视为一般变量,e 为表达

式是赋值语句的主体。其功能是先计算表达式的值,再将值转成与左边变量V类型一致的值并赋给此变量。例如:a=3*5+4;先计算表达式值 19,然后再赋于 a,使变量 a 的值为 19(必要时进

行类型转换)。显然,在计算机程序中常出现 n=n-1;的赋值语句,这是合理的语句,而数学中 n=

n+1是一个矛盾的公式。上述赋值语句是一种显式形式。在C 语言中还采用“隐式的”赋值语句,例如 x++;

p――;x+=2;等,它们分别与 x=x+1; p=p 一 1; x=x+2;等价,而且比前者更简练。此外 C 语言还允许连续赋值。其形式是V1=V2=…=Vn=e;它等价于 V1=e;V:=

e;…Vn=e;应用赋值语句时要注意,表达式中的变量在语句执行前应先赋初值,否则由于变量值

不确定,表达式值也不确定。C 语言中的赋值语句具有其他高级语言中赋值语句的特点和功能,但两者又有不同之

处:(1)C 语言中赋值号是运算符。(2)大多数语言没有“赋值表达式”的概念,而 C 语言中可以存在赋值表达式并可以

包含在其他表达式中,例如语句“a=((x=y)<z);”的含义是先将 y 值赋给 x,然后再与 z 比较,最后将比较结果赋于变量 a,其中(x=y)是赋值表达式。

5.8 例题详解例 5-8 写出下列程序运行结果。

main(){ charcl='b',c2='d',c3='f',c4='\103','c5='\118';

printf("a%cc%c\te%c\tgh\n",c1,c2,c3);printf("\t\b%c%c",c4,c5);}分析:c4='\103',其中 103是八进制,相当十进制的 67,即字符'C'的 ASCII 码,

因此它与 c4='C'完全等效。同理 c5='\118'与 c5='P'等效(ASCII 码 80),第一个打印语句中\t 为制表符,\n 为换行。

Page 101: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

↓tab(制表位) ↓tab解:该程序运行结果为 abcd ef gh

C P例 5-9 求以下表达式值。(1)设 x=3.2,a=10,y=3.9。计算 x+a%3*(int)(x+y)%2/4。解:

x + a % 3 * ( int ) ( x + y ) % 2/41 7

10

3.2因此上式为 3.2。

(2)设 a=4,b=3,x=6.3,y=7.4。计算(float)(a+b)/2+(int)x%(int)y。解:

( float )( a + b ) /2+( int ) x % ( int ) y 7.0 6 7

3.5 6

9.5因此上式为 9.5。

5.9 本章小结本章首先介绍了标识符和变量的概念。标识符是由字母或下划线(_)开头,后跟由字

母、数字和下划线组成的序列(包括空串),大小字母在 C 语言中是有区别的,读者应注意 C 语言中的 32 个关键字和 7 个特定字有独特的含义,不能单独作为用户标识符使用。

数据项在程序中不是常量就是变量。习惯上变量用小写字母表示,并且要遵循”先说明后使用”的原则。

本章叙述了 C 语言中基本的数据类型,包括整型(int)、单精度浮点型(f1oat)、双精度浮点型(double)及字符型(char)、对整型数据前面可加限定词(shat,long,signed,unsigned)有时可省略 int 本身。接着讲述了 C 语言中常量的概念,请读者记住各种常量的表达方法(整型常量、实型

常量、字符常量等),尤其要区分'a'和"a"的区别。前者是单字符常量,占用一个字节,后者是字符串常量占用两个字节(在后面讲述)。

本章重点在于 C 语言中的表达式及赋值语句。C 语言中提供了丰富的运算符,包括算术运算符、关系运算符、逻辑运算符、自增自减

运算符、赋值运算符、逗号运算符、条件运算符、位运算符等。有些运算符(如指针运算符)后面再作介绍。读者应掌握这些运算符的作用,尤其对以前很少遇到的自增、自减运算符、复合赋值符、赋值表达式、逗号表达式等要倍加注意,稍有疏忽就会出错。你可以在计算机上求取表达式的值,以验证你的理解是否正确。按位运算是 C 语言的特色,也是称它为“中级”语言的主要原因,使用它可以对变量

中的二进制位进行运算,但读者要记住,数值在计算机中是以补码形式出现,因此用十进制表示时应该进行转换。由于表达式中有各种运算符及各种类型的数据(操作对象),对前者要注意优先级和

Page 102: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

结合性,尤其是一些运算符是从右向左结合,与习惯不一致;对后者要注意类型的自动转换和强制转换问题。

5.10 练习题5.10.1选择题

1.下面标识符中,不合法的用户标识符为 。(A)Pad (B)a_10(C)CHAR (D)a#b2.下面标识符中,合法的用户标识符为 。 (A)long (B)E2(C)3AB (D)enum3.以下 组中的常数都是合法的 C 语言常量。(A)一 0 (B)"222"'/N' 7FF2E5 03(C)'123' (D)"12.50"'\678' -0Xlal'{' 03e5

4.在 C 语言中,int、char 和 short 三种类型数据所占用的内存 。(A)均为 2 个字节 (B)由用户自己定义(C)由所用机器的字长决定 (D)是任意的5.在 C 语言中,int 类型数据范围是 。(A)0至 255 (B)0至 65535(C)一 32768至 32767 (D)一 255至 2556.以下 是不正确的转义字符。(A)'//' (B)'/'(C)'081' (D)'\0,'7.若有说明.charsl='/067';chars2="1";chars3='l';则 s1 中 [1] ,s2 中 [2]

,s3 中 [3] 。[1](A)包含 3 个字符 (B)包含 2 个字符

(C)包含 1 个字符 (D)无定值,说明不合法[2](A)包含 1 个字符 (B)包含 2 个字符

(C)包含 3 个字符 (D)无定值,说明不合法[3](A)包含 1 个字符 (B)包含 2 个字符

(C)包含 3 个字符 (D)无定值,说明不合法8.在 C 语言中,char 型数据在内存中以 形式存储的。(A)原码 (B)补码(C)ASCII 码 (D)反码9.以下运算符中优先级最低的算符为 [1] ,优先级最高的为 [2] 。(A)&& (B)& (C), (D)!=10.若有运算符:<、*=、<<、%、sizof,则它们按优先级(由低至高)的正确排列次序

为 。

Page 103: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

(A)*=→<<→>→%→sizeof (B)>>→*=→>→%→sizeof(C)*=→>→<<→sizepf→% (D)*=→>→<<→%→sizeof11.若有以下类型说明语句:char w;int x float y:double 2:则表达式 w*x+z-y 的结

果为 类型。(A)float (B)char(C)int (D)doule12.设 x、y 为 float 型变量,则以下 是不合法的赋值语句。(A)++x (B)y=float(3)(C)x=y=2=0 (D)x*=y+813.若 x 为 int 型变量,则执行下列语句后 x 的值为 。

x=6;x+=x-=x*x;

(A)36 (B)-60(C)60 (D)-2414.若 x、y、2均为 int 型变量,m 为 long 型变量,则在 16 位机上执行下列语句后,y

(十六进制形式)值为 [1] ,x 值为 [2] ,z 值为 [3] ,m 值为 [4] 。y=(x=32767,x+1);z=m=0xffff;

[1](A)FFFF (B)7FFFF(C)7FFFE (D)80000

[2](A)-32768 (B)0(C)32768 (D)32767

[3](A)0 (B)32768(C)-1 (D)65535

[4](A)0 (B)32768(C)-1 (D)65535

15.若w=1,x=2,y=3,2=4,则条件表达式 x<x?w:y<z?w:y 的结果为 。(A)4 (B)3(C)2 (D)116.若 x 为 int 型变量,则逗号表达式(x=4*5,x*5),x+25 的结果为 [1] ,x 的值为

[2] 。[1](A)20 (B)100

(C)表达式不合法 (D)45[2](A)20 (B)100

(C)125 (D)4517.若有说明语句 int i,j;且 i 的值为 6,则执行语句 j=(++i)+i++)后 j 的值为

。(A)4 (B)14(C)13 (D)1518.设 x 和 y均为 int 型变量,则执行以下语句后的输出为 。

x=15;y=5;printf("%d\n",x%=(y%=2));

(A)0 (B)1(C)6 (D)12

Page 104: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

19.若 x、y、z、m、n均为 int 型变量,则执行下面语句后的 x 值为 [1] ,y 值为 [2] ,z 值为 [3] 。

m=10;n=5;x=(——m==n++)?一一 m:++n;y=m++;z=n;

[1](A)5 (B)6(C)10 (D)7

[2](A)11 (B)6(C)9 (D)10

[3](A)5 (B)10(C)6 (D)7

20.若m、x、y、z均为 int 型变量,则执行下面语句后的 m 的值是 。m=1; x=2; y=3; z=4;m=(m<x)?m:x;m=(m<y)?m:y;m=(m<z)?m:z;

(A)1 (B)4(C)2 (D)321.若有说明语句:int w=1,x=2,y=3,z=4;则表达式 w>x?w:z>y?z:x 的值

是 。(A)4 (B)3(C)2 (D)122.设 a 和 b均为 int 型变量,且 a 值为 15,b 值为 240,则表达式(a&(B)&&b 的

结果为 [1] ,表达式(a&(B)&b‖b 的结果为 [2] 。[1](A)0 (B)1

(C)true (D)false[2](A)0 (B)1

(C)true (D)false

5.10.2填空题1.在 16 位 PC 机环境下,字符常量'a'在内存中应占 个字节,字符串"a"应占

个字节。2.在 16 位 PC 机环境卜,int 类型数据应占 个字节,short 类型数据应占 个字节,

long 类型数据应占 个字节,double 类型数据应占 个字节。3.在 16 位 PC 机环境下,short 类型数据的取值范围是 ,unsigned int 类型数据的取

值范围是 [2] 。4.若采用十进制数的表示方法,则 077是 ,0111是 ,0X29是 ,OXAB是 。5.若有说明 char sl='077',s2="\";则 s1 中包含 个字符,s2 中包含 个字符。6.设 x 为 float 型变量,设 y 为 double 型变量,设 a 为 int 型变量,设 b 为 long 型变量,

设 c 为 char 型变量,则表达式 x+y*a/x+b/y+c 的结果为 类型。7.设 a、c、x、y、z均为 int 型变量,请在下面对应的 上写出各表达式的结果。(1)a=(c=5,c+5,c/2); (2)x=(y=(2=6)十 2)/5;

Page 105: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

(3)18+(x=4)*3; 8.若有说明 int x=10,y=20;请在下面对应的 上写出各 printf 语句的输出结果。(1)printf("%3x\n",x+y); (2)printf("%30\n",x*y); (3)printf("%30\n",x%y,x,y); (4)printf("%30\n",(x%y,x-y,x+y)) 9.设有说明 int a=1234;请在下面对应的 上写出各 printf 语句的输出结果。(1)printf("%05d\n",(A); (2)printf("%-05d\n",(A); (3)printf("%05d\n",a++); (4)printf("%%05d\n",——(A) 10.设 a、b 为 int 型变量,x、y 为 float 型变量,c1、c2 为 char 型变量,且设 a=5,b=

10,x=3.5,y=10.8,c1='A',c2='B',为了得到以下的输出格式和结果,请写出对应的 printf 语句。

(1)a=5,b=10,x+y=14.3printf(" ", );

(2)x-y=-7.3 a-b=-5printf(" ", );

(3)cl='A'or 65(ASCII)c2='b'or 66(ASCII)printf(" ", );

11.若已有说明:int a=123;float b=456.78;double c=-123.45678;

请在以下各 printf 语句后的 上写出相应的输出结果(设在 16 位 PC 机环境下)。(1)printf("%.3f%.3e%.1f\n",b,b,(C); (2)printf("%08.3f%08.3e%g\n",b,b,(C); (3)printf("%u%一 10.3f%一 10.3e\n",a,b,(C); 12.若已有说明:int a;float b,x;char cl,c2;为使 a=3,b=6.5,x=12.6,c1='

a',c2='A',请写出适当的 scanf 函数调用语句及对应的数据输入。scanf(" ", );printf("a=%d,b=%.if,x=%.if,c1=%c,c2=%c\n

",a,b,x,cl,c2);从第一列开始输入数据: 。13.在 C 语言中,用 表示逻辑“真”值。14.若执行下面语句时,从第一列开始输入数据:1234 01234%67<回车>,则变量 a

的值为 ,b 的值为 ,s 的值为 ,c 的值为 。int a;float b,c;char s;scanf("%d%f%c%f\n",&a,&b,&s,&(C);

15.设 x、y、z均为 int 型变量且 x=3,y=-4,x=5,请在下面的 上写出各表达式的结果。

(1)x&&y)==(x‖z) (2)!(x>y)+(y!=z)‖(x+y)&&(y-z)

Page 106: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 5 章 基本数据类型和表达式

(3)x++一 y+(++z) 16.表达式 5&7 的值为 ,表达式 5|7 的值为 ,表达式 5^7 的值为 。17.请在相应的 上填入运行以下程序后各变量的值。

main(){ int a,b,c,d,e,f,g;

int i=1,j=3,k=0;a!k;b=i!=j;printf("c=%d,b=%d\n",a,(B);c=k&&j;d=k‖j;printf("c=%d,d=%d\n",c,(D);e=i&j;f=i|j;g=i^j;printf("e=%d,f=%d,g=%d\n",e,f,g);}

a= b= c= d= e= f= g= h=

Page 107: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 6 章 简单的 C 语言程序设计

第 6 章 简单的 C 语言程序设计6.1 语句概述

6.1.1 控制语句6.1.2 函数调用语句6.1.3 表达式语句6.1.4 空语句

6.2 数据输出6.2.1 字符输出函数 putchar6.2.2 格式输出函数 printf

6.3 数据输入6.3.1 字符输入函数 getchar()6.3.2 格式输入函数 scanf

6.4 例题详解6.5 本章小结6.6 练习题

第 6 章 简单的 C 语言程序设计6.1 语句概述

和其他高级语言一样,C 语言的语句用来向计算机发出操作指令,一个语句编译后可产生若干条机器指令。在 C 语言中所有语句都是“可执行语句”,没有非执行语句。

C 语言中的语句分为简单句和复合句两大类,简单句由分号(;)结尾,表示一个语句的终结,复合句用一对花括号({ })进行组合(相当 PASCAL 中的 begin...end),在语法上相当一个简单语句。例如:

if(d=b*b-4*a*c>=0){ x1=(-b+SQRT(d))/(2*a);

x2=(-b-SQRT(d))/(2*a);}

else{ x1=(-b+SQRT(-d))/(2*a);

x2=(-b-SQRT(-d))/(2*a);}

注意,复合语句中所组合的最后一个语句的分号(;)不能省略。6.1.1 控制语句

控制语句用来完成一定的控制功能,它改变了程序中语句一步接一步执行的次序,C语言中共有九种控制语句。

(1)if( )~else~ 条件语句(2)for( )~ 循环语句之一(3)while( )~ 循环语句之二

Page 108: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 6 章 简单的 C 语言程序设计

(4)do~while( ) 循环语句之三(5)continue 结束本次循环语句(6)break 中止执行 switch 或循环语句(7)switch 多分支选择语句(8)goto 转向语句(9)return 返回语句(从函数返回)上面九种语句中的( )是一个条件,"~"表示内嵌的语句。例如"for( )~",

具体可表示为"for(s=0;i<=100;i++)s=s+i"(计算 s=1+2+3+…+100 的循环语句)。6.1.2 函数调用语句由一个函数调用加上一个分号(;)组成的语句,例如:

printf("How do you do?\n");6.1.3 表达式语句由表达式加一个分号(;)构成的语句,最典型的是由赋值表达式构成的赋值语句。

例如 a=5+6是一个赋值表达式,而 a=5十 6;是一个赋值语句,可见分号(;)是语句中不可缺少的一部分,而不仅仅是个分隔符!(这与 PASCAL 语言不同)。例如:

i=i+l 是表达式(赋值表达式)i=i+l; 是表达式与分号构成的赋值语句i++; 是语句(相当于 i=i+1)x+y; 是语句(但是不把 x+y 值赋于一个变量,因此它并无实际意义)

6.1.4 空语句单独由分号(;)构成的语句称为空语句,例如:;

它什么动作也不执行,有时用来作为一个转向点,或循环语句中的循环体(空循环)。6.2 数据输出

C 语言本身不提供输入/输出语句,它由函数来实现。C 语言标准函数库中提供 printf 和scanf 函数,在程序中可以直接使用。

本节中介绍两个最基本的输出函数——字符输出函数和格式输出函数,它们都以终端(系统隐含的输出设备)为对象进行输出。6.2.1 字符输出函数 putchar

putchar(c);用以输出字符 c 的值,c可以是字符变量也可以是整型变量(其值是ASCII 码),在使用标准 I/O(输出/输出)函数时,应该用预编译命令"#include<stdio.h>",把 stdio.h 文件包括到源程序中(但只有 printf 和 scanf两个函数例外,可以不用)。以下两种写法是等效的,

#include"stdio.H"#include<stdio.H>

Page 109: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 6 章 简单的 C 语言程序设计

例 6-1 #inclue<stdio.h>main(){ char a,b,c;

a='W';b='T';c='O';putch(a);putch(b); putch(c); }摈程序运行结果为:WTO。如果在最后三个语句的左边都加上控制符输出,例如 putch('\

n');那么本例输出为:WTO 当然,也可以输出其他转义字符。

例如:putch('\103'); /*输出八进制 103 对应字符'c'*/putch('\'); /*输出单引号'*/putch('\015'); /*输出八进制 015,即光标移到行首*/putch(65); /*输出英文字母'A'*/

6.2.2 格式输出函数 printf

1.格式。printf是 C 语言中最常用的输出函数,其作用是向终端输出若干个任意类型的数据(putch仅能输出一个字符)。

printf 的调用格式是:printf("控制字符串",参数 1,参数 2,…,参数 n);

其中,每个参数代表一个输出数据,可以是常量、变量或表达式(输出它们的值)。控制字符串用于描述变量的输出方式,其形式为%附加格式说明符、格式转换符(附加格式说明符^可以省略),它包括两类,一类是按原样输出的字符;另一类是格式说明,用于描述输出数据的显示方式,以%号开头(若输出%本身;应在%号前加一个%号,即两个%号连写)。

例 6-2printf("%f%f",a,b)printf("a=%d b=%d",a,b)

若 a=2.1、b=5.0,则上式输出 2.15.0,下式输出 a=2.1 b=5.0。2.格式说明。(1)d 格式(输出十进制整数);%d——按数据实际长度输出;%md m——是指定的输出字段宽度,若实际数据位数<m,则数据左端补空格,

若实际数据位数>m,按实际位数输出;%ld——输出长整型数据,也可在 1之前再加上 m。

例 6-3 若 a=123,b=12345,c(1ong 类型)=123456,则:printf("%4d,%4d",a,b);

输出:□123,12345printf("%ld,%9ld",c,c);

输出:123456,□□□123456:(注意,c是 long 类型,不能用%d 格式输出。)

Page 110: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 6 章 简单的 C 语言程序设计

(2)o 格式(输出八进制整数)。把内存单元(连同符号位)一起按八进制形式输出,因此,不会输出负号,例如-l在内存中以补码存放,二个字节中值为

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1因此若

a=-1;printf("%d,%O",a,a);

输出:-1,177777

同 d 格式符一样,有%o,%mo,%lo等形式。(3)x 格式(输出十六进制整数)。类似 o 格式,也有%x,%mx,%lx 形式,不会输

出负值。例如 a=-l,则:

printf("%x,%O,%d",a,a,a);输出:

FFFF,177777,-1(4)u 格式(以十进制形式输出 unsigned 数据类型)。例 6-4main(){ unsigned a=65535;

int b=-13printf("a=%d,%o,%x,%u\n",x,x,x,x);printf("b=%d,%o,%x,%u\n",y,y,y,y);

}a=65535 存储单元中存放二进制为:

1111111111111111b=-13 存储单元中存放-13补码:

1111111111101011因此运行结果为:x=-1,177777,FFFF,65535y=-13,177753,FFEB,65515

(5)C 格式(用以输出一个字符,其范围 ASCII 码在 0~255之间)。例 6-5main(){ char c='A';int d=97;

printf("%c,%d\n",c,c);printf("%c,%d\n",d,d);}该程序输出

A,65a,97

(6)s 格式(用于输出字符串)。%s——按原样输出字符串。例:printf("%s","China");

输出:China(注意,不输出双引号);

%ms——当字符串长度大于 m 时,按实际长度输出,否则左边补空格;

Page 111: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 6 章 简单的 C 语言程序设计

%-ms——同上,但当字符串长度小于 m 时右边补空格;%m.ns——输出 m列,但只取字符串左边的 n 个字符,左边补空格;%-m.ns——同上,但 n 个字符右边补空格。例 6-6main(){printf("%2s,%6.4s,%3.4s,%-5.3s\n",

"Hello","Hello","Hello","Hello");}输出显示为:

Hello,□□Hell,Hello,Hel□□第一个字符串输出时突破场宽 3,第三个字串输出时,因为 m<n,自动使 m=n=4后

再输出。(7)f 格式(以小数点形式输出实数)。%f——不指定宽度时,由系统自动确定,整数部分全部输出,小数部分输出 6 位,但

有效数位单精度时为 7 位,双精度时为 16 位。例 6-7main(){ float a,b;

double x,y;a=333333.333;b=111111.111;x=2222222222222.222222;y=5555555555555.555555;printf("%f\n,%f\n",a+b,x+y);}输出显示:

444444.428125(仅前 7 位有效)7777777777777.777010(仅前 16 位有效)

%m.nf——指定输出共 m列,小数 n 位,若数值长度小于 m左端补空格。%一 m.nf——同上,输出数据长度小于 m 时右端补空格。例 6-8main(){ float x=2314.758;

printf("%f\n%9f\n%9.3f\n%.2f\n%-9.2f\n",x,x,x,x,x);

}运行结果为:2314.757994 (实数存放有一定误差)123.455994 (共输出 10 位)□□2314.758 (小数两位,前补 4 个空格)2314.75 (未指定 m,按实际位数输出,但小数为两位)2314.75□□□ (同 10.2f 格式,但右补空格)

(8)e 格式(以指数形式输出实数)。%e——数值按规定格式数形式输出(即小数点前有一位非零数字),系统自动确定6

位小数部分和 5 位阶码部分(其中 e 本身占一位,阶符一位,阶三位,例如 e+003)。例如:123.456 用%e 输出为:1.234560e+002。

Page 112: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 6 章 简单的 C 语言程序设计

%m.ne%-m.nem 为总列数,n 为小数点后位数。例 6-9main(){ float x=1234.56;

printf("%e\n%10e\n%10.2e\n%.2e\n%一 10.2e\n",x,x,x,x,x);}该例程序显示:

1.234560e+003 (系统自动确定 6 位小数,5 位阶码)1.234560e+003 (自动使 n=6,突破场宽 10)□□□1.23e+002 (共 10列,小数 2 位,左补空格)1. 23e+002 (未给出 m,按实际长度计)1.23e+002□□□ (共 10列,小数 2 位,右补空格)(9)g 格式(输出实数,系统自动选用 e 或 f 格式且不输出无意义的 0)。系统自动在

e 和 f 格式中选择输出宽度小的一种方式。例 6-10main(){ float x=1234.56;

printf("%f\n%e\n%g\n",x,x,x);}输出为:

1234.560001.234560e+0031234.56

printf 函数常用的格式转换字符见表 6-1,附加格式说明符见表 6-2。表 6-1 printf 的格式转换字符

格式 说明%d

%o

%x

格式

带符号的十进制整数输出(正数不输出+号)以八进制形式输出整数(无符号,不输出前缀)以十六进制形式输出整数(无符号,不输出前缀)

说明%u

%c

%s

%f

%e

%g

以无符号十进制形式输出整数以字符形式输出一个字符

输出字符串以小数形式输出单、双精度实数(小数部分6位)以标准指数形式(6位小数5位阶码)输出单双精度数在%f 或%e 中自动输出较短的格式,且不输出无意义的0

表 6-2 printf 附加格式说明格式 说明

l

m(正整数)n(正整数)

用于输出长整型数据可以在前面指定数据最小域宽

对实数表示小数位个数,对字符串为截取字符数目

Page 113: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 6 章 简单的 C 语言程序设计

- 数据在输出域内向左对齐排放

6.3 数据输入6.3.1 字符输入函数 getchar()该函数没有参数表,表示从键盘(或系统隐含的标准输入设备)输入一个字符,使用

此函数前应采用"include<stdio.H>",因为该函数要用到标准I/O库的信息。例 6-11#include<stdio.h>main(){ char c;

c=getchar();putchar(c);}在从键盘输入时,键入 S↙,此时把字母'S'送给了变量 c,并把它的值('S')显

示在屏幕上。注意;getchar()值也可以不赋给任意变量而直接输出。例如:printf("%c

",getchar())。6.3.2 格式输入函数 scanf

格式输入函数常用来从键盘输入数据,其调用格式为:scanf("控制字符串",参数 1,参数 2,…,参数 n);

格式字符串与 printf 函数类似,其格式转换字符见表 6-3,附加格式说明符见表 6-4。表 6-3 scanf 格式转换字符

格式转换字符 说明d

o

x

c

s

f

输入十进制整数输入八进制整数

输入十六进制整数输入单个字符

输入字符串输入实数(小数或指数形式)

表 6-4 scanf 附加格式说明符附加格式说明符 说明

l

h

正整数*

输入长整型数据及 double 实型数据输入短整型数据

指定输入数据宽度读入后不赋给相应变量

注意;格式转换字符和附加格式说明符只能用小写字母(如%d而不能写成%D),参数部分的每个参数若为数值变量和字符变量,要在变量名前加上“&”(地址运算符),而对字符数组不必加“&”。下面举例说明 scanf 函数调用方法。

1.scanf 中没有%u 格式符,对无符号数据以%d、%o 或%x 格式进行输入。

Page 114: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 6 章 简单的 C 语言程序设计

2.指定 m后,系统按照m 自动截取所需数据。例 6-12 scanf("%4d%2d%3d",&x,&y,&z);当输入序列 1234567890↙时,执行结果为变量 x=1234,变量 y=56,变量 z=789,输

入的最后一个0被丢掉,因为参数表中再没有参数与其对应。3.%*表示跳过相应数据。例 6-13 scanf("%2d,%*3d,%2d",&x,&y),当输入 12,345,67↙时,把 12 赋于 x,67 赋于 y,跳过 345,注意,此例中因为 scanf

格式中用“,”分隔,因此输入数据时也该用“,”隔开。4.输入时不能规定精度,例如,scanf("%7.2f",&a),是不合法的。5.用"%c"输入字符时,空格和转义字符均为有效字符输入。例如:scanf("%c%c%c",&cl,&c2,&c3);当输入:a□b□c 时,将'a'赋

给 c1,'□'赋给 c2,'b'赋给 c3。6.若“格式字符串”中除格式说明外,还有其他字符时,则输入时应该输入与这些字

符相同的字符,例如 scanf("%d,%d",%x,%y);在输入时应输入 12,63↙,而不应该输入 12□63↙。

7.输入数据时遇到下列情况之一时,认为数据输入结束。(1)空格、回车、跳格(Tab)。(2)遇到宽度满足时,例如"%4d",只取 4列。(3)遇到非法输入。例 6-14 scanf("%d%c%f",&x,&y,&z);当输入 98765a67O.34↙(其中把数字 0 错打为英文字母O),则把 98765 赋给 x,'a

'赋给 y,34 赋给 z。6.4 例题详解

例 6-15 从键盘输入一个英文小写字母,输出相应的大写字母。分析:英文大写字母与英文小写字母,在ASCII 码表上位置差 32,即'A'的 ASCII

码为 65,'a'的 ASCII 码为 97,因此只要把输入小写字母减去 32就可以变为大写字母,因为 C 语言中一个字符和它的 ASCII 码是自由转换的,不需要专用的转换函数,所以直接用 C2=C1-32;就可以把小写字母 C1 变成大写字母 C2。

程序:#include"stdio.h" /*程序中用的 getchar 应加这一行*/main()

{ char cl,c2; c1=getchar(); /*等待用户输入字符*/printf("%c,%d\n",c1,c1);c2=c1-32;printf("%c,%d\n",c2,c2);}运行情况:

m↙m,109M,77

例 6-16 写出下面程序输出结果。main()

Page 115: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 6 章 简单的 C 语言程序设计

{ int a=4,b=7,c=-5float x=12.3456,y=-246.135;char ch='B'; long n=7654321;unsigned u=65535;printf("%d%d%d\n",a,b,c);printf("%3d%3d%3d\n",a,b,c);printf("%f,%f\n",x,y);printf("%8.2f,%8.2f,%4f,%4f\n,%3f,%3f\n",

x,y,x,y,x,y);printf("%e,%10.2e\n",x,y);printf("%c,%d,%o,%x\n",ch,ch,ch,ch);printf("%ld,%lo,%1x\n",n,n,n);printf("%u,%o,%x,%d\n",u,u,u,u);printf("%s,%7.5s\n","Over!","Thanks");}运行情况:

本例表示 printf 中各种格式符的使用方法,其运行结果是:47-5

4 7 -512.345602,-246.135013

12.34, -246.13,12.345601,-246.13501212.345602,-246.1350111.23450e+01,-2.46e+02 B,66,102,427654321,35145661,74cbbl65535,177777,ffff,-lOver!, Thank

例 6-17 用 scanf("%4d%4d%c%c%f%f%*f%f",&a,&b,&chl,&ch2,&x,&y,&z);输入数据,使 a=22,b=44,ch1='A',ch2='z',x=2.24,y=-4.5,z=12.3。请问在键盘上如何输入?

分析:按照 scanf 格式控制符可以确定各个变量类型,在输入 a,b 值时,其格式为%4d,因此必须补足 4 位,即左边加空格,对于%*f是用来禁止赋值的,因此可以任意打入一个实数(例如 3.14),该值不会赋给任意变量。

程序:main()

( int a,b;float x,y,z;char ch1,ch2;scanf("%4d%4d%c%c%f%f%*f%f,&a,&b,&ch1,&ch2,&x,

&y,&z);}运行时应输入:

□□22□□44Az2.24 -3.7 3.14 67.8↙例 6-18 设圆柱底面半径为 R,圆柱高为 H,求圆柱表面积和体积。分析:圆柱体积为底面积×高,即 πR2H,表面积为 2πR2+2πRH,其中 π可以定义为常

Page 116: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 6 章 简单的 C 语言程序设计

量 PI=3.14159(注意,程序中不能出现希腊字母 π 本身),圆底半径 R 和圆柱高 H可作为变量(用小写字母)表示,并在程序运行时由用户输入,其类型可为实型,计算出来的圆柱表面积和体积可用 S 和 V两个变量分别表示。

程序:#define PI 3.14159main()

{ float r,h,s,v;printf("input r,h please:\n");scanf("%f,%f",&r,&h);s=2*PI*r*(r+h);v=PI*r*r*h;printf("S=%.2f\n",s);printf("V=%.2f\n",v);}运行情况:

input r,h please::1.5,3↙S=42.41V=7.07例 6-19 分析下列程序中 printf 语句输出结果。#include<stdio.h> /*该句可省略*/main()

{ int a=2,b=4,c=6;a+=b+=c; /*第一句*/printf("%d\n",a<b?b:a); /*第二句*/printf("%d\n",a<b?a++:b++); /*第三句*/printf("%d,%d\n",a,b); /*第四句*/printf("%d\n",c+=a>b?a++:b++); /*第五句*/printf("%d,%d\n",b,c); /*第六句*/a=5;b=c=7;printf("%d\n",(c>=b&&b==a)?l:0); /*第七句*/printf("%d\n",c>=b&&b>=a); /*第八句*/}分析:

(1)该句先进行 b=b+c=4+6=10,再进行 a=a+b=2+10=12;因此该行执行后 a=12,b=10,c=6;

(2)因为 a<b 为假,因此输出 a 的值为 12;(3)同理先输出 b 值为 10,再进行 b++使 b=11(a 不自加);(4)输出 a 和 b 值,即输出 12,11;(5)先进行 a>b?a++:b++,因此取 b++,再进行 c+=b即 c=c+b=6+11=

17,最后进行 b++运算,使 b=12,因此此句输出 c 的值为 17;(6)输出 b 和 c 的值,因此输出 12,17;(7)上一句重新赋值 a=5,b=c=7,该句 c>=b 为真,b==a 为假,进行&&运算

结果为假,根据条件语句,输出0;(8)该句 c>=b 为真,b>=a也为真,&&运算结果为真,因此输出 1。例 6-20 分析下列程序运行结果。

Page 117: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 6 章 简单的 C 语言程序设计

main(){ int a=3,b=7,x,y;

x=a++*a++*a++;y=-–b*--b*--b;printf("a=%d,x=%d\n",a,x);printf("b=%d,y=%d\n",b,y);}分析:

(1)x=a++*a++*a++为后缀形式,先取 x 值为三个 a相乘,再对 a 自加三次,因此第一个打印语句显示:a=6,x=81。

(2)y=——b*――b*――b 为前缀形式,先对 b 自减三次,然后求 y 值,因此第二个打印语句显示:b=4,y=64。

6.5 本章小结本章先介绍了 C 语言中语句的概念,每个语句必须用分号(;)结束,C 语言中有九

种控制语句(实现分支、循环、转向等功能)在程序中得到广泛使用,表达式和表达式语句是有差别的,请不要混淆。

本章然后介绍了数据输出函数 putchar 和 printf,重点在格式输出函数 printf,这是程序中最常用的输出函数,几乎每一个程序都离不开它。读者应该熟练掌握控制字符串的含义,例如%d、%f、%c 的使用,表 3-1 和表 3-2是 printf 格式符的小结。

本章还介绍了数据输入函数 getchar 和 scanf,重点也在格式输入函数 scanf 上,它用来从键盘输入数据,格式符类似 printf 中格式符,但没有%u、%e 和%g,也不能使用 m、n 格式。请注意%*f 的使用,它跳过所读入的一个实数,最为重要的是当输入数值和字符时,变量必须是存储单元的地址,即变量名前加上'&',否则就会出错。

本章最后提供的 6 个实例,描述了一般的 C 程序结构。6.6 练习题

6.6.1选择题1.设 m均为 float 型变量,则执行以下语句后的输出为 。

m=1234.123;printf("%-8.3f\n",m);printf("%10.3f\n",m);

(A)1234.123 (B)1234.123 1234.123 1234.123(C)1234.123 (D)-1234.123001234.123 1234.12300

2.若 n 为 int 型变量,则执行语句后的输出为 。n=32767;printf("%o10d\n",n);printf("%10d\n",n);

(A)0000032767 (B)3276732767 0000032767

Page 118: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 6 章 简单的 C 语言程序设计

(C)32767 (D)输出格式描述不合法32767 32767

3.若 x 为 unsigned int 型变量,则执行语句后的 x 值 。x=65535;printf("%d\n",x);

(A)65535 (B)1(C)无定值 (D)-14.若 x 为 char 型变量,则执行以下语句后的输出为 。

X='l';printf("%3c\n",x);printf("%2c%2c\n",x,x);printf("%1c%4c\n",x,x,x);

(A)l (B) 1 1 l 1 l 1 l l 1 (C)1 (D) l

l 1 l 1l l 1 l

5.若 x 为 int 型变量,则执行语句后的输出为 。x=0xdef;printf("%4d\n",x);printf("%4o\n",x);printf("%4x\n",x);

(A)3567 (B)35676757 6567def def(C)3567 (D)356706757 67670xdef 0def

6.若 x、y均为 int 型变量,则执行语句后的输出结果为 。x=015;y=0xl5;printf("%4o%4x\n",x,y);printf("%4x%4d\n",x,y);printf("%4d%4o\n",x,y);

(A)015015 (B)1515d 2l d2113 15 1325(C)0150x15 (D)15 15

0x15 21 d 2113 25 13 25

7.若 x、y、z均为 int 型变量,则执行以下语句后的输出结果为 。y=(x=10,x+5,z=l0);printf("x=%d,y=%d,z=%d\n",x,y,z);z=(x=10,y=5,x+y);printf("x=%d,y=%d,z=%d\n",x,y,z);

(A)x=10,y=15,z=10 (B)x=10,y=10,z=10x=10,y=5,z=10 x=10,y=5,z=10

Page 119: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 6 章 简单的 C 语言程序设计

(C)x=10,y=10,z=10 (D)x=10,y=10,z=10x=10,y=5,z=15 x=10,y=5,z=5

8.若 x、y、z均为 int 型变量,则执行语句后的输出结果为 。x=(y=(z=10)+5)-5;printf("x=%d,y=%d,z=%d\n",x,y,z);y=(x=z=0,x+10);printf("x=%d,y=%d,z=%d\n",x,y,z);

(A)x=10,y=15,z=10 (B)x=10,y=10,z=10x=0, y=10,z=0 x=0,y=10,z=0

(C)x=10,y=15,z=10 (D)x=10,y=10,z=10x=10,y=10,z=0 x=0,y=10,z=0

9.若 d1、d2、d3、d4均为 char 型变量,则执行以下语句后的输出结果为 。d1='1'; d2='2';d3='3'; d4='4';printf("%1c\n",d1);print{("%2c\n",d2);print{("%3c\n",d3);print{("%4c\n",d4);

(A)1 (B)1 2 2 3 3 4 4(C)1 (D)输出格式描述不合法 02 003 0004

10.若w、x、z均为 int 型变量,则执行以下语句后的输出结果为 。w=3;z=7;x=10;printf("%d\n",x>lO?x+100:0);printf("%d\n",w++‖z++),printf("%d\n",!w>z);printf("%d\n",w&&z);

(A)0 (B)1 l 1 l 1 1 l(C)0 (D)0 1 1 0 0 1 0

11.执行语句 printf("The promgram’s name is c:\\tools\book.txt");后的输出是 。(A)The promgam’s name is c:tools book.txt(B)The promgam’s name is c:\tools book.txt(C)The promgam’s name is c:\\tools book.txt(D)The promgam’s name is c:\toolook.txt12.若 x是 int 型变量,y是 float 型变量,所用的 scanf 调用格式为:scanf("x

=%d,y=%f",&x,&y)则为了将数据 10 和 66.6 分别赋给 x 和 y,正确的输入为 。

Page 120: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 6 章 简单的 C 语言程序设计

(A)x=10,y=66.6(回车) (B)10 66.6(回车)(C)10()66.6(回车) (D)x=10(回车)y=66.613.若w、x、y、z均为 int 型变量,则为了使以下语句的输出:1234+123+12+1,正确的

输入为 。scanf("%4d+%3d+%2d+%1d",&x,&y,&z,&w);printf("%4d+%3d+%2d+%ld:,x,y,x,w);

(A)1234123121(回车) (B)1234123412341234<回车>(C)1234+1234+1234+1234<回车> (D)1234+123+12+1<回车>14.若 x、y均为 int 型变量,z 为 double 型变量,则以下不合法的 scanf 函数调用为 。(A)scanf("%d,%1x,%1e",&x,&y,&z)(B)scanf("%2d*%d%1f", &x,&y,&z)(C)scanf("%x%*d%o",&x,&y,&z)(D)scanf("%x%o%6.2f,&x,&y,&z)15.设 a、b均是 int 型变量,则以下不正确的 scnaf 函数调用为 。(A)getchar()(B)putchar('\108')(C)scanf("%d%*2d",&a,&(B);(D)putchar('\")16.若有变量定义:int x;float y; char z[10];且执行语句 scanf("%3d%f%3s",

&x,&y,z);时,从第一列开始输入以下数据:12345 123%<回车>

则 x 的值为 [1] ,y 的值为 [2] ,z 的值为 [3] 。[1](A)12345 (B)123

(C)345 (D)45[2](A)无定值 (B)45.0

(C)45 (D)123.0[3](A) (B)123(C)123% (D)无定值17.执行下面语句段后的 x 值为 。

int a=14,b=15,x;char c='A';x=((a&(B)&&(c<'A'==;

(A)TRUE (B)FALSE(C)0 (D)118.下列程序正确的运行结果为 。

#include(stdiO.h)main()

{ printf("%d\t",NULL);}(A)1 (B)0

(C)一 1 (D)不确定值(因变量无定义)19.下列程序正确的运行结果是 。

#include<stdio.H>#include<math.H>main()

Page 121: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 6 章 简单的 C 语言程序设计

{ int a=1,b=4,c=2;float x=5.5,y=9.0,z;z=(a+(B)/c+sqrt((double)y)*1.2/c+x;printf("%f\n",z); }(A)9.800000 (B)9.300000

(C)8.500000 (D)8.000000

6.6.2填空题1.在 C 语言中,&作为双目运算符时表示的是 ,而作为单目运算符时表示的是 。2.设 x、y 和 z均为 int 型变量,请用 C 语言描述下列各题。(1)x 和 y 中有一个小于 z (2)x、y 和 z 中有两个是负数值 (3)y是奇数值 3.若已说明 x、y、z均为 int 型变量,请在以下 上写出各 printf 语句的输出结果。(1)x=y=z=0;

++x‖++y&&z;phntf("x=%d\t y=%d\t z=%d\n",x,y,z);

(2)x=y=z=-1;++x&&++y&&++z;printf("x=%d\t y=%d\t z=%d\n",x,y,z);

(3)x=y=z=-1;x++&&--y&&++z--‖--x;printf("x=%d\t y=%d\t z=%d\n",x,y,z);

4.设 a=3,b=4,c=5,请在以下 上写出各逻辑表达式的值。(1)a‖b+c&&b==c (2)!(x=(A)&&(y=(B)&&0 (3)!(a+(B)+c-1&&b+c/2 5.若有说明语句:int x=1,y=0,请在以下 上写出各表达式的结果。(1)(x<=y++)?'a':'A'==x++ (2)x-->(y+x)?10:12.5>y++?'A':'Z' (3)++x*--x==y?12%5:'x'

Page 122: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 6 章 简单的 C 语言程序设计

Page 123: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 7 章 分支结构

第 7 章 分支结构7.1 分支程序设计

7.1.1 if 语句7.1.2 if 语句嵌套7.1.3 条件运算符的作用

7.2 Switch 语句7.3 goto 语句7.4 例题详解7.5 本章小结7.6 练习题

第 7 章 分支结构7.1 分支程序设计

程序通常是按语句的编写顺序依次执行的,但是如果程序要完成各种复杂的计算问题,仅仅按顺序来执行程序就不太方便了。C 语言提供了改变执行顺序的语句,本章介绍分支语句。

分支程序往往需要一个关系表达式或者逻辑表达式作为判决的条件。根据其值是真还是假来决定执行相应的语句。

7.1.1 if 语句if 语句在 C 语言里有两种基本形式:(1)if (条件) 语句; (2)if (条件) 语句 1;

else 语句 2;无论是哪种形式的 if 语句,都要首先判断( )内表达式的值,若为真(不为 0),执

行( )后的语句(第(2)种形式为语句 1);若为假(为 0)则执行( )后面语句之后的语句(第(2)种形式为 else后的语句 2)。图 7-1 为这两种形式的程序框图。

条件

语句

F

T

条件

语句 1

F

T

语句 2

Page 124: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 7 章 分支结构

图 7-1 两种 if 语句的程序框图注意,这两种形式 if后的“条件”大多是逻辑表达式或关系表达式,根据是 0还是非

0执行“假”或“真”的处理。此外,语句之后一定有分号(;),它是语句的组成部分,不能省略(尤其是 else前的分号)。同时,若 if 和 else后有多个语句,可以用{ }形成复合语句。

例 7-1 输入两个实数,按代数值由小到大次序输出这两个数。main(){ float a,b,x;

printf("Please input a,b:\n");scanf("%f,%f”,&a,&b);if(a>b)

{ x=a;a=b;b=x;}printf("%f,%f\n",a,b);}

运行情况如下:4.5,2.8↙2.8,4.5

if 条件后面是复合语句,完成两个变量的交换,不能用 a=b,b=a;来进行交换,常用第三个变量来暂存变量值。

例 7-2 若上例改为由大到小次序。main(){ float a,b,x;

printf("Please input a,b:\n");scanf("%f,%f”,&a,&b);if(a<b)

{ x=a;a=b;b=x;}printf("%f,%f\n",a,b);

}运行情况如下:

4.5,2.8↙4.5,2.8

例 7-3 输入三个实数,求最大者,赋给变量 max。main(){ float a,b,c,max;

priintf("Please input a,b,c:\n");

Page 125: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 7 章 分支结构

scanf("%f,%f,%f",&a,&b,&c)max=a;if(b>max) max=b;if(c> max) max=c;prinf("%5.2f\n",max);}

运行情况如下:please input a,b,c;5.5,8,6.3↙max=8.00

本例使用两个个 if 语句,以依次比较出最大者。

7.1.2 if 语句嵌套一个 if 语句可以包含另一个或多个 if 语句称为语句配套,注意 e1se总是与它最近的一

个 if 配套,这一点与 Pascal 语言相同。if (条件)

if(条件) 语句 1else 语句 2

elseif(条件) 语句 3else 语句 4

请注意以下两个语句的差别:(1)if(条件 1)

if(条件 2) 语句 1else 语句 2

(2)if (条件 1){if (条件 2) 语句 1}

else 语句 2第(1)个语句中 else后面语句 2 与条件 2 有关,在条件 1成立的情况下,条件 2 不成

立就执行语句 2,当条件 1 不成立时,语句 1 及语句 2都不执行;第(2)个语句指条件 1和条件 2均成立时,执行语句 1,若条件 1 不成立就执行语句 2,即语句 2 的执行与否同条件 2无关。

例 7-4 以下程序输入一个 x 值,输出 y 值。

试判定下列程序段正确与否。(1)main()

{ int x,y;scanf("%d",&x);if(x<0) y=1

内嵌 if

内嵌 if

0 ( x=0 )y=1 ( x<0 )- 1 ( x>0 )

Page 126: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 7 章 分支结构

if(x=0) y=0if(x>0) y=-1printf("x=%d,y=%d\n",x,y);}

说明;该程序使用三个 if 语句,对 y 赋值,因为 x取值只能使三个证语句中的一个条件为真,因此 y只进行一次赋值,本程序是正确的。

(2)main(){int x,y;

scanf("%d",&x);y=1;if(x!=0)if(x>0) y=-1;else y=0;printf("x=%d,y=%d\n",x,y);}

说明:该程序中 if(x!=0)中内嵌一个 if(x>0)语句,当输入 x=0 时,y 值为 1,显然与原意不符,程序有错,如果花括号把 if(x>0)y=1;括起来,那么 else就与 if(x!=0)匹配,这样当 x=0 时执行 y=0;语句,程序就可以运行正确。

(3)main(){ int x,y;

scanf("%d",&x);y=0;if(x>=0)if(x>0) y=-1;else y=1;printf("x=%d,y=%d\n",x,y);}

说明:该程序当 x<0 时,输出 y=0,显示与原意不同,其原因与上述相同,为更正它,也只需用花括号把 if(x>0)y=1;括起来。

7.1.3 条件运算符的作用C 语言中 if(a<b) min=a;

else min=b;可简写为: min=(a<b)?a;b;条件运算符的功能曾在第二章提到,它需要三个操作时象,是 C 语言唯一的三目运算

符。下面进一步可以说明,(1)注意执行的顺序“el?e2:e3”中先执行表达式 e1,若为非零(真)求解表达式 e

2,并把 e2 值作为整个表达式的值;若 e1 值为零(假)求解表达式 e3,并把 e3 值作为整个表达式的值,在min=(a<b)?a:b;中把 a、b 中小的值赋于 min。

(2)条件运算符优先于赋值运算符,即先求解后赋值,但条件运算符优先级又低于关系运算符和算术运算符,因此min=(a<b)?a:b;中括号可以省略,写成min=a<b?a:b;

例如:

Page 127: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 7 章 分支结构

a>b?a:b+1相当于 a>b?a:(b+1);不相当于(a>b?a:b)+1(3)条件运算符是“自右向左”结合的。例如:若 a=1,b=3,c=5,d=7,那么:

a>b?a:c>d?c:d;相当于 a>b?a:(c>d?c:d);该语句执行后,表达式值为 7。 (4)条件表达式不能取代一般的 if 语句,只有 if 语句中内嵌语句为赋值语句且赋予同

一变量时才能取代。例如:if(x>y) printf("%d",a)else printf("%d",b);

不能用一个条件表达式替代,但可用以下语句代替:printf("%d",x>y?a:b);

(5)el、e2、e3 三个表达式类型可以不同,当 e2、e3 类型不同时自动进行类型转换。例如:

x>y?1.2:2若 x>y 表达式值为 1.2,否则为 2.0(整型→实型)。

7.2 Switch 语句if 语句只有两个分支供选择,当有多个分支时应该使用嵌套 if 语句,但嵌套层次一多

时,程序结构复杂,阅读和修改比较困难,C 语句中提供多分支选择语句 switch 语句来解决多分支选择问题。日常生活中,往往会遇到“分类”问题,例如学生成绩分类(90 分及以上为'A'等,

80~89 分为'B'等,70~79 分为'C'等,……)、人口统计分类(按年龄分为老年、中年、青年、少年,儿童……)、工资统计分类、银行存款分类等。这些问题可用 switch 语句来解决。

switch 语句的一般形式为:

switch 语句执行流程是:先计算“表达式”的值,然后顺序地与后面 case子句中列出的各个常量相比较,若表达式值等于常量 i则执行相应的“语句序列 i”,再执行 break 语句跳出 switch子句,若“表达式”值与 case子句后所有常量都不相等,且有 default子句,那么执行“语句序列 n+1,如果没有 default子句,则直接跳出 switch 语句。

使用 switch 语句应注意以下问题:(1)switch 语句和 if 语句不同,它只能判断一种逻辑关系,即表达式值是否等于指定

的常量,而 if 语句可以计算并判断各种表达式。(2)case子句后的常量可以是整型、字符型、枚举型数据或者是整型表达式,但不允

switch (表达式){ case 常量 1:语句系列 1; break; case 常量 2:语句系列 2; break;

case 常量 3:语句系列 3; break;default:语句系列 n+1;}

Page 128: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 7 章 分支结构

许是变量,即允许是与 switch后表达式类型一致的常量。(3)同一个 switch 中 case后的常量不能相同,但在相互嵌套的不同层次 switch之间

允许有相同的常量。(4)default子句可以省略。(5)case 和 defaulf后的“语句序列”允许由多个语句构成并且不必(也可)用花括号括起

来。(6)case 及 defaulf 语句出现的次序是任意的,可以变换位置,并不影响 switch功能。(7)多个 case可共用一组执行语句,例如:

case'A':case'B':case'C':prinf(">60\n");break;

当表达式值为'A'、'B'或'C'时都执行 printf 语句。(8)switch 语句中 break 语句作用是重要的,它保证语句序列执行结束后跳出 switch

语句,否则会执行下一个语句序列,当然最后一个语句后的 break可以省略。例如:switch(grade){ case'A':printf"90-100\n"};

case'B':printf("80-89\n");case'C':printf("70-89\n");case'D':printf("60—69\n");case'E':printf("<60\n");default:printf("error!!\n");

}当 grade='C'时,执行此 switch 语句,将输出:

70-7960-69<60error!!

因此在每个 case后都应该用 break跳出 switch 语句。

7.3 goto 语句goto 语句是无条件语句,转向带有标号的语句行去执行,所谓标号同变量一样,用标

识符来表示,只是其后加有冒号(:)而已,标号加到 goto 语句转去执行的语句前面。goto 语句一般形式是:

goto 标号;使用 goto 语句应该注意三个问题:(1)goto 语句中有标号的必须是本函数段内已存在的合法标号。(2)不能从 switch 或循环体外面转移到循环体或 switch 语句中。(3)goto 语句仅在函数内有效,不能在不同函数之间使用 goto 语句。

例如:用 if 及 goto 语句计算

100

1n

n。

Page 129: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 7 章 分支结构

main( ){ int i,sum=0;

i=1;loop:if(i<=100)

{ sum=sum+i;i++;goto loop;}printf("sum=%d",sum)

}运行结果:sum=5050。

7.4 例题详解例 7-5 给出一个不多于 3 位的正整数,要求:(1) 求出它是几位数;(2) (2)分别打印每一位数字;(3) (3)按逆序输出该数(例如原数为 421,输出为 124)。分析:假定 3 位数 n=n3n2n1,其中 i(i=1~3)为 n 中相应数位,即

n=n3×102+n2×101+n1×100

本题关键是如何从 n 中把 ni 分解出来,可以用整除的方法来解决此问题。例如:n3=n/100,n2=n/100-n3*10…,获得各个 ni后,n又可作为输入数据的位数标志

(n=1~3)。程序:

main(){ int n,n3,n2,n1;

printf("please input n:");scanf("%d",&n);n3=n/100;n2=n/10-n3*10;n1=n%10;

n=3;if(n3= =0)n=2;if((n3= =0)&&(n2= =0))n=1;printf("\n This number is%d digits \n",n);printf("This number’s digits are;\n");switch(n)

{ case 3:pintf("%d,%d,%d",n3,n2,n2);break;case 2:printf("%d,%d",n2,n1);break;case l:printf("%d",n1);}

printf("\n\nThis opposite order number is:\n”);printf("%d\n",n1*100+n2*10+n3);}

运行情况:please input n:248↙

Page 130: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 7 章 分支结构

This number is 3 digitsThis number's digits are:

2,4,8This opposite order number is 842

例 7-6 已知银行存款利率如下(年利率):

要求:输入存款本金和期限,求到期时能得到的利息和本金总计。分析:活期存款利息公式是:利息=本金×活期年利率×存款年限。定期存款利息公式

是:利息=本金×存款年限×定期年利率。计算出利息后再与本金相加为本利总计,我的可以定义本金为 meney,年利率为 rate,存取年限为 year,本利总计为 total。既可以用嵌套的 if 语句,也可用 switch 语句来完成上述功能。

程序 1:#include〈stdio.h〉main( )

{ float year,money,rate,totol;printf("Input money & year=?\n");scanf("%f,%f,&money,&year);if(year>=5)

rate=0.0541;else if(year>=3)

rate=0.0433;else if(year>=1)

rate=0.0392;else if(year>=0)

rate=0.023;else

rate=0;total=money+money*rate*year;printf("Total=%.2f\n",total);}

说明:为简化问题,认为超过年限部分的利息按照原年限计息而不是按活期计息。程序 2:

#include〈stdio.h〉main()

{ float year,money,rate,total;printf("Input money & year=?\n");scanf("%f,%f",&money,&year);if(year<=0)

rate=0;else swith((int)year)

年利率活期 2.3%

一年定期 3.92%

三年定期 4.33%

五年定期 5.41%

Page 131: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 7 章 分支结构

{ case 4:case 3:rate=0.0433;break;case 2:case 1:rate=0.0392;break;case 0:rate=0.023;break;default:rate=0.0541;}

total=money+money*rate*year;printf(”Total=%.2f\n",total);)

说明:(int)year强制把实型转变为整型,当(int)year 大于等于 5 时,均按 5年计算利率,程序中要用 default 实现。

例 7-7 输入两个整数及一个字符操作符+、-、*、/分别对两数进行相应运算。分析:根据输入的字符 ch 为'+'、'='、'*'、'/'时,分别计算,因此可以采用:

switch 语句。程序:

main(){ int a,b;char ch;printf("输人整数 a 和 b 及操作符 ch:\n");scanf("%d,%d,%c",&a,&b,&ch);switch(ch)

{ case'+':printf("%d+%d=%d\n",a,b,a+b);break;

case'-':prinf("%d-%d=%d\n",a,b,a-b);break;

case'*':printf("%d*%d=%d\n",a,b,a*b);break;

case'/':printf("%d/%d=%f\n",a,b,a/b);break:

}

7.5 本章小结本章介绍了选择控制语句 if 和 switch 语句,前后主要用于双分支的控制,可以通过 if

语句的嵌套来实现多分支问题,后者解决多分支问题。if 语句中的“条件表达式”用来决定程序的流向,当条件表达式为非零值(真)时执行

表达式后面的语句;当条件表达式为零值(假)时,执行 else后面的语句,并请注意语句最后一定有分号(即分号是语句的组成部分)。

switch 语句用于多个分支情况,表达式值往往是整型或者字符型,然后根据其值选择执行不同的语句,请特别注意 break 的使用,在执行完语句后应该用 break 语句退出 switch语句。

Page 132: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 7 章 分支结构

goto 语句是无条件转移语句,后跟语句标号,通常用 goto 语句转向后面的语句或退出循环,但尽量不用或少用 goto 语句,因为 goto 语句会影响程序的结构化,降低程序清晰度、可读性和可修改性。

7.6 练习题7.6.1选择题

1.判断 char 型变量 c1是否为小写字母的最简单且正确的表达式为 。(A)'a'<=cl<='z' (B)(c1>=(A)&&(c1<=2)(C)scanf("%d%*2d",&a,&B) (D)(c1>='a')&&(c1<= '2')2.若 a、b、c均为 int 型变量,则执行以下语句后的 a 值为 [1] ,b 值为 [2] 。

a=b=c=1;++a||++b&&++c;

[1](A)不正确 (B)0(C)2 (D)1

[2](A)1 (B)2(C)不正确 (D)0

3.若已知 w=1,x=2,y=3,z=4,a=5,b=6,则执行以下语句的 a 值为 [1] ,b 值为 [2] 。

(a=w>x)&&(b=y>z);[1](A)5 (B)0

(C)1 (D)2[2](A)6 (B)0

(C)1 (D)44.以下 为不合法的 if 语句。(A) if(x>y);(B) (B)if(x==y)x十=y;(C)if(x!=y)scanf("5b",&(C)else scanf("%d",&y);(D)if(x<y){x++;y++;}。5.C 语言对嵌套 if 语句的规定是:else总是与 配对。(A)其之前最近的 if (B)第一个 if(C)缩进位置相同的 if (D)其之前最近且不带 else 的 if6.若有说明 int x,yI则下面程序段 不能实现以下的函数关系:

(A)if(x<0)y=一 1; (B)y=一 1;else if(x==0) y=一 1 if(x!=0)else y=1: if(x>0) y=1;

else y=0;(C)y=0; (D)if(x)=0):

y=-1 (x<0)0 (x=0)1 (x>0)

Page 133: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 7 章 分支结构

if(x>=0) if(x>0)y=1;{if(x>0)y=1;} else y=0;

else y=一 1; else y=一 1;7.以下关于 switch 语句和 break 语句的描述中,只有 是正确的。(A)在 switch 语句中必须使用 break 语句。(B)break 语句只能用于 switch 语句。(C)在 switch 语句中,可以根据需要使用或不使用 break 语句。(D)break 语句是 swich 语句的一部分。8.设有说明语句:int a=1,b=0;则执行以下语句后,输出为 。

switch((A){ case l:

switch((B){ case 0:printf("**0**\n");break;

case l:printf("**1**\n");break;}

case 2:printf(”**2**\n”);break;}

(A)**0** (B)**0****2**

(C)**0** (D)有语法错误**1****2**

9.以下不正确的描述是 。(A)break 语句不能用于循环语句和 switch 语句外的任何其他语句。(B)在 switch 语句中使用 continue 语句和 break 的作用相同。(C)在循环语句中使用 continue 语句是为了结束本次循环,而不是终止整个循环的执

行。(D)在循环语句中使用 break 语句是为了使流程跳出循环体,提前结束循环。

7.6.2填空题1.阅读下面程序,将问题的答案填人对应的 中。

#include〈stdio.h〉main()

{ int a,b,m,n;scanf("%d%d,\n",&d,&(B);m=1;n=1;if(a>0)m=m+n;if(a<b)n=2*m;else if(a= =(B)n=5;else n=m+n;printf("m=%d n=%d\n",m,n);

Page 134: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 7 章 分支结构

}问题:(1)当输人为;-1 -2(回车),程序的运行结果 。(2)当输人为:10〈回车〉程序的运行结果为 。(3)为了输出 n=4,变量 a 和 b 应具备条件 。

Page 135: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 8 章 循环控制

第 8 章 循环控制8.1 while 语句8.2 do-while 语句8.3 for 语句

8.3.1 for 语句的一般格式8.3.2 条件表达式缺省的 for 语句8.3.3 条件表达式中包含逗号运算符的 for 语句

8.4 三种循环语句的比较8.5 break 语句和 continue 语句

8.5.1 break 语句8.5.2 Continue 语句

8.6 例题详解8.7 本章小结8.8 练习题

第 8 章 循环控制在许多问题中需要用到循环控制,例如要求 100 个数之和,计算全班各个学生的成绩

及其平均值等。循环结构是结构化程序设计的三种基本结构之一,它和顺序结构、选择结构共同作为各种复杂程序的基本构造单元。因此熟练掌握选择结构和循环结构的基本概念和使用技巧是程序设计的最基本的要求。 请考虑以下一个问题:要计算全班各个学生某门课程考试的平均成绩应如何做呢?假定

该班有 40 名学生,我们可以在程序中写 40 个 scanf 函数,从键盘上输入 40 个学生的成绩。实质上是重复 40 个同样的函数,如果你还能“忍受”的话,那么如果要统计全校 1000 名学生某门课程的成绩,难道你要在程序中写上 1000 个 scanf 函数吗?这种重复操作的现象,在计算机中称为“循环”,程序设计中采用“循环语句”来完

成该功能。在任何一种高级语言中都存在循环语句。我们将反复运行的那一部分程序称为循环的“循环体”。在 C 语言中有三种可以实现循环的语句:while 语句、for 语句和 do 一 while 语句。

8.1 while 语句while 语句的一般形式是:

Page 136: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 8 章 循环控制

while(表达式)语句while 语句的执行流程是先计算表达式的值,如果值非零(真),则循环控制条件成立,

执行 while 中的“语句”,然后再计算表达式的值,如果此值仍旧为非零(真)则仍旧执行 while 中的“语句”……,如此循环,直到表达式值为零(假),程序控制退出 while 语句。图 8-1是该语句执行的控制流程。

图 8-1 while 语句流程

例 8-1 计算

100

1n

n。

main( ){ int i,sum=0;

i=1; while(i<=100)

{ sum=sum+i; i++;} printf("sum=%d",sum) ;}

运行结果:5050

说明:(1)循环语句不止一个语句时应该用花括号括起来构成复合形式。本例中若不加花括

号,那么只对 sum=sum+i;一个语句循环;(2)i++是必要的,它可以逐步改变循环的表达式值。若无此语句 i 值不变,总是为 1

(<=100),会形成“无穷循环”(俗称“死循环”),这是不允许的。例 8-2 输出下列三角形乘法九九表。

* 1 2 3 4 5 6 7 8 91 12 2 43 3 6 94 4 8 12 165 5 10 15 20 256 6 12 18 24 30 367 7 14 21 28 35 42 498 8 16 24 32 40 48 56 649 9 18 27 36 45 54 63 72 81

表达式

语句

0

≠0

Page 137: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 8 章 循环控制

若用 i 表示行,j 表示列,则第 i 行输出 i 个值,在第 i 行第 j列上值为 i*j,为得到三角形九九表,只有在 j≤i 时才输出 i*j 值。

include〈stdio.h〉main( )

{ int i=1,j   /*i 为行计数,j 为列计数*/printf("%4c",'*');  /*打印标题行的*号*/while(i<=9)printf("%4d",i++);    /*打印标题行 1~9*/printf("\n");i=1;while(i<=9)

{ j=1;printf("%4d",i); /*输出最左列*/while(i<=i) /*嵌套的=重循环*/

{ printf("%4d",i*j);i++;}printf("\n");

i++;}

}说明:(1)本例有三个 while 循环,第一个循环是显示标题行上的 1、2、3…9,每个数

字占四列宽,然后用 printf("\n");进行换行;第二、三个循环构成二重循环,外循环控制行数,从第一行到第九行,一行打印完后用 printf("\n");换行,并用 i++进行计数。内循环打印 i*j 的值,直到 j>i 为止退出内循环,打印时采用"%4d"格式是为了按列对齐。

(2)在while(j<=i)的循环体中,j++用来进行列计数,循环体也可以改写“while(j<=i) printf("%4d",j++);”,读者从中可以看出 C 语言中“++”、“--”运算的特性。

8.2 do-while 语句do-while 语句的形式是:

do{语句}while(表达式);在 do-while 语句中,首先要执行一次 do后面的语句,然后判断条件表达式,其值不为

0,则再次执行 do后的语句,其值为 0则 do 语句终止执行。可见 do-while 语句和 while 语句的差别是:do-while 不论表达式值如何,先执行一次 do后面的语句,即先执行语句后判断条件;while 语句先判断条件再根据条件的真或假决定是否执行后面的语句,因此若吝一次判断时条件值为 0,则什么也不执行,退出 while 语句。

例 8-3 用 do-while 语句执行

100

1n

n。

main(){ int i=1,sum=0;

do{ sum+=i;i++;} while(i<=100);

Page 138: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 8 章 循环控制

printf("sum=%d",sum);}

例 8-4 输入一个正整数,以相反顺序输出,例如,输入 2468 输出 8642。main()

{ unsigned number;printf("Input a number:");scanf("%d",&number);do{ printf("%d",number%10); /*输出低位*/

mubmer/=10;} while(number!=0); /*原数缩小 10倍*/

printf("\n");}

运行情况:Input a number:8354↙4538

说明:本例中输入 0 输出也为 0。如果简单把此 do-while 语句改为 while 语句,那么当输人为 0 时,无法输出为 0,必须另行处理,可见 do-while 语句具有 while 语句不能完全替

代的作用。

8.3 for 语句高级语言中大多都有 for 语句,用它来控制循环次数事先已知的循环,但 C 语言中 for

语句功能更强、使用更灵活。

8.3.1 for 语句的一般格式for 语句的一般格式为:

for(表达式 1;表达式 2;表达式 3)语句;for 语句的工作流程如图 8-2所示。其工作流程也可用 while 语句来表达:

表达式 1;while(表达式 2)

{ 循环语句;表达式 3;}

执行表达式 1

表达式 2成立

语句

执行表达式 3

N

Y

Page 139: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 8 章 循环控制

图 8-2 for 语句工作流程例 8-5 输入 a、b两个整数,计算从 a到 b 的整数之积。

main(){ int a,b,mul;

printf("input a&b:");scanf("%d,%d",&d,&b);for(mul=1;a<=b;a++)

mul*=a; /*循环体*/printf("mul=%\n",mul);

}运行情况:

input a&b:6,9↙3024

说明:本例 for 语句的执行过程是,先使用赋值语句 mul=1,使存放积数的变量 mul 置成 1,接着判别 a<=b?,若成立则进行 mul=mul*a,利用 a++使 a 增 l,然后再次判别a<=b?,若成立,进行 mul=mul*a…,直到 a>b 为止(即 a<=b 为假)。

8.3.2 条件表达式缺省的 for 语句for 语句的三个表达式可以省略一个、两个甚至三个,但无论省略几项,两个分号决不

能缺少,在表达式 2 或者三个表达式均省略的情况下,for 语句将无限循环下去,因为表达式 2 不存在时,编译程序认为其值恒为真。

例 8-6 #include〈stdio.h〉main()

{ for(;;)putchar('c');

}该程序会不停地打印出字符'c'。该程序相当于:#include<stdio.h>

main(){ while(1)

putchar('c')'}

Page 140: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 8 章 循环控制

8.3.3 条件表达式中包含逗号运算符的 for 语句for 语句中的表达式 1 和表达式 3可以使用逗号运算符。例如:

for(i=0,j=20;i<j;i++,j--)其中"i=0,j=20"为表达式 1;"i++,j--"为表达式 2。这两个表达式均从左到右

运算,表达式的最终类型和值由右操作数的类型和值决定。

8.4 三种循环语句的比较C 语言中提供了三种循环语句;for、while 和 do-while。这三种语句各有特点:(1)三种循环可以用来处理同一问题,一般情况下它们可以互相代替。(2)while 和 do-while 循环,在while后面指定循环条件,在循环体内包含应反复执行

的语句,包括使循环趋于结束的语句(如 i++;或 i=i+1;等)。for 循环在表达式 3 中包含使循环趋于结束的语句,甚至可以将循环体中操作全部放入

表达式 3 中(用逗号运算符),因此凡能用 while 循环完成的,用 for 循环也能完成。(3)用 while 和 do-while 循环时,循环变量初始化操作应在while 和 do-while 语句之

前完成,而 for 语句在表达式 1 中实现循环变量初始化。(4)while 和 for 循环是先判断条件再执行语句,而 do-while 循环是先执行语句后判断

表达式。(5)循环语句可以嵌套,循环间可以并列,但不能交叉,多重循环时只能将控制(例

如 goto 语句)从内层循环转移到外层循环,不允许从外层循环直接转入到内层的循环体中。总之,使用循环语句时应充分考虑三个要素:① 循环初始条件的确定,这是循环的起点,它直接决定今后循环的结果。 ②必须安排好循环体中语句的次序,并且至少要有一条语句对循环结束条件产生影响,

否则会形成"死循环"(除非使用 break 语句等非常手段)。 ③选择适当的循环结束条件,使结束条件最终能够得到满足(除非用 break、goto 和 retu

rn 语句退出循环)。

8.5 break 语句和 continue 语句8.5.1 break 语句

break 语句的形式是:break;

break 语句是中止语句,可以从循环语句中跳出。在循环体中一遇到 break 语句,程序就无条件地从包含 break 语句的最小 while、do-while、for 和 switch 循环中跳出,break 语句不能用于循环语句和 switch 语句之外的任何其他语句中。

例 8-7main()

{ int i;

Page 141: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 8 章 循环控制

float area,pi;pi=3.14159;for(i=1;i<=20;i++)

{ area=pi*i*i;if(area>100)break;printf("%f,area);}

printf("End of programme")}

本例计算 i=1到 i=20 的圆面积,直到面积 area 大于 100 为止。当 area>100 时,退出循环,不再继续执行其余的循环。

例 8-8 编写程序判断 n是否为素数。main()

{ int i=1,n;printf("Input n:\n");scanf("%d",&n);while(++i<n)if(n%i= =0)

{ printf("not prime\n");break;}

if(i= =n)printf("prime\n");

}}

运行情况:Input n:240↙not prime

8.5.2 Continue 语句Continue 语句与 break 语句不同,它不跳出循环,而是结束循环体的本次循环,即跳过

尚未执行的语句,再进行下一次循环的判定。Continue(继续)语句常常作为 if 的执行语句,其一般形式为:

continue;例 8-9 打印数码 1到 20,但不打印 4 和 19。

main(){ int i=0;

while(++i<=l0){ if(i= =4||i= =19)continue;

printf("%d\n",i);}

Page 142: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 8 章 循环控制

}该程序当遇到 i=4 或 i=19 时不进行打印(跳过 printf),循环继续。例 8-10 输入 15 个整数,求其中负数的个数及平均值。

main( ){ int i,count,j,sum;

sum=count=0;for(i=1;i<=15;i++)

{ printf("Input integer;")scanf("%d",&j);if(j>=0)continue; /*正数和零结束本次循环*/

count++;sum+=i;}

if(count)printf("numer:%d,average value:%.2f",

count,1.0*sum/count);else

printf("No!");}

注意:此程序中用 1.0*sum/count来计算出平均值(实数),并且用"%.2"格式保证打印两位小数,从逻辑上讲改变 if 语句条件就可以不用 countinue 语句。

8.6 例题详解例 8-11 已知当前产值为 2亿元,年增产速度为 r(由键盘输入,例如 9%),计算产值

翻一番需要多少年?分析:设当前产值为 c=2亿元,下一年产值为 c1,即 c1=c*(1+r),再过一年为

c1=cl*(1+r)…,直到 cl>2*c 时打印出所需年份数 y,这里可用两个 for 语句的嵌套和 break 语句来完成。

程序:main( )

{ float c1,r,cint y;c=200000000.00 /*当前产值*/for(;;) /*无限循环*/

{ y=0;print{("年增长率 r=\n");scanf{("%f,&d);if(r<=0.0)break; /*退出整个程序*/c1=c;for(; ;) /*内嵌的 for 语句*/

{ c1*=(1+r);y++;

Page 143: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 8 章 循环控制

if(cl>2*c)break;}

print{("r=%f\t years=%d\n",r,y);}

}

例 8-12 用

71

51

311

4

…公式求取 π 的近似值,直到最后一项绝对值小于 10-4

为止。分析:本例涉及到绝对值,我们可采用绝对值函数 fabs(x),求|x|(见下一章),此

外每一项的符号是正负交替的,为此可以用 s=1 及 s=一 s来改变其符号。程序:

#include<math.h>main()

{ int s;float t,pi,n;t=1;pi=0;n=1.0;s=1;while((fabs(t))>=le 一 4)

{ pr=pi+t;n=n+2;s=-s;t=s/n}pi=pi* 4;printf("pi=%10.6f\n",pi);}

}运行情况:

pi= 3.141397例 8-13 求斐波那契数列 l,1,2,3,5,8,13···的前 30项值。分析:斐波那契数列第一、二项为 1,第三项开始,每一项为前两项之和,由于数值上

升很快,到第 40项将远远超过 32767。因此每一项不应该用 int 类型而用 long int 型。同理在输出时也不能用"%d"形式,而应用"%ld"形式。此外在输出时一行不可能输出 30 个值,我们采用 if 语句,使它打印出 5 个数据之后换行。

程序:main( )

{ long int f1=l,f2=1;int I;for(i=1; i<=30;i++);

{ printf("%121d%121d",f1,f2);if(i%5= =0)print{("\n");f1=f1+f2;f2=f2+f1;}

}例 8-14 求 1到 n之间的所有素数。分析:素数是除 1 和自身之外不能被其他整数整除的自然数。例如,2,3,5,7,11,

13等都是质数,从中可以看出除 2之外,所有素数都是奇数,因此只需要把某奇数 N 不断

Page 144: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 8 章 循环控制

除以 3,5,7,9,11…,直到N/2 为止,若该数 N 不能被这些数之一整除,则它一定是素数。在 C 语言中判断整除方法往往是采用取模运算(%)即可。

程序:#include <stdio.h>main( )

{ int n,m,i,j,s;do {printf("Input n:");scanf("%d",&n);}while(n<2); /*判断输入数应≥2*/

printf("\n%4d\n",2); /*打印第一个质数 2*/m=3;for(i=m;i<=n;i+=2)

{ s=sqrt(i);for(j=3;j<s;j+=2)if(!(i%j)

break; /*能被整除,退出循环*/if(j>=s) printf("%4d\n",i); /*打印质数*/}

}例 8-15 在《算经》中有一个著名的“百鸡”问题:鸡翁一值钱五,鸡母一值钱三,鸡雏

三值钱一;百钱买百鸡,翁、母、雏各几何?分析 1:假设买 x只公鸡,y只母鸡,z只小鸡,由问题得到下列方程:

x+y+z=100 15x+3y+z/3=100显然两个方程,三个未知数,其解不是唯一的。另外,x、y、z 一定是从 0到 100之间的

整数,最简单的方法是采用穷举法,把 x、y、z 的所有值的组合代人方程组计算,以寻找满足此方程组的解。

程序 1:#include〈stdio.h〉main( )

{ int x,y,z,j=0;for(x=0;x<=100;x++)for(y=0;y<=100;y++)for(z=0;z<=100;z++)if(x+y+z= =100&&5*x+3*y+z/3= =100)

printf("%2d:cock=%2d hen=%2d chicken=%2d\n",++j,x,y,z);

}运行情况 1:

1:cock=0 hen=25 chicken=752;cock=3 hen=20 chicken=773:cock=4 hen=18 chicken=784:cock=7 hen=13 chicken=805:cock=8 hen=11 chicken=81

Page 145: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 8 章 循环控制

6:cock=11 hen=6 chicken=837:cock=12 hen=4 chicken=84

分析 2:分析上面运行结果,发现第 2、4、6 组解有问题,chicken 值为 77、80 和 83都不能被 3 整除,其原因为 C 语言中整除时只保留商数,舍去小数部分,因此可以把 if 语句条件改为:

if(x+y+z= =100&&15*x+9*y+z= =300)…运行程序,可得到正确的结果。

运行情况 2:1:cock=0 hen=25 chicken=752:cock=4 hen=18 chicken=783:cock=8 hen=1l chicken=814:cock=12 hen:4 chicken=84

分析 3:上列中是用三重循环穷量 x、y、z 全部组合,尽管编程简单但运行速度很慢,其原因是要执行循环体 101×101×101次,如何节约时间呢?我们可以想到 100 元钱不可能买100只公鸡,最多只能买 20只,同理 100 元钱最多只能买 33只母鸡,因此可改变 x、y 的循环条件。

程序 3:#include<stdio.h>main()

{ int x,y,z,j=0;for(x=0;x<=20;x++)for(y=0;y<=33;y++)for(z=0;z<=100;z++)if(x+y+z= =100&&15*x+9*y+z= =300)

printf("%2d:cock=%2d hen=%2d chicken=%2d\n",++j,x,y,z);

}分析 4:上述程序执行循环次数为 21×34×101,与程序 1相比减少了约 93%,使时间

大大缩短,实际上对该程序可以进一步优化:当 x 值确定之后,y 值最大不会超过(100 一5*x)/3,而当 x、y确定之后,z=100-x-y也可唯一确定,这样就可以取消最里层的 for 语句。

程序 4:#include<stdio.h>main()

{ int x,y,z,i=0;for(x=0;x<=20;x++)for(y=0;y<=(100-5*x)/3;y++)

{ z=100-x-y;if(15*x+9*y+z=300)

printf("%2d:cock=%2d hen=%2d chicken=%2d\n",++j,x,y,z);

}}

这个程序中两重循环次数少于 21×34,与程序 3相比循环次数减少 99%,其运行速度

Page 146: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 8 章 循环控制

进一步提高。从这个例题读者可以看到,不论问题如何简单,都应该充分地进行分析,充分认识问

题中隐含的条件才能设计出正确的算法,提高程序质量和运行的速度。

8.7 本章小结

本章介绍了 C 语言中的三种循环语句 while、do-while 和 for。这三种语句各有特点,while 语句是先判定条件后执行循环体中的语句,因此有可能循环体中语句一次也不执行。同时在循环体中应该有语句来逐步改变循环的判定条件,以防止无限循环;do-while 语句是先执行后判断,因此循环体中语句至少执行一次。同样也应该有语句来逐步改变判断条件,以防止无限循环。for 语句功能较强,表达式 1、表达式 2 和表达式 3(用两个分号分开)放在 for后面的圆括号内,表达式 1 用于实现变量初始化,设置循环变量的初值,表达式 2是每次循环前的判定条件,即循环控制(终止)条件,表达式 3 用于在每次循环结束后修改循巧控制变量。

for 语句三个表达式中分号不可缺少,初学者常常忽略,有时甚至误以为是逗号,若在for 语句中使用逗号则另有含义,是逗号(,)运算符,可使用在表达式 1 和表达式 3 中。

for 语句中表达式可以省略一个、=个或三个,但两个分号不能省略。当表达式 2 省略或三个表达式都省略时会产生无限循环,不得不用 break来退出循环。

本章最后谈及了 break 和 continue两个语句的作用。用 break可以退出 break 语句所在的循环,eoutinue 语句结束本次循环,返回到条件判定式,继续进行循环,灵活使用 break 和continue 语句可以大大方便程序的编制。

8.8 练习题8.8.1选择题

1.以下不是无限循环的语句为 。(A)for(y=0,x=1;x>++y;x++);(B)for(;;x++);(C)while(1){x++;};(D)for(i=10;;i--) sum+=i;2.若 a、b均为 int 型变量,且 a=100,则以下关于 for 循环的正确判断为 。for(b=100;a!=b;++a,b++)printf("----\n")(A)循环体只执行一次 (B)是死循环(C)循环体一次也不执行 (D)输出----3.while(!x)中的(!x)与下面条件 等价。(A)x= =0 (B)x= =1(C)x!=1 (D)x!=04.以下不正确的描述是 。(A)使用 while 和 do-while 循环时,循环变量初始化的操作应在循环语句之前完成。(B)while 循环是先判断表达式,后执行循环体语句。

Page 147: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 8 章 循环控制

(C)do-while 和 for 循环均是先执行循环体语句,后判断表达式。(D)for、while 和 do-while 循环中的循环体均可以由空语句构成。5.若 a、b 为 int 型变量,则执行以下语句后,b 的值为 [1] ,a 的值为 [2] 。

a=1;b=10;do{

b-=a;a++;}while(b--<0);

[1](A)9 (B)一 2(C)一 1 (D)8

[2](A)4 (B)2(C)1 (D)3

6.若 x是 int 型变量,则执行以下语句的结果是 。for(x=1;x<100;x++)if(++x%2= =0)if(++x%3= =0)if(++x%5= =0)

printf("%d",x);(A)30 60 90 (B)29 59 89(C)不打印任何内容 (D)31 6l 917.若 x、y均是 int 型变量,则执行以下语句的结果是 。

for(x=1;x<5;x+=2){ for(y=1;y<5;y++)

printf("%2d",x*y);if(y= =5)printf("\n");

}(A)1 2 3 4 (B)2 3 4 5

3 6 9 12 6 9 12 15(C)2 3 4 6 9 (D)2 3 4

6 9 1210 15 20

8.若 a 为 int 型变量,则执行以下语句后的结果为 。a=5;do{

printf("%2d\n",a--);}while(!A);

(A)5 (B)不打印任何内容(C)4 (D)陷人死循环9.若 x、y是 int 型变量,则执行以下语句后的 x 值是 [1] ,y 值是 [2] 。

for(y=l,x=l;y<=50;y++){ if(x>=10)break;

if(x%2= =1){ x+=5;

contnue;

Page 148: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 8 章 循环控制

}x--=3;}

[1](A)1 (B)6(C)7 (D)10

[2](A)6 (B)2(C)4 (D)8

10.若运行下列程序时,输入以下数据,则正确的运行结果为 。#include<stdio.h>main( ) { int s;

while((s=getchar())!='\n'){ switch(s-'2')

{ case 0:case 1:putchar(s+4);case 2:putchar(s+4);break;case 3:putchar(s+3);default:putchar(s+2);break;}

}printf("\n");}

输人数据(第一列) 2473〈回车〉(A)6688766 (B)6778777 (C)668966 (D)668977

8.8.2填空题1.设 a 和 b均为 int 型变量,则对于下面的 for 循环中的 scanf 语句将最多执行 次。

for(a=0,b=0;b!=123&&a<3;a++)scanf("%d",&(B);

2.设 a、j、k均为 int 型变量,则执行完以下 for 语句后 k 的值是 。for(i=0,j=10;i<=j;i++,j--)

k=i+j3.设说明 int y=10;则执行完以下语句后,y 的值为 。

do{

y--;}while(--y);

printf("%d\n",y--);4.设 c 为 char 变量,若从终端上由第一列开始输入以下数据;right<回车>,则下面三

个程序段的执行结果分别为 , , 。(1)c=getchar(); (2)while((c=getchar())!='?');

whle(c!='?') putchar(c++);

Page 149: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 8 章 循环控制

{ putchar((C);c=getchar();

}(3)while(putchar(getchar())!='?');5.下面的 for 循环语句最多可执行 次。

for(x=0,y=0;(y!=99)&&(x<4);x++);6.下面程序运行结果为 。

main( ){ int i=1;

while(i<15)if(++i%3!=2)continue;else printf("%d",i);printf("\n");

}7.下面程序的运行结果为 。

main( ){ int i,j,k;

char space='';for(i=0;i<=5;i++)

{ for(j=1;j<=i;j++)printf("%c",space);for(k=0;k<=5;k++)printf("%c",'*');printf("\n");}

}8.下列程序的作用是求以下算式中 x、y、z 的值,请在 处填人正确内容。

XYZ+ YZZ

5 3 2main(){ int x,y,z,i result=532;

for(x=1; ;x++)for(y=1; ;y++)for(z= ; ;z++)

{ i=( )+(100*y+10*2+z);if(i= =result)

printf("X=%d,Y=%d,Z=%d\n",x,y,z);}

}9.下面程序的运行结果为 。

#include<stdio.h>void main()

{ int i,j,k=0; ,

Page 150: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 8 章 循环控制

for(j=1l;j<=30;j++){ if(k%10= =0)

printf("\n");for(i=2;i<j;i++)if(!(j%i))

break;if(i>=j-1)

{ printf("%d\t",j);k++;

}

Page 151: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

第 9 章 函数与变量类型9.1 函数

9.1.1 概述9.1.2 函数定义的一般形式9.1.3 有关函数的说明9.1.4 函数的调用形式9.1.5 函数的递归调用9.1.6 库函数简介

9.2 变量类型9.2.1 自动型变量(局部变量)9.2.2 外部型变量(全局变量)9.2.3 静态型变量9.2.4 寄存器变量

9.3 变量初始化9.4 编译预处理器

9.4.1 宏定义9.4.2 文件包含9.4.3 条件编译

9.5 例题详解9.6 本章小结9.7 练习题

第 9 章 函数与变量类型9.1 函数

C 语言源程序都是由函数组成的。运行时程序从主函数 main()开始执行。到main()的终止行结束。由main()或别的函数或自身调用(递归)后组成可执行程序。本章介绍函数调用、递归、参数替代及返用值等问题。

9.1.1 概述

Page 152: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

图 9-1是函数调用的示意图。程序设计中常常把一些常用功能模块编写成函数形式,放在函数库中供选用。程序员应该熟悉这些函数,善于运用这些函数以减小编程工作量。

例 9-1main( )

{ printstar( );print-message( );printstar( );}

print-message( ){ printf("\t\tThis is a C program!\n");}

printstar( ){ printf("\t\* * * * * * * * * * * * * * * * * *\n");}

运行情况:* * * * * * * * * * * * * * * * * *

This is a C program!* * * * * * * * * * * * * * * * * *

说明:(1)一个源程序文件可由一个或多个函数组成,一个源程序文件作为一个编译对象,

函数不单独作为编译对象。(2)一个 C 程序由一个或者多个源程序文件组成,对于一个较大的程序可放在几个源

程序文件中,分别进行编译以提高调试的效率。(3)一个 C 程序是从主函数 main()开始运行的,调用其他函数后返回到main()

函数,main是系统所定义的。(4)所有的函数都是独立的,一个函数不能从属于另一个函数,即函数不能嵌套定义,

函数可以相互调用,但任何函数不能调用 main()函数。(5)从用户使用角度来看,函数分两种:标准函数(库函数)--由系统所提供的函数,用户不必自己定义,不同系统的标准函

数略有不同,但大多是共同的;用户自定义函数——用户自己定义的函数,以满足用户的需要。(6)从函数的形式来看,函数也可分为两种:

main

a b c

a1 a1 b1 c1 c2

b11 b12

图 9-1 函数的调用

Page 153: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

无参函数(没有参数传递)——通常用来执行所指定的操作;有参函数(有参数传递)——在调用和被调用函数之间传递参数。

9.1.2 函数定义的一般形式(1)无参函数的定义:

类型标识符 函数名( ){ 说明部分

语句}

见例 9-1,函数名后括号中没有参数。(2)有参函数的定义:

类型标识符 函数名(形式参数表)形式参数说明

{说明部分语句}

例 9-2int sum(a,b) /*不能有分号*/int a,b; /*形参说明,必须在括号外*/

{ int sum; /*说明部分必须在括号中*/sum=a+b;return(sum); /*将 sum 值返回给函数值*/}

(3)空函数定义。这是一个非常特殊的函数,定义形式为:类型说明符 函数名( )

{}

例如,dummy(){

}调用此函数时什么也不做,不起任何作用,在程序中写上空函数表示“这里需要调用

一个函数”,待以后扩充函数功能时再补上。尽管这个函数尚未编好,先抢占一个位置。例 9-3 定义计算 n!的函数,并在主程序中调用。

#include〈stdio.h〉main()

{ int n;long nn;long facto(); /*函数说明,说明 facto返回值为 long 型*/printf("Enter n=?");scanf("%d",&n);nn= jiec(n); /*以 n 为参数调用 facto,返回值赋于 nn* /printf("\nThe%d! is%1d\n",n,nn);

}

Page 154: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

long jiec(x) /*函数定义*/int x; /*形参说明*/

{ long y; /*以下为函数体*/for(y=l;x>0;--x)

y*=x;return(y); /*控制返回到调用函数*/}

9.1.3 有关函数的说明(1)类型说明符是说明函数中 return 语句返回值的类型,即称为函数的类型,它可以

是任意 C 的合法数据类型,如 int、long、float、char等,也可以是以后所讲到的指针、结构等。如果类型说明符省略,则 C 语言默认它为 int 型。

(2)函数名是一个标识符,在程序中标识函数的名字,在一个程序中若有多个函数定义时不允许函数名重名。

(3)形式参数表中是用逗号(,)分隔的一组变量名称为形式参数,括号是绝对不可省略的(即使没有形式参数,也要用括号)。调用函数时所用的参数称为实际参数(实参),实参与形式参数(形参)相结合,称为“形实结合”,此时必须遵循“三个一致”的原则,即类型一致,顺序一致,数量一致(但字符型和整型可以互相通用)。

(4)形式参数说明对形参表中每一个形参的类型逐个进行说明(但顺序允许不同),形式参数说明之后在函数体中不必重新说明,函数体内可以同一般变量一样直接使用。

(5)用花括号括起来的是函数体部分,它是函数的主体,由 C 语言中的语句组成(空函数中没有任何语句,但花括号不能缺少)。

(6)函数体内部的说明部分与形式参数说明含义完全不一样,前者说明一个局部于函数体内的一般变量,后者说明函数之间的传递数据的形式变量。此外,前者要写在花括号之内是函数体的组成部分,后者一定要在函数体花括号之外,两者不能混淆,不能混在一起书写。

(7)C 语言一个程序可以由多个文件组成,每个文件都可以单独编译,最后将几个文件连接生成一个可运行文件,但一个函数不能跨越在两个文件中,函数在一个文件中必须保持完整。

(8)有关形参及实参的说明。① 函数定义中指定的形式参数在未出现函数调用之时,它们不占用内存中的存储单元,

只有在发生函数调用时才被分配内存单元,调用结束后,形参所占的内存单元也被释放。② 实参可以相同,也可以是表达式,例如max(a,a)、max(a-{-a,a,b),但要求

它们有 确定的值,在调用时通常实参值传递给形参,形参不可以相同也不可以为表达式,但如果它是数组名则实参传递的是数组首地址而不是变量的值。

③ 语言规定实参变量对形参变量是“值”传递,即单向传递,并不返回,如图 9-2所示。该图表示调用函数时,为形参分配内存单元,将实参 a=2 和 b=3 传递给 x 和 y,使 x=2,y=3,若在执行函数过程中 x 和 y 值分别改变为 4 和 9,调用结束后,实参仍为原值。

④ 形参类型也可以在形参表中直接说明(ANSI新标准)。例如:int max(int x,int y)

{…}

Page 155: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

int max(x,y) int x,y;

{…}

(9)函数返回值的说明。通常希望通过函数调用使主调函数能得到一个确定的值。即就是函数的返回值。

① 函数的返回值是通过函数中的 return 语句获得的。因此如果需要从被调用函数带回一个函数值(供主调函数使用),被调用函数中必须包括 return 语句。如果不需要从被调用函数带回函数值时可以不要 return 语句。

(a)调用时 (b)返回时图 9-2 “值”调用

② 一个函数可以有一个以上的 return 语句,执行到哪一个 return 语句,则哪一个语句起作用。return 语句后面括号也可以省略,例如 return z,等价于 return(z);同时 return也可以是表达式形式,例如 return(x<y?x:y);这样程序更为简洁,用一个 return 语句同时解决求值和返回问题。③在函数名前的类型说明符,说明函数返回值的类型(iht、char、double…),若不加

说明一律默认为 int 型。因此 return 中表达式类型应该与其一致。如果不一致则以函数类型说明符说明的类型准,对数值型数据自动进行类型转换。

例 9-4 main( )

{ float a,b;int c;scanf("%f,%f,&a,&b);c=min(a,b);printf("Max is%d\n",c);}

max(x,y);float x,y;

{ float z;z=x<y?x:y;return(z);}

运行情况:4.5,7.3↙Max is 7

2

2 3

3a

x

b

y 4

2a

x 9

3b

y

Page 156: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

由于函数 max 定为整型,而 return 语句中的 z 为实型,二者不一致因此先将 z 转化为整型再返回。如果main 中变量 c 定义为 float同时 printf 语句中也用%f 输出,那么输出也为:Max is 7.000000。④有时为了明确表示“不带回值”,可以用“void”定义“无类型”(或空类型)。例 9-5 本例是一个演示程序。其功能是显示数字 1到 100,每显示 10 行就暂停,等待用

户按任一键后继续显示。#include〈stdio.h〉void kbnit(void) /*void 类型,无返回值*/

{ getch( ) /*getch 为库函数等待用户按键*/}

main(){ int i,j;

for(i=1;j=0;i<=100;i++){ printf("%d\n",i)

if(++j= =10){ j=0;

kbhit(), /*调用函数*/}

}}

本例中 kbhit 函数类型是 void 类型,没有参数,因此函数名 kbhit后可以为空括号(),也可以写成(void)以明确表示没有形式参数。

9.1.4 函数的调用形式C 语言中在表达式、语句或参数中直接写出函数名并用实参代替形参就可以调用函数,

一旦出现函数的调用就要去执行这个函数,然后返回函数执行结果,根据被调用函数在源程序中位置可分为三种调用形式:

(1)函数语句调用。被调用函数作为一个独立的语句出现在源程序中,这种语句称为函数语句;

(2)函数表达式调用。被调用函数出现在表达式中;(3)函数参数调用。被调用函数以函数(函数参数)形式出现。1.函数语句调用。这种调用很简单,只要把被调用函数的函数名直接写出来,并以实

参替代形参。例 9-6

main(){ printf("Good Morning!.\n");

a();e();n();}

a(){ printf("Good Afternoon!\n");

Page 157: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

}e()

{ printf("Good Evening!\n");}

n(){ printf("Good Night!\n");}

运行结果:Good Morning!Good Afternoon!Good Evening!Good Night!

此程序中这函数 main()调用三个函数 a()、e()和 n(),它们都是函数语句的调用。

例 9-7main( )

{ printf("Good Morning!\n");aen( );}

aen(){ Printf("Good Afternoon!\n");

e()}

e( ){ Printf("Good Evening!\n");

n()}

n(){Printf("Good Night!\n");此程序主函数调用 aen(),aen()函数中调用 e();e( )中又调用 n( ),运行

结果同例 9-6,这种情况称为函数嵌套调用。注意嵌套形式的函数调用与函数编写顺序无关,因此本例中也可以先定义 e(),再定义 aen(),最后定义 n()。

(2)函数表达式调用。这种调用形式是被调用函数出现在表达式中,其条件是被调用函数必须有返回值,这里尤其要注意的是被调用函数返回值的类型。

例 9-8main( )

{ int i=3;while(i<100)

{ i= square(i);printf("%d\n",i);}

}square(x)int x{return(x*x);

Page 158: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

}运行结果:

9816561

因为函数为整型,主函数中无须对它进行类型说明,可得正确结果。例 9-9 上例中想得到浮点数平方,可改为以下程序。

main( ){ float i=2.5;

while(i<100.0){ i=square(i);

printf("%f\n",i)}

square(x)int x;

{ return(x*x);}

虽然本例中主函数已把 i 类型由整型改为实型,但函数 square()类型说明为整型,仍不能获得正确结果。

例 9-10 把上例改为 square( )类型为实型。……double square(x)float x;

{ return(x*x);}

但由于主函数中没有 square()原类型说明,编译时仍旧报错。例 9-11 在主函数中增加 square()类型说明,其格式是:

数据类型 被调用函数名( )。main( )

{ float i=2.5;double square( ); /*square( )类型说明*/while(i<200.0)

{ i=square(i); /*函数调用*/printf("%f\n",i)}

}double square(x) /*函数 square 定义*/float x;

{ return(x*x);}

运行情况:6.25000039.0625001525.878906

Page 159: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

(3)函数参数调用。这种调用方式尽管形式上不同于函数表达式调用,但调用条件和注意事项与函数表达式调用是相同的。例如:

x=max(a,b);printf("x=%d",x);

改为:printf("x=%d",max(a,b));

其功能是一样的,此时函数 max()是以 printf()函数的参数形式出现的,即max(a,b)作为一个函数参数。

例 9-12main( )

{ int i;for(i=0;i<5;i++)printf("%d,%d,%d\n",i,add(2,i),add(一 3,i));}

add(a,b) /*计算 a+b*/int a,b;

{ int p;p=a+b;return(p);}

运行情况:0, 2, —3l, 3, -22, 4, —13, 5, 04, 6, 1

9.1.5 函数的递归调用函数调用一般指一个函数调用另一个函数。此外还可以自己调用自己,这种调用称为

递归调用。使用递归应注意两个问题:通过递归应该一次次接近所求的解而不是离解愈来愈远:

应有递归结束的条件,不能无限止地递归下去。递归调用分为直接递归和间接递归两大类,直接递归是指函数自己调用自己,即函数

A 调用函数 A;间接递归是通过另一个函数调用自己,即函数 A 调用函数 B,函数 B又调用函数 A。图 9-3(a)所示为直接递归,图 9-3(b)所示为间接递归。

int f(x)int x;{ int y,x;

z=f(y)

return(2*z)} (a)

int f1(x)int x;{int y1 z;z=f2(y);return(2*z);}

int f2(t) int t;{int a,b;

b=f1(a);return(3*b) }

Page 160: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

(a)直接调用 (b)间接递归图 9-3 函数递归调用

例 9-13 计算 ab(用递归实现)。main( )

{ int a,b;scanf("%d,%d",&a,&b);printf("%d**%d=%d",a,b,Power(a,b));}

Power(x,y);int x,y;

{ int p;if(y>0)p=Power(x,y-1)*x;else p=1;return(p);}

考虑到 xy=x*xy-1,xy-1=x*xy-2,…,x0=l,在 Power(x,y)中定义了递归调用,其结束条件是当 y=0 时 p=1。

例 9-14 计算 n!(用递归实现)。我们知道 n1=n*(n 一 1)!,(n 一 1)!=(n 一 1)*(n 一 2)!。直到 0!=1,因此可定义一个阶乘定义 jiech(x)使得 jiech(x)=x*jiech(x 一1),直到 fac(0)=1 为止。

main( ){ int n;

printf("input n please:");scanf("%d",&n);if(n>=0)

printf("%d!=%d\n",n,jiech(n));else

printf("Error!n<0!");}

jiech(x)int x;

{ if(x=0) return(1);else return(x*fac(x 一 1));}

运行情况:input n please:6↙6!=720

例 9-15 Hanoi(汉诺)塔问题。相传印度布拉玛神庙中放置一块大铜板,板上有 A、B、C 三个柱子,在柱A 上大小互不相等的 64 个金盘(中间有孔),按以下规则把 64 个金盘从柱A移到另一个柱(例如 C)上。

A B C

Page 161: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

①每次只能搬动一个金盘;②小盘放在大盘上,反之不允许;③移动位置仅限于三个柱子。神庙的方丈预言,当人们把 64 个金盘从一根柱子移到另一根柱子时,世界末日就到了。根据统计共需移动 264 一 1次,若每次移动一个盘需要 1秒钟,并日夜不停地搬动共需

5849亿年!而太阳的寿命也仅 100~150亿年,用现代计算机模拟,若 lms移动 1次也需 100万年。

分析:对这一个问题的解可采用递归方式来解决。其思想是:①要把所有金盘从柱A移到柱 C,首先必须把柱A 上(n 一 1)个金盘,从柱A移到

柱 B(中间可使用柱 C)。②把柱A最底下的第 n 个盘从柱A移到柱 C 上(即一个盘的移动,极易解决)。③再把柱 B 上的(n 一 1)个盘移到柱 C 上(中间可使用柱A)。也就是说,要解决 n 个金盘问题就要解决(n 一 1)个盘的问题,为解决(n 一 1)个

盘移动问题就要解决(n 一 2)个盘问题……,最后要解决 1 个盘移动问题,显然是易于实现的。令 n 个盘从源柱 s 上要移到目标柱 t 上并使用柱 u。则可以定义函数 hanoi(n,s,t,

u),这样递归过程为:hanoi(n,s,t,u)

{ if(n==1)将 n 号盘从 s移到 t;else{ ①hanoi(n 一 1,s,u,t);②将 n 号盘从 s 上移到 t 上;③hanoi(n 一 1,u,t,s);}}

程序:main()

{ unsigned n;printf(“input the number of discs:");scanf("%d,&n");printf("the step to moving %3d diskes:",n);hanoi(n,'a','c','b'); /*将柱A 上 n 个盘移到柱 C*/

}hanoi(n,s,t,u)unsigned n;char s,t,u;

{ if(m= =1)printf("%2d 一(%2d):%c= =>%c\n",++i,n,s,t);

/*将 s 上的一个圆盘移到 t 上*/else

Page 162: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

{ hanoi(n-1,s,u,t); /*将 s 上 n 一 1 个盘移到柱 u*/printf("%2d-(%2d):%c= =>%c\n",++i,n,s,t);

/*将 s 上第 n 个盘移到柱 t*/ hanoi(n-1,u,t,s); /*将柱 u 上的 n 一 1 个盘移到柱 t*/

}}运行情况:

input the number of disks:3↙the step to moving 3 diskes:

1 一(1): a= =>b2-(2): a= =>c3 一(1): b= =>c4 一(3): a= =>b5 一(1): c= =>a6 一(2): c= =>b7 一(1); a= =>b

9.1.6 库函数简介C 语言中没有直接计算诸如 Sin 或 Cos 的语句,也没有用于显示的语句,而只能使用 P

rintf 库函数显示结果。C 语言的库函数并不是 C 语言本身的一部分,它是由编译程度跟据一般用户的需要编制并提供用户使用的一组程序,它极大地方便了用户也补足了 C 语言本身的不足。用户在编写 C 语言程序时应该尽可能地使用库函数。

使用函数库时,应该在程序中嵌入(用#include)该函数对应的头文件(也称包含文件),不同版本的 C 语言,具有不同的库函数,读者使用时应该查阅相关的手册,下面列举 TurboC 中的部分常用函数。

TurboC 中的库函数共分九类:(1)I/O 函数。它包括各种输入/输出操作,需要头文件 stdio.h。例如:getchar,putchar,printf,scanf,fopen,Sclose.fgetc,fgets,fprintf,fscanf,fputc,fp

uts,fseek,fread,fwrite等。(2)字符串、内存和字符函数。它包括对字符串的各种操作和对字符的操作函数,需

要的头文件是:string.h,mem.h 或 ctype.h。例如:用于检查字符的函数:isalnum,isalpha,isdigit,islower,isspace等;用于字符串操作

的函数 strcat,sirchr,strcmp,strlen,strstr等。(3)数学函数。包括各种常用的三角函数、双曲线函数、指数和对数函数等。需要头文

件 math.h。例如:abs,sin,cos,exp,log,sgrt,pow等。

(4)时间、日期及与系统有关的函数。用于对时间、日期进行操作和设置计算机系统状态等,需头文件 time.h。例如:

time(返回系统时间),asctime(返回以字符串形式表示的日期和时间)。(5)动态存储分配。它包括"申请分配"和"释放"内存空间的函数。需头文件:allo

c.h 或 stdlib.h。例如:calloc,free,malloc,realloc等。

Page 163: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

(6)目录管理。包括磁盘目录建立、查询、改变等操作的函数。(7)过程控制。包括最基本的过程控制函数。(8)字符屏幕和图形功能。包括各种绘制点、线、圆、方和填色等函数。(9)其他函数。使用这些库函数应清楚以下四个方面的内容:函数的功能及所能完成

的操作;参数的数目及顺序以及每个参数的含义及类型;返回值的含义及类型;需要使用的头文件。

9.2 变量类型前面我们已对变量的类型作了一些说明,但是从数据类型的角度来进行介绍的,本节

中我们将从存储类型以及它们的作用域方面来进行介绍。C 语言中说明和定义是两个不同的概念,所谓说明是对一个变量的性质(例如,其类

型)加以说明,但并不分配存储空间;所谓定义是对变量既说明其性质又为其分配存储空间。对函数也如此,但在形式上两者也不同,函数定义的第一行函数名圆括号后不能有分号,而函数说明第一行函数名圆括号后必定有分号。

C 程序的源程序可以分散在几个文件中,事先编好的程序也可以从库里装入,这就涉及到变量的作用域范围。通常变量作用域应该分为对整个程序、一个文件、一个函数及一个程序段起作用等四个层次。

9.2.1 自动型变量(局部变量)在函数内部定义的变量称为自动型变量。它的作用域定义在函数内部,不同的函数中

若出现相同名字的变量,则它们是毫不相干的。自动型变量定义以 auto 标志,但在函数内部可以省略,因此通常都不标有 auto。例 9-16

main( ){ int x=1;

{int y=2;printf("%d,%d",x,y); }

printf("%d,%d",x,y);}

printf("%d,%d\n",x,y);}

该程序有三个模块,变量 x是一个自动型变量,在一开头就已说明,因此其作用是整个主函数,即在所包含的两个模块中也是存在的;变量 y在第一个子模块中说明,也是自动型变量。其作用域在第一个子模块,因此第二、三个 printf 语句中 y是不存在的,因此编译会出现错误。由于 C 语言编译对自动型变量是动态分配存储空间,即进入函数时给予分配堆栈空间,

一旦退出该函数,所分配给自动型变量的空间即消失,因此自动型变量不能被任何其他函数所调用,也不能保存其值。因此两个函数之间要实现自动型变量的值传递,只有通过函数的参数来实现。

Page 164: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

当自动型变量与某外部型变量具有相同名字时,该函数中定义的自动变量起作用,退出函数之后仍为全局变量起作用。

例 9-17main( )

{ int a=5;{int a=7;

{int a=9;printf("%d\n",a);}

printf("%d\n",a);}

printf("%d\n",a);}

运行情况:975

总之,自动型变量的作用域仅限于所定义的函数内部。

9.2.2 外部型变量(全局变量)“外部”是相对“内部”而言的,外部型变量就是在任何函数的外部所定义的变量,

它可以为一个程序中的所有函数来使用。因此 C 语言中不允许一个函数中再来建立其他函数。外部型变量具有“全局”的含义。引用外部变量有三个原因:

(1)外部型变量在整个程序内都可以存取,所以它提供了函数之间数据通讯的一种方法。只要将用作函数间通讯的参数说明为外部型变量(不反映在形参和实参中),然后在函数中对它直接操作即可。

用外部变量比用长的参数表更为方便,但必须小心谨慎。因为它会导致程序中数据的联系很不明显:减少了程序的通用性。

(2)使用外部型变量与初始化有关,具体讲,外部数组可以被赋予初值,而自动型数组 是不能赋初值的。

(3)外部型变量是永久性的,在一次函数调用到下一次函数调用之间仍保持它以前的值。外部型变量必须在任何函数之外定义,在整个程序(可能有几个文件)中,只能在一

处定义和初始化。对定义的外部型变量,由编译静态地为它们分配适当的存储空间。由于 C语言中每一个函数都可以独立编译,为了使其他函数知道这些外部变量已经定义以及它的数据类型,这些外部变量在存取它的函数中也应加以说明,可以显式地用 extern 进行说明或通过上、下文隐式进行说明。

例 9-18int add(x,y) /*定义 add 函数*/int x,y;

{ int z;z=x+y;return(z);

Page 165: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

}main()

{ extern int a,b; /*外部变量说明*/printf("%d",add(a,b));}

int a=13,b=一 9; /*外部变量定义*/运行结果:

4本例中外部变量定义在函数 main之后,因此main 函数引用外部变量 a 和 b之前,应田

extern 进行外部变量的说明,否则编译时会出错。一般做法是外部变量定义放在引用它的所有函数之前,这样就可以避免在函数中多加一个 extern 说明。在同一个源文件中外部型变量与自动型变量如果同名,则在自动型变量的作用范围内,

外部变量不起作用。例 9-19

int a=5,b=7; /*a、b 为外部变量*/add(a,b)int a,b; /*a,b 为自动型变量*/

{ int c;c=a+b;return(c)

}main( )

{ a=8; /*a 为自动型变量*/printf("%d",add(a,b));}

运行情况:15

这里故意重复使用 a、b 作为变量名,第一行定义外部变量 a、b,并初始化。第二行开始定义函数 add,使用 a、b 作为形参,形参也是局部变量,它不是外部变量,它们的值是由实参传给形参的,外部变量 a、b在 add 函数范围内不起作用,最后四行是main 函数定义了一个局部变量 a,因此外部变量 a在main 中不起作用,但外部变量 b起作用,因此,printf 函数中的 add(a,b)相当于 add(8,7),因此返回 15。

9.2.3 静态型变量上两节是从变量的作用域(即空间上)角度把变量分为全局变量(外部型变量)和局

部变量(自动型变量)。从另一个角度,即变量值存在的时间(即生存期)角度可以分为静态型变量和动态型变量。前者是指程序运行期间分配固定的存储空间方式,后者是在程序运行期间根据需要进行动态分配存储空间的方式。

静态型变量可以是局部(内部)变量也可以是全局(外部)变量,通常在普通类型定义语句之前加上关键字 static 例如:static burp;

内部静态变量类似于自动型变量,它的作用域仅限于函数内部。但不同于自动型变量,

Page 166: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

它始终占有内存单元,而不是在进出函数时被建立或消除。例 9-20

#include〈stdio.h〉main()

{ double w,s,Compute( );for(;;)

{ printf("Enter,Weight:");scanf(%1f,&w); /*接收行李重量*/if(w= =0) exit(0); /*重量为零时退出*/s=Compute(w); /*计算托运费*/printf("%.2f\n",s); /*打印托运费*/}

}double Compute(x) /*计算托运费函数*/double x;

{ double s;static double total=0; /*total 为内部静态变量*/if(x<=30.0)

s=l2*x; /*12 元/kg*/else

s=30*l2+(x 一 30)*18; /*超重部分 18 元/kg*/total+=s; /*记录托运费总计*/printf("Total:%.2f\n",total);return(s);}

该程序计算托运费,重量不超过 30kg 时托运费 12 元/kg,重量超过 30kg 时超出部分 18 元/kg,每一笔托运费加入到内部静态变量 total 中,total 为双精度类型,它不会因退出函数而消失;外部静态变量作用域仅限于对它进行定义的源文件,而其他的文件不可以使用这个变量。

9.2.4 寄存器变量寄存器变量定义形式为:

register 类型名 变量名;一个变量被定义为寄存器型主要是通知编译,变量如允许尽可能以机器的寄存器来定

义,即存在放在寄存器中,由于寄存器是有限的,对不足使用寄存器的变量将分配给内存(相当于 registor 不起作用),我们可把程序中频繁使用的变量定义为寄存器变量以加快程序运行速度。

寄存器类型说明通常只能定义 int、char 和指针类型的变量,若定义不允许的类型,register将不被理睬,同时寄存器类型也只适用于自动型变量和函数中的形参说明,不适宜作外部变量和静态变量。

例 9-21int fact(n)

Page 167: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

int n;{ regist int i,p=1; /*定义寄存器变量*/

for(i=1;i<n;i++)p=p*i;return(p);}

main( ){ int i;

for(i=1;i<=10;i++)printf("%d!=%d\n",i,fact(i));}

本例中局部变量 p 和 i是寄存器变量,如果 n 较大,程序效率提高较快。

9.3 变量初始化简单变量都可以在定义时明确地加上初始值,方法是在定义中的变量后加上"="和

一个数字表达式,例如:int x=10;char squote="\";long day=60*24; /*minutes in a day*/

对外部和静态变量来说,只能做一次初始化工作,在编译时进行初始化,对自动型和寄存器变量,初值不限于常数,可以包括以前已定义过的值。每进入函数或复合语句一次就初始化一次。

C 语言中任何以花括号“{”和“}”括起来的复合语句称为“块结构”,在块内可以对变量进行定义,在块内定义的变量仅限于块内起作用。例如:

if(n>0){ int i;

for(i=0;i>n;i++)……}

i 定义仅属于块内定义,作用域在块内。

9.4 编译预处理器C 语言预处理器是 C 编译程序的一部分,它负责处理几种特殊的语句,这些语句称为

预处理语句,它们有三种:宏定义、文件包含和条件编译。为了与一般的 C 语言语句相区别,所有预处理语句都以"#"符号开头。

9.4.1 宏定义1.不带参数的宏定义。宏定义是用一个标识符来代表字符串,其形式为:

Page 168: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

#define 标识符 字符串例如:

#define PI 3.1415926#define YES 1#define No 0

这种方法使用户在程序中能以一个简单名字(例如 P1)来代表一串字符 (3.1415926)。因此有时把该标识符称为“宏名”(往往以大写字母表示,以区别源程序中的变量),在预编译时将宏名替代为字符串,其过程称为“宏展开”。但注意,引号中字符串不能展开,例如:printf("PI");中的 PI是不能展开的。

例 9-22#define PI 3.1415926mian(){float l,r;printf("Input radius:");scanf("%f",&r);l=2*PI*r;printf("\n r=%10.4f\n l=%10.4f\n",r,l);}

运行情况:Input radius:4↙r= 4.0000l= 25.1327

说明:(1)宏名习惯上采用大写字母以与变量名相区别,但这并非是规定,也可以用小写字

母。(2)采用宏名代替字符串可以减少程序中工作量,例如程序中要用到五次冗的值,不

需要写五次“3.1415926”,而只需宏定义后写五次 PI即可。当需要修改其值时只需修改宏定义,而不需修改五次。

(3)宏定义不是 C 语句,不能加分号(;),如果加了分号,会连分号一起进行置换。(4)通常#define命令写在文件开头,函数之前,作为文件的一部分,在本文件内有效。(5)进行宏定义时也可使用已定义的宏名。例如:

#define R 3.0#define PI 3.1415926#define L 2*PI*R#define S PI*R*R……

2.带参数的宏定义。带参数的宏定义不仅进行简单的字符串替换还可进行参数的替换,其定义格式为:

#define 宏名(参数表) 字符串字符串中应该包括括号中的指定参数。例 9-23

#define PI 3.1415926

Page 169: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

#define S(r) PI*r*rmain( )

{ float a,area;a=3.6;area=S(a);printf("r=%f\narea=%f\n",a,area);}

运行情况:r=2.300000area=16.619011

说明:(1)对带参数的宏的展开只是将宏名后面括号内的实参字符串代替#define命争行中

的形参。上例中,若出现语句 area=S(a+b);此时把实参替代形参,变为 area=PI*a+b*a+b;

注意 a+b没有括号!显然与设计者意顾不符,因此在宏定义时应加上括号,即#define s(r) PI*(r)*(r)展开时为 area=PI*(a+b)*(a+b)。

(2)宏定义时,在宏名与带参数的括号之间不能有空格,否则将空格以后的字符都作为替代字符串的一部分。例如:

#define S(r) P1*r*r被认为 S是符号常量(不带参数的宏名),它代表字符串“(r)PI*r*r”。

读者也许容易把带参数的宏和函数混淆,的确,它们之间有一定类似之处,但带参数的宏定义与函数是不同的,主要有:

(1)函数调用时,先求出实参表达式的值,然后代人形参,而宏只是进行简单的字符替换,例如上面的 s(a+b),在宏展开时并不求取 a+b 的值,而是将实参字符"a+b"替代宏目义中的参数 r。

(2)函数调用是在程序运行中处理的,分配临时的内存单元,宏展开是编译时进行的,不分配内存单元,不进行值的传递,也没有"返回值"的概念。

(3)函数中的实参、形参都要定义类型,=者类型要求一致,若不一致时,应进行类型转换,而宏是展开为字符串,无类型问题。

(4)宏展开后会使程序增长,而函数调用不使源程序变长。 (5)宏替换不占运行时间,只占编译时间,而函数调用则占运行时间(分配单元、保

留现场、值传递、返回)。(6)有些问题,用宏和函数部可以实现,但用宏代表简短表达式比较合适。例 9-24 用宏实现:

#define ADD(x,y) (x)+(y)……main()

{ int a,b,c,d,t;……t=ADD(a+b,c+d);……} .

赋值语句展开后为:t=(a+b)+(c+d);

Page 170: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

用函数实现;int add(x,y)int x,y

{ return(x+y);}main( )

{ int a,b,c,d,t;……t=add(a+b,c+d);……

}

9.4.2 文件包含文件包含指的是一个程序把另一个指定文件的内容包含进来,例如;

#include "filename"#include 〈filename〉

引号或尖括号是必要的,一般 C 系统中带有大量的.h 文件,用户可以根据不同的需要将相应文件包含进来。图 9-4 表示“文件包含”的含意,图中文件 filel。c 中有一个#include"file2.c"命令及

其他内容(A),若文件 file2.c 中内容为(B),编译时把 file2.c 全部内容(B)插入到#include"file2.c"处,将“包含”以后的 filel.c 文件作为一个源文件单独进行编译。“文件包含”是很有用的,可节省程序人员大量劳动,例如可把一组固定的符号常量

如(g=9.81,Pi=3.1415926,e=2.718,c=…)的宏定义作为一个文件,在需要时用#include命令把该文件包含到自己编写的源文件中。

说明;

(1)一个 include命令只能指定一个被包含的文件,若要包含 n 个文件应用 n 个 aclude命令。

(2)若文件 1 包括文件 2,文件 2 包括文件 3,则可以在文件 1 中用两个 include命令分别包含文件 2 和文件 3,但文件 3 应出现在文件 2之前,即在 filel.c 中定义:

#include〈file3.c〉#include〈file2.c〉

这样,filel、file2都可以用 file3 的内容,在 file2 中不必再用#include"file3.c"。

file1.c

#include 〈file2.c〉 A

B B

A

file2.c file1.c

包含

图 9-4 文件包含的概念

Page 171: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

9.4.3 条件编译条件编译是指对程序中一部分内容指定编译的条件,有时希望当满足某条件时对一组

语句进行编译,而条件不满足时编译另一组语句,这称为“条件编译”。条件编译有以下三种形式:

其作用时,若标识符已经定义过,那么程序段 1 参加编译,否则程序段 2 参加编译。其中"#else 程序段 2"也可以缺省。例如:在调试程序中往往要打印出一些所需信息,在调试完后不再输出这些信息,可

以在源程序中编人以下的条件编译:#ifdef DEBUGprintf("x=%d,y=%d,z=%d,x,y,z");#endif

如果它的前面有#define DEBUG,则程序运行时会输出 x、y、z之值,以便调试时进行分析。一旦调试结束,只需删除此#define命令即可。这样#define DEBUG相当于“开关”一样。

第一行是#ifndef,其作用是若标识符未被定义,则编译程序段 1,否则编译程序段 2。上例中如用:

#ifndef RUNprinf("x=%d,y=%d,z=%d",x,y,z);#endif

那么调试时因尚未定义 RUN会输出 x、y、z之值,调试结束后,源程序中加上#define RUN,则不再输出 x、y、z 值。可见这种形式与第一种形式相反。

当表达式值为非零(真)时执行编译程序段 1,否则编译程序段 2。

9.5 例题详解

# ifdef 标识符 程序段 1#else 程序段 2#endif

# ifndef 标识符 程序段 1#else 程序段 2#endif

# if 表达式 程序段 1#else 程序段 2#endif

Page 172: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

例 9-25 用两个函数分别求两个整数(a、b)的最大公约数和最小公倍数。分析:下图为求正整数 a、b最大公约数的程序框图,采用辗转相除的方法求取最大公

约数 m,获得最大公约数 m后,最小公倍数=a*b/最大公约数 m。用函数 hcf(a,b)求 a、b 的最大公约数 m,再用函数 lcd(a,b,m)来返回最小公倍数。

s

程序:hcf(a,b) /*定义函数 hcf*/int a,b;

{ int x,y,t,m,r;if(a>b)

{ t=a;a=b;b=t;} /*a、b交换*/x=a;y=b;while((r=y%x)!=0)

{ y=x;x=r;}

m=x;return(m);}

lcd(a,b,h) /*定义函数 lcd*/int a,b,h,

{ return(a*b/h);}

main(){ int a,b,h,l;

开始

输入a,b

求 a/b余数

r=0

b=>ar=>b

m<=b

输出m

结束

Page 173: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

printf("Input a,b please:");scanf("%d,%d",&d,&b);h=hcf(a,b);printf("\n H.C.F=%d\n",h);l=lcd(a,b,h);printf("L. C. D=%d\n",1);}

运行情况:Input a,b please:32,28H.C.F=4L.C.D=224

例 9-26 用一个函数判断是否为素数,并在主函数中判断一个整数是否为素数。分析:可以用 prime(num)来判定 num是否为素数,若是素数则返回值 1,不是素数

返回0,主函数中根据该返回值打印有关信息。程序:

main(){ int n;

printf("input a int number please:\n");scanf("%d",&n);if(prime(n))

printf("\n%d is prime number。",n);else

printf("\n%d is not prime number!",n);}

int prime(num) /*定义函数*/int num;

{ int f=1,m,k; k=sqrt(m);

for(m=2,m<k&&f= =1;m++)if(num%m= =0) f=0;return(f);}

例 9-27 定义一个带参数的宏,使两个参数的值互换,并在程序中交换两个值。#define SWAP(a,b) t=b;b=a;a=tmain()

{ int x,y,t;printf("input x,y please :");scanf("%d,%d",&x,&y);SWAP(x,y);printf("\n swap:x=%d,y=%d\n",x,y);}

运行情况:input x,y please :x,y:22,33↙swap:x=33,y=22

Page 174: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

例 9-28 三角形面积 area=√s(s--a)(s--b)(s--c),其中 s=1/2(a+b+c),a、b、c 为三角形三条边长,定义两个宏,一个用来求 s,另一个用来求 area,并在主函数中调用它。

#include 〈math.h〉#define S(a,b,c) ((a+b+c)/2)#define AREA(a,b,c)

(sqrt(S(a,b,c)*(S(a,b,c)-a)*(S(a,b,c)-b)*(S(s,b,c)-c)))

main(){ float a,b,c;

printf("input a,b,c please:");scanf("%f,%f,%f",&a,&b,&c);if(a+b>c&&a+c>b&&b+c>a)

printf("\narea is:%.2f\n",AREA(a,b,c));else

printf("error!");}

运行情况:(1)input a,b,c please:6,8,10↙

其面积为;24.00(2)input a,b,c please:2,7,4↙

error!

9.6 本章小结本章第一部分介绍了函数的定义和调用,理论上每个函数返回一个值(用 RETURN 语

句),但实际上有时可忽略(用 Void 说明函数类型)。C 语言中对函数的定义和说明是不同的概念,说明一个函数是让程序其他部分知道该函数以便调用它,定义一个函数则会给出函数本身的实际代码,同时前者函数形参表后一定有分号,后者函数的形参表后没有分号。

函数调用时要使形参和实参结合起来(称为形实结合),通常要做到数量、顺序和类型的一致,若类型不一致要进行自动转换,函数允许嵌套调用(但不允许嵌套定义),函数也允许递归调用。采用递归要注意:

(1)每一次递归应向它的解靠拢。(2)具有递归结束条件,不能无限递归下去,采用递归使程序简明扼要,但理解和调

试比较困难,递归有直接递归和间接递归两种方式。本章第二部分讲述了变量的类型。从作用域讲有外部变量和局部变量(自动型变量),

外部变量和局部变量是相对而言的。局部变量在结束定义它的函数之后就不再起作用,外部变量在两个函数之间保持它的值;从内存分配来看有静态变量(前加 static)和动态变量。静态变量可以是外部变量也可以是内部变量,当它是内部变量时作用域仅在函数内部,但不同于自动型变量的是它始终占有内存单元,在两个函数之间也保持它的值。

本章第三部分介绍了 C 预编译概念,叙述了宏的定义,文件包含和条件编译三个预处理语句。宏定义是用一串字符来替代一个名字,该串字符可以是常量,任何字串。宏定义中也可以带有参数(与函数调用不同,是展开为机内代码)。文件包含是一个程序把另一个

Page 175: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

程序内容包含进来。C 语言中包含大量带有.h 的文件(头文件),用户可以根据需要,把它包含进来,条件编译使一个程序在不同编译条件下生成不同的目标代码,通常帮助解决程序的移植问题,也可用于程序的调试。

9.7 练习题9.7.1选择题

1.以下不正确的描述为 。(A)调用函数时,实参可以是表达式(B)调用函数时,实参与形参可以共用内存单元(C)调用函数时,将为形参分配内存单元(D)调用函数时,实参与形参的类型必须一致2.以下正确的叙述是 。(A)C 语言的主函数是无参函数(B)C 语言的主函数最多允许有 1 个参数(C)C 语言的主函数最多允许 2 个参数 (D)C 语言的主函数可以有 2 个以上参数3.C 语言的函数 。(A)可以嵌套定义 (B)不可以嵌套调用(C)可以嵌套调用,但不能递归调用 (D)嵌套调用和递归调用均可4.C 语言中函数返回值的类型是由[ ]决定的。(A)return 语句的表达式类型 (B)调用该函数的主函数类型(C)调用函数时临时指定 (D)定义函数时所指定的函数类型5.若 x 为 int 型变量,则以下函数 fun 。

fun(x)…

(A)返回值 void 类型 (B)无法确定返回值(C)返回值为 int 类型 (D)没有返回值6.以下不正确的描述为 。(A)不同函数中可以使用相同名字的变量(B)形式参数是局部变量(C)一个函数内部定义的变量只能在本函数范围内有效(D)在一个函数内部的复合语句中定义的变量可以在本函数内有效7.C 语言规定,调用一个函数时,实参变量和形参变量之间的数据传递是 。(A)地址传递(B)值传递(C)由实参传给形参,并由形参传回来给实参(D)由用户指定传递方式8.若用数组名作为函数调用时的实参,则实际上传递给形参的是 。(A)数组首地址 (B)数组的每一个元素值(C)数组中全部元素的值 (D)数组元素的个数

Page 176: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

9.凡在函数中未指定存储类别的变量,其隐含的存储类别为 。(A)自动(auto) (B)静态(stati(C)(C)外部(extern) (D)寄存器(register)10.在 C 语言中,对于存储类型为 的变量,只有在使用它们时才占用内存单元。(A)static 和 auto (B)register 和 extern(C)register 和 static (D)auto 和 register11.在一个源程序中定义的全局变量的作用域为 。(A)本文件的全部范围(B)本程序的全部范围(C)本函数的全部范围(D)从定义该变量的位置开始至本文件结束12.在一个 C 源程序文件中,若要定义一个只允许本源文件中所有函数使用的全部变

量,则该变量需要使用的存储类别是 。(A)exten (B)register(C)auto (D)static13.以下不正确的描述为 。(A)在函数之外定义的变量称为外部变量,外部变量是全局变量(B)在一个函数中既可以使用本函数中的局部变量,又可以使用全局变量(C)外部变量定义和外部变量说明的含义不同(D)若有一个源文件中,外部变量与局部变量同名,则在局部变量的作用范围内,

外部变量不起作用14.以下正确的描述为 。(A)每个 C 语言程序必须在开头用预处理命令:#tinclude〈stdio.h〉(B)预处理命令必须位于 C 源程序的首部(C)在 C 语言中,预处理命令都是以"#"开头(D)C 语言的预处理命令只能实现宏定义和条件编译的功能15.以下有关宏替换的不正确叙述是 。(A)宏替换不占用运行时间 (B)宏名无类型(C)宏替换只是字符替换 (D)宏名必须用大写字母16.C 语言的编译系统对宏命名是 。(A)在程序运行时进行代换处理(B)在程序连接时进行代换处理(C)和源程序中其他语句同时编译的(D)对源程序中其他成分正式编译之前处理的17.若有宏定义如下:

#define X 5#define Y X+1#define Z Y*X/2

则执行以下 printf 语句后,输出结果为 。int a;a=Y;printf("%d\n",Z);printf("%d\n",--a);

(A)7 (B)12

Page 177: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

6 6(C)12 (D)7

5 518.若有以下宏定义:

#define N 2#define Y(n) ((N+1)*n)

则执行语句 z=2*(N+Y(5))后的结果为 。(A)语句的错误 (B)z=34(C)z=70 (D)z无定值19.若有宏定义#define MOD(x,y)x%y,则执行下列程序段后的输出为 。

int z,a=15,b=100;z=MOD(b,(A)printf("%d\n",z++);

(A)11 (B)10(C)6 (D)宏定义不合法20.若 adct均为 int 型变量,则执行下列程序段后的输出为 。

#define MAX(A,B) (A)>(B)? (A):(B)#define PRINT(Y) printf("Y=%d\t",Y)a=1;b=2;c=3;d=4;t=MAX(a+b,c+(D);PRINT(t);

(A)Y=3 (B)存在语法错误(C)Y=7 (D)Y=021.以下程序段 中存在错误。(A) #define array __ size 100

int array [array __size];(B) #dehne PI 3.14159

#define S(r) PI*(r)*(r)

area=S(3.2);(C) #define PI 3.14159

#define S(r) PI*(r)*(r)

area=S(a+b);(D) #define PI 3.14159

#define S(r) PI*(r)x(r)area=S(a);

22.运行下面程序的 w 值为 。main( )

{ int w=2,k;

Page 178: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

for(k=0;k<3;k++){ w=f(w);

printf("%d\n",w);}

}f(x)int x;

{ int y=0;static z=3;y++;z++;return(x+y+z);}

(A)20 (B)7(C)28 (D)1323.下面程序正确的运行结果为 。

#include〈stdio.h〉main()

{ int j=4,m=1,k;k=fun(j,m);printf("%d,",k);k=fun(j,m);printf("%d\n",k);}

fun(x,y)int x,y;

{ static int m=0,i=2;i+=m+1;m=i+x+y;return(m);}

(A)8,20 (B)8,8(C)8,17 (D)8,1624.下列程序正确的运行结果为 。

#include〈stdio.h〉int x,y;num( )

{ int a=15,b=10; int x,y;x=a-b;y=a+b;return;}

main(){ int a=7,b=5;

Page 179: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

x=a+b;y=a-b;

num();printf("%d,%d\n",x,y);}

(A)12,2 (B)5,20(C)2,12 (D)不确定25.下列程序正确的运行结果为 。

#include〈stdio.h〉num()

{ extern int x,y;int a=15,b=10;x=a-b;y=a+b;

}int x,y;main( )

{ int a=7,b=5;x=a+b;y=a-b;num();printf("%d,%d\n",x,y);

}(A)12,2 (B)不确定(C)5,15 (D)2,12

9.7.2填空题1.请在下面对应的 上写出表达式的结果。(1)sqrt(fabs(一 25.0)) (2)strlen("CHINA")+strlen(℃") (3)strcmp("CHINA","china") 2.设有以下函数 pow:

pow(x,y)int x,y;

{ int i,j;j=1; .for(i=1;i<=y;++i)

j=j*x;return(j);

}现要求取消变量 i,请在以下函数 pow 的 上填入正确的内容。

pow(x,y)

Page 180: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

int x,y{ int j;

for( ; ; )i=i *x;return(j);}

3.以下函数 fun 用于求两个整数 a 和 b 的最大公约数。fun(a,(B)int a,b;

{ int i,j,m,n;if(a>(B)

{ m=a,a=b; ;} i=a,j=b;while((n= )!=0)

{ j=i,i= ;}return(i);

}4.在内存中供用户使用的存储区可分为三部分,它们是 , , ,全局变量应放在

中,局部变量应放在 中。5.设有宏定义如下:

#define MIN(x,y) (x)<(y)?(x):(y)#define T(x,y,r) x*y*r/4

则执行以下语句后,s1 的值为 ,s2 的值为 。int a=1,b=3,c=5,s1,s2;s1=MIN(a=b,b-a);s2=T(a++,a*++b,a+b+c);

6.若运行下列程序时,输入以下指定数据,则程序的运行结果为 。#include〈stdio.h〉main()

{ printf("\n");sty();printf("\n");

}sty()

{ Char ch;if(ch=getchar())!='\n')sty( );putchar(ch);}

输人数据:stuvwxyz〈回车〉7.以下程序完成的功能是 。

#include〈stdio.h〉#define SIZE 10void fun(int num[SIZE]);

Page 181: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

main(){ int i,a[SIZE];

printf("input %d numbers:\n",SIZE);for(i=0;i<SIZE;i++)

scanf("%d",&a[i]);fun(a);for(i=0;i<SIZE;i++)printf("%5d",a[i]);}void fun(int num[SIZE])

{ int i,j,k;for(i=0;i<SIZE 一 1;i++)for(j=0;j<SIZE-i-1;j++)if(num[j]>num[j+1])

{ k=num[j];num[j]=num[j+1]num[j+1]=k;}

}8.下面程序的运行结果为 。

int x1=30,x2=40;main()

{ int x3=10,x4=20;sub(x3,x4);sub(x2,x1);printf("%d,%d,%d,%d\n",x3,x4,x1,x2):}

sub(x,y)int x,y;

{ xl=x;x=y;y=x1;}

9.下面程序能够统计主函数调用 count 函数的次数(用字符#作为结束输入标志),请在 处填入正确内容。

main( ){ char ch;

while( ){ scanf("%1s",&ch);

count( );if( )

break;}

}count(char c)

{ static int i=0;

Page 182: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

i++;if([4])printf("count=%d\n",i);

}10.下面程序的运行结果为 。

#include<stdio.h>main( )

{ int i=4,j;for(j=0;j<i;j++)pic(28-j,'');pic(i+2*j,'*');putchar('\n');for(j=2;j>=0;j--)

{ pic(30-j,'');pic(i+2*j,'*');putchar('\n');}

}pic(len,c)int len;char c;

{ int k;for(k=1;k<=1en;k++) putchar((C);}

11.下面程序能够完成以下数学函数 A(x,y)的计算,请在 处填人正确内容。A(x,y)=x*x/(ez(x-y)+√1+2ex-y+3ez(x-y))#include<stdio.h>#include<math.h>main()

{ float,x,y,f1,fun();scanf("%f%f,&x,&y);f1=x*x/fun( ); printf("A=%f\n",f1);}

float fun(float f){ float f2;

f2=f*f+sqrt(1+ + );return(f2);}

12.下面程序的运行结果为 。#include<stdio.h>int k=1;main(){ int i=4;

Page 183: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

fun(i);printf("%d,%d\n",i,k);}

fun(m)int m;

{ m+=k;k+=m;{char k='B';printf("%d\n",k-'A');}printf("%d.%d\n",m,k);

}13.下面程序的运行结果为 。

#include<stdio.h>int abc(int u,int v);void main()

{ int a=24,b=16,c;c=abc(a,b);printf("value=%d",c);}

int abc(int u,int v){ int w;

while(v){ w=u%v;

u=v;v=w;}

return u;}

14.若运行下列程序,输入以下指定数据,请回答下面问题,将答案填人 中。main( );

{ int w,s,sum( );w=1;while(w! =0)

{ scanf("%d",&w);if(w!=0)

{ s=sum(w);printf("%d,%d\n",w,s);}

}}

int sum(n)int n;

{ int s;static int total=0;

Page 184: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 9 章 函数与变量类型

if(n<50) s=1*n;else s=50*1+(n-50)*2;total+=s;return(total);}

输人数据(第一列);10 20 0<回车)问题:此程序的运行结果为 。若将 sum 函数中的语句:

static int total=0;改为:

int total=0;则程序的运行结果为 。15.下面程序的运行结果为 。

main( ){ int i=5;

printf("%d\n",sub(i));}

sub(n) int n;{ int a;

if(n= =1)return 1;a=n+sub(n-1);return((A);}

Page 185: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 10 章 数组

第 10 章 数 组10.1 一维数组10.2 二维数组10.3 字符数组和字符串

10.3.1 字符数组的定义和初始化10.3.2 字符串和字符串结束标志10.3.3 字符数组的输入和输出10.3.4 字符串处理函数

10.4 例题详解10.6 练习题

第 10 章 数 组在程序设计中经常需要对若干个同类型的数据和变量进行分析和处理。例如,在统计

学生成绩时,若以 10 分为一档,那么程序中需要设置 10 个计数器,这些计数器的类型及对它的操作基本相同。如果对它们分别进行说明,那么在程序中使用就不会很方便,为了能够编写简明有效的程序,需要把这些变量有序地组织起来,这就是数组。

数组所表示对象的范围是相当广泛的。例如,一行正文可以表示成一个由字符组成的数组,一个向量可以表示成由一个整数或浮点数组成的数组;矩阵由若干列向量所组成,也可以表示成一个数组。

构成一个数组的各个元素称为数组元素,它们之间有一定的制约关系。首先必须是同一种类型的变量,不允许同一数组中出现不同类型的变量。例如,对字符数组中每个元素都具有字符类型,对整型数组来说每个元素必须是整型。其次,它们是有序的,通过数组的“下标”可以依次访问它们。

10.1 一维数组把若干个同类元素线性地组合起来可构成一维数组,在使用一维数组之前必须先对它

进行定义。一维数组定义的一般形式是:

类型说明符 数组名[常量表达式 l例如:

int xyz[20);它表明数组名为 xyz,它有 20 个元素。注意:(1)数组名定义应符合标识符要求;(2)数组名后是方括号([ ],不能用圆括号);(3)方括号中常量表达式表示数组中元素的个数,即数组的长度,例如 xyz[20]表示

数组 xyz 共有 20 个元素:xyz[0]、xyz[1]、xyz[2]、…、xyz[18]、xyz[19]。请注意,元素编号总是从 0 开始,直到 n-l 为止,因此千万不能使用 xyz[20];

(4)C 语言中不允许用变量定义数组大小,即不允许对数组大小作动态定义。下面的定义是错误的:

Page 186: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 10 章 数组

int n;scanf("%d" ,&n);int a[n];……

C 语言中规定只能对数组元素操作,而不能对整个数组进行操作。数组元素在数组中自编号称为“下标”,其值从 0~n 一 1,但要注意,C 语言中对数组的下标变量值不作合法性检查,允许数组下标越界,应引起程序员的注意,避免产生错误。

例 10-1main(){ int i,a[10];

for(i=0;i<10;i++){ a[i]=i*2; /*对数组赋值* /

printf("%d"a[i]); /*打印* /}

}运行结果:0 2 4 6 8 10 12 14 16 18例 10-2 给出斐波那契数列前 20项之值(斐波那契数列第 0、1项均为 l,第 2项起为前

两项之和)。main(){ int m ,n ,fib[20];

fib[0]=1; fib[l]=1; /*定义斐波那契第 0,l项* /for(n=2;n<20;n++)

fib[n]=fib[n 一 2]+fib[n 一 1] /*计算后 18 个元素值* /for(m=0;m<20;m++){ if(m%5==0)printf(" \n");

printf("%l0d" ,fib[m]); /*每行输出 5 个数* /}

}运行结果: 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610987 1597 2584 4181 6765例 10-3 用冒泡法对 10 个输入的数进行排序(由小到大)。

冒泡法是排序的一种方法,它将两个相邻数进行比较,把小的数调到前面(见图 11-1)。

原始数据 第一次交换后 第二次交换后 第三次交换后a[6] 6 2 2 2a[5] 7 6 3 3a[4] 3 7 6 5a[3] 8 3 7 6a[2] 2 8 5 7a[1] 5 5 8 8图 11-1 冒泡法排序程序如下:

main(){ int a[11] /*定义数组 a 有 11 个元素,使用 1~10* /

Page 187: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 10 章 数组

int i ,j ,k;printf("input 10 numbers:\n");for(i=1;i<=10;i++)

scanf("%d" ,&a[i]); /*输入 10 个数据* /printf(" \n");for(j=1;j<=9;j++)

for(i=1;i<=10 一 j;i++)if(a[i]>a[i+1])

{k=a[i];a[i]=a[i+1];a[i+1]=k;}printf("The sorted numbers are:\n");for(i=1;i<=10;i++)printf( "%5d " ,a[i]);}运行情况:

input 10 numbers:2 10 5 —42 37 85 —22 46 98 54The sorted numbors are:—42 —22 2 5 10 37 46 54 85 98

在以上例子中用赋值语句或 for 语句来对一维数组赋初值,需占用运行时间。我们也可以使数组在程序运行之前初始化,即在运行之时获得初值。

1.在定义下列数组时赋予初值:static int a[10]={0,1,2,3,4,5,6,7,8,9};

(1)初始化时前面加上 static(静态存储)或 extern(外部存储),即 C 语言规定只有静态存储的数组或外部存储的数组才能初始化;

(2)初始化值放在花括号中,从 a[0]开始初始化,本例中 a[0]=0,a[1]=1,a[2]=2,…,a[9]=9。

2.允许给部分元素初始化:static int a[10]={0 ,1 ,2 ,3 ,4 ,5};

表明对前 6 个元素(a[0]~a[5])进行初始化,后 4 个元素(a[6]~a[9])值为 0。3.若给一个数组元素全部赋为零,可写成:

static int a[10]={0,0,0,0,0,0,0,0,0,0};也可直接写为:

static int a[10];即对静态存储数组,系统会对所有元素自动赋值为零。

4.在对全部数组元素赋初值时可以不指定数组的长度。例如:static int a[ ]={1 ,2 ,3 ,4 ,5 ,6};

等效于:static int a[6]={1 ,2 ,3 ,4 ,5 ,6};

在第一种写法中,花括号中有 6 个元素,因此数组 a 自动定义长度为 6,但如果被定义的数组长度与提供初值的个数不相同时不能节省数组长度。

10.2 二维数组二维数组定义的一般形式是:

Page 188: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 10 章 数组

类型说明符 数组名[常量表达式][常量表达式];例如:

float abc[3][5],xyz[4][6];定义数组 abc 为 3 行 5列,xyz 为 4 行 6列。注意不能写成:abc[3,5]或 xyz[4,6]。C 语言中二维数组最右边的下标变化最快,例如数组 a[3][2]存放的次序为:a[0]

[0],a[0] [1],a[1][0],a[1][1],a[2][0],a[2][1],实际上,把数组 a可以理解为三个一维数组名的集合,见图 10-2。

要注意 a[m][n]的下标值,行下标为 0~m 一 1,列下标为 0~n 一 1。请读者严格区别数组定义和数组元素引用间的区别,定义 a[3][2]是用来说明数组的维

数和各维大小;引用 a[3][2]时,3、2 为下标值代表某一个元素。二维数组初始化方法:(1)分行给二维数组赋初值,例如:

static int a[3][4]={{l ,2 ,3 ,4} ,{5 ,6 ,7 ,8} ,{9 ,10 ,1l ,12}};这种赋值方法非常直观,第一个花括号中数据赋给二维数值的第一行,第二个花括号中数据赋给第二行……

(2)也可以将所有数据一起写在一个花括号内,但效果不如第一种好,尤其数据较多时,易于遗漏,也不易检查,例如:

static int a[3][4]={1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12};(3)可以对部分元素赋值,其他元素自动装置为 0,例如:

static int a[3][4]={{1} ,{2) ,{3}};赋初值后,数组 a 中元素为:

(4)如果对全部元素都赋值,则数组第一维长度可以不指定,但第二维长度必须指定,例如:

static int a[ ][4]={1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10}例 10-4 将二维数组 a 中的行列转置后放入二维数组 b 中。例如:1 2 3 1 4

a= → b= 2 54 5 6 3 6

main(){ static int a[2][3]={{1,2,3},{4,5,6}};

static int i,j,b[3][2];printf("Array a is\n");for(i=0;i<=1;i++)

{for (j=0;j<=2;j++){printf ( "%5d " ,a[i][j]);

b[j][i]=a[i][j]];}

aa[0]……a[0][0] a[0][1]a[1]……a[1][0] a[1][1]a[2]……a[2][0] a[2][1]

图 10-2 二维数组

0 0 00 0 00 0 0

Page 189: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 10 章 数组

printf( " \n ");}

printf( "Array b is \n ");for(i=0;i<=2;i++){for(j=0;j<=1;j++) printf( "%5d" ,b[i][j]);

printf( " \n ");}

}例 10-5 打印杨辉三角形(10 行)。l1 1l 2 ll 3 3 11 4 6 4 1……分析:杨辉三角形可用矩形(10×10)表示,第一列和对角线元素均为 1,其他各元素

为 a[i-1][j-1]+a[i-1][j],可用双重循环实现。程序如下:# denne N 11;main(){ int i,j,a[N][N];

for(i=1;i<N;i++) /*建立杨辉三角形* /{a[i][i]=1 ,a[i][1]=1;}

for(i=3;i<N;i++)for(j=2;j<=i-1;j++)

a[i][j]=a[i-1][j-1]+a[i-1][j];for(i=1;i<N;i++) /*打印输出* /

{ for(j=1;j<=i;j++)printf("%6d" ,a[i][j]);printf(" \n")}

printf(" \n");}运行结果如下:

ll ll 2 1l 3 3 11 4 6 4 ll 5 10 10 5 l1 6 15 20 15 6 11 7 2l 35 35 21 7 ll 8 28 56 70 56 28 8 l 1 9 36 84 126 126 84 36 9 1

10.3 字符数组和字符串10.3.1 字符数组的定义和初始化

Page 190: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 10 章 数组

用来存放字符的数组是字符数组。字符数组的定义与其他数组定义类似。例如:char s[10];s[0]='I';s[1]='';s[2]='a';s[3]='m';s[4]='';s[5]='h';s[6]='a';s[7]='p';s[8]='p';s[9]='y';赋值数组 s 的值如下所示:

s[0] s[1] s[2] s[3] s[4] s[5] s[6] s[7] s[8] s[9]I a m h a p p y

由于字符型与整型可以互相转化,因此上述定义也可以改为:int s[10];

对字符数组初始化,最易理解的是逐个字符赋值。例如:static char s[10]={'I','','a','m','','h','a','p',

'p','y'};把 10 个字符分别赋给 s[0]~s[9]。如果花括号中提供值的个数(字符个数)大于数组长

度,则为语法出错;如果小于数组长度,则将字符赋予前面那些元素,其余元素自动定义为空格,如果等于数组长度,定义时可以省略数组长度。同理也可以定义二维字符数组,例如:

static char diamond[5][5]={'','','*'},{'','*','','*'},{'*','','','','*'},{'','*','','*'},{'','','*')};

定义后,二维数组 diamond代表一个钻石型平面图形: * * * * * * * *

10.3.2 字符串和字符串结束标志C 语言中,将字符串作为字符数组处理,有时人们关心的是有效字符串的长度而不是

所定义的数组长度(例如一个字符数组定义长度为 100而实际存放的字串长度仅 20)。为测定字符串长度,C 语言中规定了一个“字符串结束标志”,以字符'\0'代表,即遇到字符'\0'时表示字符串结束。

系统对字符串常量也自动加上'\0'作为结束符。例如“The C program.”共有 14 个字符,但内存中占有 15 个字节,最后一个字节放'\0'。在ASCII 码中代码为 0 的字符是不可显示的“空操作符”,它什么也不干,仅仅作为

字符串结束标志,不会产生附加的效应。需要说明的是,字符数组并不要求它的最后一个字符是'\0',甚至可以不包含'\0

',但只要用字符串常量就会自动加上'\0'。有时为了处理一致,便于字符串测定,在字符数组中也人为地加上一个'\0'。例如:

static char s[6]={ 'C' ,'h','i','n' ,'a' ,'\0'}对于字符数组初始化 ,也可以采用字符串常量。例如:

static charc[ ]={"I am a student "};或 static char c[ ]="I am a student";后者省略了花括号,此时字符数组 c 的长度不是 14而是 15,它与

Page 191: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

str1

第 10 章 数组

static char c[ ]={'I','','a','m','','a','','s','t','u','d','e','n',t','\0')

完全等价。10.3.3 字符数组的输入和输出可用格式符"%c"输入或输出一个字符,也可用"%s"输入或输出一个字符串

(string)。例如:static char c[ ]="China";printf("%s" ,c);

此时内存中数据为:C h i n a \0

输出时遇到结束符'\0'就停止输出,其输出为:China注意:

(1)用"%s"输出时,printf 中为字符数组名,而不是数组元素名,因此不能写成:printf("%s",c[0]);

(2)如果数组长度大于字符串实际长度时,也只遇到' \0'结束,例如:static chr c[20]="I am a student";printf("%s",c);

输出"I am a student"14 个字符,而不会输出 20 个字符。(3)若一个字符数组中包含一个以上的'\0'时,则遇到第一个'\0'就结束输出。(4)字符串输入时是以空格分隔字符串的。例如:

static char strl[6],str2[6],str3[9];scanf("%s%s%s",str1,str2,str3); /*注意不加&* /

输入数据:we are students↙输入后三个数组状态为:

W e \0 □ □ □

a R e \0 □ □

s T u d e n t s \0

如果改为:static char str[16];scanf("%s" ,str);

输入数据:we are students↙实际上不把这 15 个字符再加一个'\0'进入 str 中,而只将数据前的 we 作为一个字

符串,再加上'\0'进入 str。(5)输入时字符'\0'不会被输出。

(6)scan 函数中采用数组名,前面不加'&',因此不能够写成:scanf("%s" ,&str);

因为 C 语言编译系统对数组名的处理是:数组名代表该数组的起始地位。

str2

str3

Page 192: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 10 章 数组

10.3.4 字符串处理函数C 函数库中提供一些处理字符串的函数,使用较为方便。(1)puts(字符数组)。屏幕上输出字符数组内容(以'\0'结束),由于可以用

printf来输出字符串,因此 puts 函数用得不太多(puts只能输出一个字符串)。(2)gets(字符数组)。从键盘输入一个字符串到字符数组并返回字符数组的起始地

位(只能输入一个字符串,不能写成 gets(strl,str2)。(3)strcat(strl ,str2)。把 str2接到 strl后面,结果放在 strl 中,并返回 strl 的起始地

址。例如:static strl[30]="People's Republic of";static str2[ ]="China";printf("%s" ,strcat (strl ,str2));

输出:People's Republic of China说明:

·strl 必须足够大,能容纳连接后生成的新字符串。本例中定义 strl长度为 30。若定义为static strl[ ]="People's Republic of";就会出问题。

·连接之前 strl,str2均以' \0'结尾,连接后 strl后面的' \0'被取消,只在新串后面保留一个' \0'。

(4)strcpy(字符数组 1,字符串 2)。该函数把字符串 2"拷贝"到字符数组 1 中。例如:

static strl[10] ,str2[ ]="China";strcpy (strl ,str2);

执行后 strl 内容为:C H i n a \0

说明:·字符数组 1 的大小必须大于或等于字符串 2 的长度。·字符数组 1必须写成数组名形式(如 strl),字符串 2可以是数组名也可以是字符串

常量。例如:strcpy (strl,"China");

作用与前相同。·拷贝时连同字符串末尾的'\0'一起拷贝。·不能用赋值语句把一个字符串常量或字符数组直接赋予一个字符数组。例如:

strl="China";str2=strl;

都是错误的,赋值语句只能够将一个字符赋给变量或字符数组元素。·可以用 strcpy 函数将字符串 2 中前面若干个字符拷贝到字符数组 1 中去。例如:

strcpy(strl,str2 ,3);它将 str2 中前面 3 个字符拷贝到 strl 中去,然后再加上一个'\0'。

(5)strcmp(strl,str2)。用该函数比较 strl,str2两字符串,字符从左向右逐个比较(按ASCII 码值)。如果 strl=str2返回函数值为 0;如果 strl>str2 函数值为一正整数;如果 strl<str2 函数值为一负整数。注意:对两个字符串比较不能采用 strl==str2 形式,即不能用

if (strl==str2) printf("yes");

Page 193: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 10 章 数组

只能用if(strcmp(strl ,str2)==0) printf("yes");

(6)strlen(str)。测试字符数组 str 的长度(不包含'\0'在内)。例如:static char s[10]={"Beijing";}printf("%d",strlen(s));

输出结果不是 10也不是 8,而是 7。(7)strlwr(str)。把字符串 str 中的大写字母转换为小写字母(1wr是 lowercase 的缩

写)。(8)strupr(str)。把字符串 str 的小写字母转换为大写字母(urp是 uppercase 的缩

写)。10.4 例题详解

例 10-6 输入一行字符串,统计其中有多少个单词,单词之间用空格隔开。分析:单词数目可以由空格数目决定(连续若干个空格作为一次空格,且一行开头空

格不计在内)。若某一个字符为非空格,而它前面的字符是空格,则说明“新的单词”开始,可使单词数(words)加 1,前面是否为空格可用 space=1(空格)和 space=0(非空格)来标志。

程序:# include <stdio .h>main()

{ char string[80];int i ,words=0 ,space=1;int i,words=0,space=1;char ch;gets (string);for(i=0;ch=string[i]!=' \0';i++)if(ch= ='')space=1;else if(space= =1)

{space=0;words++;}printf("There are %d words.\n",words);

}运行情况:This is a C program! ↙There are 5 words.例 10-7 求一个 3×3矩阵对角线元素之和。main()

{ floata[3][3] ,sum=0;int i ,j;printf("input elements please: \n");for(i=0;i<3;i++)for(j=0;j<3;j++)

scanf("%f" ,&a[i][j]);for(i=0;i<3;i++)

sum=sum+a[i][j];

Page 194: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 10 章 数组

printf("sum=%.2f" ,sum);}运行情况:input elements please:1.25 3.12 5.3↙2.21 4.35 6.71↙3.33 5.15 8.37↙sum=13.97

10.5 本章小结数组是程序设计中使用十分广泛的一种数据结构,它由同类型有序的若干元素组成。

通过数组“下标”可以依次对数组元素进行访问。在 C 语言中只能对数组元素进行操作,而不能对整个数组操作,同时数组名实际上是一个地址(指针),指向内存中数组第一个元素的地址。

数组定义时规定了数组大小(n),下标使用时从 0到 n-1,但 C 语言中不对下标“越界”作任何语法检查,由程序人员自己控制,因此需格外小心。

二维数组定义时必须写两个方括号。例如 x[2][3],表示 x 为 2 行 3列的数组,不能写成x[2,3],这是与其他程序设计语言不同的地方。对数组 x[m][n],下标的使用也是 0~m-1和 0~n-1。多维数组概念与二维数组类同。

数组初始化有各种不同的方法,若定义数值时就进行初始化,应加上 static(静态存储)。例如 static int x[5]={1,2,3,4,5};,也可对部分元素初始化,例如 static int x[l0]={0,1,2,3};(后 6 个元素自动置 0)。当对全部元素赋值时也可以不定指数组长度,例如 static int x[ ]={0,1,2,3,4};但这种情况下,对二维数组赋值时第一维长度可以不指定,第二维长度必须指定。例如,static int x[ ][4]={1,2,3,4,5,6,7,8};。

C 语言中存放字符的数组称为字符数组,其操作与一般数组相类似,例如,static char c[l4]={'I','','a','m','','a','','s','t','u','d','e','n','t'};这 14 个字符分别放在 c[0]~c[l3]中。字符串可作为字符数组来处理。由于人们比较关心的是字符串长度。因比 C 语言中用' \0'作为字符串的结束符。例如"I am a student"有 14 个字符。但实际上占有 15 个内存字节。同样 static char c"I am a student";(注意,用双引号)共有 14 个元素加上一个' \0'符。而 c[l4]=' \0'。输入一个字符串时,scanf 中不能用'&'符号(因为字符数组名相当于一个地址),同时遇到空格作为一个字符串输入结束的标志。

有关字符串中的函数很多,读者可参考有关手册,本章介绍了puts、gets、strcat、strcpy、strcmp、strlen、strlwr 及 strupr 共 8 个函数,请掌握它们的调用方法及所完成的字符串处理功能。

10.6 练习题10.6.1选择题

1.若有以下语句,则下面 是正确的描述。Static char x[ ]="12345";Static char y[ ]={'l' ,'2' ,'3' ,'4' ,'5'};

(A)x 数组和 y 数组的长度相同。 (B)x 数组长度大于 y 数组长度。(C)x 数组长度小于 y 数组长度。 (D)x 数组等价于 y 数组。

Page 195: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 10 章 数组

2.为了比较两个字符串 s1 和 s2是否相等,应当使用 。(A)if(s1=s2) (B)if(sl=s2)(C)if(strcpy(sl,s2)) (D)if(strcmp(s1,s2)==0)3.(多项选择)若有语句:char strl[10],str2[10]={"books"};则能将字符串 books

赋给数组 strl 的正确语句是 。(A)strl={"books"}; (B)strcpy(strl,str2);(C)strl=str2; (D)strcpy(str2,strl);4.以下程序的输出是 。

static char a[ ]="-12345";int k=0 ,symbol ,m;if(a[k]= ='+'‖a[k]= ='一')填

symbol=(a[k++]= ='+')?1:-1;for(m=0;a[k]>='0'&&a[k]<='9';k++)

m=m*l0+a[k]一'0';printf("number=%d \n" ,symbol*m);

(A)number=一 12345 (B)number=12345(C)number=一 1000 (D)number=100005.下面程序正确的运行结果为 。

#include<stdipo.h>#include<string.h>main( ){ char s[10]\{'s','t','n','d','e','n','t'};

printf("%d\n" ,strlen(s));}(A)7 (B)8

(C)9 (D)146.下列程序正确的运行结果为 。

main( ){ static char str[ ]="abcdef";

abc(str)printf("str[ ]=%s\n" ,str):}

abc(str)char str[ ];

{ int a ,b;for(a=b=0;str[a]!=0='\0';a++)if(str[a]!='c')

str[b++]=str[a];str[b]='\0';}(A)str[ ]=abdef (B)str[ ]=abcdef

(C)str[ ]=a (D)程序中有语法错误10.6.2填空题

1.若有说明 static char str[ ]="abcdefghij";请在以下各 printf 语句后的 中写出相

Page 196: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 10 章 数组

应的输出结果。(1)printf("%%%20s%% \n" ,str); (2)printf("%%%-20s%% \n" ,str); 2.执行以下程序段后,s 的值为 。

static char ch[ ]="600";int a,s=0for(a=0;ch[a]>='0'&&ch[a]<='9';a++)s=10*s+ch[a]一'0';

3.没有说明 charstr[20];如果想从终端上把以下字符;this is a book,送到数组 str 中,应当调用 [1] 函数,调用形式为 [2] 。

4.下面函数用于确定一个给定字符串 str 的长度。strlen(str)char str[ ];

{ int num;num=0; while( )++num;return( );}

5.下面函数用于统计一行字符中的单词个数,单词之间用空格分开。word_num(str)char str[ ];

{ int i ,num=0 ,word=0;for(i=0 ,str[i]!= ;i++)if( = =' ') word=0;else if(word= =0)

{ word=1; ;}

return(num);}

6.以下函数用于求出一个 2×4矩阵中的最大元素值。max_ value(arr)int arr[ ][4];

{ int i ,j ,max;max=art[0][0];for(i=0; ;i++)for(j=0; ;i++)if( >max)max= return(max);}

7.以下函数 inverse 的功能是使一个字符串按逆序存放。inverse(str)charstr[ ];

{ char m; int i ,j;for(i=0 ,j=strlen(str);i< ;i++ , )

Page 197: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 10 章 数组

{ m=str[i];str[i]= = ; }

}8.以下函数 conj把两个字符串 s1 和 s2连接起来。

conj(s1 ,s2)charsl[ ] ,s2[ ];

{ int i=0 ,i=0;while(s1[i]!= )

i++;while(s2[j]!= )

s1[++]= ='\0';

}9.以下函数 cpy把字符数组 s2 中的全部字符复制到字符数组 s1 中 ,复制时'/0'也

要复制过去,'\'后面的字符不用复制。cpy(s1 ,s2)char s1[ ] ,s2[ ];

{ int i;for(i=0 ,i<=strlen( );i++)s1[i]= ;}

10.下面函数 chnum将一个整数字符串(放在字符数组 str 中)转换为一个整数num,num将作为函数的返回值。

int chnum(str)charstr[ ];

{ int i,j,k,h,len,num=0;len=strlen(str);for(i=0; ;i++)

{ k=1;j=len=len-1;while( )

{ k=k*10;j--;}

h= -48;num=num+h*

}return(num);}

11.下面 count 函数用来计算子串 subter在母串 str 中出现的次数 ,请填空。count(str ,substr)char*str ,*substr

{ int x ,y ,z;int num=0;for(x=0 ,str[x]!= ;x++)

Page 198: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 10 章 数组

for(y= ,z=0;substr[z]= =str[y];z++;y++)if(substr[ ]= =NULL)

{ num++;break;}return( );}

12.以下函数 del-blank可以删除字符串中的所有空白(包括空格,制表符,回车符,换行符等),请在 内填人正确的内容。

#include<stdio.h>#include<ctype.h>del_blank(str> str;

{ int i ,temp;chart str[81];for(i=0 ,temp=0;str[i]!= ; )if(isspace( )= =0)

tstr[ ]=str[i];tstr[temp]=NULL;strcpy(str ,tstr);printf("the deleted string is:%s\n " ,tstr);}

13.以下 substr 函数用于确定字符串 sl是否为 s 的子串,如果 s1 不是 s 的子串,函数返回 0,否则返回子符串 sl,在 s 中第一次出现时其第一个字符的位置。 请填空。例如;s="computer=com",s1="om",函数 substr(s1,s)返回 2。

substr(s1 ,s)

{ int x=0 ,y=0;while(s1[x]!= &&s[x]!='\0')if(s[x++]!=s[y++])

{ y-= ;x=0;}

if(s1[x]= ='\0')return( );return(0);}

14.若运行下列程序时,输入以下指定数据,则下面程序的运行结果为 。#include<stdio.h>main()

{ int i ,s;char sl[l00] ,s2[100];printf("Input stringl:\n");gets(s1);printf("Input string2:\n");gets(s2);i=0;while((s1[i]= =s2[i])&&(s1[i]!='\n'))

Page 199: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 10 章 数组

i++;if(s1[i]= ='\0'&&s2[i]= ='\n')

s=0;else

s=s1[i]-s2[i];prinf("%d\n" ,s);

}输人数据(第一列):aid(回车)and{回车}

15.阅读下面程序,将问题的答案填人对应的 中。main( )

{ int s[4][4] ,i ,j ,k;for(i=0;i<4;i++)for(j=0;j<4;j++)

s[i][j]=i-j;for(i=0;i<3;i++)for(j=i+1;j<4;j++)

{ k=s[i][j];s[i][j]=s[j][I];s[j][i]=k;}

for(i=0;i<4;i++){ printf("\n");

for(j=0;j<4;j++)print("%4d" ,s[i][j]);

}}问题:

(1)此程序的运行结果为 。(2)若将程序中的 for(j=i+1;j<4;j++)改成 for(j=0;j<3-i;j++),则此程序的运行结果为 。

Page 200: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 10 章 数组

Page 201: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

第 11 章 指 针11.1 指针的概念11.2 指针和指针变量

11.2.1 指针变量定义11.2.2 指针变量引用

11.3 数组和指针11.3.1 通过指针访问数组元素11.3.2 数组作为函数参数11.3.3 指向多维数组的指针和指针变量

11.4 字符串和指针11.4.1 字符串的表达形式11.4.2 字符串指针作函数参数

11.5 函数与指针11.5.1 指针函数11.5.2 函数指针

11.6 指针数组和指向指针的指针11.6.1 指针数组11.6.2 指向指针的指针

11.7 Turbo C 的内存分配函数11.8 本章小结11.9 练习题

第 11 章 指 针指针是 C 语言中一个重要的概念,是 C 语言的一个重要特色,也是我们学习中的一个

难点,每一个学习 C 语言的人都应该深入学习和掌握指针的概念和应用,可以说不掌隆指针就不掌握 C 语言的精华,读者在学习本章内容时务必多思考、多比较、多实践,逐步掌握它。

11.1 指针的概念如果程序中定义了一个变量,在编译时就给这个变量分配内存空间,系统根据变量的

Page 202: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

类型进行分配,例如,许多微机的 C 语言系统对整型变量分配连续的两个字节,实型变量四个字节,字符变量一个字节……。内存在每一个字节都有一个编号,称为“地址”,相当于房间号码,在地址所标志的单元中存放数据(相当房间中的旅客),因此务必弄清内存单元的地址与内存单元内容这两个概念的区别。

图 11-1 为内存中存放数据的示意图,假定程序中定义了二个整型变量 a,b 及一个实型变量 c,编译时可能把 2000 和 2001两个字节分配给变量 a,2002,2003 分配给变量 b,2004-2007四个字节分配给变量 c,这样在内存中就不再有 a,b,c这些变量名,而是通过它们的地址进行输入或输出。

例如:pintf(″%d″,a);

根据变量名 a 与地址对应关系,找到其地址为 2000,然后从 2000 开始的两个字节中取出数据(即变量 a 的值 5),然后输出到屏幕上,再如,seanf(″%f″,&c)就把磁盘输入的值(7.2)送人变量 c 的地址 2004 开始的四个字节中,这种按照变量地址存取变量值方式称为“直接访问方式”。另一种访问内存的方法称为“间接访问方式”,变量 a 的地址(2000)放入另一内存

单元(3000 和 3001 中),即其内容为&a,此时要存取变量 a 的值,首先通过寻找 a-pointer的值(即 2000),然后再由 a-pointer 中的值,去寻找 a 的值,正如你到房间 3000去寻找某个朋友,但发现一张留言条,告诉你他已去 2000房间,那么你得到的将是一个“地址”,再根据这个地址到 2000房间找到你的朋友。在 C 语言中,一个变量的地址称为该变量的指针,例如地址 2000是变量 a 的指针;如

果有一个变量专门用来存放另一个变量的地址(指针),那么称它是指针变量,上述 a-pointer就是一个指针变量,因此指针变量中的值不是变量而是指针(地址),因此一定要区分指针和指针变量的不同概念,因此我们说变量 a 的指针是 2000,而不能说它的指针的变量是 2000。在不同机器上,或在同一机器上不同的运行时间,变量的分配地址是不确定的,即&a

的值可能会发生变化,但无论&a返回什么值它都是分配给变量 a 的存储空间地址,困此不应该人为对&a 赋值,例如写成&a=2000;是错误的。

11.2 指针和指针变量变量的指针是一个地址,可以定义一个指向变量的指针变量,图 11-2 中 a-pointer代表

abc

200020022004

2000

(a-pointer)3000

图 11-1 内存中存放数据示意图

5

6

7.2

2000

Page 203: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

指针变量,用‘*’表示“指向”,即*a-pointer 表示 a-pointer所指向的变量值,从图 11-2可知*a-pointer就是 a 的值,所以 a=5;表示把 5 赋给变量 a,而*a-pointer=5;表示把 5 赋给 a-pointer所指向的变量,其含义是一样的。

11.2.1 指针变量定义C 语言规定所有变量在使用之前必须定义,规定其类型,指针变量不同于整型变量和

其他类型的变量,它是专门存放地址的,应把它定义为“指针类型”。例如:int a,b;

int *a-pointer,*b-pointer;这样定义了两个类型数 a 和 b,定义了两个指针变量 a-pointer 及 b-pointer,可以用赋值

语句使一个指针变量指向一个整型变量。a-pointer=&ab-pointer=&b

此后,a-pointer 指针变量能指向整型变量 a,b-pointer 指向 b。指针变量一般定义形式是:

类型标识符 *标识符;说明:(1)标识符前面的‘*’表示该变量为指针变量,指针变量名是标识符名(不包括前

面的*),这是与前面一般的变量定义是不同的,因此上面 a-pointer,b-pointer都是指针变量名,但*a-pointer 和*b-pointer都不是指针变量名。

(2)一个指针变量只能指向同一个类型的变量,例如上面 a-pointer,只能指向整型变量,通常用*a-pointer 及*b-pointer 分别表示指针变量 a-pointer 及 b-pointer所指的变量。

11.2.2 指针变量引用指针变量中存放的是地址(指针)不是变量值。因此下面赋值语句是错误的:

a-pointer=5;引用指针变量时有两个有关的运算符:

& 取地址运算符。* 指针运算符(间接访问运算符)。

例如:&d 表示变量 a 的地址,*p 为指针 p所指向的变量。例 11-1

main(){ int a,b;

int *a-pointer,*b-pointer;a=1;b=2a-pointer=&a; /*把变量 a 地址赋给指针变量*/b-pointer=&b; /*把变量 b 地址赋给指针变量*/printf(″%d,%d\n″,a,b)prinft(″%d,%d\n″,*a-pointer,*b-pointer)}

Page 204: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

运行结果:1,21,2

说明:(1)开始定义了两个指针变量 a-pointer 及 b-pointer,但什么也没有指向,它可以指向

任意一个整型变量,至于指向哪一个要由程序来确定,因此程序中第五、六行,使 a-pointer中为变量 a 的地址(可用&),b-pointer 中为变量 b 的地址。

(2)程序中出现两次*a-pointer 及*b-pointer,但其含义不同,程序第三行是对 a-pointer 及 b-pointer两个指针变量进行定义,它们前面的‘*’仅标志它们是指针变量,程序最后 prinft 语句中的*a-pointer 及*b-pointer 为 a-pointer 及 b-pointer所指向的变量,

(3)可写为 a-pointer=&a但不能写成*a-pointer=&a,因为 a 的地址是赋给指针变量 a-pointer,而不是赋给*a-pointer(即变量 a 本身)。‘&’及‘*’两个运算符优先级相同,但执行时按从右向左方向结合。如果执行了“a-pointer=&a”;语句,那么&*a-pointer 含意是什么呢?它应该先执行,*

a-pointer,它就是变量 a,再执行‘&’运算,因此&*a-pointer等价于&a。 若 b-pointer=&*a-pointer;则把 a 的地址赋予指针变量 b-pointer,因此此后 b-pointer 不再指向 b而是指向 a。同理。*&a等价于 a,如图 11-3所示:(*a-pointer)++ 相当于 a++ 注意此时括号是不可缺少的,如果没有括号,则变成*

(a-pointer++),显然,此时 a-pointer 不再指向变量 a了。

例 11-2 输入 x、y、z 三个整数,按先大后小顺序输出。main()

{ int *pl,*p2,*p3,a,y,z,*p;scanf(″%d,%d,%d″,&d,&y,&z);p1=&x,p2=&y;p3=&z;if(x<y) {p=p1;p1=p2;p2=p;}if(x<z) {p=p1;p1=p3;p3=p;}if(y<z) {p=p2;p2=p3;p3=p;}printf(″\n x=%d,y=%d,z=%d\n″,x,y,z);printf(″max=%d,middle=%d,min=%d″,*p1,*p2,*p3);}

输入:2,1,3↙输出:x=2,y=1,z=3

max=3,middle=2,min=1说明:该问题算法不是交换类型变量值,而是交换指针变量值(即交换 x、y、z 值的地

址)。图 11-4 表明交换前后情况。

a-pointer a

*a-point*&a

图 11-3 *&a 与 a等价&a

P1 a P1 a

P P2 b p P2 b

P3 c P3 c

(a)交换前 (b)交换后图 11-4 指针交换&b

&c

3

&a

&b

1

2&a

&b

&c

2

1

3

Page 205: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

11.2.3 指针作为函数参数引用函数的参数也可以是指针类型,其作用是将一个变量地址传到一个函数中。例 11-3 比较输入两数的大小,按先小后大进行输出。

main(){ int a,b:

int *a-pointer,*b-pointer;scanf(″%d,%d″,&a,&b);a-pointer=&a;b-pointer=&b;if(a>b) swap(a-pointer,b-pointer);prinft(″\n%d,%d″,a,b);}

swap(pl,p2)int p1,p2;

{ int p; p=*pl;*p1=*p2;*p2=p;}

输入:4,1↙输出:1,4说明:(1)swap是用户自定义函数,其作用是交换 p1 及 p2两个指针所指向的变量之值(不

是交换指针本身)。(2)主程序中先输人 a,b之值,并设 a-pointer 指向 a,b-pointer 指向 b,接着因为

a>b执行 if 语句中执行部分,形实结合,把&a 及&b 分别赋于 p1 及 p2,此时 p1 及 a-pointer都指向 a,p2 及 b-pointer都指向 b (见图 11-5(a)、(b))。

(3)执行函数体,使*p1 及*p2 内容互换,即使 a 和 b 的值互换,函数调用结束 p1、p2被释放,不再返还(见图 11-5(c)、(d))。

(4)在main 输出 a 和 b 的值是已交换过的值。例 11-4 求字符串长度。

main()

Page 206: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

{ char *s;scanf(″%s″,s);printf(″%d″,strlen(s));}

strlen(s)char *s;

{ int n;for(n=0;*s !=′\0′;++s)++n;return(n);}

本例给出了函数 strlen 的定义,采用了字符指针作为函数的参数。例 11-5 求字串长度。

main(){ char *p;

scanf(″%″,p);prinft(″%d\n″,strlen(p))'}

strlen(s)char *s;

{ char *p=s;while( *p! =′\0′) p++;return(p-s);}

P1

a a

b

b (a) P1 P2 (b) a

a

b b

P2 (c) (d)图 11-5 调用 SWAP 函数

&aa-pointer 5

&bb-pointer 7&bb-pointer

7

&b

5

&aa-pointer

&a

&bb-pointer5

&b

7

&aa-pointer

&a

&a

a-pointer

7

&b

b-pointer

5

Page 207: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

11.3 数组和指针

11.3.1 通过指针访问数组元素C 语言中指针和数组有着密切的联系,凡是用数组下标的操作皆可以用指针来实现,

既然每个数组元素相当于一个变量,那么指针变量可以指向一般的变量同样也可以指向数组元素。

例 11-6# include <stdio.h>main()

{ int a[ ]={10,20,30,40,50,60};int x,y,*p;p=&a[0]; /*指针变量 p 指向数组元素 a[0]*/

/*等价于 p=a*/x=*(p+2); /*把 p+2 指向内容赋于 x,相当*/y=*(p+4); /*于 x=a[2] y=[4]*/}

输出:*p=10,x=30,y=50

说明:(1)p=&a[0];是把数组元素 a[0]地址(即数组 a 的首地址)赋于指针变量 p,因此该

语句等价为 p=a(数组名 a代表了一个地址,是数组 a 的首地址,它不同于指针变量)。(2)对于指向首地址的指针 p,p+i(或 a+i)

是数组元素 a[i ]的地址,图 11-6 表示了它们之间的关系。

对数组元素的访问,下标方式和指针方式是等价的,但从 C 语言系统内部处理机制上讲,指针方式效率高,但是指针方式不如下标方式直观,下标方式可以直接了当地看出访问的是哪一个元素,而对指向数组的指针变量,进行运算后指针变量值改变了,它指向的数组元素是哪一个就不再一目了然。

&a 为变量 a 的地址,*p 为指针变量 p所指向的变量,因此&及*的作用相反,若 p 指向数组 a中的第 i 个元素 a[i],则:

*p++(自右向左结合,相当于*(p++),表示先得到*p,即取得 a[ i ],然后再进行 p++(p+1)→1)相当于 a[i++]。

*++p(自右向左结合,相当于*(++p),先进行 p+1→p,然后得到*p,即取得 a[i+1],相当于 a[++i]。

指针方式 下标方式 P(&a[0]) a[0]

a[1]

P+2 a[2]

a[3]

P+4 a[4]

a[5]

图 11-6 指针方式和下标方式

10

20

30

40

50

60

Page 208: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

(*p)++是表示先取出*p(a[ i ]),然后对其自加 1,即 a[ i ]+1,元素值加 1。例 11-7 输出 5 个元素的数组内容。(1)下标法

main(){ int a[5],

int i;printf(″input 5 numbers:\n″);for(i=0;i<5;i++)scanf(″%d″,&a[i]);for(i=0;i<5;i++)printf(″%d″,a[门];}

(2)通过数组名访问main()

{ int a[5];int i;print{(″input 5 numbers:\n″);for(i=0,i<5;i++)

scan{(″%d″,&a[ i ]);for(i=0;i<5;i++)

printf(″%d″,*(a+i);}

(3)用指针变量main()

{ int a [5];int *p,i;printf(″input 5 numbers:\n″);for(i=0;i<5;i++)

scanf(″%d″,&a[ i ]);for(p=a;p<(a+5),p++)

printf(″%d″,*p);}

以上三个程序运行结果相同,第(1)、(2)个程序执行效率相同,C 语言编辑系统将a[i ]转换为*(a+i)处理,即先计算元素地址,再进行运算。第(3)个程序直接使用指针,其效率较前两种高,此外进行 p++操作速度也较快,但用下标方法比较直观,易于理解,因此从程序理解性角度来看,第一个程序最好。注意:(1)第三个程序中,可以使用 p++,同为 p是指针变量,能否采用 for(p=a;a<(p

+5);a++)呢? 是不行的。其原因是 a 为数组名,它是数组的首地址,是一个常量而不是变量,无法实现 a++运算。

(2)想输出数组 a 的 5 个元素,也可以用下列语句:p=a; 或 p=a;while(p<a+10) while(p<a+10)printf(″%d″, *p++); { printf(″%d″,*p);

Page 209: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

p++;}

(3)本例中若写成:main()

{ int,p,i,a[5];p=a;for(i=0;i<5;i++)

scanf(″%d″,p++);for(i=0;i<5;i++,p++)

printf(″%d″,*p);}

该程序无法得到预期结果,在输入 5 个元素后,p 指针已指向数组 a 的末尾,因此再用p++来输出*p 时,实际上是输出 a[5]及以后的元素,因此应该在第二个 for 语句之前加上 p=a;(让 p 指针返回到指向 a[0])。

11.3.2 数组作为函数参数1.数组元素作为函数实参。数组元素与普通变量一样可以作为函数的实参使用,它采

用单向传递即“值传送”方式。例 11-8 有两个数组 a 和 b,各有 10 个元素,将它们逐个进行比较,若 a 中较大的元素

数目比 b 中较大的数目要多,则认为 a>b。main()

{ int a[10],b[10],i,m=0,n=0,k=0;printf(″input array a please:\n″); /* 输人数据到数组 a */for(i=0,i<10;i++)

scanf(″%d″,&a[i ]);printf(″\n″);printf(″input array b please:\n″); /*输人数据到数组 b*/for(i=0;i<10;i十+)

scanf(″%d″,&b[ b ]);printf(″\n″);for(i=0;i<10;i++) /*逐个元素比较并计数*/

if(1arger(a[i],b[i])==1) m=m+1;elseif(1arger(a[i],b[i])==0) n=n+1;else k=k+1

printf(″a[i]>b[i])%d times\n a[i]=b[i]%d times\na[i]<b[i]%d time\n″,m,n,k); /*输出*/if(m>k) printf(″array a is larger then array b\n″);else if(m<k) printf(″array a is smaller then array b\n″);else printf(″array a is eguql to array b\n″);}

larger(x,y) /*比较元素大小的函数*/int x,y;

Page 210: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

{ int flag;if(x>y) flag=1;else if(x<y) flag=-1 else flag=0;return(flag);

}本例中用 m 记录 a[i]>b[i]的元素个数,用 k 记录 a[i]<b[i]的元素个数,用 n 记录 a[i]=

b[i]元素个数,再根据 m,k,n之值打印相应信息。2.数组名作函数参数。实参和形参都可使用数组名或数组指针,此时要注意函数之间

传递的是数组元素的地址。例 11-9 求一维数组 a 中各元素平均值。

# include <stdio.h>main()

{ float average();static float a[7]={20.5,32.0,7.8,4.3,3.52,2.1,6.4}prinft(″The average of array a is%f\n″,average(1,7));/*调用函数*

/}

float average(aa,n) /*求平均值函数*/int n,float aa[ ], /*形参为一维数组,数组大小由调用函数的数组决定*/

{ int i;float sum=0;for(i=0;i<n;i++)sum+=aa[i],return(sum/n);

}说明:(1)用数组名作函数参数,应该在主调函数和被调出函数中分别定义数组,本例中 a

a 为形参数组名,a 为实参数组名,分别在两方定义不能只定义一方。(2)实参数组与形参数组类型应该一致,如不一致则结果出错。(3)实参数组与形参数组大小可以一致也可以不一致,C 编辑系统对形参大小不作检

查,只将实参数组的首地址传送给形参数组,形参数组可能大于实参数组,若要求形参数组得到实参数组全部的元素值,应该指定形参数组与实参数组大小一致,形参数组也可以不指定大小,用一个空方括号,需要的可以在调用函数中另设一个参数,传递数组元素个数。

(4)数组名作函数参数时不是“值传送”,不是单向传递,而是把实参数组起始地址传递给形参数组,这样两个数组占用同一个内存区域,因此形参数组中各个元素值的变化,会使实形参数数组中元素值同时发生变化,这称为“地址传递”。

例 11-10 编写程序交换 a,b两个数组的对应元素。 # include <stdio.h>swap(pa,pb)int *pa,*pb, /*函数的形参是指向整数的指针*/

{ int temp;temp=*pa;*pa= *pb;*pb=temp;

Page 211: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

} main()

{ int a[5]={2,4,6,8,10};int b[5]={1,3,5,7,9};int i;for(I=0;i<5;i++)

swap(&a[ i ],&b[ i ]);for(i=0;i<5;i++)

printf(″a[%d]=%d,″,i,a[i]);printf(″\n″);for(i=0;i<5;i++)

printf(″b[%d]=%d,″,i,b[i]);}

运行结果:a[0]=1,a[1]=3,a[2]=5,a[3]=7,a[4]=9,b[0]=2,b[1]=4,b[2]=6,b[3]=8,b[4]=10,

3.多维数组作为函数参数多维数组元素可以作为函数实参,进行“值传递”,这与一维数组一样。多维数组名作为实参和形参,同样需要在主调函数和被调函数中双方进行说明,在被

调函数中说明时,可以指定每一维的大小,也可以省略第一维的大小说明,但不能省略二维及以上的维数说明,允许实参数组大于形参数组大小,这时形参数组只取实参数组的一部分,其余部分不起作用。

例 11-11 有一个 3×6矩阵,求其中最小元素。min-valne(array) /*求最小元素函数*/int array[3][6];

{ int i,j,k,min;min=array[0][0];for(i=0,i<3;i++)

for(j=0;j<6;j++)if( array [i][j] <min)

min=array[ i ][ j ];return(min)}

main(){static int a[3][6]={{1,3,5,7,8,0},{20,4,6,50,8,9},

{1,52,24,-17,-19,30});printf(″min value is:%d\n″,min-value(a));}

运行结果:min value is:-19

归纳起来,若有一个实参数组,想在函数中改变此数组的元素值,实参与形实对应关系有四种:

(1)形参和实参都用数组名例如:

Page 212: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

main() f(x,n){int a[10] int x[ ],n

{

f(a,10);}

}程序中实参 a 与形参 x 共用一个内存地址,即在调用 f 期间 a 和 x是指同一个数组,如

图 11-7所示。(2)实参用数组名,形参用指针变量例如:main() f(x,n)

{ int a[10] int *x,n;{

f(a,10);}

}函数调用开始时,指针 x 指向 a[0],即 x=&a[0],通过 x 变化可以指向 a[i]。(3)实参、形参都用指针变量例如:main() f(x,n)

{ int a[10],* p int * x,n;p=a; {

f(p,10); }

}实参 p 和形参 x都是指针变量,先使 p 指向数组 a,p 的值为&a[0],然后将 p 值传递给

x,x 的初始值也是&a[0],通过 x 变化也可访问数组 a 的任一个元素。数组 a, x

a[0], x[0] a[1],x[1]

a[9],x[9]

图 11-7 a 与 x 共用一个内存空间

Page 213: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

(4)实参为指针变量,形参为数组名例如:main() f(x,n)

{ int a[10] *p; int x[ ],n;p=a; {

f(p,10); }

}实参 p 为指针变量,其值为&a[0],形参 x 为数组名,当把 p 传给 x 时,即使 x也取得

数组 a 的首地址,它们共用一个内存区,通过 x 值改变可以访问数组 a 中任一个元素。以上四种方法都不是“值传递”而是“地址传递”。

11.3.3 指向多维数组的指针和指针变量指针变量可以指向一维数组也可以指向多维数组,但在概念和使用上后者更为复杂。以二维数组 x(三行五列)为例,其定义为 static int x[3][5]={{1,3,5,?,9},{2,4,

6,8,10},{10,20,30,40,50}};如图 11-8所示,可以理解为 J是一个数组名,它包括三个元素 x[0]、x[1]及 x[2],而每一个元素又是一个一维数组,它包括 5 个元素。例如:x[0]代表的一维数组包括 5 个元素,它们是 x[0][0],x[0][1],x[0][2],x[0][3]及 x[0][4]。

若 x[0][0]地址为 2000,即 x 数组首地址也是 x[0]的首地址,那么,x[1]的首地址,即 x+1 为 2010,因为第 0 行有 5 个整数,每个整数为两个字节,同样 x十 2 为 2020。

x[0]、x[1]、x[2]是一维数组名,数组名代表数组首地址,因此 x[0]代表&x[0][0],x[1]代表&x[1][0],x[2]代表&x[2][0],那么第 0 行第 1列元素地址如何表示呢? 可以用 x[0]+1 表示,这里‘1’表示一列元素的字节数,即 2 个字节,因而 x[0]为 2000,x[0]+1是 2002 (不是 2010。),图 11-9 表示数组 x 的地址。前面已提到 x[0]和 *(x十 0)等价,x[i]和 *(x+i )等价,因此 x[1]+2 和 *(x+1)+2

的值都是&x[1][2] (即图 11-9 中的 2014),注意不要把 *(x+1)+2 错写为 *( x +1+2),

x 2000

2010

2020 图 11-8 多维数组

x[0]

x[1]

x[2]

1 3 5 7 9

2 4 6 8 10

10 20 30 40 50

Page 214: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

因为后者相当 *(x+3)是 x[3]。x[ i ]指什么呢? x[i]从形式上看是 x 数组中第 i 元素,如果是一维组数值,它是 x 中 i 个

元素的值,它占有内存单元,本身有地址&x[i],如果 x是二维数组,x[i]代表的是一维数组,名它是一个指针,本身不占有内存单元仅是一个地址,因此,x、x+I、x[i]、*(x+i)、*(x+i)、*(x+i)+j、[i]+j都是地址,而*(x[i]+j)、*(*(x+i)+j)才是 x[i][j]的值,见表 11-1。

读者也许难以理解,为什么 x+1 和 *(x十 1)都是 2010呢? 难道“x+1”的值与“x+1”的地址一样吗? 显然,如果 x是一维数组,那么(x+1)与 *(x+1)是完全不同的概念。但这里 x是二维数组,问题就复杂一些,这里 x+1是地址,它指向第 1 行第 0列的元素,即指向 x[1][0],但*(x+1)是 x[1][0]的内容吗? 不是。注意,x+1 不是一个变量,也谈不上它有什么内容,这里*(x+1)实质上就是 x[l],而 x[l]是一个一维数组,所以*(x+1)也是地址。

表 11-1 二维数组地址表示表示形式 含义 地址

xx[0], *(x+0), *x

x+1x[1]+2, *(x+1)

x[1]+2, *(x+1)+2, &x[1][2]

*(x[1]+2), *(*(x+1)+2, x[1][2]

二维数组名,数组首地址第 0 行,第 0列的元素地址

第 1 行的首地址第 1 行第 0列元素地址第 1 行第 2列元素地址第 1 行第 2列元素地址

20002000201020102014

6

同样,这里不要把&x[i]理解为 x[i]的物理地址,同为并不存在变量 x[i],它只表明了一种地址的计算方法,以得到 i 行的首地址,在二维数组 x 中,x+i=x[i]=*(x+)=&x[i]=&x[i][0],即它们的地址值是相等的。

例 11-12 分析以下程序:main()

{ static int a[3][4]={2,4,6,8,10,12,14,16,18,20,22,24};printf(″%d,%d\n″,a,*a);printf(″%d,%d\n″,a[0],*(a+0));printf(″%d,%d\n″,&a[0],&a[0][0]);

图 11-9 数组 x 的地址

x[0]

x[1]

x[2]

20001

20023

20045

20067

20089

20102

20124

20146

20168

201810

202010

202220

202440

202640

202850

x[0] x[0]+1 x[0]+2 x[0]+3 x[0]+4

Page 215: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

printf(″%d,%d\n″,a[1],a+1);printf(″%d,%d\n″,&a[1][0],*(a+1)+0);printf(″%d,%d\n″,a[2],*(a+2));printf(″%d,%d\n″,&a[2],a+2);printf(″%d,%d\n″,a[1][0],*(*(a+1)4-0));}

分析:假定系统对数组 a 分配的首地址是 2000,图 11-10 表示本例中 a 数组的地址及内容。

图 11-10 数组 a 的地址及内容第 1 个 printf 输出 a 及*a,注意不能够用*a代表 a[0][0]内容。它相当于*(a+0),即 a

[0][0]地址,因此将输出两个 2000;第二个 printf 输出 a[0]及*(a+0),也是指第 0 行的首地址(读者注意 a[0]是地址,而 a[0][0]才是元素内容),因此也是输出两个 2000;第三个prinft 输出&a[0]及&a[0][0],也输出两个 2000(注意&a[0]及 a[0]值是一样的,但含义不同,&a[0]指向行,而 a[0]指向列);第四个 printf 输出 a[l]及 a+1,是第一行地址,因此输出两个 2008;第五个 printf 输出&a[1][0]及*(a+1)+0同样都指第一行首地址,再次输出两个 2008,第六个 printf 输出 a[2]及*(a+2)将输出第二行首地址,输出两个 2016;第七个 printf输出&a[2]和 a+2再次输出两个 2016;最后一个 printf 输出 a[l][0]值,*(*(a+1)+0)也为a[l][0]之值,因而输出两个 9,所以八个 printf 输出为:

2000,20002000,20002000,2000 2008,20082008,20082016,20162016,201610,10

学习以上的概念后,可以用指针变量指向多维数组及其元素。例 11-13 用指针变量输出多维组数的元素值。

main(){ static int a[4][3]={2,4,6,8,10,12,14,16,18,20,22,24};

int *p; /*定义指针 p,注意是一个整数的指针变量*/p=a[0] /*也可写成 p=a 或 p=&a[0][0] */

a[0]

a[1]

a[2]

20002

20024

20046

20068

201010

201212

201414

201616

202018

202220

202422

202624

a[0] a[0]+1 a[0]+2 a[0]+3

Page 216: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

for(p=a[0];p<a[0]+12;p++){ printf(″%4d″,*p);

if(p-a[0]%3==0)printf(″\n″);

}}

运行结果:2 4 68 10 1214 16 1820 22 24

本例是顺序输出数组 a 中各个元素,比较简单,如果要输出某个元素 a[i][j],可以计算相对于数组起始位置的相对位置值 i*n+j(数组为 m 行 n列),例如:为获得 a[2][3]的地址,可以用*(p+2*3+3)表示,这里假定 p 指向数组 a 的首地址,这里 p是一个指向整数的指针变量,p+l相当地址+2,指向下一个元素。

例 11-14 输出二维数组指定行列的元素值。main()

{ staic int a[4][3]={2,4,6,8,10,12,14,16,18,20,22,24};int (*p)[4],i,j /*定义 p是一个指向数组的指针变量*/p=a;printf(″input i,j please:″);scanf(″%d,%d″,&i,&j); /*输入 i 及 j 值*/printf(″a[%d][%d]=%d\n″,i,j,*(*(p+i)+j);

运行情况:input i,j please:2,2a[2][2]=18

注意:(1)(*p)[3]表示 p是一个指针变量,它指向一个包括四个元素的一维数组,即 p是

行指针,p只能是一维数组的首地址,不能指向一维数组中的第 j 个元素。*p (数组)

p

(2)程序中 p+i是二维数组 a 的第 i 行的地址,因此,*(p+2)+3是 a 数组第 2 行第 3列元素的地址(即指向列的指针),所以*(*(p+2)+3)为 a[2][3]值,这里的括号是必不可少的。*(p十 2)+3 中括号外的 3 与 p 的指向单位不同,是指一维数组内各元素的长度单位,因此如果遗漏括号,写成 p+2+3是指第 5 行的首地址,所以尽管 p+2 和*(p+2)有相同的值,但(p+2)+3 和*(p+2)+3 值并不相同。

11.4 字符串和指针11.4.1 字符串的表达形式

( *p ) [0] (*p)[1] ( *p ) [2] (*p)[3]

Page 217: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

C 语言中可以用数组表示字符串,也可以用字符指针来指向字符串中任一字符。例 11-15(1)main()

{ static char string[ ]=″This is a C program!″;printf(″%5s\n″,string);}

本例中 string[5]代表字符串中第 5 个元素′i′,实际上 string[5]就是指*(strlng+5)。其中,string+5是指向字符′i′的指针。

(2)main(){ char *string=″This is a C program!″;

printf(″%s\n″,string);}

这里没有定义字符数组,但定义了字符指针 String,把字符串“This is a C program”的首地址赋予它,千万不要以为 string是一个字符串变量。这里

char *string=″This is a C program!″;等价于

char *string;string=″This is a C program!″;

输出用 prinft(″%s\n″,string),先输出一个 string 指向的字符,然后使 string+1再输出一个字符,直到遇见′\0′为止(′\0′是系统自动加入的)。

通过字符数组名或字符指针变量可以输出一个字符串,而对一个数值型数值是不能用数组名输出它的全部元素的,只能一个个地把元素依次输出。

11.4.2 字符串指针作函数参数一个字符串指针可从一个函数传到另一个函数中,它采用“地址传送”方法,即被调

用函数对字符串内容的改变,将返回到调用的主函数中。例 11-16 用函数调用实现字符串的复制。1.用字符数组作为参数

void copy-string(from,to)char from[ ],to[ ];

{ int I=0;while(from[i]!=′\0′

{ to[i]=from[i];i++;}

t[i]=′\0′ /*加上字符串结束符*/}

main(){ char a[ ]=″This is a C program!″,b[20];

copy-string(a,b);printf(″\n string-a=%s\n string-b=%s\n″,a,b),

Page 218: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

}本例中主函数中也可定义 char *a=“This is a C program!”,*b;结果相同。2.用字符指针变量作为形参void copy-string(from,to)char *from, *to

{ for(;*from !=′\0′;from+++,to++)*t0=*from;*to=′\0′;}

对本例函数体可以简化为:(1)

while((*to=*from) !=′\0′){ t++;from++;}

这里在while 语句中把赋值语句和判定语句合二为一,先赋值再判定,因此当最后一个字符′\0′赋予 to 后,结束循环,因而不必再加上*to=′\0′;语句。

(2)更一步进行简化为{while((*to++;*from++)!=′\0′);}

这里进一步把 to++和 from++也合并到while 条件中去。(3)由于字符可用 ASCII 码值来代替,′\0′的 ASCII 码为 0,在while 中 0代表

“假”,非 0代表“真”,因此可进一步简化while(*to++=*from++)

(4) while也可以改用 for 语句for(;(*to++=*from++)! = 0; );

或for(;(*to++=*from++););

(5)也可以采用指针变量void copy-string(from,to),Char from[ ],to[ ];

{ char *p1,*p2;p1=from;p2=to;while((*p2++=*p1++) != ′\0′);}

可见 C 语言流程十分灵活,利用各种形式可以达到同一目的。

11.5 函数与指针本节介绍指针函数及函数指针两个不同的概念。

Page 219: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

11.5.1 指针函数指针函数是返回值为指针的一个函数,如:int *f( );说明 f 是一个指针函数,其返

回一个指向整数的指针。例如:C 函数 malloc就是一个指针函数,定义为 void * malloc(size),它返回一个指

向长度为 size 的内存区的首地址,若内存已不够分配,返回一个空指针 NULL,采用此函数,可以把一个字符串复制到一个安全地方,其空间内 malloc来确定。

例 11-17 保存字符串 s到合适地方。#include <stdio.h>main()char *strsave(s) /*定义字符串保存的指针函数*/char *s; /*定义 s 为指向字符串的指针变量*/

{ char *p *malloc();if((p=malloc(strlen(s)+1))!=NULL) /*strlen返回长度*/

strcpy(p,s); /*把 s复制到 p*/return(p)}

例 11-18 有 5 个学生的成绩(每个学生 4门课程),要求用户输入学生学号后,能输出该生的全部成绩,用指针函数实现。

main(){ static float score[5][4]={{88,76,90,84},{66,78,82,76},

{86,85,93,90},{57,68,75,77},{62,80,85,82};float *search(); /*说明指针函数*/float *p /*定义指针 p*/int i,m;printf(″enter the number of student:″);scanf(″%d″,&m);if(m<0 | | m>4)

printf(″\n ERROR NUMBER !!!″);else

{ printf(″\n The Score of No.%d are:\n″,m);p=search(score,m); /*寻找第 m 个学生成绩,返回指针*/

for(i=0;i<4;i++)printf(″%5.2f \ t″,*( p +i ) );}

}float *search(pointer,n) /*定义指针函数*/float( * pointer)[3];int n;

{ float *pt;pt= *(pointer + n); return( pt );}

运行情况:

Page 220: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

enter the number of student:3↙The scores of No.3 are:57.00 68.00 75.00 77.00

说明:(1)学生序号是从 0 开始,函数 search 为指针函数,其形参 pointer 为指向包含 4 个元

素的一维数组的指针变量,因此 pointer +l 应指向 score 数组第一行,*(pointer +1)为指向第一行第一列指针,(见图 11-11)。

88

76 90 8466 78 72 8686 85 93 9057 68 75 77

62808582图 11-11 score 数组(2)main 中调用 search 函数,将 score首地址(指向行的地址)传递给 pointer,m是

要寻找的学生学号,其值在 0到 4之间,超出范围程序提示错误信息。(3)调用 search后返回一个地址,指向第 m 个学生第 0门课程,赋予 p,并打印该学

生的 4门课程成绩(用*(p+i)表示第 i 门成绩)。请读者注意指针变量 p、pt 和 pointer 的区别。如果将 search 函数中语句 pt=*(pointer +n);,改为 pt=*pointer+n;,则运行结果

为:The scores of No.3 are:84 66 78 72

为什么?请读者分析。例 11-19 对上例中的学生成绩,找出其中有优秀(90以上)成绩的学生的学号,并输

出其成绩。main()

{ static float score[5][4]={{88,76,90,84},{66,78,82,76},{86,85,93,90},{57,68,75,77},{62,80,85,82};

float *search( ); /*说明指针函数*/float *p;int i,j ;for(i=0;i<5; i++)

{ p=search(score+i);if(p== *(score +i))

{ prinft{″No.%d scores are:″,i };for(j=0;j<4;j++)

prinft(″%5. 2f\t″,*(p +j));prinft(″\n″);}

}

pointer

Pointer+1

Page 221: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

}float *search(pointer) /*定义指针函数*/float( *pointer)[4];

{ int i;float *pt;pt= *( pointer+1);for(i=0;i<4;i++)if( *( * pointer +i)>90)

pt=*pointer;return(pt);}

运行情况:No.0 scores are:88.00 76.00 90.00 84.00No.2 scores are:86.00 85.00 93.00 90.00

说明:(1)search 用来检查一个学生有无不及格课程,在 search 中 pointer是指向一维数组的

指针变量,指向一维数组(4 个元素),pt是一个指向实型变量的指针变量,从实参传送给形参 pointer 的是 score +i,即 score 第 i 行首地址,见图 11-12a。

88

76 90 84

66 78 72 8686 85 93 90

5768757762808582 (a) (b)

图 11-12 找出优秀成绩(2)在 search 中,先使 pt=*(pointer+1),即把 pt 置于本行的末尾,见图 11-

12(b),若检查 4门课程中有优秀的,使 pt 置于本行第 0 个元素,若全在 90以下,保持pt在末尾(即下一行第 0 个元素地址)。

3)将 pt返回main 函数,并赋予 p,再判定 p是否与*(score+i)相等,若相等表示有不及格成绩,输出该生学号及课程成绩。

pt pt (非优秀) (优秀)88 76 90

*pointer *pointer+1

pointer

pointer+1

Page 222: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

11.5.2 函数指针C 语言中,一个易于引起混淆而又相当有用的概念是函数指针,尽管函数本身不是个

变量。但在内存中仍然有其物理位置,该位置能赋给一个指针(即指针指向函数的入口地址),因此可以用该指针来代替函数名,这样就使得函数作为实参传递给其他函数。

用 int(*fn)(),说明 fn是一个函数指针,它指向一个返回整型数的函数(注意,并没有说明它具体指向哪一个函数),这里 * fn 的圆括号是必不可少的,若不加括号,写成 int *fn( );正如前所述,说明 fn是一个指针函数(返回一个指向整型数的指针),因此加不加括号,其含义全然不同。

为了使函数指针指向一个特定的函数,例如:lookup,它返回一个整数,那么用赋值语句 fn=lookup;表示,类似于数组名是数组的首地址一样,函数名实际上是函数的地址,如果 lookup没有在程序中事先定义,那么在使用 fn=lookup;之前,应事先进行说明,即使用语句:int lookup( );我们可以通过调用指针变量来调用函数,其方法是把′*′加到该指针变量之前,并加上

一对圆括号,括号内为参数表,例如( * fn)(a、b、c);表示把 a、b、c 作为实参数传递给函数,如果函数没有形参,当然也不会有实参,但圆括号仍需保留,例如( * fn)( );。

例 11-20 定义数字串比较函数和交换函数。numcmp(N1,N2) /*数字串比较函数*/char *N1,*N2;

{ double atof( ),f1,f2;f1=atof(N1);f2=atof(N2)if(f1<f2) return(一 1);else if(f1>f2) return(1);else return(0);}

其中 atof(s)是 C 语言内部函数,它把数字串(字符串)转换为浮点数,然后进行比较,依N1<N2,N1=N1,N1>N2 分别输出 -1,0,1。

swap(pa,pb) /*交换函数*/char *pa[ ],*pb[ ];

{ char *t;t=*pa;*pa=*pb*pb=t}

例 11-21 求 a、b两者较大者。main( )

{ int max( ); /*说明函数 max */int( *p)( ); /*说明 p 为函数指针*/int a,b,t;p=max; /*令 p 指向函数 max */printf(″please input two numbers:″);seanf(″%d,%d″,&a,&b);t=( *p)(a,b) /*调用函数 max*/

Page 223: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

printf(″\n a=%d,b=%d,max=%d\n″,a,b,t);}

max(a,y) /*定义函数 max*/int a,y;

{ int z;if(a>y) z=a;else z=y;return(z);}

这里,int( *p)( );,说明 p是函数指针,该函数带回一个整数值:p=max;是把函数 max 的入口地址赋予 p,即 p 和 max 均指向函数首地址,t=( *p)(a,b);,等价于 t=max(a,b);,表示通过指针 p来调用函数,与数组指针不同,p+n,p++,p 一一是毫无意义的,因为 p是一个指向函数入口地址的指针。

11.6 指针数组和指向指针的指针11.6.1 指针数组

指针本身也是变量,所以将指向相同类型对象的指针变量集合在一起,就可以构成一个指针数组,显然指针数组的每一个元素都是指针变量。例如:int *a[10],说明 a 是一个数组,它由 10 个元素组成,每个元素都是指向整型对象的指针,由于各个指针所指向的地址里的数据长度可以不同,这样要比直接使用二维数组节省内存空间。

例 11-23 定义指针数组。main()

{ char *a[5];int i;a[0]=″CAR″;a[1]=″WTO″;a[2]=″CATT″;a[3]= ″INCC″;a[4]=″CBA″;for(i=0;i<6;i++)

printf(″%s\n″,*(a +i));}

图 11-14给出了指针数组示意图。

指针数组 a 字符串图 11-14 指针数组示意图

a[0]

a[1]

a[2]

a[3]

a[4]

CAR\0

WTO\0

CATT\0

INCC\0

CBA \0

Page 224: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

例 11-24 对上例字符串按字母顺序由小到大排序输出。main()

{ void sort( );void print( );static char *a[ ]={″CAR″,″WTO″,″CATT″,

″INCC″,″CBA″};int n=5;sort(a,n);print(a,n);}

void sort(name,n)char *name[ ];int n;

{ char *temp;int i,j,k;for(i=0;i<n-1 ; i++)

{ k=i ;for(j=i+1; j<n ; j++)

if(strcmp(name [k],name[ j ] ) >0) k = j ;if(k !=0 )

{ temp=name [ i];name[i]=name[k];name[k]=temp;}

}}

void print(name,n)char *name[ ] ;int n;

{ int i;for(i=0;i<n;i++)printf(″%s\n″,name[ i ]);}

运行情况: CARCBACCATT INCCWTO

说明:(1)main 定义指针数组 a,它有 5 个元素,指向 5 个字串的首地址,这些字符串长短

不一。(2)sort 函数作用是对字符串排序,其形参 name是指针数组名,接受实参传过来的 a

的首地址,因此形参 name 数组及实参 a 数组指的是同一个数组,用选择法进行排序,strc

Page 225: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

mp是字符串比较函数, name[k] 及 name[j] 是第 k 个及第 j 个字符串的起始地址,strcmp(name[k],name[j] )的值为:如果 name[k]所指字符串大于 name[ j ]所指的字符串,则函数值为正值,若相等则函数值为 0,若小于则函数值为负值。if 语句作用是将两个宇串中 “小”的那个串的序号(k 或 j之一)保留在 k 中,当执行完内循环 for后,从第 i 个到第 n个字串中,第 k 个串最“小”,若 k≠i 表示最小的串不是第 i 串,则交换 name[k]及 name[ j ]。

图 11-15 排序后的情况

(3)print 作用是输出各个字符串,name[0]到 name[5]分别是已排序的各字符串首地址,用“%s”格式符输出,图 11-15给出了排序后情况。

(4) if 语句中,采用条件为 strcmp(name[k],name[j ])>0,若采用 if( * name[ k ]> *name[ j ])……,则只比较字串第一个字符。

11.6.2 指向指针的指针在上面定义的指针数组 a 中,每个元素都是指针变量(地址),既然 a是个数组,则

数组名。a代表该数组的首地址,a+i 为 a[i]的地址,因此 a+i 实际上是一个指向指针的指针。我们用 char * * p; 定义一个指向指针的指针变量 p ,p 的前面有两个‘ * ’,而‘ * ’

是从右到左结合的, * * p相当于*( * p),其中,p前若没有另一个‘ * ’,那么就定义了一个指向字符数据的指针变量,现在它前面又有一个‘ * ’,表明*p是 p 指向的另一个指针变量。

例 11-25 输出 a 中的指针所指向的字符串。main()

{ static char *a[ ]={″CAR″,″WTO″,″CATT″,″INCC″,″CBA″};

char **p;int i;for(i=0;i<6;i++)

{ p=a+i;prinft(″%s\n″,*p);}

}

11.7 Turbo C 的内存分配函数

a[0]

a[1]

a[2]

a[3]

a[4]

CAR\0

WTO\0

CATT\0

INCC\0

CBA \0

Page 226: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

定义指针的一个原则是一定要给它一个指向的地址值,这就是指针的初始化过程(只能初始化一次,不能重复初始化),即所有指针在使用之前一定要赋予它一个地址值,否则它就随机指向一个存储空间,这可能会导致程序运行失败,甚至有可能对磁盘文件进行破坏。

Turbo C提供了内存分配函数,最主要的是malloc( )和 calloc( ),它们是 C 语言函数库的一部分,能在内存中为所要写入的数据分配一个安全区,一旦找到一个大小合适的内存空间就分配给它们,并且把这部分内存的地址作为一个指针返回,两者的差别是malloc()仅分配一块内存区域,但所有字节内容维持原有随机值,calloc()清除所分配的内存字节,即置零所有分配的字节,另一个函数是 free(),它用以释放所分配的内存空间,这三个函数均在〈stdio.h〉中,使用时应该用 # include<stdio.h> 语句,把它们包含进去。

malloc( )和 calloc( )都返回一个 void 型的指针,即返回的值可以为任何合法数据类型的指针,可在声明中进行声明。例如:

char *p;p=(char *) malloc(100);

分配 100 个字节内存区域,供指针 p 使用。例 11-26 把字符串 y 的内容拷贝到字符串 X 中(采用内存分配函数)。

# include<stdliy.h># include<stdio.h># include<string.h>main( )

{ char *X,y[256], *malloc( );gets(y);X=malloc(strlen(y));if(X==NULL)

{ printf(″out of memory!\n″);exit(1);

}else

strcpy(X,y);}

例 11-27# include <st4~io.h># define NULL 0# define ALLOCSIZE 1000 /*分配空间长度*/static char allocbuf [ALLOCISZE]; /*分配空间*/static char *allocp=allocbuf; /*定义指针*/main( )

{ char * * alloc( ); / *说明函数 */char *pint nscanf(″%s″,p);prinft(″%d\n″,alloc(p));free(p);

Page 227: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

}char *alloc(n) /*定义函数,返回指针*/int n;

{ if(allocp+n <= allocbuf + ALLOCSIZE){ allocp+=n;

return(allocp-n);}

elsereturn(NULL);

}free(p) /*释放空间 */char *p;{ if(p > allocbuf &&p < allocbuf + ALLOCSIZE)

allocp = p;}

该程序调用两个子程序 alloc(n)及 free(p),负责存储管理的分配和释放任务,当请求 alloc给出 n 个字符位置时,它检查在 allocbuf[ ]中是否还有足够的空间,若满足,alloc返回 allocp 值(开始位置),然后 allocp 增加 n,使 allocp 指向下一个区域。

本程序中使用大量指针运算,如订语句利用地址比较运算,来测试检查是否有足够空间满足 n 个字符的请求,若满足 alloc 返回一个普通指针,否则返回信号告诉用户已没有空闲空间,返回NULL(0)表示一种异常情况。

11.8 本章小结1.有关指针的数据类型。表 12-2是有关指针的数据类型,为便于比较也列入一些其他类型定义。2.指针运算(1)赋值可将一个变量地址赋给一个指针,但不能把一个整数或整型变量赋予指针(如 p1000;

p=i 都是不对的)。例如:p=&d; (将整型变量 a 的地址赋给指针 p)p=array; (将数组 array 的首地址赋给指针 p)p=&array[ i ]; (将数组 array 第 i 个元素地址赋给指针 p)p=max; (max 为已定义函数,把入口地址赋给 p)p1=p2; (把指针 p2 值赋给指针 p1 )

指针变量允许有空值,即它不指向任何变量,为此可用 p=NULL;实现,其中 NULL是<stdio.h>文件中的符号常量,其值为零,当然也可以事先定义 #define NULL 0;。请读者注意,p 的值是NULL 与未对 p 赋值是两个不同的概念。未对 p 赋值并不等于 p无值,只是它的值是不确定的,即有可能指向一个事先未指定的单元,这种情况是很危险的,因此在引用指针变量之前应对它进行赋值。

表 11-2 有关指针的数据类型

Page 228: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

定义 含义int i;

int *p;

int a[n];

int *p[n];

int (*p)[n];

int f();

int *p();

int (*p)();

int **p

整型变量 I 的定义定义指针 p,p 指向整型数据定义一维数组 a,它有 n 个元素定义指针数组 p,它由 n,个元素,每个元素都是指针,指向整型数据定义 p 为指向含 n 个元素的一维数组的指针变量定义 f 为返回整型的一个函数定义一个返回指针值的函数,该指针指向一个整型数据p 为指向一个函数入口地址的指针,该函数返回一个整型值p 为一个指针变量它指向另一个指针变量,后者指向整型数据

(2)指针的移动可以使指针加(减)一个整数来移动指针,例如;p++、p 一一、p+i、p-i、p+=i、p 一=i

等,C 语言规定 p+i 实际上代表 p+C*i,式中 C 为系数(数据占用字节数),对大多数微机系统中,对整型数据 C=2,实型数据 C = 4,字符 C=1,这样才能保证 *(p+i ) 为 p 下面的第 i 个元素,这才有实际意义。两个指针变量如果指向同一个数组的不同元素,那么两个指针可以求差,其差值为两

个指针之间的元素数目,例如,图 11-16 中,p1 指向数组元素 a[1],p2 指向数组元素 a[5],那么 p2- p1=4,但 p1+p2并无实际意义。同时 p1 与 p2可以进行比较操作。(3)C 语言中新增加一种“void * ”指针类型,即可以定义一个指针,但不指定它指

向哪一种类型,即可指向任一类型数据,在将它的值赋给另一指针变量时要进行强制类型变换。总之,指针使用十分灵活。程序人员可以利用它编写出颇有特色的、质量优良的程序,

但应用时也易于出错,并且这种错误难以察觉,因此有人说指针有利有弊,甚至是“好坏参半”,因此使用指针要小心谨慎,多进行上机调试,弄清一些细节并逐步积累经验。

11.9 练习题11.9.1选择题

1.设 ptrl 和 ptr2 均为指向同一个 int 型一维数组的指针变量,k 为 int 型变量,则下面不能执行的赋值语句是 。

(A)k= * ptrl+ * ptr2 (B)int *p= *a(C)int p=&a (D)int *p=&a2.若已定义 a 为 int 型变量,则 是对指针变量 p 的正确说明和初始化。(A)int *p=a (B)int *p= * a(C)int p=&a (D)int *p=&A3.若有以下语句:

intx[ ]={1,3,5,7,9,11}, *ptr; ptr=k;

Page 229: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

则 是对数组元素的正确引用(A)x (B)*(ptr--)(C) x[6] (D)*(一一 ptr)4.执行下列语句后,a 的值为 [1] ,b 的值为 [2] ,c 的值为 [3] 。

int a,b,c,l=4,m=6,n=8;int *p1=&l, *p2=&rn, *p3;a=p1==&;b=3*(*p1)/(*p2) + 7;c=*(p3= &n)= *pl *( * p2);

[1](A)-1 (B)1(C)0 (D)4

[2](A)5 (B)6(C)7 (D)10

[3](A)0 (B)24(C)8 (D)7

5.若有说明:char s1[4]=″12″;char *ptr;则执行下列语句的输出为 。ptr=s1;printf(″%d\n″,*(ptr + 1);

(A)字符′2′ (B)字符′1′(C)字符′2′的地址 (D)不正确6.执行以下程序段后的 y 值为 。

static int a [ ]={1,3,5,7,9};int y,k,*ptr;y=1; ptr=&d[1]for(x=0;x<3;x++)

y*=*(ptr+x);(A)105 (B)15(C)945 (D)无定值。7.执行以下程序段后,m 的值是 。

static int a[ ]={7,4,6,3,10};int m,k,*ptr;m=10;ptr= &a[0];for(k=0:k<5 ; k++)m=( *(ptr+k) < m) ? *(ptr+k):m;

(A)10 (B)7(C)4 (D)6

8.执行以下程序段后,s 的值为 [ ]。satic int a[ ]={5,3,7,2,1,5,4,10};int s=0,k;for(k=0 ; k<8 ; k+=2)

s+= *(a+k);(A)17 (B)27(C)13 (D)无定值

Page 230: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

9.若有以下语句,且 0<k<6,则 是对数组元素地址的正确表示。static int x[ ]= {1,3,5,7,9,11}, *ptr,k;ptr = k;

(A)x++ (B)Lptr(C)~.ptrLk] (D)&(x+1)10.若有说明语句,int ,x [3] [4] ; 则以下关于 x ,*x, x[0] , &x[0] [0] 的正确描述是 。(A)x,x,x[o],&x[ 0 ][ 0 ]均表示元素 x[0][0]的地址(B)只有 x,x[0]和 x[0][0]表示的是元素 x[0][0]的地址(C)只有 x[0]和&x[0][0]表示的是元素 x[0][0]的地址(D)只有&x[0][0 ]表示的是元素 x[0][0]的地址11.若有说明语句:int i,x[3][4] ,则不能将 x[l][1]的值赋给变量 i 的语句是 。(A)i=*(*(x+1)) (B)i=x[1][1](C)i=*x(x+1) (D)i=*(x[1]+1)12.以下程序段的结果为 。

static char a[ ]=″program″;char *ptr;ptr=a;for(ptr=a;pyt< a+7;ptr+=2)putchar(*ptr);

(A)program (B)porm(C)有语法错误 (D)por13.以下程序段的输出为 。

static char a[ ]= ″language″,b[ ]= ″programe″;char *ptr,*ptr2; for(k=0;k< 7;k++)

if( *(ptrl + k)== *(ptr2+k))printf(″%c″,*(ptrl+k));

(A)gae (B)ga(C)1anguage (D)有语法错误14.执行以下程序段后,m 的值为 。

static int a[2][3]={{1,2,3},{4,5,6}};int m, *ptr;ptr = &d[0][0];m=( *ptr) *(ptr+2)*(*(ptr+4));

(A)15 (B)48(C)24 (D)无定值15.执行以下程序段后的结果为 。

static char a[ ]= ″1anguage″;char *ptr;ptr=a;while( *ptr)

{ prinft(″%c″,*ptr 一 32)ptr++;}

Page 231: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

(A)LANGUAGE (B)陷入死循环(C)有语法错误 (D)language16.若有以下说明语句:

static int a[2][3]={1,3,5,7,9,11};int m,n;

且 0<=m<=1,0<=n<=2,则 是对数组元素的正确引用。(A)a[m]+n (B)*(a+5)(C)*(*(a十m)+3) (D)*(*(a + m)+m)17.以下程序段的输出为 。

static char a[ ]=″Basic″;char *ptr;for(ptr=a;ptr< a+5;ptr++)

printf(″%s\n″,ptr);(A)Basic (B)b

asic a sic s ic ic c

(C)c (D)Basic ic sic asic Basic

18.若有以下说明语句;static int a[2]L3]={2,4,6,8,10,12};

则 是对数组元素地址的正确表示法。(A)*(a+1) (B)*(a[1]十 2)(C)a[1]+3 (D)a[0][0]。19.语句 int( *ptr)( );说明了 。(A)ptr是指向一维数组的指针变量。(B)ptr是指向 int 型数据的指针变量。(C)ptr是指向函数的指针,该函数返回一个 int 型数据。(D)ptr是一个函数名,该函数的返回值是指向 int 型数据的指针。20.设有说明:char *str=″\t\c\\Language\n″;,则指针 str 所指字符串的长度

为 。(A)17 (B)13(C)15 (D)说明不合法21.设有以下程序段,则在main 函数中使用语句 是无意义的。

main() min(x,y){ int x,y;

int min(); {int a,b,c(*p)(); ······ p=min; }

······

Page 232: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

}(A)printf(″%d\n″,min(a,b));(B)c=min(a,b);(C)c=(*p)(a,b);(D)p++;22.若有语句:char sl[ ]=″stringl″,s2[8],*s3,*s4=″string2″则 是对库函数 strcpy

的错误调用。(A)strcpy(sl,″string2″); (B)strcpy(s4,″stringl″);(C)strcpy(s3,″stringl″); (D)strcpy(″string2″,s2);23.以下函数 ABC 的功能是 。

ABC(ps)char *ps;

{ char *p;p=ps;

while(*p++);return(p-ps);

}(A)比较两个字符串的大小 (B)求字符串的长度(C)将串 ps复制到串 p 中 (D)以上三种说法都不对24.若有说明 int( *p)[3];则以下 是正确的叙述。(A)p是一个指针数组(B)p是一个指针,它只能指向一个包含 3 个 int 类型元素的数组(C)p是一个指针,它可以指向一个一维数组中的任一元素(D)(*p)[3]与 *[3]等价25.下面程序的运行结果为 。

main( ){

char *1etter[5]={″ab″,″efgh″,″ijk″,″mnop″,″st″};char **ptr;int i;ptr=1etter;for(i=0;i<4;i++)

printf(″%s″,ptr[i] );printf {″\n″};

}(A)abef (B)abefg(C)abefghijkmnopst (D)abefghijkmnop26.下列程序正确的运行结果为 。

#include <stio.h>main( )

{statlc int a[ ]={2,6,10,14,18};static *ptr[ ]={&a[0],&a[1],&a[2],&a[3],&a[4]};int * * p,i;

Page 233: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

for(i=0;i<5;i++);a[i]=a[i]/2+a[i] ; p=ptr;printf(″%d\n″,*( *(p+2 )));printf(″%d\n″,*(*(++p)));

}(A)15 (B)3

9 27 (C)21 (D)9

15 2l

11.9.2填空题1.设有以下语句:

static inta[3][2]={1,2,3,4,5,6};int(*p)[2];p=a;

则*(a+2)+1是元素 的地址, *( *(a+2)+1)的值为 ( *(p+1)+1)的值为 , *(p+2)是元素 的地址。

2.以下程序的输出结果为 。char *p;int i,d;p=″PDP1 - 0″;for(i=0;i<7;i++)

{d=isdiqit( *(p+i);if(d!=0)prinft(″%d\n″, *(p+i ));

}3.执行以下程序段后,sum 的值为 。

static int a[3][3]={7,2,1,3,4,8,9,2,6};int sum, *p;p=a[0];sum=(*p)*(*(p+4))*(*(p+8));

4.设有以下语句:static int a[4]={2,4,6,8};static int *p1[4]={&a[0],&a[1],&a[2],&a[3]};int **p;

则* *(p+2)的值是 , *(p+3)的值是元素 的地址。5.下面程序的运行结果为 。

# include <stdio.h>int a[ ]={1,5,7,9,11,13};

{int *p;

Page 234: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

p=a+3;printf(″%d,%d\n″,(*p,*p++);printf(″%d,%d\n″,*(p 一 2),*(a+4),}

6.下面程序的运行结果为 。# include <stdio.h>main()

{char *ptrl,*ptr2;ptrl=ptr2=″abcde″;while( *ptr2!=′\0′)putchar( *ptr2++);while( 一 一 ptr2 >= ptrl )putchar(*ptr2);putchar(′\n′);}

7.下面程序的运行结果为 。# include <stdio.h>char *a=″COMPUITER″;char b[ ]=″computer″;main( )

{ int i=0;prinft(″%c,%s″, *a,b+1);while( putchar(*(a+i)))

i++;putchar(′\n′);prinft(″%d,″,i) ;while(一-i) putchar(*(b+i ));putchar(′/n′);prinft(″%s″,&b[3]);}

8.下面程序的运行结果为 。main( )

{char a[ ]= ″This is a computer.″,b[20];while(a[i ]!=′\0′)

{ b[i]=a[i];i++;}

b[i]=′\0′;printf(″string a is:%s\n″,(A);printf(″string b is: ″);for(i=0;*(b+i)!=′\0′;i++)

printf(″%c″,*(b+i));

Page 235: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

printf(″\n″);}

9.下面程序的运行结果为 。main()

{ int a[10]={ll,12,13,14,15,16,17,18,19,20},n=10,i;sub(a,&n);for(i=0;i<n;i++)printf(″%d,″,a[i ]);printf(″\n″);}

sub(s,n)int *s,*n;

{ int i,j=0;for(i=0;i< *n;i++)if( *(s+i )%2 !=0) s[ j++]=s[ i ];*n = j;}

10.下面程序的运行结果为 。# include <stdio.h>main()

{char *s=″CEAedea″;sort(s,5);printf(″\n%s″,s);}

sort(s,num)char *s;int num;

{int i,j=num;char t;while(j 一一 >1)for(i=0;i<j ; i++)if(s[ i ] < s[i+1])

{t=s[i ];s[i]=s[i+1]s[i+1]=t:}

}11.下面程序的运行结果为 。

main( ){

static int a[ ] ={5,8,7,3,2,9};

Page 236: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

int s1,s2,i, *ptr;s1=s2=0;ptr=&a[0];for(i=0;i<5;i +=2)

{s1+=*(ptr+i );s2+=*(ptr+i+1);}

printf(″s1=%d,s2=%d\n″,s1,s2);}

12.若运行下列程序时,输入以下指定数据,则程序的运行结果为 。# include<stdio.h># define TRUE 1# define FALSE 0int func(char *c, int s);main()

{int flag=TRUE;char ch;do {ch=getchar( );

flag=func(&ch,flag);putchar(ch);}while(ch!=′.′);

printf{″\n″};}

int func(char *c,int s){

if(*c= =′′)return(TRUE);

e1se{

if(s&& *c < =′z′&& * c >=′a′)*c + =′A′一′a′;

return(FALSE);}

}输人数据(第一列):this is a lest question.<回车>13.以下程序能从所读入的若干字符串中,找出最大的一个串,并输出该串(用串***

**作为结束输入的标志),请在 处填入正确内容。# include<stdio.h># include<string.h>main()

{char ss[10][5],*ps;int n;

Page 237: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

reading(ss,&n);find max(ss,n,&ps);printf(″max=%s\n″,ps);

}reading(a,num)char (*(A) [5];int *num;

{int i=0;gets(a[i]);while(!strcmp(a[i],″* * * * *″)==0 { ;gets( a[i]);} =i;}

findmax(a,num,max)char(*a)[5], ;int num;

{int i;for(*max=a[0],i=1 ; i< num;i++)if(strcmp(a[i],*max)>0)

;}

14.下面程序的运行结果为 。# include <stdio.h>main()

{ int *p1,*p2[5],k;if((pl=malloc(100 * sizeof(int)))! = NULL)

{ p2[0 ]=pl;for(k=1;k<5; k++)p2[k]=p2[k-1]+7;for(k=0;k<100 ; k++)*p1++ = k;for(k=0;k<5 ; k++)printf(″%3d,″,*p2[k]);}

printf(″\n″); }

15.以下程序能将串 program!反向打印出来,请在 处填入正确内容。# include <stido.h>main( )

{out(″\nprogram!\n″);

}out(char *str)

{ char *s=

Page 238: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 11 章 指针

if(*s== )return;

while(*s)s++;

s--;printf(″%c″, ) =NULLout(str);

}16.下面程序的运行结果为 。

main( ){

char ss[10]= ″aprogram″;int num=4;sub(ss,0,num-1);sub(ss,num,6);sub(ss,0,6);printf(″%s\n″,ss) ; }

sub( s,numl,num2)char *ss;int numl,num2

{ char t, *p;p=ss+nam2;ss=ss + numl ; while(ss <p) {t=*ss; *ss=*p;*p=t ; ss++;p--;}}

Page 239: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

第 12 章 结构体与共用体12.1 结构体的定义及其变量的初始化

12.1.1 结构体定义12.1.2 结构体变量的初始化12.2 结构体类型变量的引用

12.3 结构体数组12.3.1 定义12.3.2 结构体数组初始化12.3.3 应用举例

12.4 指针和结构体12.4.1 指向结构体变量的指针12.4.2 指向结构体数组的指针12.4.3 结构指针参数

12.5 用指针处理链表12.5.1 链表12.5.2 建立链表12.5.3 链表输出12.5.4 对链表中的元素进行删除12.5.5 对链表插入结点12.5.6 主函数

12.6 共用体(联合)12.6.1 概念12.6.2 引用方式12.6.3 共用体的特点

12.7 枚举12.8 用 typedef 定义类型12.9 例题详解12.10 本章小结12.11 练习题

Page 240: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

第 12 章 结构体与共用体数组所处理的数据必须是同一类型的,但有时我们需要把不同类型的数据一起进行考

虑。例如,通讯录是由姓名、地址、电话、邮编等组成,像这样的实体是难以用数组表达的。C 语言中提供了一种新的称为结构体的数据类型来处理这类问题。本章要介绍结构体的定义、说明和使用、结构体与数据组和指针等问题,并讲解共用体(有的书称为联合)的概念。

12.1 结构体的定义及其变量的初始化12.1.1 结构体定义

结构体类似于数组,是由若干元素构成的,习惯上称这些元素为“成员”,能够作为结构体成员的除了基本数据类型(int、float、char),还可以是数组、指针、甚至另一个结构体,为了指定某个成员,我们可用成员运算符“.”(即圆点)。

定义一个结构体应采用关键字 struct,其一般形式:struct 结构体类型名称

{ 数据类型 成员名 1;数据类型 成员名 2;……

数据类型 成员名 n;};

通常结构体的定义有三种方式:1.结构体类型和结构体变量同时定义例 12-1

struct Student{ int num;

char *name;char sex;int age;char *address;}s;

Page 241: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

main(){ s.num=0501

s.name=″Li ming″;s.sex=M;s.age=21;s.address=″Beijing″;printf(″%d\n%s\n%c\n%d\n%s\n″,s.num,s.name,s.sex,

s.age,s.address,);}

运行情况:0501Li mingM21Beijing

说明:(1)struct后面的 Student是结构体名(结构标识符),有无皆可,若有,以后对同

类型结构体进行说明时,可用此结构体名代替结构类型。(2){ }中是结构体成员表,name 和 address是字符型指针,num是整型数,代表

学号。(3)花括号之后的 s是一个结构型变量,可定义多个结构型变量,结构体中的每个成

员引用的一般形式是结构变量名.成员名。2.结构体类型和结构变量分开定义例 12-2

struct Student{ int num;

char *name;char sex;int age;char *address;}; /*别忘记这里的分号*/

struct student s1,s2,s3; /*不可缺少 struct */说明:(1)本例首先定义名为 student 的结构体,包括 5 个成员。(2)s1,s2,s3 为三个同类型(student)的结构体变量,用结构名来说明,注意结构

名之前的 Student 不可缺少。(3)s1,s2,s3 结构体变量的定义必须放在可执行语句之前。(4)成员名可以与程序中变量名相同,两者互不干扰,例如程序中也可定义变量 num。3.直接定义结构体类型变量(不出现结构体名)struct

{ int num;char *name;

Page 242: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

char sex;int age;char *address;}s1,s2,s3;

请读者注意类型与变量是不同的两个概念,只能对变量赋值,存取或运算,而不能对类型赋值、存取或运算,编译时对类型不会分配内存空间,只对变量分配内存空间。

此外,结构体中的成员也可以是另一个结构体变量。例如:struct date

{ int day;int month;int year;};

struct student{ int num;

char name[10];char sex;struct date birthday; /*别忘记 struct*/float score[4];char *address;}s1,s2,s3;

12.1.2 结构体变量的初始化对结体构变量初始化,只需把成员所对应的初始值按成员顺序依次给出即可,但要注

意类型的一致性。1.外部存储类型的结构体变量初始化。当结构体变量为全局变量或静态变量时,可直

接进行初始化。例 12-3

struct Student{ int num;

char *name;char sex;int age;char *address;}s={0502,″Li ming″,′M′,21,″Beijing″};

main(){ printf(″No:%d\n name:%s\n sex:%c\n age:%d\n address:%s\n

″,s.num,s.name,s.sex,s.age,s.address);}

运行情况:No:0502name:Li ming

Page 243: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

sex:Mage:21address:Beijing

2.对静态存储类型结构体进行初始化。上例中的定义部分也可以放在主程序中。例 12-4

main(){ struct Student

{ int num;char *name;char sex;int age;char *address;}s={0502,″Li ming″,′M′,21,″Beijing″};

printf(″No:%d\n name:%s\n sex:%c\n age:%d\n address:%s\n″,s.num,s.name,s.sex,s.age,s.address);

}3.对自动存储变量不能在定义时初始化,因为它是局部变量,在函数被执行时才存在,

因此只能在执行时对其各个成员赋值。例 12-5

main(){ struct Student

{ int num;char *name;char sex;int age;char *address;}s;

s.num=0502;s.name=″Li ming″;s.sex=′M′;s.age=21s.address=″Beijing″;printf(″No:%d\n name:%s\n sex:%c\n age:%d\n address:%s\n″,s.num,s.name,s.sex,s.age,s.address);

}

12.2 结构体类型变量的引用定义了结构体变量以后,就可以引用这个变量,但应遵循以下原则:(1)不能将一个结构体变量作为一个整体加以引用,例如已定义了结构体变量 a,并

且已有值,不能这样引用:Printf (″%d,%s,%c,%s″,a);

而只能对各个成员分别引用,例如 a.num,其中′.′是成员运算符,它在所有的运算

Page 244: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

符中优先级最高,因此可以看成为一个整体。(2)如果成员本身又是一个结构体类型,则应该用若干个′.′一级一级地找到最低级

的成员。例如使用 s1.birthday.month,而不能使用 s1.birthday来进行访问,因为后者 birthday本身是个结构体变量。

(3)对成员变量可以像普通变量一样进行各种运算。例如 s2.sex=s1.sex s1.age++等。(4)可以引用成员的地址,也可引用结构体变量的地址,例如:

scanf(″%d″,&1.num); /*输入 s1 的学号*/print(&a); /*把变量 a首地址作为函数实参*/

12.3 结构体数组结构体数组是一个数组,它们其中每个元素都是一个结构体类型的数据,它们都分别

包括各个成员(分量)项。

12.3.1 定义和定义结构体变量方法相同,只需说明其为数组即可。例如:

struct student{ int num;

char name[10];char sex;char *address;};

struct student a[3];定义数组 a 有 3 个元素 a[o]、a[1]、a[2]是一个结构体数组,如图 12-1所示,它是一维数

组,各元素在内存中连续存放。num

name Sex Address

001 Li ming M 123 Beijing Road002 Wang Lin F 130 Shanghai Road003 Gong Jin M 101 Beijing Road

图 12-1 结构体数组

12.3.2 结构体数组初始化结构体数组可以在定义时初始化,但只能对全局的或静态存储的数组进行初始化。例如:

a[0]a[1]a[2]

Page 245: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

struct student{ int num;

char name[10];char sexchar * address;}a[3]={{0011,″Li ming″,′M′,″123 Beijing Road″},

{0012,″Wang Lin″,′F′,″130 Shanghai Road″},{0013,″Gong Jin″,′M′,″101 Beijing Road″}};

也可以在定义数组 a 时不指定元素,可用 a[ ]={{……},{……},{……}};,可见结构体数组初始化的形式是在定义数组后面加上={初值表列};。

12.3.3 应用举例例 12-6 对候选人得票的统计程序。设有 4 个候选人,每次输入一个得票的候选人的名

字,输出其得票结果。Struct person

{ char *name;int count;}leader[4]={″deng″,0,″zhou″,0,″wang″,0,″li″,0};

main(){ int i,j;

char name[20]for(i=0,i<=12;i++)

{ scanf(″%s″,name);for(j=0;j<4;j++)if(strcmp(name,leader[j].name)==0)

leader[j].count++;}

printf(″\n″);for(i=0;i<4;i++)

printf(″%s:%d\n″,leader[i].name,leader [i].count);}

运行情况:li↙deng↙zhou↙deng↙wang↙zhou↙zhou↙deng↙zhou↙

Page 246: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

wang↙li↙zhou↙

deng:3zhou:5wang:2li:2

说明:(1)程序定义一贯全局的结构体数组,它有 4 个元素,每一元素包含两个成员

name(姓名)和 count(票数)。定义时进行初始化,使 4 位候选人的票数都先归零。(2)在主函数中定义字符数组 name,在 12次循环中每次输入一个姓名,将它与 4 个

候选人的姓名(leader[j].name)相比较,看它和哪个相同,并使相同的成员的票数值(leader [i].Count)加 1。

(3)输入和统计结束后,将候选人的姓名和票数输出。

12.4 指针和结构体12.4.1 指向结构体变量的指针

例 12-7main()

{ struct leader{ int num;

char name[10];char sex; char *address;};

struct leader a,*p;p=&a;a.num=001;strcpy=(a.name,″Li Ming″);a.sex=′M′;strcpy=(a.address,″123 Beijing Road″);printf(”No:%d\n name:%s\n sex:%c\n address:%s\n″,

a.num,a.name,a.sex,a.address);printf(″No:%d\n name:%s\n sex:%c\n address:%s\n”,

(*p)num,( *p).name,(*p).sex,(*p).address)}

一个结构体变量的指针是该变量所占内存空间的首地址,本例中用指针 p来指向一个结构体变量 a,上述两个 printf 语句输出内容是一样的。

C 语言中为使用方便和直观,可以把(*p).mum改为 p→num来代替,因此以下三种形式是等价的:a.num、(*p).hum 和 p→num,其中→称为指向运算符。

Page 247: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

12.4.2 指向结构体数组的指针可以使用指向结构体变量、数组或数组元素的指针。例 12-8

struct worker{ int num;

char name[10];char sex;char *address;};

struct worker w[3]={{0011,″Li ming″,′M′,″123Beijing Road″},{0012,″Wang Lin″,′F′,″130 Whanghai Road″},{0013,″Gong Jin″,′M′,″101 Beijing Road″}};

main(){ struct worker *p;

printf(″No.Name Sex address\n″);printf(″\n″);for(p=w;p<w+3;p++)

printf(″%5d%-10s%3c%s\n″,p→num,p→name,p→sex,p→address);

}本例中 p 是指向 struct worker 结构体数组的指针变量,在 for 语句中,先使 p=w,即 p

指向数组 w 的起始地址,第一次循环输出 w[0]的各个成员值,然后执行 p++,使 p 指向 w[1]的起始地址,再在第二次循环中输出 w[i ]的各个成员值,再执行 p++,p 指向 w[2]的起始地址,再输出 w[2]各个成员值,再执行 p++后,p 值已变为 w+3 不再小于 w+3,结束循环。

注意:(++p)→num 是先使 p 自加 1,然后指向元素中成员 num 值。(p++)→num 是先得到 p→num 值,再进行 p++。

12.4.3 结构指针参数函数的参数可以是指向结构体的指针,这样就可以把一个结构体传递给函数。例 12-9

struct book { int count;

double price:};

total(p)struct book * p;

{ double x;x=p→count*p→price;

Page 248: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

printf(″x=%f\n″,x);}

main(){ static struct book b={3,18.5};

total(&b);}

运行情况:x=55.500000

程序中调用 total 函数,其形参 p是指向结构体的,调用时用&b 作为实参进行调用。

12.5 用指针处理链表12.5.1 链表

在计算机中链表是常见的一种数据结构,它可以动态地进行内存分配。图 12-2 表示一种最简单的链表结构,它有一个“头指针”(head)指向第一个元素,链表中每个元素称为一个“结点”,每个结点包括两部分:一是用户存放的数据;二是指向下一个结点的地址(指针),最后一个结点不再指向下一个元素,因此其地址部分为 NULL(空指针)。

从图 12-2可知,链表中各个元素在内存中不是连续存放的,要找到某一个元素必须首先找到前一个元素,如果不提供“头指针”(head),那么整个链表都无法访问,链表好似一条铁链,一环扣一环,中间不能断开。

结构体变量包含若干个成员,其中也可以包括指针成员,该种成员可以指向其他结构体类型,也可以指向它所在的结构体类型。例如:

struct student{ int num;

char name[10];struct student *next;}

其中 next是成员名,它是指针类型,它指向 struct student 类型数据(就是 next所在的结构体类型)。

注意上面只定义了一个 struct student 类型,并未实际分配任何存储空间,前面提到链表结构是动态分配的,即需要时才开辟一个结点的存储单元。C 语言中用 malloc(size)在

head 1211 1315 1225 1427

图 12-2 简单的链表结构

1211 ′A′ ′B′ ′C′ ′D′

NULL

Page 249: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

内存中分配一个长度为 size 的内存连续空间并返回起始地址的指针,若此函数未能成功执行,则返回值 NULL(0),另一个函数是 calloc(n,size)分配 n 个长度为 size 的内存连续空间,而 free(pt)释放由 pt 指向的内存区。

12.5.2 建立链表建立链表指从无到有建立一个链表,即一个个地输入各结点数据并建立前后相链的关

系。1.算法:先设立三个指针变量 head、p1 和 p2,它们都指向结构体型数据,先用 malloc 开辟一个

内存区,使 pl、p2均指向它,再从键盘读人一个学生的学号及考试成绩(三门课程),并以学号为零作为建立链表的结束标志。

2.函数#define NULL 0#define LEN sizeof(struct student) /*LEN 为结构体长度*/struct student

{ int num;float score[3];struct student,next; /* next 为指向下一结点指针*/};

int n;struct student *creat() /*此函数返回一个指向链表头的指针*/

{ struct student *head, * pl, *p2;n=0;p1=p2=(struct student *) malloc (LEN); /*开辟一个新存储单元*

/scanf(″%d,%f,%f,%f

″,&pl→num,&p1→score[0],&p→score[1];&p1→score[2]);

head=NULL;while(pl→num!=0)

{ n=n+1;if(n==1) head=p1;else p2→next=p1;p2=p1;p1=(struct student *) malloc (LEN);scanf(″%d,%f,%f,%f″,&p1→num,&p1→score[0],

&p1→score[1],&pl→score[2]);}

p2→next=NULL;return(head);}

3.说明:

Page 250: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

(1)第一行#define令NULL 为 0,表示空地址,第二行#define令 LEN代表 struct student 结构体类型数据的长度,sizeof 为“求字节数运算符”。

(2)第九行定义函数 creat是一个指针类型的函数,它返回指针 head,实际上是一个链表的开始地址。

(3)malloc(LEN)作用是开辟一个长度为 LEN 的内存区,一般情况下 malloc返回的是指向字符的指针,而 p1,p2是指向 struct student 的指针变量,两者类型不同,必须强制进行类型转换,因此在malloc之前加上“(struct student *)”进行强制类型转换,注意这里′x′不能缺少,否则转换成 struct student 类型而不是指针类型。

(4)n是结点数目,算法思路是让 p1 指向断开的结点,p2 指向链表中最后一个结点,把 p1所指结点连接到 p2所指结点的后面(p2→next=p1;来实现)。图 12-3(a)~(d)表示建立链表的过程。

12.5.3 链表输出将链表各个结点数据依次输出,其条件是应该已知 head 值,先设一个指针 p,先指向

第一个结点输出该结点内容,然后使 p后移一个结点再输出,直到链表结尾。函数:void print(head)

headP2

(a) n=1 (b)=2

head

(c)n=3head

(d)n=4(退出 while 语句后)图 12-3 链表建立过程

00290

87.571

0088587

62.5

064908869

P1001657992

P2

001657992

00290

87.571

P1 001657992

00290

87.571

0088587

62.5

headP2

P1

064908869

NVLL

0000

0088587

62.5

00290

87.571

001657992

P1P1

Page 251: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

struct student *head;{ struct student *p;

printf(″The list records are:\n″);p=head;if(head!=NULL)do

{ printf(″%d\t%5.1f\t%5.1f\t%5.1f\n″,p→num,p→score [0],p→score[1],p→score[2]);p=p→next;}while(p!=NULL);

}

12.5.4 对链表中的元素进行删除如果要删除链表中某个结点(例如:结点 C),只要把该结点前的结点(结点 B)与

它脱离,并指向后一个结点(结点 D)即可,见图 12-4。

1.算法:我们以指定的学号(num)作为删除结点的标志,例如输入 002 表示要删除 002学号

的结点,从 p 指向链表的第一个结点开始,检查该结点中的 num 值是否等于 002,若相等则删除该结点,否则 p后移一个结点,再进行比较,如此下去,直到遇到链表结尾为止。

可以设定两个指针变量 p1 和 p2,先使 p1 指向第一个结点,如果要删除的不是第一个结点,则使 p1 指向下一个结点(p1=p1→next);但在此之前应将 p1 值赋予 p2,使 p2 指向刚才检查过的结点。

如果已找到要删除的结点又分两种情况:1)要删除的是第一个结点此时只需把 p1→next 赋给 head,即 head 指向第二个结点,尽管第一个结点仍与链表相连接,但实际上已无法访问,第一个结点已“丢失” (见图 12-5(a));2)要删除的不是第一个结点,只需把 p1→next 赋给 p2→next,此时 p2→next 指向 p1 的下一个结点,p1 指向的结点已不再是链表的一部分,即已经删除,见图 12-5(b)。

图 12-4 删除链表中结点 C

A B

BA C D E

C D E F

F

00290

87.571

P2001657992

0088587

62.5

064908869

NULL

00290

87.571

0088587

62.5

P1headhead

headP1

Page 252: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

(a)删除第一个结点 (b)删除中间结点图 12-5 链表中元素的删除

; 还应该考虑到链表是空表(无结点)和链表中找不到要删除结点的情况。2.函数:struct student *del(head,num)struct student *head;int num;

{ struct student *pl,*p2;if(head=NULL)

{ printf(″\n The list is NULL!\n″);goto end;}

p1=head;while(pl→num!=num&& p1→next !=NULL )

{ p2=P1;p1=p1→next;} /*p1后移一个结点*/if(pl→num==num) /*找到删除结点*/

{ if (pl==head) head=p1→next; /*删除第一个结点*/else p2→next=pl→next; /*删除中间点*/printf(″delete:%d\n″,num);n=n-1; /*为链表结点数*/}

else printf(″%d not been found! \n″); /*找不到结点*/end;return(head); /*返回头指针*/

}

12.5.5 对链表插入结点将一个结点插入已有链表中,设已有链表已按学号(num)由小到大顺序排列。1.算法:用指针变量 p0 指向待插入的结点,p1 指向第一个结点,将 p0→num 与 p1→num 比较,

如果前者较大,说明结点不应插入到 p1所指结点之前,此时 p1后移,并事先用 p2 指向 p1原来位置。再将 p0→num 与 p1→num 比较,如果前者仍旧较大,再使 p2 指向 p1,然后 pl后移,如此等等,直到 po→num 小于或等于 p1→num,此时应将 p0所指结点插入到 p1所指结点之前,如果 po-nulil 大于所有结点的 num,那么 p0 结点应插入到链表末尾。

如果插入位置在第一个结点之前(即 p1=head),则只需把 p0 赋予 head,并将 p1 赋予 p0→next;如果插入位置在链表中间,只需将 p0 值赋给 p2→next(即 p2→next 指向待插入

Page 253: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

结点),然后将 p1 的值赋给 p0→next;如果插入结点在链表末尾,应将 p0 赋予 p1→next,NULL 赋予 p0→next。

2.函数:struct student *insert(head,stud)struct student *head,*stud;

{ struct student *p0,*p1。*p2;p1=head; /*pl 指向链表第一个结点*/p0=stud; /*p0 指向要插入的结点*/if(head==NULL) /*原链表是空表*/

{head=p0;p0→next=NULL;} /*使 p0 作为头指针*/else

while((p0→num >pl→num)&&(pl→num!=NULL)){ p2=pl;pl=p1→next;} /*pl后移*/

if (p0→num<=p1→num){if (head==p1) head=p0; /*插入链表开头*/

else p2→next=p0; /*插入到 p2 结点之后*/p0→next=p1;}

else{p1→next=p0;p0→next=NULL;}/*插入到最后*/

n=n+1; /*结点数加 1*/return(head);

}

12.5.6 主函数将以上建立、输出、删除、插入函数组织在一个程序中,用 main 函数作为主调函数。

main(){ struct student head,*stu;

int del num;printf(″input records:\n″); head=creat(); /*返回头指针*/print(head); /*输出全部结点*/printf(″\n Input the delete num:″);scanf(″%d″,&del num); /*输入要删除学号*/head=del(head,del num); /*删除后的头指针*/print(head); /*输出删除后链表结点*/printf(″\n Input the inserted recond :″); /*输入要插入记录*/scanf(″%d,%f,%f,%f″,&stu.num,&stu,score[0],

&stu.score[1],&stu.score[2]); /*插人数据*/head=insert(head,&stu); /*返回地址'*print(head); /*输出插入后链表*/}

此程序运行结果是正确的,但如果要插入两个记录,重复写以上最后四行,运行结果

Page 254: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

却是错误的,如果结合 main 和 insert 函数考察,可知 stu是一个有固定地址的变量。第一次把 stu 结点插入到链表中,第二次再用它时就把第一个插入的结点数据冲掉了。为解决此问题必须在每插入一个结点时新辟一个内存区。为此修改main 函数,使它能删除多个结点(直到输入要删除的学号为 o),也能插人多个结点(直到输入要插入的学号为 0)。

修改后main()函数如下:main()

{ struct student *head,*stu;int del num;printf(″input records:\n″);head=treat();print(head);printf(″\n Input the deleted num:″);scanf(″%d″,&del num);while(del num!=0)

{ head=del(head,del num);print(head);printf(″\n Input the deleted num:″);scanf(″%d″,&del num);}

print(head);printf(″\n Input the inserted record:″);stu=(struct student *) malloc(LEN);scanf(″%d,%f,%f,%f″,&stu→num,&stu→score[0],&stu→score[1],&stu→score[2];while(stu→num !=0)

{ head=insert(head,stu);printf(″\n Input the inserted record:″);stu=(struct student *)malloc(LEN);scanf(″%d,%f,%f,%f″,&stu→num,&stu→score[0],

&stu→score[1],&stu→score[2];}

print(head);}

12.6 共用体(联合)12.6.1 概念

共用体同结构体的定义形式上相同,只是把关键字 struct改为 union。有时需要把几种不同类型的变量放在同有一内存区域中,见图 12-6,把一个整型变量,

一个字符变量,一个实型变量放在同一内存区域中,尽管三个变量占用字节数各不相同,但起始地址都一样(例如 1000)它要用“覆盖’’技术,使多个变量互相覆盖。这种结构称为共同体或者联合。

Page 255: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

定义共用体方式类似结构体。例如:

union data 或 union 或 union data{ int i; { int i; {int i;

char ch; char ch char chfloat f; float f; float f;}a,b,c; }a,b,c; };

union data a,b,c;“共用体”和“结构体”定义形式相似,但其含义不同。结构体变量所占内存长度是

各成员的内存之和(如图 13-6 为七个字节),但共用体变量所占内存长度是最长成员的长度(如图 13-6 中为 4 个字节)。

12.6.2 引用方式先定义共用体变量后才可以引用它。不能引用共用体变量本身。而只能引用其中的成员。

例如:printf(″%d″,a);是错误的,printf(″%d″,a.i);是正确的。例 12-10

main(){ union tdate

{ int uint;long tlong;float tfloat;doudle tdouble;char *tstring:

}t;t.uint=3;printf(″%d\n″,t.uint);t.tlong=300;printf(″%1d\n″,t.tlong);t.tfloat=3.0;printf(″%f\n″,t.tfloat);t.tdouble=3.00;printf(″%f\n″,t.tdouble);t.tstring=″stu″;printf(″%s\n″,t.tstring);}

12.6.3 共用体的特点

首地址 1000 字符变量 ch

图 12-6 共用体概念

整型变量 i

实型变量 f

Page 256: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

(1)同一内存段可放几种不同类型的成员,但每一瞬间只能存放一种。例如:a.i=1;a.c=′a′;a.f=2.1;

在完成以上三个运算后,只有 a.f是有效的,a.i 及 a.c都不再有效,因此用printf(″%f″,a.f);是可以的。但不能用 printf(″%c″,a.c);,所以引用共同体变量时应该特别注意当前放的是什么数据。

(2)共用体变量地址及其各成员地址都是同一地址。即&a,&a.i,&a.c,&a.f 值相同。

(3)不能对共用体变量名赋值。也不能定义时进行初始化。(4)不能把共用体变量作为函数参数,也不能使函数返回共同体变量,但可以使用指

向共用体的指针。(5)允许定义共用体数组。

12.7 枚举枚举是一个整型常数的集合。其构造类似于结构体,用关键字 enum 表示枚举。其一般

形式为:enum 枚举名 {枚举表}变量表;

枚举名和变量名可以是选择的。例如:enum coin{penny,nickel,dime,guarter,

half-dollar,dollar};enum coin money;

除非进行初始化。否则第一个枚举符号值为 0,第二个为 1,依次类推,因比 printf(″%d,%d″,penny,guarter);屏幕上显示 0 和 3两个值,读者可能认为不用枚举变量,而直接用常数 0代表“penny”,常数 1代表“nickel”……不也可以吗? 完全可以,但显然用枚举符号更为直观。使人“见名知意”,而且也限制其取值范围。

12.8 用 typedef 定义类型C 语言中允许用 typedef来定义新的类型来替代已有的类型,其一般形式是:

typedef 已定义类型 新类型例如:

typedef int INTEGER;typedef float REAL;

这样可以使熟悉 Pascal 或 FORTRAN 语言的程序员,用 INTEGER来定义整型变量,用 REAL来定义整型变量。

12.9 例题详解

Page 257: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

例 12-11 分析以下程序运行结果。# include ″stdio.h″struct s

{ int x,*y; 结构体中成员,为指向整型的指针*/} *p /*是指向结构体的指针*/

int a[6]={200,400,600,800,100,300}; /*data 为类型数组*/struct s b[6]={10,&a[0],30,&a[1],50,&a[2],

70,&a[3],90,&a[4],20,&a[5]};/*a 为结构体数组*/

main(){ p=b; /*p 指向 a 的首地址*/

printf(″For printer:\n″);printf(″%d\n″,p→x);printf(″%d\n″,(*p).x);printf(″%d\n″,*p→y);printf(″%d\n″,*(*p).y);printf(″%d\n″,++p→x);printf(″%d\n″,(++p)→x);printf(″%d\n″,p→x++);printf(″%d\n″,p→x);printf(″%d\n″,++(*p→y));printf(″%d\n″,++*p→y);printf(″%d\n″,*++p→y);printf(″%d\n″,p→x);printf(″%d\n″,*( ++p)→y);printf(″%d\n″,p→x);printf(″%d\n″,*p→y++);printf(″%d\n″,p→x);printf(″%d\n″,*(p→y)++);printf(″%d\n″,p-x);printf(″%d\n″,*p++→y);printf(″%d\n″,p→x);}

本程序涉及 21 个 printf 语句,其格式均是″%d\n″(除第一个外),因此均是输出一个整数后换行,分析其执行过程如下:

p→x 取结构体指向的结构体的成员取出其值 输出 10(*p).x 同上 输出 10*p→y 取结构体指针 p 的按指针成员 y 的内容 输出 200*(*p).y 同上 输出 200++p→x p所指向的 x 值先加 1再输出(p 不变) 输出 11(++p)→x p 加 1,再输出 p→x 值(x 不变) 输出 30p→x++ 先取出 p→x 值输出,再使 x 加 1 输出 30p→x 输出 x 值 输出 31++(*p→y) P 指向 y 内容先加 1 输出(p,y均不变) 输出 401++ *p→y 同上 输出 402++p→y P所指的 y 先加 1,再取 y 内容(p 不变) 输出 600p→x 输出 x 值 输出 31*(++p)→y P 先加 1后取 y所指内容 输出 600p→x 输出 x 值 输出 50*p→y++ 取 p所指内容输出,然后 y 值加 1 输出 600p→x 取 x 值 输出 50*(p→y)++ 取 p所指 y 内容,然后使 y 值加 1 输出 8000p→x 取 x 值 输出 500*p++→y 取 p所指 y 内容,再使 p 加 1 输出 100

Page 258: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

p→x 取 x 值 输出 70图 9-7 为结构数组 b 初始化后状态。

程序结束运行时,指针与结构数组状态如图 12-8所示。

图 12-8 程序结束时状态

例 12-12 有 m 个小孩围成一圈并依次编号,教师指定从第 n 个小孩开始报数,当报到 s时,即令其出列,然后从下一个小孩开始重新报数,数到第 s 个小孩又令其出列,依次类推直到所有孩子都出列,编写程序求小孩出列顺序,这个问题称为约瑟夫问题。

分析:由于小孩围成一圈可以用一个环形链表来表示,结构类型以 hild 表示,数组名为 link,nextp 为下一个小孩序号,no 为小孩序号,出列时打印 no

程序:#include <stdio.H>struct child /*定义结构体 child*/

{ int nextp,no;}link[80] /*说明结构体数组 link*/

main()

图 12-7 结构体数组的初始化情况

10

20

30

40

50

60

data[0]

data[1]

data[2]

data[3]

data[4]

data[5]

data

100 ·

200 ·

300 ·

400 ·

500 ·

600 ·

a[0]

a[1]

a[2]

a[3]

a[4]

a[5]

x y

11

22

30

40

50

60

data[0]

data[1]

data[2]

data[3]

data[4]

data[5]

data

101 ·

201 ·

300 ·

400 ·

500 ·

600 ·

a[0]

a[1]

a[2]

a[3]

a[4]

a[5]

x y

Page 259: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

{ int m,n,i,s,k,y,count=0; /*count 为计数器*/printf(“input the number of the children:”);scanf(“%d”,&m);printf(“\n input the started number:”);scanf(“%d”,&n);printf(“\n input the number of counting:”);scanf(“%d”,&s);for(i=1;i<=m;i++) /*根据孩子数目 m 建立环*/

{ if(i==m)link[i].nextp=1; /*最后一个,下一个是第 1人*/ else link[i].nextp=i+1; /*第 i 个,下一个是第 i+1人*/link[i].no=i /*第 i 个序号为 i*/

} printf(“\n stand out\n”);if(n==1)

k=m;else

k=n-1; /*k 定义在开始计数的前一个人上*/while(count !=m)

{ for(i=0;i!=s;){ k=link[k].nextp;

if(1ink[k].no!=0)i++. /*未出列时 no 为非零*/}

printf(“%7d',link[k].no)link[k].no=0;if(++count%5==0)printf(“\n”);}

} 说明:程序中输入小孩总数 m,计数起始位置 n 及计数步长 s。然后由m来构成一个结

构数组 link。为使用方便 link从下标 1 开始使用,由于数组长度说明为 80,因此m必须不大于 79,变量 k 用来记录下一次需计数的数组下标。开始时 k 应在开始报数小孩的前一个位置(k=n-1)。

在while 循环中使用 count 计数,对已列出的小孩,将 no清零。变量 i是报数计数器,当 link[k]不为 0 时才进行 i++,语句 k=link[k].nextp;含意是将下一个孩子所在下标位置送人变量 k 中。

运行情况:input the number of the children:12↙input the started number:4↙input the number of counting:5↙stand out:8 1 6 12 73 11 10 2 59 4

12.10 本章小结

Page 260: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

结构体和共用体是 c 语言中能把不同类型的数据放在一起作为整体考虑的数据结构。本章首先讲述了结构体的定义方法,它用关键字 struct 表示,在定义结构体类 m 时可以同时说明结构变量,也可以分开进行说明。初学者应该区分类型和变量的差别。正如 int i;中 int与 i 的差别一样。

通常对结构体中的成员(元素)进行访问,此时应采用成员运算符`.`。对结构体变量初始化时对全局变量或痴态变量可以直接进行初始化,而对局部变量只能一个个成&进行初始化。同时不能对一个结构体变量整体进行引用,而只能对其中成员进行引用。

结构体数组的每一个元素都是结构体变量(每个结构体变量又包括若干个成员),对全局或静态存储的结构体数组也能直接进行初始化,可以享用一个指针指向结构体数。可以用(*P).num 或 P→num来表示结构数组中的成员,其中→称为指向运算符。本章例13-12是一个具体的例子。读者应该很好地掌握。

链表的生成、插入元素、删除元素、显示等操作是指针和结构体相结合的一种应用。也是计算机中常用的数据处理方法之一。读者请注意在任何时候都不能丢失链表的头指针 (head),否则链表就无法访问。

本章介绍了“共用体”(联合)的概念。其形式与结构体相似,但实质不同,各个成员共用一个内存区域,采用了“覆盖”技术。

12.11 练习题12.11.1选择题

1.若有以下说明,则对结构体变量 studl 中成员 age 的不正确引用方式为 。struct student

{ int age;int num;}studl,*p;

(A)studl.Age (B)student.Age(C)p→age (D)(*p).age2.若有以下程序段,则 是不正确的使用。

struct student{ int num;

int age;};

struct student stu[3]={{1001,20},{1002,19},{1004,20}};main()

{ struct strdent *p;p=stu;}

(A)(p++)→num (B)p++(C)(*p).num (D)p=&stu.age3.若有以下的说明,则在 scanf 函数调用语句中对结构体变量成员的不正确引用 a 方

式为 。

Page 261: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

struct pupi{ char name[20];

int age;int sex;}pup[5]*p;

(A)scanf(“%s”,pup[0].name);(B)scanf(“%d”,&pup[0].age);(C)scanf(“%d”,&(p→sex));(D)scanf(“%d”,&(p→age);4.若已定义如下的共用体类型变量 x,则 x所占用的内存字节数为 (设在 16 位 pc

机的环境)。union data

{ int i;char ch;double f;}x;

(A)7 (B)11(C)8 (D)105.设有以下语句:

struct s{int i1;struct s*i2;};static struct s a[3]—{5,&a[2],7,&a[2],9,`0`},*ptr;

ptr=&a[0];则以下表达式 的结果是 6。(A)ptr→i1++ (B)ptr++→i1(C)*ptr→i1 (D)++ptr→i16.以下 是对 C 语言中共用体类型数据的正确叙述。(A)一旦定义了一个共用体变量后,即可引用该变量或该变量中的任意成员。(B)一个共用体变量中可以同时存放其所有成员(C)一个共用体变量中不能同时存放其所有成员(D)共用体类型数据可以出现在结构类型定义中,但结构类型数据不能出现在共用

体类型定义中。7.若有以下定义,则语句 是正确的。

union data{ int i;

char c;float f}a;

int n;(A)a=5; (B)a={2,`a`,1.2};(C)printf(“%d\n”,a); (D)n=a;8.设有以下说明,则下面不正确的输出是 。

union data{ int i;

char C;

Page 262: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

float f;}a;

(A)a所占的内存长度等于成员 f 的长度。(B)a 的地址和它的各成员地址都是同一地址。(C)a可以作为函数参数。(D)不能对 a 赋值,但可以在定义 a 时对它初始化。9.执行下列语句后的结果为 。

enum weeklyday{sun,mon=3,tue,wed,thu};enum weeklyday workday;workday=wed;printf(“%d\n”,workday);

(A)5 (B)3(C)4 (D)编译时出错10.若有定义:

enum weekday{mon,tue,wed,thu,fri}workday;则 是不正确的语句。

(A)workday=(enum weekday)3;(B)workday=(enum weekday)(4-2);(C)workdav=3;(D)workday=thu;11.设有以下说明,则 是对位段中数据的错误引用。

strute packed_data{ unsigned a:2;

unsigned b:3;unsigned c:4;int d;}data;

(A)data.a=2 (B)data.b=8(C)data.c=4 (D)data.d=1012.下列程序正确的运行结果为 。(提示:c[0])在低字节,c[l]在高字节)。

#include(stdio.h)union p

{ int i;char c[2];}x;

main(){ x.c[0]=13;

x.c[1]=0;printf(“%d\n”,x.i);}

(A)208 (B)14(C)13 (D)20913.下列程序正确的运行结果为 。

Struct S

Page 263: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

{ int n;int *m;}*p;

int d[5]={10,20,30,40,50};struct s arr[5]=

{ 100,&d[0],200,&d[1],300,&d[2],400,&d[3],500,&d[4]};

#include(stdio.h)main()

{ p=arr;printf(“%d\n”,++p→n);printf(“%d\n”,(++p)→n);printf(“%d\n”,++(*p)→m);

}(A)101 (B)101

200 20 2l 30

(C)200 (D)100101 1012l 10

12.11.2填空题1.若以定义了以下结构体变量 stud,则它在内存中将占 个字节。(设在 16 位 PC 机

环境下)struck student

{ int num;charname[20];char sex;int age;}stud;

2.若已定义:sruct num{int a;int b;float f;}n={1,3,5.0}}

struct num *pn=&n;则表达式 pn→b/n.a*++pn→b 的值是 ,表达式(*pn).a+pn→f 的值是 。

Page 264: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

3.设已定义:union

{ charc[2];int K;}s;

若执行 s.x=0x4241后,s.c[0]的十进制值为 ,s.c[l]的十进制值为 。4.设有以下定义和语句,请在 printf 语句中填上能够正确输出的变量及相应的格式说

明。union

{ int i;double y;}num;

num.i=10;num.y=10.5;printf(“ ”, );

5.下面程序的运行结果为 。main()

{ union{ long i;

int k;unsigned char s;

}abc;abc.i=0x12345678;printf(“%x\n”,abc.k);printf(“%x\n”,abc.s);}

6.下面程序的运行结果为 。main()

{ union mum{struct {int x;int y;}in;int a;int b;}n;

n.a=1;n.b=2;n.in.x=n.a*n.b;n.in.y=n.a+n.b;printf(“%d,%d\n”,n.in.x,n.in.y);

}

Page 265: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 12 章 结构体与共用体

Page 266: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 13 章 文件

第 13 章 文件13.1 文件概述13.2 文件的处理

13.2.1 文件指针13.2.2 文件的打开和关闭13.2.3 文件的读和写

13.3 例题详解13.4 本章小结13.5 练习题

第 13 章 文件文件(file)是程序设计中一个重要的概念,所谓“文件”可定义为存储在外部介质上

数的集合,操作系统通过文件名来读写文件,这里“读”是指从文件中读出数据,“写”是指把数据写入文件之中,每一个与主机相连的输入输出设备也可看作是一个文件(设备文件)。例如,键盘是输入文件(用 CON 表示),显示屏和打印机是输出文件(分别用CON 和 PRN 表示)。

13.1 文件概述C 语言中把“文件”看成是一个字符的序列,即由一个个字符(字节)的数据顺序组

成,据数据的组织形式可分为 ASCII 文件和二进制文件两种,ASCII 文件又称为文本(text)文件,每一个字节放一个 ASCII代码,代表一个字符。二进制文件按数据在内存中形式原样存放在磁盘上。例如:整数 1034 用 ASCII 码存放占用 4 个字节,若按二进制形式存放只占用 2 个字节,如图 13-1。

(a)二进制形式 (b)ASCⅡ 形式图 13-1 整数 1034 的存放形式

由上例可知:用 ASCII 码表示,字符与字节一一对应,便于对字符逐个处理,也便于直接进行字符输出,但一般占用存储空间较多,而且要花费二进制形式与 ASCII 形式间的转换时间。用二进制形式节省存储空间,并且不需转换时间,但一个字节不对应一个字,

00000100 00001010 00110001 00110000 00110011 00110100

Page 267: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 13 章 文件

不能直接输出显示。与其他高级语言不同,C 语言中的文件并不是由记录(record)组成的,对文件的存取

以字符(字节)为单位的。C 语言对文件的输入输出是由库函数来完成的,它没有输入输出语句。从内存向磁盘出数据必须先送到内存中的缓冲区,装满缓冲区后才一次送往磁盘,反之,从磁盘读出据到内存,也先把一批数据送人内存缓冲区(充满缓冲区)。然后再从缓冲区逐个将数据人内存数据区,缓冲区大小各个具体 C版本不完全相同,一般为512kB,图 13-2 表明缓区的概念。

有关文件操作的函数属于 C 语言标准输入输出库中的函数,为使用其中的函数,应在源程序文件的开头写上#include<stdio.h>。

输入 输出 磁盘

图 13-2 缓冲区概念

13.2 文件的处理13.2.1 文件指针

C 语言文件结构是由系统定义的,包含在 stdio.h 头文件中,其结构包括文件名、文件状态等等,在 C 程序中凡是要打开文件进行操作都要通过指向该文件的指针进行。为此需要在程序中说明指向文件结构的指针变量,其说明形式是:

FILE *文件指针名;若在程序中用到多个文件。则需要说明多个文件指针。例如:

FILE *fp1,*fp2,*fp3;但对于标准设备文件名(CON.PRN等)由系统自动打开和关闭,用户在程序中可以直接使用,无需再进行说明。

13.2.2 文件的打开和关闭同所有高级语言一样,在使用文件前必须打开该文件,使用文件后应关闭文件(指磁

盘文件),因此其过程是打开→使用→关闭。1.文件的打开(fopen 函数)C 语言中用函数 fopen来打开文件,其调用格式为:

FILE *fp;

程序 数据区

输入文件缓冲区

输入文件缓冲区

Page 268: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 13 章 文件

fp=fopen(文件名、文件使用方式);函数功能是以指定的方式打开指定的文件,其中文件名为要打开的磁盘文件名称,文

件使用方式见表 14-1所示,文件打开后,fp就指向该文件。例如:fp=fopen(“A:\ABC”,“r”);

表示打开 A盘上名为 ABC 的文件,使用方式为“读入”。fopen带回的指针赋给 fp,即 fp 指向文件 ABC。

说明:(1)用“r”方式打开的文件只能从文件“读出”,不能向文件“写入”,而且文件必

须已经存在。否则会打开时出错;用“w”方式打开的文件只能向文件“写入”而不能从文件“读出”。如果原先该文件不存在则新建这个文件。如果文件已存在,则打开时原文件内容删去;若想对已存在的文件末尾添加数据(原文件内容保留)则应采用“a”方式。

表 13-1 使用文件方式 格 式 含 义 “r”(只读) “w”(只写)

“a”(追加)“rb”(只读)“wb” ( 只

写)“ab” ( 追

加)“r+” ( 读

写)“w+” ( 读

写)“a+” ( 读

写)“rb+” ( 读

写)“wb+” ( 读

写)“ab+” ( 读

写)

为输入(读)打开一个文件为输入(写)打开一个文件向文本文件末尾增加数据为输入(读)打开二进制文件为输出(写)打开二进制文件向二进制文件末尾增加数据为读\写打开一个文本文件为读\写打开一个新的文本文件为读\写打开一个文本文件为读\写打开一个二进制文件为读\写打开一个新的二进制文件为读\写打开一个二进制文件

(2)若对文件又要读又要写,可用“r+”、“w+”和“a+”,但用“w+”时原文件内容被删,然后先向文件写入数据,再可以读出数据。

(3)在 r、w、a后加上 b,则可以对二进制文件进行打开和读写。(4)若不能实现文件打开任务,fopen 函数会带回出错信息(原因可能是用“r”打开

一个存在的文件,磁盘已满无法建立新文件等),此时 fopen返回一个空指针 NULL。(在studio.h 中 NULL已定义为 0)。因而常用下列方式打开一个文件:

if((fp:fopen(“filel”,“r”))==NULL){ printf(“Cannot open filel\n”);

Page 269: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 13 章 文件

exit(0);}

其中 exit(0)作用是关闭所有文件,终止调用过程,待程序员检查并改正错误后再运行。(5)在从文本文件向计算机读入时,将回车换行符转换为一个换行符,在向文件写

入·,把换行符转换成为回车和换行两个字符,在使用二进制文件时不进行这种转换。2.文件的关闭(fclose 函数)使用完一个文件后应马上关闭它,以防止再误用它。“关闭”就是使文件指针变量与

文件“脱钩”,即不再指向该文件,以后也不能再对此文件进行读写操作,除非再次打开它。

fclose 函数关闭指针的一般调用形式是:fclose(文件指针);

例如:fclose(fp);

fclose也返回一个值,当返回值为 0 表示正常执行了关闭功能,如果返回值为非 0,则表示关闭时有错误,可以用 ferror 函数来检测。

13.2.3 文件的读和写文件在打开后就可以对它进行读写操作,常用读写函数有:

·字符输入/输出函数 fgetc 和 fputc·字符串输入/输出函数 fgets 和 fputs·格式化输入/输出函数 fscanf 和 fprintf·数据块输入/输出函数 fread 和 fwrite·文件定位函数 feek,rewind 和 ftell·其他函数 feof,ferror 和 clearerr

1.fgetc 和 fputc 函数(1)字符输入函数 fgetc从指定文件(该文件必须以读或读写方式打开)读入一个字符,其格式为

ch=fgetc(fp);fp 为 文 件 型 指 针 变 量, ch 为 字 符 变 量, fgetc 返回一 个 字 符 赋给 ch,如果执行

fgetc(fp);读出字符遇到文件结束符,函数返回一个文件标志 EOF,EOF在 stdio.h 中定义为-1。如果要从一个磁盘文件顺序读入字符并显示出来,可参考下列程序:

ch=fgetc({p};while(ch 2=EOF)

{ prtchar(ch);ch=fgetc({p};}

(2)字符输出函数 fputcfputc 函数把一个字符 ch 写到磁盘文件中,其一般形式是

fputc(ch,fp)该函数也返回一个值,若输出成功则返回值就是输出字符,如果输出失败。返回

EOF(-1)。

Page 270: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 13 章 文件

(3)使用举例例 13-1 将一个磁盘文件的信息复制到另一个磁盘文件中。#include <stdio.h>main()

{ FILE *in,*out;char Ch;if((in=fopen(“infile.txt”,“r”))==NULL)

{ printf(“cannot open file:infile.txt\n”);exit(0);

}if((out=fopen(“outfile.txt”,“w”))==NULL)

{ printf(“cannot open file:outfile.txt\n”);exit(0);

}while(!feof(in))fputc(fgetc(in),out);fclose(in);fclose(out);}

上例中是按文本文件来处理 infile.txt 及 outfile.txt两个文件的,如果是复制一个二进制文件,只需在 fopen 函数中将“r”、“w”分别改为“rb”和“wb”。

例 13-2 上例中能把 infile.txt、outfile.txt 作为命令行的两个参数来输入,这样可以使程序有更好的通用性,这时就需要用 main 函数的参数。在先前的程序中主函数 main 本身是不带参数的 main(),但实际上 main可以有参牧

数。例如main(argc,argv),这里 avgc 及 argv 为 main 的参数(形参)。其中 argc是命令行中参数的个数(文件名本身也算一个参数),argv是指针数组(每个元素指向一个字符串)见图 13-3所示。即其参数形式为:

main(argc,argv)int argc;char *argv[];

{┇}

argv[0] 程序文件名\0

argv[0] 第一个实参\0

argv[0] 第二个实参\0

┇┇

┇ ┇

argv[0] 第 n 个实参\0

图 13-3 main 的形参

argv

Page 271: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 13 章 文件

本例程序可以为:#include(stdio.h)main(argc,argv) /*带形参的主函数*/int argcchar *argv [ ]

{ FILE *in,*out;char ch; if(argc!=3) /*检查命令行中参数个数*/

{ printf(“You forgot to enter a file name\n”);exit(0)}

if((in=fopen(argv[1],“r”))==NULL){ print[(“Cannot open file %s\n”,argv[1]);

exit(0);}

if((fb=[open(argv[2],“w”)]==NULL){ printf(“Cannot open file %s\n”,argv[2]);

exit(0)}

while(!feof(in))fputc(fgetc(in),out);fclose(in);fclose(out)}

例如该程序文件名为 exam.c经编译后得到 exam.exe,那么执行时可输入以下命令C:\>exam a.txt b.txt↙

例 13-3 从键盘上输入若干字符,逐个送人到磁盘文件中,直到输入一个“#”号为止。include(stdio.h)main()

{ FILE *fp~;char ch,filename[10];printf(“Input the filename please:\n”);scanf(“%s”,filename);if((fp=fopen(filename,“w”))==NULL)

{ printf(“cannot open file\n”);exit(0);}

ch=getchar();while(ch!=`#`){ fputc(ch,fp);

putchar(ch);ch=getchar();}

fclose(fp);}

2.fgets 及 fputs 函数

Page 272: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 13 章 文件

fgets是从指定文件读取一个字符串,其格式是:fgets(str,n,fp)

其中 str是一个字符数组名或指向字符串的指针,n 为要读取的最多的字符个数,fp 为所要读取的文件型指针,fgets功能是从 fp所指的文件中读取长度不超过 n-1 个字符的字符串,并放人字符数组 str 中,函数返回指向 str 的首地址指针。

在从文件中读取字符串开始时遇到文件结束出错,函数返回 NULL,另一种是:1)已读取了 n-1 个字符还未遇到文件结尾;2)未读完 n-1 个字符就遇到回车符“\n”或文件结符 EOF,这两种情况均结束文件读取,从 fgets 函数返回,并将读出的字符串放人 str 中(包括读出的`\n`)在串尾加上`\0`字符,图 14-4 表示 fgets 读出的情况。

s1 s2abc\n abc\n\0 abc\n abc\0

(a) fgets(s1,5,fp1) (b) fgets(s2,4,fp2) s3 s4

abc\n abc\n\0 abcd abcd\0

(c) fgets(s3,10,fp3) (d) fgets(s4,10,fp4) 返回NULL

图 13-4 fgets 作用fputs是将 s 指向的字符串或数组名内容写入 fp所指向的文件中,写入的字符串末尾的

`0`被自动除去,调用成功时返回值 0,调用不成功返回非零值。其格式为:fputs(s,fp);

例 13-4 从键盘输入若干行字符送人磁盘文件 file.txt 中。#include(stdio.h)main()

{ FILE *fp;charstr[81];if((fp=fopen(“file.txt”,“w”))==NULL)

{ printf(“Cannot open file\n”);/exit(0); }

while(strlen(gets(str))>0) /*键盘上读人一行字符送 str*/{ fputs(str,fp); /*若该字符串非空,送人 f.txt*/

fputs(“\n”,fp);}

fclose(fp);}

3.文件格式化输入输出函数第二章中介绍过 scanf 及 printf两个格式化输入输出函数,它们适用于标准的设备文件

(键盘、显示屏)。C 标准函数提供了 fscanf 及 fprintf两个格式化输入输出函数用于满足磁盘文件的格式化读写要求。

(1)格式化输入函数 fscanf(),格式是:fscanf(fp,格式控制符,输入列表);

fp 为 要 读取文 件 的 文 件 型 指 针,格 式 控 制 符 及 输 入列表 含 义同 scanf。例如,fscanf(fp,“%d,%f”,&i,&t);从指定的磁盘文件上读取,并按照“%d”及“%f”格式把ASCII 字符转换为二进制形式(自动转换)赋予变量 i 及 t。

fp1 fp2

fp3 fp4

Page 273: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 13 章 文件

(2)格式化输出函数 fprintf(),格式是: fprintf(fp,格式控制符及输出列表);

fp 为 要 写 入 的 文 件 的 指 针,格 式 控 制 符 及 输 出列表 含 义同 printf。例如 fprintf (fp,“%d,%6.2f”,i,t);将整数变量 i 值以%d 格式,实型变量 t 值以%6.2f 格式写入到 fp所指向文件中(二进制自动转换为 ASCII 形式)。由于用 fscanf 和 fprintf 要进行二进制及 ASCII 码之间转换,费时较多,在内存与磁盘

频繁交换数据的情况下,最好不用这两个函数,改用 fread 和 fwrite 函数。4.文件数据块输入输出函数 fread 和 fwrite。实现一次读写一组数据的功能,采用这种

方法对数组和结构体进行整体输入输出比较方便,这种方法一般适用二进制文件的读写。其调用格式是:

fread(buffer,size,count,fp);fwrite(buffer,size,count,fp);

其中:buffu是一个指针,对 fread来说是读人数据的存放地址,对 fwrite来说是要输出数,

据的起始地址;size 指要读写的字节数;count 为要读写多少个 size 字节的数据项;fp 为文件指针。例如:

fread(a,4,5,fp);a是一个实型数组名,一个实型变量占四个字节,该函数从 fp所指的文件读出五次

(每次四个字节,共二十个字节)数据,存储到数组 a 中。如果 fread 或 fwrite 调用成功,函数返回 count 值(即输入或数据项的个数)。例 13-5 从键盘输入三个教师数据,把它们存放在文件 teacher 中,然后再从文件

teacher 中读出数据显示于屏幕上。#include(stdio.h)#define SIZE 3struct teacher /*定义结构体*/

{ int nun;char name[10];int age;char address[10];}teach[SIZE],out;

void fsave(){ FILE *fp;

int i;if((fp=fopen(“teacher”,“wb”))==NULL) /*以二进制方式打开文件*

/{ printfc”Cannotopenfile\n”};

exit(1);}

for(i=0;i<SIZE;i++) /*将教师信息(结构)写入文件*/if(fwrite(&teachr[i],sizeof(struct teacher),1,fp)!=1)

printf(”Filewriteerror!\n”);fclose(fp);}

main()

Page 274: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 13 章 文件

{ FILE *fp;int ifor(i=0;i<SIZE;i++) /*从键盘读入教师信息*/

{ printf(“Inputteacher%d:”,i+1);scanf ( “ % d , % s , % d ,

%s”,&teach[i].num,str[i].name,&str[i].age,teach[I].address);

}fsave();fp=fopen(“teacher”,“rb”); /*从文件读出并显示*/printf(“No. Name Age Address\n”),while(fread(&out,sizeof(out),1,fp))

printf(“%8d,%10s,%4d,%los\n”,out.num,out.name,out.age, out.address);

fclose(fp); }

5.文件的定位。对文件的操作都是顺序读写,即从某一个数据开始依次进行读写,由指向文件的指针自动移位。但实际应用中有时需对文件中某个特定数据进行处理,这就要求文件具有随机读写的功能,即强制文件指针指向用户所希望的指定位置。C 语言提供了三种有关函数。

(1)改变文件位置指针函数 fseek,fseek 调用格式为:fseek(fp,offset,position);

其中 fp是文件类型指针:position 为起始点,用 0、l、2 分别表示“文件开始”、“当前位置”和“文件末尾”;offset 为位移量,指从起始点开始到要确定的新位置的字节数目(该参数应为长整型量,应在参数后加标志 L)。

fseek 函数一般用于二进制文件,因为文本文件要发生字符转换,计算位置时会产生混乱。例如:

fseek(fp,100L,0);将位置指针移到离文件头 100 个字节处。fseek(fp,50L,1);将位置指针移到从目前位置开始向后(即文件末尾方向)

移动 50 个字节。fseek(fp,-10L,2);将位置指针移到离文件末尾 10 个字节的位置。

例 13-6 实现对磁盘文件上十个教师数据中的第 l,3,5,7,9:ff 个教师数据显示出来。

struct teacher{ charname[10];

int nam;int age;char sex;}teach[10];

main(){ int i;

FILE *fp;if((fp=fopen(“teacher.dat”,“rb”))==NULL)

{ printf(“Cannot open file\n”);

Page 275: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 13 章 文件

exit(0);}

for(i=0;i<l0;i+=2){ fseek(fp,i*sizeof(struct teacher),0);

fread(&teach[i],sizeof(struct teacher),1,fp);printf(“%s%d%d%c\n”,teach[i].name,teach[i].num,teach[i].age,

teach[i].sex);}

fclose(fp);}

(2)位置指针重返文件头函数 rewind,rewind 函数调用形式为:rewind(fp);

使 fp 指定的文件指针移到文件开始位置例 13-7 把文件 file1复制到文件 file2。#include(stdio.h)main()

{ FILE *fpl,*fp2;fpl=fopen(“file1”,“r”);fp2=fopen(“file2”,“w”);while(!feof(fpl))

putchar(fgetc(fpl)); /*屏幕上显示 n 内容*/rewind(fpl); /*显示完后指针在 f1末尾,把它移到开始位置*/while(!feof(fpl))

fputc(fgetc(fpl),fp2); /*文件 n 内容复制到 f2*/fclose(fpl);fclose(fp2);

}(3)位置指针当前值函数 ftell,调用格式为:

ftell(fp); 其中 fp 为文件指针,该函数返回 fp所指文件的当前读写位置。即位置指针的当前值,该值是个长整型数,是从文件开始到当前读写位置的位移量字节数,如果返回值为-1 说明出错。例如:

i=ftell(fp); if(i==-1L)printf(“error\n”);

6.文件操作的出错检测C 语言提供两种手段检查函数调用情况和文件的状态,其一是由函数返回值可以知道

文件调用是否成功,例如,调用 fgets、fputs、fgetc、fputc等若文件结束或出错返回 EOF;在调用 fread、fopen、fclose等函数时,若出错返回NULL。其二,是由C 函数库提供对文件操作状态和操作出错的检测函数。包括 feof、ferror 及 clearerr 函数。

(1)文件状态检测函数 feof,格式:feof(fp);

其中 fp 为文件型指针,feof测试文件位置指针是否到达文件结尾,如果已达文件结尾,则返回非零值,否则返回零(文件尚未结束)。

(2)报告文件操作错误状态函数 ferror,格式:

Page 276: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 13 章 文件

ferror(fp);其中 fp 为文件指针,测试 fp所指的文件是否有错误,如果没有错误返回值为 o;否则

返回一个非 0 值表示出错。(3)清除错误标志函数 clearerr,格式:

clearerr(fp);其中 fp 为文件指针,清除 fp所指文件的错误标志和文件结束标志(即使其变为 0)。

13.3 例题详解例 13-8 阅读及分析以下程序作用。

#include(stdio.h) #define LEN 20main()

{ FILE,fpchar strl[LEN],str0[LEN];if((fp=fopen(“t.txt”,“w”))==NULL)

{ printf(“cannot open file\n”);exit(0);}

printf(“fputs string:”);gets(str1);fputs(strl,fp);if(ferror(fp))

printf(“\n errors processing file t.txt\n”);fclose(fp);fp=fopen(“t.Txt”,“r”);fgets(str0,LEN,fp);printf(“fgets string:%s\n”,str0);fclose(fp);}

分析:程序运行时首先从键盘输入一个字符串 str1,然后把它写入文件 t.txt。然后重打开 t.txt。从文件中读取数据到数组 str0 中,最后显示 str0 中内容。

例 13-9 从键盘输入一行字符串,将其中大写字母换成小写字型,然后输入到一个磁盘文件“f”中保存。

#include(stdio.h)main()

{ FILE *fp;charstr[100],filename[15];int i;if((fp=fopen(“f”,“W”))==NULL);

{ printf(“Cannot open the file\n”);exit(0);}

Page 277: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 13 章 文件

printf(“Input a string:”);gets(str); /*读入一行字符串*/for(i=0;str[i]&&i<100;i++)

{ if(str[i]>=`A`&&str[i]<=`Z`)str[i]+=`a`-`A`; /*大写字母→小写字母*/fputc(str[门,fp]; /*写入文件 f*/}

fclose(fp);fp=fopen(“f”,“r”);fgets(str,100,fp); /*从文件中读出一行字符串*/printf(“%s\n”,str);fclose(fp);}

例 13-10 将命令行中的指定文件名内容追加到另一个文本文件之后。#include(stdio.h)main(argc,argv)int argc;char*argv[1]

{ FILE *fpl,*fp2;int c;if(argc!=3)

{ printf(“usage:filenamel filename2\n”);exit(0); /*若运行程序参数不对退出*/}

if((fpl=fopen(argv[1],“r”))==NULL) { printf(“Cannot open%s\n”,argv[1]);

exit(1);}

if((fp2=fopen(argv[2],“a”))==NULL){ printf(“Cannot open%s\n”,argv[2]);

exit(1);}c=fseek(fp2,0L,2); /*定位第二个文件到文件末尾*/

/*由于第二个文件以“a”形式打开的,指针已到末尾,因此此句可省略*/while((c=fgetc(fpl))!=EOF)fputc(c,fpl);fclose(fpl)Jclose(fp2);}

13.4 本章小结常用文件系统函数

Page 278: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 13 章 文件

分 类 函数名 功 能打开文件关闭文件

fopen()fclose()

打开文件关闭文件

文件定位 fseek()rewind()ftell()

改变文件指针位置使文件指针重新置于文件开始返回文件位置指针当前值

文件读写 fgetc() ,getc()fputc(),putc()fgets(),fputs()getw(),putw()fread ( ) ,fwrite()fscanf(),fprintf()

从指定文件读取一个字符把字符输出到指定文件从指定文件读出字符串,把字符串写入文件中从指定文件读出一个字(int 型),八字输出到文件中从指定文件读取数据项,把数据项写入文件中按格式把数据写入文件,按格式从文件读出数据

文件状态 feof()ferror()clearevr()

若到文件尾,函数值为真(非零)若文件操作出错,函数值为真(非零)使 ferror 和 feof 函数值为

13.5 练习题13.5.1选择题

1.C 语言中标准库函数 fget(string,m,fp)的作用是 。(A)从 fp所指向文件中读取长度不超过 m 的字符串,存入由指针 string 指向的内存(B)从 fp所指向的文件中读取长度为 m 的字符串,存人入由指针 string 指向的内存(C)从 fp所指向的文件中读取m 个字符串,存入由指针指向的内存(D)从 fp所指向文件中读取长度不超过 m-1 的字符串,存入由指针 string所指向的

内存2.以下程序将一个名为 f1.dat 的文件拷贝到一个名为 f2.dat 的文件中。请选择正确的答案填人 中。

#include(stdio.h)main()

{ char C;FILE *fpl,*fp2;fpl=fopen(“f1.dat”, [1] );fp2=fopen(“f2.dat”, [2] );fputc(c,fp2);c=fgetc(c,fp2);

Page 279: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 13 章 文件

}fclose(fpl);fclose(fp2);return;}

[1](A)“a” (B) “rb”(C) “rb+” (D) “r”

[2](A)“wb” (B)“wb+”(C)“w” (D)“ab”

13.5.2填空题1.在 C 语言中,对文件的存取是以 为单位的。2.在 C 语言的文件系统中,最重要的概念是“文件指针”,定义文件指针的方法为:

*fp;,其中 fp是一个指向[2: FILE ]类型结构体的指针变量。3.如果调用 fopen 函数不成功,则函数的返回值为 如果调用 fclose 函数不成功,则

函数的返回值为 。4.以下程序把从键盘输入的字符存放到一个文件中。

(用字符#作为结束输入的标志)请在 中填人正确的内容。#include(stdio.h)main()

{ FILE *fp;char ch,fname[10];printf(input the name of file\n”);gets(fname);if((fp=fopen(fname,[1]))==NULL)

{ printf(“cannot open\n”);exit(0);}while((ch=getchar())!=`#`)fputc([2],fp);fclose(fp);}

Page 280: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 14 章 常见错误分析和程序调试

第 14 章 常见错误分析和程序调试14.1 常见错误分析

14.1.1 遗漏分号或分号位置错误14.1.2 路径表示的错误14.1.3 混淆赋值号(=)与比较符(==)14.1.4 遗漏花括号14.1.5 括号不配对14.1.6 大小写字母的区别14.1.7 忘记定义变量14.1.8 错误使用指针14.1.9 开头语句中忘记中断语句 break14.1.10 混淆字符和字符串的表示形式14.1.11 自加(++)和自减(一一)错误14.1.12 地址传送失败14.1.13 数组及数组下标14.1.14 int 型数据的数值范围14.1.15 函数的使用14.1.16 混淆数组名及指针变量区别14.1.17 混淆结构体类型和结构体变量区别14.1.18 使用文件时忘记打开文件或打开文件方式不对

14.2 错误的检出与分离14.3 程序调试

第 14 章 常见错误分析和程序调试C 语言功能强,使用方便灵活,所以得到广泛应用。一个有经验的 C 语言程序人员可以

编写出能解决复杂问题的、运行效率高、占内存少的高质量程序。但是要真正学好,用好C语言并不容易。C 语言″灵活″固然是好事,但也不容易掌握。尤其初学者出错了也不知错在何处。C 语言编译程序不如其他高级语言那样严格,因此程序员应该不断积累经验,提高程序设计和调试程序的水平。

14.1 常见错误分析14.1.1 遗漏分号或分号位置错误

下面语句中 printf 语句遗漏分号,而 for 语句又多了分号printf (″How are you?\n″) /*遗漏分号*/for(i=0;i<100;i++); /*不应有分号*/

请读者注意,这是一个常见的错误。就是水平较高的程序员有的也会犯此类错误。14.1.2 路径表示的错误

Page 281: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 14 章 常见错误分析和程序调试

反斜杠(\)表示一个 DOS 的路径。但 C 语言中表示一个换码字符(例如\n 换行,\t 制表符),因此一定要表示路径时应用两个反斜杠。

fp=fopen(″c:\new\tools.″C,″:″); /*错误*/fp=fopen(″c:\\new\\tools,c″,″r″) /*正确*/

14.1.3 混淆赋值号(=)与比较符(==)C 语言中‵=‵是赋值符(Pascal 中是比较符,赋值符用:=表示)。‵==‵是比较符,

检查前后两个表达式是否相等。if(a=b) puts(″Egual″);else puts(″Not egual″); /*错误*/if{(a==b) puts(″Egual″);else puts(″Not egual″) /*正确*/

同样要注意千万不要忘记 puts(″Egual″)后面的分号(;)。14.1.4 遗漏花括号

C 语言中对复合语句应加上花括号,不能遗漏。例如sum=0;i=l;while(i<=100)

sum=sum+i;i++;

本意是实现 1+2+3+…+100。但上面语句只重复执行 sum+1操作,而且陷入无限循环,其原因是 i 值始终没有变化,因此必须在while 语句中加上花括号:

while(i<=100){ sum=sum+i;

i++;}

14.1.5 括号不配对语句中出现多层括号时,易犯这类错误,主要是粗心所致。例如:while((c=getchar()!=‵#‵)

putchar(c);缺少一个右括号。

14.1.6 大小写字母的区别例如:

main(){ int a,b,c;

a=2;b=3;C=A+B;printf(″%d+%d=%d″,A,B,C);}

Page 282: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 14 章 常见错误分析和程序调试

编译时 a 和 A是两个不同变量,同样 b 和 B,c 和 C都代表不同的变量。

14.1.7 忘记定义变量main(){ a=2;b=3;

c=a+bprintf(″%d+%d=%d″,a,b,c);

}C 语言中对变量应先定义后使用,即程序中遗漏了 a、b 和 c 的定义,应开头加上 int

a,b,c;学习过 BASIC 或 FORTRAN 语言的读者较易犯这样的错误。

14.1.8 错误使用指针指针是最易混淆的概念,应注意何时使用指针?何时不用指针?何时用指示操作符(‵*

‵)?何时用操作符地址(‵&‵)?1.使用初始化指针一个严重问题是赋予一个值给某个指针,但该指针尚未赋予地址。例如:main()

{ int *iptr;*iptr=421;printf(″*iptr=%d\n″,*iptr);}上例中把值 421放人 iptr所指地址单元中去,但 iptr 地址是不定的,有可能破坏机器代

码本身,因此应事先对指针分配空间,例如在使用 xiptr=421;之前,应增加语句 iptr=(int*)malloc(sizeof(int));这样的错误往往较难以发现。

2.字符串字符串可以定义为 char 指针,也可定义为 char 数组。例如:main()

{ char *name;char msg[10];printf(″what is your name?″);scanf(″%s″,name);msg=″Hello,″;printf(″%s%s″,msg,name);

}本例有两个错误:(1)scanf(″%s″,name);本身是合法的,name是指针,前面不能加上‵&‵,然后

程序显没有为 name事先分配内存空间,name 指针指向随机的地址,因此往往会得到警告:Possible use of‵name‵before definition.为此可在该语句之前加上语句″name=(char *)malloc(10);″,并且在程序开头加上#include(alloc.h)。

(2)msg=″Hello,″;编译认为是把msg 设为常量字符串″Hello″的地址,而数组名是常量而不是变量。会给出错误信息。为此可以把该语句修改为:

strcpy(msg,″Hello,″);解决以上问题另一种方法是把花括号中前两个语句改为:

char name[10];

Page 283: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 14 章 常见错误分析和程序调试

char *msg;14.1.9 开头语句中忘记中断语句 break

例如:switch(score)

{ case 5:printf(″Verygood!″);case 4:printf(″Good!″);case 3:printf(″Pass!″);case 2:printf(″Fail!″);defuh:printf(″Data error!″);}由于漏写了 break 语句,当 score(成绩)为 5 时。输出将为;VeryGood!Good!Pass!

Fail!Data error!为改正错误,应在 case 5到 case 2 的语句后面加上 break;。14.1.10 混淆字符和字符串的表示形式

例如:char sex;sex=″M″;

sex是字符变量,只能放一个字符,应用 sex=‵M‵;这里″M″是字符串,它包括两个字符‵M‵及‵\0‵,无法放人一个字符变量 sex 中。14.1.11 自加(++)和自减(一一)错误

例如:main()

{ int *p,a[6]={1,3,5,7,9,11};p=a;printf(″%d″,*p++);}不少人认为*p++是使 p 先加 1,即指向 a[1],然后输出其中值 3,但事实上,执行 P++

即先执行 p原值,再使它+1,因此,输出 a[0]为 1,然后再进行 p 加 1,如果上式改为 x(++p),那么先执行 p 指向 a[l]再输出 a[l]值。14.1.12 地址传送失败若 a、b是整型变量。那么 scanf(″%d%d″,a,b)是错误的,应改为&d 和&b。若 a、b

先说明为指针(例如 int *a,*b),那么就不能用&d 和&b,只能用 a 和 b。14.1.13 数组及数组下标

(1)数组下标是从 0 开始而不是从 1 开始。例如:main()

{ int list[100],i;for(i=1;i<=100;i++)list[i]=i*i;

Page 284: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 14 章 常见错误分析和程序调试

}本例中,丢失 list 中第一个元素 list[0]。还使用了一个不存在的元素 list[100],正确循环应该是 for(i=0;i<100;i++)。

(2)引用数组元素时误用圆括号。例如:main(){ int i,a(10);

for(i=0;i<l0;i++)scanf(″%d″,&a(i));……

}C 语言对数组定义及数组元素的使用应该用方括号而不应用圆括号。(3)对二维或多维数组定义和引用方法不对。例如:

main(){ int a[4,5];

……print(″%d″,a[l+2,2+2]);

……}本例中,方括号中[1+2,2+2]是逗号表达式。其值为 4,因此方括号中实际为 4,即 a

数组第 4 行的首地址,因此 printf 输出不是 a[3][4]值而是 a[4]的首地址。因此定义时用 int a[4][5];使用时用 a[1+2][2+2]。(4)误以为数组名代表数组中全部元素。例如:

main(){ static int a[4]={l,3,5,7};

printf(″%d%d%d%d\n″,a);}

C 语言不能用数组名来输出四个元素,它仅仅是一个地址(指针),因此只能改为 printf(″%d%d%d%d\n″,a[0],a[1],a[2],a[3]);

14.1.14 int 型数据的数值范围一般微机对 int 整型数分配两个字节,因此一个整数范围为一 32768~32767。例如:

int num;num=89101;printf(″%d″,num);

输出值不是 891011 其原因是 num 值已超出 int 数值范围,为此可以采用 long 型,即修改程序为:

long int numnum=89101;printf(″%d″,num); /*不能用%d 输出,否则仍出错*/

14.1.15 函数的使用1.将函数的形参和函数中的局部变量一起定义。例如:

max(x,y)int x,y,Z;

{ z=x<y?x:y;

Page 285: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 14 章 常见错误分析和程序调试

return(z);}形参应该在函数体之前定义,而函数中使用的局部变量应该在函数体内定义。因此应

修改为:max(x,y)int X,y;

{ int z;z=x<y?x:y;return(z);}

2.所调用的函数在调用语句之后才定义,而在调用前未加说明。main()

{ float x,y,z;x=2.6;y=——6.7;z=max(x,y);printf(″%f\n″,z);}float max(x,y)float x,y;

{ return(z=x>y?x:y);}该程序编译时有出错信息,原因是max是实型函数,在main 出数之后才定义,可用下

列两种方法之一进行改错。(1)在main 函数中间增加一个对 max 函数的说明,即:

main(){ float max(); /*说明 max 函数为实型*/

float x,y,z;……}(2)将max 函数定义调到main之前

float max(x,y)float x,y;

{ return(z=x>y?x:y);}main(){……}

3.形参与实参关系。把一个变量传递给函数时,就构造出一个变量的副本,切记,为保持函数之间各个变量的独立性,函数是不接收实际变量的(即值传送),但数组和指针是个例外,当函数接受数组时实际上是接受数组的首地址(即地址传送),形参的改变返回给实参。

例如:main()

{ int x=7;square(x);printf(″\n The square is %d″,x); }

Page 286: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 14 章 常见错误分析和程序调试

square(i)int i;

{ return(i*i);}本例中程序员传递 x 的一个副本到形参 i,在函数中 i 变成 i*i,但一离开 square()就

消失了副本,因而也不存在于 main()中。应该使用指针把 x 的地址传给该函数,即使用 square(&x),而 square()函数也应

修改如下:square(i)int *i;{ *i*=*i; /*即*i=(*i)*(*i)*/

}当然,若通过使用返回值也可以不用指针,例如上述程序可改为:main()

{ int x=8;x=square(x);printf(″\n The square is %d″,x);}

square(i)int i;

{ return(i*i);}

3.函数的实参和形参类型不一致。main()

{ int a=4,b=5,c;c=fun(a,b)……}

fun(x,y)float x,y;{……}实参 a,b 为整型,形参 x,y 为实型,C 语言要求实参与形参类型一致。

5.不同类型指针的混用。main()

{ inti=5,*pl; float a=1.5,*p2;p1=&j;p2=&a;p2=p1;printf(″%d,%d\n″,*pl,*p2);} 本例中使用 p2=p1 时企图使 p2也指向 p1 的数据,但 p1 与 p2 类型不同,必须强制进行

类型转换,应写为 p2=(float *)p1;作用是先将 p1 值转换为指向实型的指针,然后再赋给 p2。

6.函数参数的求值顺序。例如:i=5;

Page 287: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 14 章 常见错误分析和程序调试

printf(″%d,%d,%d\n″,i,++i,++i;许多人认为输出必然为 5,6,7其实不然,在许多系统中是采取自右至左顺序求参数值的,本例中,先求最右也一个

参数值(++i)的值 6。再求第 2 个参数值(++i)值为 7,最后求最左边参数值(i)值为7,因此输出为 7,7,6。

为防止这种二义性,可以改为:i=5;j=i+1;k=j+1;Printf(″%d,%d,%d\n″,i,j,k);

14.1.16 混淆数组名及指针变量区别main()

{ int i,a[6]; for(i=0;i<6;i++)scanf(″%d″,a++);……}本例企图通过 a++改变,使指针下将到下一个元素,但数组名代表数组首地址,它是

常量而不是变量,其值不能改变,应修改为下列程序:int i,a[6],*p;p=a;for(i=0;i<6;i++)scanf(″%d″,p++);…… 或者int a[6],*p;for(p=a;p<a+6;p++)scanf(″%d″,p);……

14.1.17 混淆结构体类型和结构体变量区别例如:

struct worker{ int num;

char name[20];char sex;int age;}

worker.num=123;strcpy(worker.name,″Gong Ming″);worker.sex=‵M‵;worker.age=17;……是错误的,不能对类型赋值,只能对变量赋值。

上例,在结构类型定义之后应修改为:struct worker{int num;

Page 288: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 14 章 常见错误分析和程序调试

……}struct workerw1; /*定义变量 wl*/w1.num=123;strcpy(w1.name,″Gong Ming″);

w1.sex=‵/M‵;w1.age=17; ……

14.1.18 使用文件时忘记打开文件或打开文件方式不对例如:

if((fp=fopen(″fest″,″r″))==NULL) { printf(″cannot open this file\n″);

exif(0); }

ch=fgetc(fp);while(ch!=‵#‵)

{ ch=ch+4;fputc(ch,fp);ch=fgetc(fp);}该例以″r″(只读)形式打开文件,进行即读又写操作显然是错误的,同时也遗漏了关

闭文件的语句(虽然系统退出程序时会自动关闭所打开文件,但可能会丢失数据)。总之,程序出错有两种情况:(1)语法错误:违反了 C 语言语法,这种情况下 C 语言编译时一般都给出“出错信

息”并告诉你错误出现在哪一行,只要细心调试是可以很快排除的;(2)逻辑错误:程序无违背语法规则,但执行结果与原意不符,这种错误又称运行错

误,这种错误比语法更难检查,要求程序员有较丰富的经验。14.2 错误的检出与分离

错误检测的首要工具是编译程序,它能把语法上的错误找到并分离出来。大多数编译程序会告知出错的原程序行号。所以错误的校正归结为重新编辑源程序并再次编译。

不过要注意,对于复杂的程序,编译指出的错误行号,不一定就是该行有错,一般要向前面找,对出现多种错误的程序,一般不要企图一次修改成功,因为有些错误相互关联,纠正了一个错误会纠正好几个错误,也有可能纠正一个错误又引起其他新的错误,因此在排除了确定的几个错误之后再次编译,看看还会有什么错误,然后再根据新的信息进行修改。困难在于要寻找“逻辑错误”,或“运行中的错误”,通常这些错误只有把某些数据

集合加到程序上时才表现出来,我们可以把已知的数据送入程序,并把程序“划小”,直到错误被分离开来,为此可以插入若于个 printf 语句,打印出中间结果进行检查。当然,用 printf 语句在调试完后,还要把它去掉,为便于去掉这些语句可以编制一个

专用的排错函数 debug()。提供一个把在排错过程中所用的共同信息打印出来的办法,在“排错”以后,可用编辑程序的“查找”功能很快地找出所有的 debug()调用并去掉这些调用。

Page 289: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 14 章 常见错误分析和程序调试

debug() 程序如下:其 中 1et 为字 符,c_array 为字严数 组,n_array 为整 型数 组num,opt 和 asize均是整型变量,其思想是要把打印的数据类型传送给它,并由后面的 case语句给它打印出来。getchar()作用是引起程序暂停,直到按一键之后才继续下去。

debug(1et,c_array,n_array,asize,num,opt)int num,n_array[],opt,asize;char let,c_array[];

{ int i;switch(opt)

{ casel:printf(″\n The valne is %d″,num);break;

case2:printf(″\n The letter is %c″,let);break;

case3:puts(″\n The numeric array contains\n″);for(i=0;i<asize;++i);

printf(″%d″,n_array[i]);break;

case4:puts(″\n The character array contains\n″);for(i=0;i<asize;++i)

printf(″%c″,c_array[i]);break;

defaule:puts(″\n invalid option selected″)break

}puts(″\n\t Press any key to continue......″);getchar();}显然对下述调用含意是:debug(0,0,0,0,num,1); /*显示 Bum 值*/debug(1et,0,0,0,0,2); /*显示字符*/debug(0,0,c_array,6,0,3); /*显示字符数组 6 个元素*/debug(0,n_array,0,6,0,4); /*显示整数数组 6 个元素*/debug(0,0,0,0,num,7); /*选择无效*/

14.3 程序调试程序调试是对程序的查错和排错,调试程序通常分以下几个步骤:1.人工检查(静态检查)。程序编好后不要匆匆去上机,应对纸面上的程序认真检查,

这可以发现编写程序中的许多错误。有人曾希望把一切推给计算机去做。但这样会占用过多机器时间,每个程序员应养成严谨的科学作风,不要把问题留给后面的工序。

程序编写时应注重程序可理解性,要使程序结构清晰,易于理解也易于修改,建议:(1)采用结构化程序设计编程;(2)尽可能增加注解,对每段程序作用及主要变量进行说明,好的程序注解部分占全

部篇幅的 1/4~1/3;3)采用模块结构,不要把全部语句都放在 main()函数中,要利用函数定义及函数调用,用一个函数(模块)来完成一个功能。

2.上机调试。上机发现错误称为动态调试,编译时可以根据提示信息找到出错之处并

Page 290: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 14 章 常见错误分析和程序调试

改正之,有时提示出错的类型并非绝对准确。由于出错情况繁多而且各种错误之间有关联,因此要善于分析,找出真正的错误。

有时显示出一大片错误信息往往使人感到问题严重,无从下手,其实可能只有一、二个错误,例如,对所用的变量未定义,编译会对所有含该变量的语句发出错误信息,只要加上一个变量定义,所有错误都消失了。

3.改正编译错误后程序联接(Link)后,就可得到可执行程序,输人数据运行后得到结果,但应所得结果进行分析,看它是否符合要求,为此要选择一些″试验数据″进行测试。

运行结果不对大多是逻辑错误,对这类错误往往需要仔细检查和分析才能发现。

Page 291: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

第 14 章 常见错误分析和程序调试

Page 292: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

附录 1 ASCII 码表

附录 1 ASCII 码表十进制 十六进制 说明 十进制 十六进制 说明 十进制 十六进制 说明

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

00

01

02

03

04

05

06

07

08

09

0A

0B

0C

0D

0E

0F

10

11

12

13

14

15

16

17

18

19

1A

1B

1C

1D

1E

1F

20

21

22

23

24

25

26

27

28

NULL

SOH

STX

ETX

EOT

ENQ

ACK

响铃退格HT

换行VT

FF

回车SO

SI

DLE

DC1

DC2

DC3

DC4

NAK

SYN

ETB

CAN

EM

SUB

ESC

FS

GS

RS

US

空格!″#

¥%

&

‵(

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

2B

2C

2D

2E

2F

30

31

32

33

34

35

36

37

38

39

3A

3B

3C

3D

3E

3F

40

41

42

43

44

45

46

47

48

49

4A

4B

4C

4D

4E

4F

50

51

52

53

+

,—.

/

0

1

2

3

4

5

6

7

8

9

:

;

<

=

>

?

@

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

P

Q

R

S

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

56

57

58

59

5A

5B

5C

5D

5E

5F

60

61

62

63

64

65

66

67

68

69

6A

6B

6C

6D

6E

6F

70

71

72

73

74

75

76

77

78

79

7A

7B

7C

7D

7E

V

W

X

Y

Z

[

\

]

^

—‵a

b

c

d

e

f

g

h

i

j

k

l

m

n

o

p

q

r

s

t

u

v

w

x

y

z

{

|

}

Page 293: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

附录 1 ASCII 码表

41

42

29

2A

)*

84

85

54

55

T

U

127 7F DEL

注:ASCII 码中 0~31 为不可显示的控制字符

Page 294: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

附录 2 Turbo C 常用库函数

附录 2 Turbo C 常用库函数库函数并不是 C 语言的一部分,它是由编译程序根据一般用户的需要编制并提供用户

使用的一组程序。每一种 C 编译系统都提供了一批库函数,不同的编译系统所提供的库函数的数目和函数名以及函数功能是不完全相同的。ANSIC 标准提出了一批建议提供的标准库函数。它包括了目前多数 C 编译系统所提供的库函数,但也有一些是某些 C 编译系统未曾实现的。考虑到通用性,本书列出 Turbo C 2.0版提供的部分常用库函数。由于 Turbo C 库函数的种类和数目很多(例如:还有屏幕和图形函数、时间日期函数、

与本系统有关的函数等,每一类函数又包括各种功能的函数),限于篇幅,本附录不能全部介绍,只从教学需要的角度列出最基本的。读者在编制 c 程序时可能要用到更多的函数,请查阅有关的 Turbo C 库函数手册。

(1)数学函数使用数学函数时,应该在源文件中使用命令:

#include″math.h″ 函数名 函数与形参类型 功 能 返回值acos double acos(x)

double x计算 cos-1(x)的值-1<=x<=1

计算结果asin double asin(x)

double x计算 sin-1(x)的值-1<=x<=1

计算结果atan double atan(x)

double x计算 tan-1(x)的值 计算结果

atan2 double atan2(x,y)double x,y

计算 tan-1(x/y)的值 计算结果cos double cos(x)

double x计算 cos(x)的值x 的单位为弧度

计算结果cosh double cosh(x)

double x计算 x 的双曲余弦 cosh(x)的值

计算结果exp double exp(x)

double x求 ex 的值 计算结果

fabs double fabs(x)double x

求 x 的绝对值 计算结果floor double floor(x)

double x求出不大于 x 的最大整数 该整数的双精度

实数fmod double fmod(x,y)

double x,y求整除 x/y 的余数 返回余数的双精

度实数frexp double frexp(val,eptr)

double valint *eptr

把双精度数 val 分解成数字部分(尾数)和以 2 为底的指数,即 val=x*2n,n 存放在 eptr 指向的变量中

数字部分 x0.5<=x<1

log double log(x)double x

求 logex即 lnx 计算结果

Page 295: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

附录 2 Turbo C 常用库函数

log10 double log10(x)double x

求 log10x 计算结果modf double modf(val,iptr)

double valint *iptr

把双精度数 val 分解成数字部分和小数部分,把整数部分存放在 ptr 指向的变量中

val 的小数部分

pow double pow(x,y)double x,y

求 xy 的值 计算结果sin double sin(x)

double x求 sin(x)的值x 的单位为弧度

计算结果sinh double sinh(x)

double x计 算 x 的 双 曲 正 弦 函 数sinh(x)的值

计算结果sqrt double sqrt (x)

double x计算√x,x≧0 计算结果

tan double tan(x)double x

计算 tan(x)的值x 的单位为弧度

计算结果tanh double tanh(x)

double x计 算 x 的 双 曲 正 切 函 数tanh(x)的值

计算结果

(2)字符函数在使用字符函数时,因该在源文件中使用命令:

#include“ctype.h”函数名 函数和形参类型 功能 返回值isalnum int isalnum(ch)

int ch检查 ch是否字母或数字 是字母或数字返

回 1;否则返回 0isalpha int isalpha(ch)

int ch检查 ch是否字母 是字 母返回 1;

否则返回 0iscntrl int iscntrl(ch)

int ch检查 ch 是否控 制 字 符 ( 其ASCⅡ 码在 0 和 0xlF之间)

是控制字符返回1;否则返回 0

isdigit int isdigit(ch)int ch

检查 ch是否数字 是数 字返回 1;否则返回 0

isgraph int isgraph(ch)int ch

检查 ch是否是可打印字符(其ASCⅡ 码在 0x21 和 0x7e 之间),不包括空格

是可打印字符返回 1;否则返回 0

islower int islower(ch)int ch

检查 ch是否是小写字母(a~z)

是 小 字 母 返 回1;否则返回 0

isprint int isprint(ch)int ch

检查 ch是否是可打印字符(其ASCⅡ 码在 0x21 和 0x7e 之间),不包括空格

是可打印字符返回 1;否则返回 0

ispunct int ispunct(ch)int ch

检查 ch是否是标点字符(不包括空格)即除字母、数字和空格以外的所有可打印字符

是标 点返回 1;否则返回 0

isspace int isspace(ch)int ch

检查 ch是否空格、跳格符(制表符)或换行符

是,返回 1;否则返回 0

Page 296: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

附录 2 Turbo C 常用库函数

issupper int isalsupper(ch)int ch

检查 ch是否大写字母(A~Z)

是大写字母返回1;否则返回 0

isxdigit int isxdigit(ch)int ch

检查 ch 是否一个 16 进制数字(即 0~9,或 A到 F,a~f)

是,返回 1;否则返回 0

tolower int tolower(ch)int ch

将 ch 字符转换为小写字母 返回 ch 对应的小写字母

toupper int touupper(ch)int ch

将 ch 字符转换为大写字母 返回 ch 对应的大写字母

(3)字符串函数使用字符串中函数时,应该在源文件中使用命令:

#include“string.h”函数名 函数和形参类型 功能 返回值memchr void

memchr(buf,chc,ount)void *buf;charch;unsigned int count;

在 buf 的前 count 个字符里搜索字符 ch首次出现的位置

返回指向 buf 中 ch的第一次出现的位置指针;若没有找到 ch,返回NULL

memcmp int memcmp(buf1,buf2,count)void *buf1,*buf2;unsigned int count;

按字典顺序比较由 buf1 和buf2 指向的数组的前 count个字符

buf1<buf2,为负数buf1=buf2,返回 0buf1>buf2,为正数

memcpy void *memcpy(to , from,count)void *to,*from;unsigned int count;

将 from 指向的数组中的前count 个字符拷贝到 to 指向的数组中。From 和 to 指向的数组不允许重叠

返回指向 to 的指针

memove void *memove(to , from,count)void *to,*from;unsigned int count;

将 from 指向的数组中的前count 个字符拷贝到 to 指向的数组中。From 和 to 指向的数组不允许重叠

返回指向 to 的指针

memset void *memset(buf,ch,count)void *buf;char ch;unsigned int count;

将字符 ch拷贝到 buf 指向的数组前 count 个字符中。

返回 buf

strcat char *strcat(str1,str2)char *str1,*str2;

把字符 str2接到 str1后面,取消原来 str1 最后面的串结束符`\0`

返回 str1

Page 297: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

附录 2 Turbo C 常用库函数

strchr char *strchr(str1,ch)char *str;int ch;

找出 str 指向的字符串中第一次出现字符 ch 的位置

返回指向该位置的指针,如找不到,则应返回NULL

strcmp int *strcmp(str1,str2)char *str1,*str2;

比较字符串 str1 和 str2 str1<str2,为负数str1=str2,返回 0str1>str2,为正数

strcpy char *strcpy(str1,str2)char *str1,*str2;

把 str2 指向的字符串拷贝到 str1 中去

返回 str1

strlen unsigned intstrlen(str)char *str;

统计字符串 str 中字符的个数(不包括终止符`\0`)

返回字符个数strncat char

*strncat(str1,str2,count)char *str1,*str2;unsigned int count;

把字符串 str2 指向的字符串中最多 count 个字符连到串 str1 后面,并以 null 结尾

返回 str1

strncmp int strncmp(str1,str2,count)char *str1,*str2;unsigned int count;

比较字符串 str1 和 str2 中至多前 count 个字符

str1<str2,为负数str1=str2,返回 0str1>str2,为正数

strncpy char *strncpy(str1,str2,count)char *str1,*str2;unsigned int count;

把 str2 指向的字符串中最多前 count 个字符拷贝到串str1 中去

返回 str1

strnset void *setnset(buf,ch,count)char *buf;char ch;unsigned int count;

将字符 ch拷贝到 buf 指向的数组前 count 个字符中。

返回 buf

strset void *setnset(buf,ch)void *buf;char ch;

将 buf所指向的字符串中的全部字符都变为字符 ch

返回 buf

strstr char *strstr(str1,str2)char *str1,*str2;

寻找 str2 指向的字符串在str1 指向的字符串中首次出现的位置

返回 str2 指向的字符串首次出向的地址 。 否 则 返 回NULL

(4)输入输出函数在使用输入输出函数时,应该在源文件中使用命令:

#include“stdio.h”函数名 函数和形参类型 功能 返回值

Page 298: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

附录 2 Turbo C 常用库函数

clearerr void clearer(fp)FILE *fp

清除文件指针错误指示器 无close int close(fp)

int fp关闭文件(非ANSI 标准) 关 闭 成 功 返 回

0,不成功返回-1creat int

creat(filename,mode)char *filename;int mode

以mode所指定的方式建立文件。(非ANSI 标准)

成功返回正数,否则返回-1

eof int eof(fp)int fp

判断 fp所指的文件是否结束

文 件 结 束 返 回1,否则返回 0

fclose int fclose(fp)FILE *fp

关闭 fp所指的文件,释放文件缓冲区

关 闭 成 功 返 回0,不成功返回非0

feof int feof(fp)FILE *fp

检查文件是否结束 文件结束返回非0,否则返回 0

ferror int ferror(fp)FILE *fp

测试 fp所指的文件是否有错误

无错返回 0;否则返回非 0

fflush int fflush(fp)FILE *fp

将 fp所指的文件的全部控制信息和数据存盘

存 盘 正 确 返 回0;否则返回非 0

fgets char *fgets(buf,n, fp) char *buf;int n;FILE *fp

从 fp所指的文件读取一个长度为(n-1)的字符串,存入起始地址为 buf 的空间

返回地址 buf;若遇文件结束或出错则返回 EOF

fgetc int fgetc(fp)FILE *fp

从 fp所指的文件中取得下一个字符

返回所得到的字符 ; 出 错 返 回EOF

fopen FILE *fopen(filename,mode)char *filename,*mode

以mode 指定的方式打开名为 filename 的文件

成功,则返回一个文件指针;否则返回 0

fprintf int fprintf(fp,format,args,…)FILE *fp;char *format

把 args 的值以 format 指定的格式输出到 fp所指的文件中

实际输出的字符数

fputc int fputc(ch,fp)char ch;FILE *fp

将字符 ch 输出到 fp所指的文件中

成功则返回该字符 ; 出 错 返 回EOF

fputs int fputs(str,fp)char str;FILE *fp

将 str 指定的字符串输出到fp所指的文件中

成功则返回 0;出错返回 EOF

fread int fread(pt, size,n, fp) char *pt ; unsigned size,n;FILE *fp

从 fp所指定文件中读取长度为 size 的 n 个数据项,存到 pt所指向的内存区

返回所读的数据项个数,若文件结束或出错返回0

Page 299: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

附录 2 Turbo C 常用库函数

fscanf int fscanf(fp,format,args,…)FILE *fp;char *format

从 fp 指定的文件中按给定的 format 格式将读入的数据送到 args所指向的内存变量中(args是指针)

以输入的数据个数

fseek int fseek(fp,offset,base) FILE *fp;long offset;int base

将 fp 指定的文件的位置指针移到 base所指出的位置为基准、以 offset 为位移量的位置

返回当前位置;否则,返回-1

siell FILE *fp;long ftell(fp);

返回 fp所指定的文件中的读写位置

返回文件中的读写位置;否则,返回 0

fwrite int fwrite(ptr,size,n,fp) char *ptr ; unsigned size,n;FILE *fp

把 ptr所指向的 n*size 个字节输出到 fp所指向的文件中

写到 fp 文件中的数据项的个数

getc int getc(fp)FILE *fp;

从 fp所指向的文件中的读出下一个字符

返 回 读 出 的 字符;若文件出错或结束返回 EOF

getchar int getchat() 从标准输入设备中读取下一个字符

返回字符;若文件出错或结束返回-1

gets char *gets(str)char *str

从标准输入设备中读取字符串存入 str 指向的数组

成功返回 str,否则返回NULL

open int open(filename , mode) char *filename;int mode

以mode 指定的方式打开已存在的 名 为 filename 的 文件(非ANSI 标准)

返回文 件 号 (正数);如打开失败返回-1

printf int printf(format,args,…)char *format

在 format 指定的字符串的控制 下,将输 出列表 args的指输出到标准设备

输 出 字 符 的 个数;若出错返回负数

prtc int prtc(ch,fp)int ch;FILE *fp;

把一个字符 ch 输出到 fp所值的文件中

输出字符 ch;若出错返回 EOF

putchar int putchar(ch)char ch;

把字符 ch 输出到 fp 标准输出设备

返回换行符;若失败返回 EOF

puts int puts(str)char *str;

把 str 指向的字符串输出到标准输出设备;将`\0`转换为回车行

返回换行符;若失败返回 EOF

putw int putw(w,fp)int i;FILE *fp;

将一个整数 i(即一个字)写到 fp所指的文件中(非ANSI 标准)

返 回 读 出 的 字符;若文件出错或结束返回 EOF

Page 300: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

附录 2 Turbo C 常用库函数

read int read(fd,buf,count) int fd;char *buf;unsigned int count;

从文件号 fp所指定文件中读 count 个字节到由 buf 知识的缓冲区(非ANSI 标准)

返回真正读出的字节个数,如文件 结 束返回 0,出错返回-1

remove int remove(fname)char *fname;

删 除以 fname 为 文 件 名 的文件

成功返回 0;出错返回-1

rename int remove(oname,nname)char *oname,*nname;

把 oname 所指的文件名改为由 nname所指的文件名

成功返回 0;出错返回-1

rewind void rewind(fp)FILE *fp;

将 fp 指定的文件指针置于文件头,并清除文件结束标志和错误标志

scanf int scanf(format,args,…)char *format

从标准输 入 设备按 format指示的格式字符串规定的格式,输入数据给 args所指示的单元。args 为指针

读 入并赋给 args数据个数。如文件 结 束 返 回EOF;若出 错返回 0

write int write(fd, buf, count) int fd;char *buf;unsigned count;

丛 buf 指 示 的缓冲区 输 出count 个字符到 fd所指的文件中(非ANSI 标准)

返回实际写入的字节数,如出错返回-1

(5)动态存储分配函数在使用动态存储分配函数时,应该在源文件中使用命令:

#include“stdlib.h”函数名 函数和形参类型 功能 返回值callloc void *calloc(n,size)

unsigned n;unsigned size;

分配 n 个数据项的内存连续空间,每个数据项的大小为size

分配内存单元的起始地址。如不成功,返回 0

free void free(p)void *p;

释放 p所指内存区 无malloc void *malloc(size)

unsigned SIZE;分配 size 字节的内存区 所分配的内存区

地址,如内存不够,返回 0

realloc void *reallod(p,size)void *p;unsigned size;

将 p所指的以分配的内存区的大小改为 size。Size可以比原来分配的空间大或小

返回指向该内存区的指针。若重新分配失败,返回NULL

(6)其他函数“其他函数”是 C 语言的标准库函数,由于不便归入某一类,所以单独列出。使用这写

函数时,应该在源文件中使用命令:#include“stdlib.h”

Page 301: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

附录 2 Turbo C 常用库函数

函数名 函数和形参类型 功能 返回值abs int abs(num)

int num计算整数 num 的绝对值 返回计算结果

atof double atof(str)char *str

将 str 指向的字符串转换为一个 double 型的值

返回双精度计算结果

atoi int atoi(str)char *str

将 str 指向的字符串转换为一个 int 型的值

返回转换结果atol long atol(str)

char *str将 str 指向的字符串转换为一个 long 型的值

返回转换结果exit void exit(status)

int status;中止程序运行。将 status 的值返回调用的过程

无itoa char

*itoa(n,str,radix)int n,radix;char *str

将整数 n 的值按照 radix 进制转换为等价的字符串,并将结果存入 str 指向的字符串中

返回一 个 指 向str 的指针

labs long labs(num)long num

计算 c 整数 num 的绝对值 返回计算结果ltoa char

*ltoa(n,str,radix)long int n;int radix;char *str;

将长整数 n 的值按照 radix 进制转换为等价的字符串,并将结果存入 str 指向的字符串

返回一 个 指 向str 的指针

rand int rand() 产生 0到 RAND_MAX之间的伪随机 数。RAND_MAX在头文件中定义

返回一个伪随机(整)数

random int random(num)int num;

产生 0 到 num 之间的随机数。

返回一 个随机(整)数

rand_omize void randomize() 初始化随机函数,使用是包括头文件 time.h。

strtod double strtod(start,end)char *start;char **end

将 start 指向的数字字符串转换成 double,直到出现不能转换为浮点的字符为止,剩余的字符串符给指针 end *HUGE_VAL是 turboC在头文件 math.H 中定义的数学函数溢出标志值

返回转换结果。若为转换则返回0。若转换出错返 回HUGE_VAL 表示 上溢,或返回 -HUGE_VAL表示下溢

Page 302: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

附录 2 Turbo C 常用库函数

strtol Long int strtol(start,end,radix)char *start;char **end;int radix;

将 start 指向的数字字符串转换成 long,直到出现不能转换为长整形数的字符为止,剩余的字符串符给指针 end。转换时,数字的进制由 radix确定。*LONG_MAX 是 turboC 在头 文 件 limits.h 中 定 义 的long 型可表示的最大值

返回转换结果。若为转换则返回0。若转换出错返 回LONG_MAX 表示 上溢,或返回-LONG_MAX表示下溢

system int system(str)char *str;

将 str 指向的字符串作为命令传递给 DOS 的命令处理器

返回所执行命令的退出状态

附录 3 C 语言中的关键宇auto break case char constcontinue default do double elseenum extern float for gotoif int Iong register returnshort signed sizeof static structswitch typedef union unsigned voidvolatile while

Page 303: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

附录 4 运算符和结合性

附录 4 运算符和结合性优先级 运算符 含义 要求运算对象的个数 结合方法

1 ( ) [ ] → ·

圆括号下标运算标指向结构体成员运算符结构体成员运算符

自左至右

2

! ~ ++ -- - (类型) * & sizeof

逻辑非运算符按位取反运算符自增运算符自减运算符负号运算符类型转换运算符指针运算符地址与运算符长度运算符

1 (单目运算符) 自右至左

3 * / %

乘法运算符除法运算符求余运算符

2 (双目运算符) 自左至右

4 + -

加法运算符减法运算符

2 (双目运算符) 自左至右

5 << >>

左移运算符右移运算符

2 (双目运算符) 自左至右

6 <<=︺>>= 关系运算符 2 (双目运算符) 自左至右

7 == !=

等于运算符不等于运算符

2 (双目运算符) 自左至右

8 & 按位与运算符 2 (双目运算符) 自左至右

9 ^ 按位异或运算符 2 (双目运算符) 自左至右

10 ︱ 按位或运算符 2 (双目运算符) 自左至右

11 && 逻辑与运算符 2 (双目运算符) 自左至右

12 ‖ 逻辑运算符 2 (双目运算符) 自左至右

13 ?: 条件运算符 2 (双目运算符) 自左至右

14 =+=-=*=/=%=>>=<<= &=^=︱=

赋值运算符 2 自右至左

Page 304: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

附录 4 运算符和结合性

15 , 逗号运算符(顺序求职运算符)

自左至右

说明:(1)同一优先级的运算符优先级别相同,运算次序由结合方向决定。例如,*与/具

有相同的优先级别,其结合方向为自左至右,因此,3*5/4 的运算次序是先乘后除。一和++为同一优先级,结合方向为自右至左,因此-i++相当于一(i++)。

(2)不同的运算符要求有不同的运算对象个数,如十(加)和-(减)为双目运算符,要求在运算符两侧各有一个运算对象(如 3+5、8-3等)。而++和-(负号)运算符是一元运算符,只能在运算符的一侧出现一个运算对象(如-a、i++、--i、(float)i、sizeof(int)、*p等)。条件运算符是 C 语言中唯一的一个三目运算符,如 x?a:b。

(3)从上述表中可以大致归纳出各类运算符的优先级:初等运算符( )[ ]→ •

↓单目运算符↓算述运算符(先乘除,后加减)↓关系运算符↓逻辑运算符(不包括!)↓条件运算符↓赋值运算符↓逗号运算符

以上的优先级别由上到下递减。初等运算符优先级最高,逗号运算符优先级最低。位运算符的优先级比较分散。为了容易记忆,使用位运算符时可加圆弧号。

Page 305: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

附录 4 运算符和结合性

Page 306: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

附录 5 参考答案

附录Ⅱ 参考答案第 3 章

3.6.1选择题1.A 2.C 3.C 4.D 5.D 6.A

3.6.2填空题1.顺序 2.自顶向下、逐步求精,模块化3.汇编解释过程 4.问题5.编译、链接

第 4 章4.8.1选择题

1.C 2.B 3.C 4.A 5.D

4.8.2填空题1.主函数 2./*,*/3.函数说明部分,函数体 4.{,}

第 5 章5.10.1 选择题

1.D 2.B 3.A 4.C 5.C6.C 7[1]C [2]B [3]A 8.C9[1]C [2]D 10.D 11.D 12.B13.B 14[1]D [2]D [3]C [4]D15.D 16[1]D [2]A 17.B 18.A19[1]D [2]C [3]C 20.A 21.A22[1]A [2]B

5.10.2填空题1.1,2 2.2,2,43.-32768—32767,0—65535 4.63,73,41,1725.1,2 6.Double(或双精度)7.2,1,30 8.1e,310,12,369.01234,1234,01234,%05d10.a=%d,b=%d,x+y=%4.1f\n

Page 307: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

附录 5 参考答案

a,b,x+yx-y=%4.1f a-b=¥4.1fx-y,a-bc1=‵%c‵or%d(ASCII)c2=‵%c‵or%d(ASCII)\nc1,c2,c3

11.456.7804.57e+02-123.50456.7804.57e+02-123.457123456.78 -1.23e+02

12.%ld5%3f%f%c%c&a,&b,7x,7c1,7c231.512.6aA

13.非 0 的数 14.1234,1234.015.1,1,13 16.5,7,217.1,1,0,1,1,3,2第 6 章

6.6.1 选择题1.B 2.A 3.D 4.B 5.A6.D 7.C 8.A 9.B 10.C11.D 12.A 13.D 14.D 15.B16.[1]B [2]B [3]B 17.C 18.B19.B

6.6.2 填空题1.按位与,地址2.x<z||y<z,((x,0)&&(y<0))||()x<0)&&(z<0))||((y<0)&&(z<0)),(y%2)==13.x=1 y=0 z=0

x=0 y=-1 z=-1x=0 y=-2 z=-2

4.1,,0,1 5.0,65,2

第 7 章7.6.1 选择题

1.D 2[1]C [2]A 3[1]B [2]A4.C 5.D 6.B 7.C 8.B9.B

7.6.2 填空题m=1 n=2,m=2,n=3,a 大于 0切 a 小于 b

Page 308: read.pudn.comread.pudn.com/downloads141/ebook/607869/C%D3%EF%D1%D4%… · Web view据库技术的发展历史说明,层次数据库是数据库应用的先驱,而网状数据库则对数据库的概念,方法,技术进行了较全面的发展.它们是数据库技术中研究最早的两种类型的数据库.基于网状数据类型的数据库管理系统的运行,使数据库

附录 5 参考答案

第 8 章8.8.1 选择题

1.A 2.C 3.D 4.C 5[1]D[2]B 6.C 7.A 8.A 9[1]D[2]A 10.D

8.8.2 填空题1.32.103.04.Right,sjhiu,right?5.46.2 5 8 11 147.* * * * * *

* * * * * ** * * * * *

* * * * * ** * * * * *

* * * * * *8.x<10,y,10,z=0,z<10,100*x+108y+z9.11 13 17 19 23 29

9.7.1 选择题1.B 2.C 3.D 4.D 5.C6.D 7.B 8.A 9.A 10.D11.D 12.B 13.C 14.D 15.D16.D 17.D 18.B 19.B 20.C21.D 22.A 23.C