C语言程序设计
Program Design in C Language
二 零 零 二 年 武 汉 大 学 教 学 改 革 资 助 项 目汪同庆 张 华计 算 机 语 言 和 程 序 设 计 双 语 课 件主要内容
Contents
第一讲 C语言程序设计入门第二讲 数据类型、运算符和表达式第三讲 顺序结构第四讲 选择结构第五讲 循环结构第六讲 函数第七讲 数组与字符串第八讲 指针第九讲 结构第十讲 文件处理第十一讲 预处理器
Program Design in C Language
Introduction
Data types,operators and expressions
Sequence structure
Selection structure
Repetition structure
Functions
Arrays and strings
Pointers
Structures
File processing
The preprocessor
学习程序设计的目的是进行程序设计的基本训练,掌握程序设计的基本方法。
We will learn the C programming language and structured programming
techniques.
参考书目
References
The C Programming Language
– Brian W,Kernighan
– Dennis M,Ritchie
C How to Program
– Harvey M,Deitel
– Paul J,Deitel
C 语言程序设计
– 杨健霑
– 刘英
– 康卓
Data Structure & Program Design in C
– Robert Kruse
– Clovis L,Tondo
– Bruce P,Leung
PROGRAM DESIGN IN C LANGUAGE
目 录第一讲 C语言程序设计入门
Introduction
Program Design in C Language
目 录
1.2 C语言的发展
C Language's Evolution
1.3 结构化程序设计
Structured Programming
1.4 C程序的基本结构
Basic Structure of A C Program
1.5 C语言程序的开发
C Program Development
1.1 计算机基础回顾
Review of Computer Basic
计算机系统
Computer System
计算机 ( Computer)
– 能进行计算 ( computations) 和逻辑判断 ( logical decisions)
– 在一组指令 ( instructions) ——程序 ( programs) 的控制下处理数据
( process data)
硬件 ( Hardware)
– Various devices comprising a computer
– Keyboard,screen,mouse,disks,memory,CD-ROM,and processing
units
软件 ( Software)
– Programs that run on a computer
REVIEW OF COMPUTER BASIC
目 录第一讲 C语言程序设计入门计算机的组织
Computer Organization
计算机包括六大部件,
– Input unit(输入单元)
Obtains information from input devices (keyboard,mouse)
– Output unit(输出单元)
Outputs information (to screen,to printer,to control other devices)
– Memory unit(内存)
Rapid access,low capacity,stores input information
– Central processing unit (CPU)(中央处理单元)
Arithmetic and logic unit (ALU)(算术逻辑单元)
– Performs arithmetic calculations and logic decisions
Control unit(控制器)
– Supervises and coordinates the other sections of the computer
– Secondary storage unit(辅助存储器)
Cheap,long-term,high-capacity storage
Stores inactive programs
REVIEW OF COMPUTER BASIC
目 录第一讲 C语言程序设计入门计算机语言
Computer Language
三种编程语言 ( programming language),
– 机器语言 ( Machine language)
机器指令 ( machine instruction)
– 汇编语言 ( Assembly language)
类似英文的缩写来表示基本操作 ( elementary operation)
通过汇编程序 ( assembler) 翻译成机器语言
– 高级语言 ( High-level language)
代码 ( code) 类似日常英语
使用数学符号 ( mathematical notations)
通过编译程序 ( compiler) 翻译成机器语言
REVIEW OF COMPUTER BASIC
目 录第一讲 C语言程序设计入门
0110001100000110
0110010111001100
0000110000011011
LOAD X
ADD Y
STORE Z
Z = X + Y
Machine Language Assembly Language High-level Language
C语言的发展
C Language?s Evolution
Traditional C
– Evolved by Ritchie from two previous programming languages,BCPL
and B
– Used to develop UNIX
– Used to write modern operating systems
– Hardware independent (portable)(可移植)
– By late 1970's C had evolved to "Traditional C"
标准化 ( Standardization)
– 许多互不兼容 ( incompatible) 的 C的变种 ( variations),差异很小
– 成立委员会建立,unambiguous,machine-independent‖(明确的,独立于机器的)定义
– 正式的标准诞生于 1989年( C89),在 1999作了重大更新( C99)
C LANGUAGE’S EVOLUTION AND FEATURES
目 录第一讲 C语言程序设计入门程序概念
Program Concept
程序的概念
– 程序是计算机解决问题所需的一系列指令的集合。
– A program is a set of self-contained instructions that tells a computer
how to solve a problem or carry out a task.
程序=数据结构+算法+程序设计方法+语言工具和编程环境
– 数据结构( Data structure)是数据的类型和数据的组织形式。
– 算法( Algorithm)是为解决某个特定的问题而采用的确定且有限的步骤。
– 程序设计方法( Programming method)
– 语言工具和编程环境( Language tools and programming environment)
STRUCTURED PROGRAMMING
目 录第一讲 C语言程序设计入门例 1-1 简单程序设计
A Simple Program Design
问题
– 求方程 ax2+bx+c=0的根(设 b2-4ac≥0)
程序设计步骤
– 定义数据结构
Define data structure
– 设计算法
Design algorithm
– 确定程序设计方法
Select a programming method
– 确定语言和开发环境
Select a computer language and programming environment
– 实现
Implementation
STRUCTURED PROGRAMMING
目 录第一讲 C语言程序设计入门例 1-1 简单程序设计
A Simple Program Design (1/5)
问题
– 求方程 ax2+bx+c=0的根(设 b2-4ac≥0)
程序设计步骤 1:定义数据结构
– 根据问题确定哪些是已知数据,哪些是通过计算得到的数据。对输入、输出和存储的数据进行描述,指定数据的类型和数据的组织形式。
– 定义以下变量 ( variables),
STRUCTURED PROGRAMMING
目 录第一讲 C语言程序设计入门
a,b,c (保存输入的系数)
p,disc,q (保存中间结果)
x1,x2 (保存最后的结果)
例 1-1 简单程序设计
A Simple Program Design (2/5)
问题
– 求方程 ax2+bx+c=0的根(设 b2-4ac≥0)
程序设计步骤 2:设计算法
– 根据数学知识,知道此时方程有两个根
– 那么,可以确定解方程的方法和步骤:
STRUCTURED PROGRAMMING
目 录第一讲 C语言程序设计入门
1,输入 a,b,c;
2,计算 -b/2a,把结果存入 p,即 p=-b/2a;
3,计算 b2-4ac,把结果存入 disc,即 disc=b2-4ac;
4,计算,把结果存入 q,即 q= ;
5,计算 p+q和 p-q,把结果存入 x1和 x2,即 x1=p+q,x2=p-q;
6,输出 x1和 x2。
a acbbx 2 4
2
1 a acbbx 2 4
2
2
adisc 2/ adisc 2/
例 1-1 简单程序设计
A Simple Program Design (3/5)
问题
– 求方程 ax2+bx+c=0的根(设 b2-4ac≥0)
程序设计步骤 3:确定程序设计方法
– 结构化程序设计 ( Structured programming)
严格的方法 ( disciplined approach)
清晰 ( clear),便于测试 ( test),调试 ( debug) 和修改 ( modify)
– 面向对象程序设计 ( Object-oriented programming)
可重用 ( reusable)
更易理解 ( understandable),更好的组织 ( organized),更利于维护
( maintain)
支持模块性 ( modularity)
– 这里,采用结构化程序设计方法。
STRUCTURED PROGRAMMING
目 录第一讲 C语言程序设计入门例 1-1 简单程序设计
A Simple Program Design (4/5)
问题
– 求方程 ax2+bx+c=0的根(设 b2-4ac≥0)
程序设计步骤 4:确定语言和开发环境
– 采用 C语言
– 在 Borland C 3.1开发环境下进行程序设计
STRUCTURED PROGRAMMING
目 录第一讲 C语言程序设计入门例 1-1 简单程序设计
A Simple Program Design (5/5)
问题
– 求方程 ax2+bx+c=0的根(设 b2-4ac≥0)
程序设计步骤 5:实现
– 编写 C语言程序
STRUCTURED PROGRAMMING
目 录第一讲 C语言程序设计入门
#include <math.h>
void main()
{ float a,b,c,p,disc,q,x1,x2;
scanf(“%f%f%f”,&a,&b,&c);
p=-b/(2*a);
disc=b*b-4*a*c;
q=sqrt(disc)/(2*a);
x1=p+q; x2=p-q;
printf(“x1=%f,x2=%f”,x1,x2);
} /*CW01-01.C*/
例:
x2=4

a=1
b=0
c=-4
C程序的基本结构
Basic Structure of A C Program
Example 1-3,Hello World
– 在屏幕上打印一行文字。
Program
BASIC STRUCTURE OF A C PROGRAM
目 录第一讲 C语言程序设计入门
Comments(注释)
Preprocessor directive(预处理命令)
Function(函数)
Statement(语句)
Return 0;(返回语句)
/* Example 1-3 (CW01-03.C)
Print a line of text.
This is my first c program.*/
#include <stdio.h>
int main()
{
printf("Hello World!");
return 0;
}
Hello World!
C程序的基本结构
Basic Structure of A C Program (Cont.1/5)
BASIC STRUCTURE OF A C PROGRAM
目 录第一讲 C语言程序设计入门
/* Example 1-3 (CW01-03.C)
Print a line of text.
This is my first c program.*/
#include <stdio.h>
int main()
{
printf("Hello World!");
return 0;
}
注释 ( Comment)
– /* 文本 */
– 不被执行
– 用来对程序进行描述
C程序的基本结构
Basic Structure of A C Program (Cont.2/5)
BASIC STRUCTURE OF A C PROGRAM
目 录第一讲 C语言程序设计入门
/* Example 1-3 (CW01-03.C)
Print a line of text.
This is my first c program.*/
#include <stdio.h>
int main()
{
printf("Hello World!");
return 0;
}
预处理命令 ( Preprocessor directive)
– 告诉计算机包含某一文件的内容
– <stdio.h> 定义了标准输入 /输出操作
C程序的基本结构
Basic Structure of A C Program (Cont.3/5)
BASIC STRUCTURE OF A C PROGRAM
目 录第一讲 C语言程序设计入门
/* Example 1-3 (CW01-03.C)
Print a line of text.
This is my first c program.*/
#include <stdio.h>
int main()
{
printf("Hello World!");
return 0;
}
函数 ( Function)
– C程序包含一个或多个函数,其中必须有一个 main 函数
– 圆括号 ( Parenthesis) 指示一个函数
– int 表示 main 函数返回 ( return) 一个整数值 ( integer value)
– { } ( braces) 包含函数体 ( body)
– }( right brace) 表示 main 函数结束
C程序的基本结构
Basic Structure of A C Program (Cont.4/5)
BASIC STRUCTURE OF A C PROGRAM
目 录第一讲 C语言程序设计入门
/* Example 1-3 (CW01-03.C)
Print a line of text.
This is my first c program.*/
#include <stdio.h>
int main()
{
printf("Hello World!");
return 0;
}
语句 ( Statement)
– 一行称为一条语句
– 必须以 ; ( semicolon )结尾
– 命令计算机完成一个操作( action)
C程序的基本结构
Basic Structure of A C Program (Cont.5/5)
BASIC STRUCTURE OF A C PROGRAM
目 录第一讲 C语言程序设计入门
/* Example 1-3 (CW01-03.C)
Print a line of text.
This is my first c program.*/
#include <stdio.h>
int main()
{
printf("Hello World!");
return 0;
} Return 0;
– 退出函数的一种方法
C程序的开发阶段
Phases of C Program Development
C PROGRAM DEVELOPEMNT
目 录第一讲 C语言程序设计入门
Edit
Preprocess
Compile
Link
Load
Execute
Editor Prog.c
Compiler
Linker
CPULoader
Prog.obj
Prog.exe
RAM
Libraries
Source file(源文件)
Object file(目标文件)
Library file(库文件)
Executable file(可执行文件)
C程序的开发阶段
Phases of C Program Development (1/4)
C PROGRAM DEVELOPEMNT
目 录第一讲 C语言程序设计入门
Edit
Preprocess
Compile
Link
Load
Execute
Editor Prog.c
Compiler
Linker
CPULoader
Prog.obj
Prog.exe
RAM
Libraries
Edit(编辑)
– Program is created in
the editor and stored on
disk.
C程序的开发阶段
Phases of C Program Development (2/4)
C PROGRAM DEVELOPEMNT
目 录第一讲 C语言程序设计入门
Edit
Preprocess
Compile
Link
Load
Execute
Editor Prog.c
Compiler
Linker
CPULoader
Prog.obj
Prog.exe
RAM
Libraries
Compile(编译)
– Preprocessor program
processes the code.
– Compiler creates object
code and stores
it on disk.
C程序的开发阶段
Phases of C Program Development (2/4)
C PROGRAM DEVELOPEMNT
目 录第一讲 C语言程序设计入门
Edit
Preprocess
Compile
Link
Load
Execute
Editor Prog.c
Compiler
Linker
CPULoader
Prog.obj
Prog.exe
RAM
Libraries
Link(链接)
– Linker links the object
code with the libraries.
C程序的开发阶段
Phases of C Program Development (4/4)
C PROGRAM DEVELOPEMNT
目 录第一讲 C语言程序设计入门
Edit
Preprocess
Compile
Link
Load
Execute
Editor Prog.c
Compiler
Linker
CPULoader
Prog.obj
Prog.exe
RAM
Libraries
Execute(运行)
– Loader puts program in
memory.
– CPU takes each
instruction and
executes it,possibly
storing new data values
as the program
executes.
C程序的开发工具
C Program Development Tools
C PROGRAM DEVELOPEMNT
目 录第一讲 C语言程序设计入门
Edit
Preprocess
Compile
Link
Load
Execute
Editor Prog.c
Compiler
Linker
Prog.obj
Prog.exe
Libraries
Integrated Development
Environment (IDE)(集成开发环境)
– Turbo C/C++
– Borland C/C++
– Visual C/C++
IDE
第二讲 数据类型、运算符和表达式
Data Types,Operators and Expressions
PROGRAM DESIGN IN C LANGUAGE
目 录
2.2 变量
Variables
2.3 数据类型
Data Types
2.4 常量
Constants
2.5 整型数据
Integers
2.1 字符集 标识符 关键字
Character Set,Identifiers and Keywords
2.7 字符型数据
Characters
2.8 字符串 常量
String Constants
2.9 算术运算符
Arithmetic Operators
2.10 类型转换
Type Conversion
2.6 浮点型数据
Floating-point Data
2.11 赋值运算符
Assignment Operators
2.12 逗号运算符
Comma Operator
字符集
Character Set
C 语言源程序文件是来自一个字符集的字符序列。
A C source file is a sequence of characters selected from a character
set.
C 语言的字符集 ( character set)
– 52个大小写字母 ( Letters)
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
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
– 10个数字 ( Digits)
0 1 2 3 4 5 6 7 8 9
– 空格 ( SPACE)
– 制表符 ( Tab)
– 图形符号 ( Graphic characters)
! # % ^ & * ( _ ) - + = ~ [ ] ' | \ ;," {},,< > /?
CHARACTER SET,IDENTIFIERS AND KEYWORDS
目 录第二讲 数据类型、运算符和表达式标识符
Identifiers
标识符 ( Identifiers)
– 是一个字符序列,包括大小写字母 ( capital and small letters),数字
( digits) 和下划线 ( the underscore character) 。
– 用来标识变量名、符号常量名、数组名、函数名、结构名、类型名等。
命名规则
首字符必须是字母或下划线;
一般内部标识符的前 31个字符有效,而外部标识符的前 6个字符有效;
不能与关键字相同。
CHARACTER SET,IDENTIFIERS AND KEYWORDS
目 录第二讲 数据类型、运算符和表达式
i j k
n1 n2 sum
display_matrix
_time
1 2x
!here money$
void main integer
date-time
OK Invalid
关键字
Keywords
Keywords
– The following identifiers are reserved for use as keywords,and may not
be used as ordinary identifiers:
CHARACTER SET,IDENTIFIERS AND KEYWORDS
目 录第二讲 数据类型、运算符和表达式
auto break case char
const continue default do
double else enum extern
float for goto if
int long register return
short signed sizeof static
struct switch typedef union
unsigned void volatile while
变量
Variables
变量 ( Variables)
– 变量是在程序执行过程中其值会发生变化的量。
– Variables are program elements that change their values during the
course of program execution.
声明 ( Declaration)
<type_name> <variable_name>[,<variable_name>[,...]]
变量在使用之前必须被声明。
VARIABLES
目 录第二讲 数据类型、运算符和表达式
int x,y ;
int sum=0 ;
float volt ;
char degree ; 变量名 ( name)
是一个标识符变量类型
( type)
变量可以在声明时被初始化
( initialized)
变量与内存
Variables and Memory
变量与内存 ( Variables and Memory)
– 每一个变量有名字 ( name),类型 ( type),大小 ( size) 和值 ( value)
– 变量名对应于它在内存中的位置 ( location)
– 当一个新的值被放进 ( placed into) 变量时,它将替换 ( replace) 掉以前的值
– 从内存中读取变量的值不会改变它
A visual representation
VARIABLES
目 录第二讲 数据类型、运算符和表达式
int x = 23;
23
FF02
2Bytes
RAM x = 90;
90
printf(“%d”,x);
变量初始化
Variables Initialization
Initialization
– A variable may be initialized in its declaration.
If the variable in question is not automatic,the initialization is done once
only,conceptually before the program starts executing,and the initializer
must be a constant expression.
Automatic variables for which there is no explicit initializer have
undefined values.
VARIABLES
目 录第二讲 数据类型、运算符和表达式
char esc =?\\?;
int i = 0,limit = MAXLINE+1;
float eps = 1.0e-5;
Initializer
数据类型
Data Types
C 语言的数据类型
– 基本类型
整型 ( integer),int,short,long
字符型 ( character),char
浮点型 ( floating-point),float,double
枚举类型 ( enumeration),enum
– 构造型
结构体 ( structure),struct
共用体 ( union),union
数组 ( array)
– 指针类型 ( pointer)
– 空类型 ( void),void
DATA TYPES
目 录第二讲 数据类型、运算符和表达式基本类型
Basic Types
基本数据类型 ( Basic data types),
– 字符型 ( char)
a single byte,capable of holding one character
– 基本整型 ( int)
an integer,typically reflecting the natural size of integers on the host machine
– 单精度浮点型 ( float)
single-precision floating point
– 双精度浮点型 ( double)
double-precision floating point
此外,有几个修饰符 ( qualifiers) 可以加到基本数据类型上
short
long
signed
unsigned
DATA TYPES
目 录第二讲 数据类型、运算符和表达式常量
Constants
常量 ( Constants)
– 常量是在程序执行过程中其值不变化的量。
– Constants are program elements that do not change their values during
the course of program execution.
C语言有以下几种类型的常量:
– 整型常量 ( integer constants)
– 浮点型常量 ( floating-point constants)
– 字符型常量 ( character constants)
– 字符串型常量 ( string constants)
CONSTANTS
目 录第二讲 数据类型、运算符和表达式符号常量
Symbolic Constants
符号常量
– 符号常量是用一个标识符表示的常量。
定义规则
#define <symbolic_constant_name> <string>
Symbolic constants are handled by the C preprocessor and are defined
using the #define construct,It is a good programming practice to use
symbolic constants where possible,This enables certain changes be
made with a minimal amount of efforts.
CONSTANTS
目 录第二讲 数据类型、运算符和表达式
#define MAXSIZE 20
#define WELCOME "Welcome to you!"
#define PI 3.14
例 2-1 符号常量的应用
Symbolic Constants Application
Problem
– Calculate area of a circle.
Program
CONSTANTS
目 录第二讲 数据类型、运算符和表达式
/* Example 2-1 CW02-01.C
Calculate area of a circle.*/
#include <stdio.h>
#define PI 3.14
void main() {
float r,area;
scanf("%f",&r);
area = PI*r*r;
printf("area=%f",area);
}
1
3.140000
area
r
整数的类型和大小
Integer Types and Sizes
在微机中,不同类型的整型数据在内存中占的字节数如下表:
Integer VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式类型名称 类型说明符 字节数 数值范围基本整型 [signed] int 2 -32768~32767
短整型 [signed] short [int] 2 -32768~32767
长整型 [signed] long [int] 4 -2147483648~ 2147483647
无符号基本整型 unsigned [int] 2 0~65535
无符号短整型 unsigned short [int] 2 0~65535
无符号长整型 unsigned long [int] 4 0~4294967295
回顾:整数的存储
Review,Integer Storage (1/3)
正整数在内存中以二进制 原码 形式存放。
有符号正整数
10
INTEGER VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式符号位
0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0
00000000
00001010
RAM
回顾:整数的存储
Review,Integer Storage (2/3)
负整数在内存中以二进制 补码 的形式存放。
有符号负整数
-10
INTEGER VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式符号位
1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 0
11111111
11110110
RAM
10的原码 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0
1 1 1 1 1 1 1 1 1 1 1 1 0 1 0 1
1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 0
按位取反加一后得到 -10的补码回顾:整数的存储
Review,Integer Storage (3/3)
无符号整数的所有二进制位都存放数值。
无符号整数
65535u
INTEGER VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
11111111
11111111
RAM
整型常量
Integer Constants
有三种形式:
– 十进制 ( decimal) 整数
12 65 65535
– 八进制 ( octal) 整数:带前缀 0( zero)
014 0101 0177777
– 十六进制 ( hexadecimal) 整数:带前缀 0x 或 0X
0xc 0x41 0xffff
可以加上后缀 u 或 U 表示无符号整数 ( unsigned),或者 l 或 L 表示长整数
( long) 。
0xb5Lu
INTEGER VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式例 2-2:整型变量和常量
Integer Variables and Constants
Example 2-2,Integer Variables and Constants
INTEGER VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式
/* Example 2-2 CW02-02.C
Integer Variables and constants.*/
#include <stdio.h>
void main() {
int a,b;
unsigned c,d;
a=32767; b=-32768;
c=32768; d=65535;
printf("a=%d,b=%d\n",a,b);
printf("c=%u,d=%u",c,d);
}
a=32767,b=-32768
c=32768,d=65535
例 2-2:整型变量和常量
Integer Variables and Constants (Cont.)
Modified Example 2-2
INTEGER VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式
/* Example 2-2 CW02-02M.C
Integer Flowout.*/
#include <stdio.h>
void main() {
int a,b;
unsigned c,d;
a=32767; b=a+1;
c=32768; d=65535;
printf("a=%d,b=%d\n",a,b);
printf("c=%u,d=%u",c,d);
}
a=32767,b=-32768
c=32768,d=65535
???
溢出
Overflow
Analyzes Example 2-2
结论,a+1 的结果( 32768) 超出了基本整型变量 b 所能容纳(表示)的数值范围( -32768~32767),这种情况称为,溢出” 。
INTEGER VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
a(32767)
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
a+1(32768)
b(-32768)
浮点数的类型和大小
Floating-point Types and Sizes
在微机中,不同类型的浮点型数据在内存中占的字节数如下表:
FLOATING-POINT VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式类型名称 类型说明符 字节数 有效数字 数值范围单精度 float 4 6~7 10-37~1038
双精度 double 8 15~16 10-307~10308
长双精度 long double 10 18~19 10-4931~104932
回顾:浮点数的存储
Review,Floating-point Data Storage
浮点型数据在内存中按指数形式存放。
举例
3.14159
FLOATING-POINT VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式
0 (0.314159)10 0 (1)10
数符 小数部分 阶符 阶码
+ 0.314159 × 10+1
由此可见,小数部分的宽度决定了有效数字(精度),阶码部分的宽度决定了数值范围。
浮点型常量
Floating-point Constants
有两种形式:
– 十进制小数
12.3,65 0.
– 指数形式,< 小数 > < e | E > < 整数 >
1.2e-2,1E5 7E0
可以加上后缀 f 或 F 表示 float类型,或者 l 或 L 表示 long double类型,否则该常量是 double类型。
2.3f 1.2L,1E5f
FLOATING-POINT VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式例 2-3:浮点型变量和常量
Floating-point Variables and Constants
Example 2-3,Floating-point Variables and Constants
FLOATING-POINT VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式
/* Example 2-3 CW02-03.C
Floating-point variables and constants.*/
#include <stdio.h>
void main() {
float f;
double d;
f=33333.33333;
d=33333.3333333333;
printf("f=%f\nd=%f",f,d);
}
f=33333.332031
d=33333.333333 实数的有效数字是有限的,在有效位之外的数字被舍去。由此可能会产生一些误差。
例 2-4:浮点型数据的舍入误差
Floating-point Rounding Error
Example 2-4,Floating-point Rounding Error
FLOATING-POINT VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式
/* Example 2-4 CW02-04.C
Floating-point rounding error.*/
#include <stdio.h>
void main() {
float a,b;
a=123456.789e5;
b=a+20;
printf("a=%f\nb=%f",a,b);
}
a=12345678848.000000
b=12345678848.000000
???
舍入误差分析
Analyze Floating-point Rounding Error
Analyze Example 2-4
FLOATING-POINT VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式
a=123456.789e5;
b=a+20;
a+20的理论值应该是,12345678920
但是,一个实型变量能够保证的有效数字是 7
位,后面的数字将被舍去,是没有意义的。
因此,最后得到
b=12345678848.000000
由此可知,应当避免一个很大的数和一个很小的数直接相加或相减,否则就会“丢失”较小的数。
1.0/3*3
=?
字符型常量
Character Constants
字符型常量
– 用单引号 ( single quote) 括起来的一个字符。
'x' '9' '+'
转义字符 ( escape character)
– 指代一些特殊的字符。
CHARACTER VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式
\a alter(bell) character \\ backslash
\b backspace \? question mark
\f formfeed \' single quote
\n newline \" double quote
\r carriage return \ooo octal number
\t horizontal tab \xhh hexadecimal number
\v vertical tab
例 2-5:转义字符
Escape Character
Example 2-5,Escape Character
CHARACTER VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式
/* Example 2-5 CW02-05.C
Escape character.*/
#include <stdio.h>
void main() {
printf(" ab c\t de\rf\tg\n");
printf("h\ti\b\bj k");
}
f gde
h j k
f ab c gde
h jik
输出到显示屏 打印机输出字符数据的存储
Character Storage
在内存中,是把一个字符的 ASCII码以二进制形式存放的,占一个字节。
Example:
CHARACTER VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式
char c1,c2;
c1=?a?;
c2=?b?;
0 1 1 0 0 0 0 1 字符 a 的 ASCII码(值)为 97c1
0 1 1 0 0 0 1 0 字符 b 的 ASCII码(值)为 98c2
与整型数据的存储形式类似,因此两者之间的转换非常方便,可以把字符数据当作整型数据来用。
例 2-6:字符变量
Character Variables
Example 2-6,Character Variables
CHARACTER VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式
/* Example 2-6 CW02-06.C
Assign integers to character variables.*/
#include <stdio.h>
void main() {
char c1,c2;
c1=97;
c2=98;
printf("c1=%c,c2=%c\n",c1,c2);
printf("c1=%d,c2=%d",c1,c2);
}
c1=a,c2=b
c1=97,c2=98
例 2-7:字符变量
Character Variables
Example 2-7,Character Variables
CHARACTER VARIABLES AND CONSTANTS
目 录第二讲 数据类型、运算符和表达式
/* Example 2-7 CW02-06.C
Convert lowercase character to uppercase.*/
#include <stdio.h>
void main() {
char c1,c2;
c1=97;
c2=c1-32;
printf("c1=%c,c2=%c\n",c1,c2);
}
c1=a,c2=A
字符串常量
String Constants
字符串常量
– 用双引号 ( double quote) 括起来的字符序列。
"this is a string" "x" "12345"
The double quotes are not part of the string,but only to delimit it,A
string constant is actually represented internally as an array of
characters terminated by the null character '' (\0).
STRING CONSTANTS
目 录第二讲 数据类型、运算符和表达式
x?
x
在内存中占一个字节
“x”
x
在内存中占两个字节
\0
算术运算符
Arithmetic Operators
算术运算符 ( Arithmetic operators)
算术计算 ( Arithmetic calculations)
– 整数相除截去 ( truncates) 余数 ( remainder)
7 / 5 1
– 取模运算 ( %) 返回相除后的余数,不能用于 float 或 double 型数据
7 % 5 2
ARITHMETIC OPERATORS AND EXPRESSIONS
目 录第二讲 数据类型、运算符和表达式
C operation Arithmetic operator Algebraic expression C expression
Addition + f + 7 f + 7
Subtraction - p – c p – c
Multiplication * bm b * m
Division / x / y x / y
Modulus % r mod s r % s
算术运算符的优先级
Arithmetic Operator Precedence
运算符优先级 ( Operator precedence)
– 某些运算符先于其他运算符被执行 (例如,先乘除后加减)
必要时可以用()改变计算顺序
Example,Find the average of three variables a,b and c
Do not use,a + b + c / 3
Use,(a + b + c ) / 3
优先级和结合性 ( precedence and associativity)
ARITHMETIC OPERATORS AND EXPRESSIONS
目 录第二讲 数据类型、运算符和表达式
Operator(s) Operation(s) Precedence Associativity
() parenthesis 1 left to right
*,/,% Multiplication,
division,modulus
3 left to right
+ or - Addition or
subtraction
4 left to right
算术表达式
Arithmetic Expressions
算术表达式 ( Arithmetic expression)
– 算术表达式,是由算术运算符和括号将运算对象(也称为操作数)连接起来的式子
运算对象包括常量、变量、函数等
Examples:
ARITHMETIC OPERATORS AND EXPRESSIONS
目 录第二讲 数据类型、运算符和表达式
7/5
x+y+z
(f1*2)/f2+0.5
sqrt(a)+sqrt(b)
数学函数例 2-8:算术运算
Arithmetic
Example 2-8,Arithmetic calculation
ARITHMETIC OPERATORS AND EXPRESSIONS
目 录第二讲 数据类型、运算符和表达式
/* Example 2-8 CW02-08.C
Arithmetic calculation.*/
#include <stdio.h>
void main() {
float f1;
float f2;
f1=1/3;
f2=1.0/3.0;
printf("f1=%f\nf2=%f",f1,f2);
}
f1=0.000000
f2=0.333333
类型转换
Type Conversion
在算术表达式中允许不同类型的数据参与运算
Example,10+?a?+1.5-8765.1234*?b?
– 在进行运算时,不同类型的数据要先转换成同一类型,然后进行运算转换方式有两种:
– 自动转换,数据类型自动由低级向高级转换
– 强制转换,将表达式的运算结果强制转换成指定的数据类型
TYPE CONVERSION
目 录第二讲 数据类型、运算符和表达式自动类型转换
Automatic Type Conversion
这种类型转换由编译系统自动完成。
转换规则:
TYPE CONVERSION
目 录第二讲 数据类型、运算符和表达式
float double
long
unsigned
int
Char
short 低高说明:
1、横向的箭头表示必定的转换。
2、纵向的箭头表示当运算对象类型不同时转换的方向。
强制类型转换
Type Conversion
类型转换运算符,( )
– 将一个表达式转换成所需类型表达式:
( type-specification ) [(] expression [)]
Examples:
– (double)a
– (int)(x+y) ≠(int)x+y
– (float)(5/3) = 1.0
强制转换属单目运算,运算优先级为 2
强制转换得到的是中间变量类型,原变量类型不变
TYPE CONVERSION
目 录第二讲 数据类型、运算符和表达式例 2-13:类型转换
Type Conversion
下面表达式的类型是什么?
10+?a?+1.5-87.1*?b?
Example 2-13,Type conversion
TYPE CONVERSION
目 录第二讲 数据类型、运算符和表达式
/* Example 2-13 CW02-13.C
Type conversion.*/
#include <stdio.h>
void main() {
float f;
int i;
f=3.6;
i=(int)f;
printf("f=%f\ni=%d",f,i);
} i=3
f=3.600000
f 的类型并未因此而改变!
赋值运算
Assignment
赋值运算符 ( Assignment operators)
– 简单赋值运算符 ( Simple assignment operator),=
– 复合赋值运算符 ( Compound assignment operators),
+=,-=,*=,/=,%=
赋值表达式 ( Assignment Expression)
<variable> <assignment operator> <expression>
– 作用,将表达式的值赋给变量
– 赋值表达式的值就是被赋值的变量的值
ASSIGNMENT OPERATORS AND EXPRESSIONS
目 录第二讲 数据类型、运算符和表达式简单赋值运算符
Simple Assignment Operator
Simple assignment operator:=
– Associativity,right to left
Examples:
ASSIGNMENT OPERATORS AND EXPRESSIONS
目 录第二讲 数据类型、运算符和表达式
c=a+b
a=b=c=d=10
x=(a=5)+(b=8)
a=(a+b)
a=(b=(c=(d=10)))
a=5,b=8,x=a+b
复合赋值运算符
Compound Assignment Operators
Compound assignment operator:+=,-=,*=,/=,%=
– Associativity,right to left
简化了赋值表达式表达式格式 ( form)
<variable> <operator>= <expression>
由下面的表达式简化而来
<variable> = <variable> <operator> <expression>
Examples:
ASSIGNMENT OPERATORS AND EXPRESSIONS
目 录第二讲 数据类型、运算符和表达式
a+=5
x*=y+7
x+=x-=x*=x
a=a+5
x=x*(y+7)
x=x+(x=x-(x=x*x))

自增、自减运算符
Increment and Decrement Operators
自增运算符 ( Increment operator),++
– c++ 可以用来代替 c+=1
自减运算符 ( Decrement operator),--
– c-- 可以用来代替 c-=1
使用形式一,Preincrement
– ++c or --c
– Variable is changed before the expression it is in is evaluated
使用形式二,Postincrement
– c++ or c--
– Expression executes before the variable is changed
INCREMENT AND DECREMENT
目 录第二讲 数据类型、运算符和表达式例 2-9:自增、自减运算
Increment and Decrement Operation
Example 2-9,Increment and decrement operation
INCREMENT AND DECREMENT
目 录第二讲 数据类型、运算符和表达式
/* Example 2-9 CW02-09.C
Increment and decrement operation.*/
#include <stdio.h>
void main() {
int i=6,a,b;
printf("%d\n",++i);
printf("%d\n",i++);
a=--i; printf("%d\n",a);
b=i--; printf("%d\n",b);
printf("%d\n",-i++);
printf("i=%d\n",i);
}
7
7
7
7
-6
i =?
例 2-10:自增、自减运算
Increment and Decrement Operation
Example 2-10,Increment and decrement operation
INCREMENT AND DECREMENT
目 录第二讲 数据类型、运算符和表达式
/* Example 2-10 CW02-10.C
Increment and decrement operation.*/
#include <stdio.h>
void main() {
int i=5,j=5,p,q;
p=(i++)+(i++)+(i++);
q=(++j)+(++j)+(++j);
printf("p=%d,i=%d\n",p,i);
printf("q=%d,j=%d\n",q,j);
}
p=15,i=8
q=24,j=8
例 2-11:自增、自减运算
Increment and Decrement Operation
Example 2-11,Increment and decrement operation
INCREMENT AND DECREMENT
目 录第二讲 数据类型、运算符和表达式
/* Example 2-11 CW02-11.C
Increment and decrement operation.*/
#include <stdio.h>
void main() {
int i,j,k;
i=1;
j=1;
k=i+++j;
printf("k=%d,i=%d,j=%d\n",k,i,j);
}
k=2
i=2
j=1
k=(i++)+j;
例 2-12:自增、自减运算
Increment and Decrement Operation
Example 2-12,Increment and decrement operation
INCREMENT AND DECREMENT
目 录第二讲 数据类型、运算符和表达式
/* Example 2-12 CW02-12.C
Increment and decrement operation.*/
#include <stdio.h>
void main() {
int i=3;
printf("%d,%d\n",i,i++);
}
4,3
Order of evaluation
逗号运算符
Comma Operator
逗号运算符 ( Comma operator),,
表达式格式 ( Expression form),
<expression_1>,<expression_2>,…,<expression_n>
– 求解过程:先求表达式 1的值,再求表达式 2的值,···,直至求出表达式
n的值。
– 整个表达式的值为表达式 n的值。
COMMA OPERATOR
目 录第二讲 数据类型、运算符和表达式例 2-15:逗号运算符
Comma Operator
Example 2-15,Comma operator
COMMA OPERATOR
目 录第二讲 数据类型、运算符和表达式
/* Example 2-15 CW02-15.C
Comma operator.*/
#include <stdio.h>
void main() {
int a=2,b=4,c=6;
int x,y;
y=((x=a+b),(b+c));
printf("x=%d\ny=%d",x,y);
}
x=6
y=10
第三讲 顺序结构
Sequence Structure
PROGRAM DESIGN IN C LANGUAGE
目 录
3.2 控制结构
Control Structures
3.3 结构化程序
Structured Program
3.4 顺序结构
Sequence Structure
3.5 常用语句
Common Statements
3.1 算法
Algorithm
3.7 流
Streams
3.8 字符输出
Character Output
3.9 字符输入
Character Input
3.10 格式输出
Formatted output
3.6 输入输出
Input/Output
3.11 格式输入
Formatted Input
3.12 程序设计举例
Example
简 介
Introduction
在编写程序解决实际问题之前
– 全面的理解问题
– 仔细规划解决问题的方法 ( approach)
在编写程序时
– 了解有哪些可用的“构造块” ( building blocks)
– 使用良好的编程规则 ( programming principles)
iNTRODUCTION
目 录第三讲 顺序结构强调程序的清晰性与实用性算法
Algorithm
任何计算问题的解决方案包括
– 按照特定顺序去执行一系列动作 ( actions)
算法 ( Algorithm)
– 为解决某个特定的问题而采用的确定且有限的步骤。
– Procedure in terms of
Actions to be executed
The order in which these actions are to be executed
– 例如,早晨上学准备算法”:起床 -穿衣 -洗漱 -吃早餐 -上学程序控制 ( Program Control)
– 计算机程序中指定语句执行的顺序
ALGORITHM
目 录第三讲 顺序结构算法是程序的灵魂。
Algorithm is the spirit of a
program.
算法的表示
Representation of Algorithm
算法的表示方法
– 自然语言
Natural language
– 伪代码
Pseudocode
– 流程图
Flowchart
– 计算机语言
Computer language
ALGORITHM
目 录第三讲 顺序结构算法的自然语言表示
Algorithm (1/4),Natural Language
问题
– 计算 1+2+3+…+100
自然语言表示
– 定义数据结构:
变量 i 代表每一个数
变量 sum 表示和
ALGORITHM
目 录步骤 1,i=1,sum=0;
步骤 2,使 sum(和)加上 i,累加后的值仍放在 sum中。用公式表示就是,sum = sum+i;
步骤 3,使 i的值增一,即 i=i+1;
步骤 4,如果 i不大于 100,重复执行步骤 2和步骤 3;否则算法结束,变量 sum中的值就是要得到的结果。
第三讲 顺序结构算法的伪代码表示
Algorithm (2/4),Pseudocode
问题
– 计算 1+2+3+…+100
伪代码 ( pseudocode) 表示
ALGORITHM
目 录
i=1
sum=0
while i<=100 do
sum=sum+i
i=i+1
end while
print sum
第三讲 顺序结构
人为的、非正式的语言
与日常用语类似
不被执行
帮助程序员在写程序之前“设想出”程序
很容易被转换成 C程序
一般只包括可执行语句算法的流程图表示
Algorithm (3/4),Flowchart
问题
– 计算 1+2+3+…+100
流程图 ( flowchart) 表示
ALGORITHM
目 录
start
i=1
sum=0
i<=100
sum=sum+i
i=i+1
Out,sum
end
Y
N
第三讲 顺序结构程序的开始和结束动作 ( action)
流程线 ( flowline)
判断 ( decision)
输入 /输出 ( input/output)
连接 ( connection)
算法的计算机语言表示
Algorithm (4/4),Computer Language
问题
– 计算 1+2+3+…+100
C语言表示
ALGORITHM
目 录
main()
{ int i,sum;
i=1; sum=0;
while (i<=100)
{ sum=sum+i;
i=i+1;
}
printf("1+2+3+...+100=%d",sum);
}
第三讲 顺序结构控制结构
Control Structure
顺序执行 ( Sequential execution)
– 程序中的语句按照它们的书写顺序一句接一句地执行控制转移 ( Transfer of control)
– 把待执行的下一个语句指定为不是书写顺序中的下一个语句
– goto语句带来很多问题
程序结构不清晰、可读性差、不利于维护结构化技术 ( 1970s),所有的程序只用 3种结构就可以写出来
– 顺序结构 ( Sequence structures)
Built into C
Programs executed sequentially by default
– 选择结构 ( Selection structures)
C has three types,if,if-else,and switch
– 循环结构 ( Repetition structures)
C has three types,while,do/while and for
CONTROL STRUCTURES
目 录第三讲 顺序结构结构化程序
Structured Program
单入 /单出 ( Single-entry/single-exit) 控制 结构
– 3种控制结构都是单入 /单出的
– 把控制结构的出口处与下一个控制结构的入口处连接起来
– 使程序开发非常容易结构化程序由 3种结构通过以下方式组合而成:
– 堆叠 ( stacking)
– 嵌套 ( nesting)
STRUCTURED PROGRAM
目 录第三讲 顺序结构
sum=sum+i
i=i+1
sequence structure
stacking
nesting
顺序结构
Sequence Structure
Sequence Structure
– Programs executed sequentially by default
Control flow:
– Statements executed one after the other in the order written
SEQUENCE STRUCTURE
目 录
statement 1
statement 2
Sequence Structure
第三讲 顺序结构常用语句
Common Statements
C语言程序常用的语句:
– 表达式语句
expression;
– 函数调用语句
function-name(parameter-list);
– 空语句;
– 复合语句 ( compound statement)
COMMON STATEMENTS
目 录第三讲 顺序结构
{}
{
int x,y;
x=y=10;
printf(“x=%d,y=%d\n”,x,y);
}
输入 /输出
Input/Output
输入输出是以计算机主机为主体而言的。
– 输出:从计算机向外部输出设备输出数据。
– 输入:从外部通过输入设备向计算机输入数据。
C语言中数据的输入、输出是由函数来实现的。
– 字符输入函数,getchar
– 字符输出函数,putchar
– 格式输入函数,scanf
– 格式输出函数,printf
– 它们的原型 ( prototype) 都在 stdio.h 中
INPUT/OUTPUT
目 录第三讲 顺序结构主机键盘磁盘光盘扫描仪
……
显示器打印机磁盘 ……

Streams
流 ( stream)
– 按直线排列的字符序列
每个序列包括 0个或多个字符,并用换行符结尾
ANSI C支持至少 254个字符的序列
– 所有的输入 /输出都是用流来进行的开始执行程序时,3个流自动连接到程序上
– 标准输入 ( standard input),keyboard
– 标准输出 ( standard output),screen
– 标准错误 ( standard error),screen
– 操作系统允许这些流重定向 ( redirected) 到其它设备
STREAMS
目 录第三讲 顺序结构
type myprog.c > prn
S@!ci?[]
字符输入 /输出
Character Input/Output
putchar
getchar
使用说明
– 程序中必须包含 stdio.h 头文件 ( head file)
CHARACTER INPUT/OUTPUT
目 录第三讲 顺序结构
#include <stdio.h>
字符输出
Character Output
putchar
putchar(character);
– 向标准输出流输出一个字符 character
使用说明
– character可以是以下数据:
字符型变量
整型变量
字符型常量
转义字符
PUTCHAR
目 录第三讲 顺序结构
S@!ci?[]
output stream
k
RAM
例 3-1:字符输出
Character Output
Example 3-1,putchar
PUTCHAR
目 录第三讲 顺序结构
#include <stdio.h>
main()
{ char a; int b;
a=?B?;
b=79;
putchar(a); putchar(?\n?);
putchar(b); putchar(?\n?);
putchar(?Y?);
} /*CW03-01.C*/
B
O
Y
字符输入
Character Input
getchar
variable=getchar();
– 从标准输入流读取一个字符使用说明
– 只读取一个字符
– 该字符可赋给字符变量、整型变量或作为表达式的一部分
GETTCHAR
目 录第三讲 顺序结构
S@!ci?[]
Input stream
RAM
例 3-2:字符输入
Character Input
Example 3-2,getchar
GETCHAR
目 录第三讲 顺序结构
#include <stdio.h>
main()
{ char c;
c=getchar();
putchar(c);
} /*CW03-02.C*/
a
a
abc
a
98
9
1
2
3
格式输入 /输出
Formatted Input/Output
printf
scanf
使用说明
– 程序中可以不明确指定包含 stdio.h 头文件
FORMATTED INPUT/OUTPUT
目 录第三讲 顺序结构
#include <stdio.h>
可以省略此命令格式输出
Formatted Output
printf
printf(format-control-string,output-list);
– 按格式控制字符串规定的格式,向指定的输出设备输出输出表列中的输出项。
使用说明
– 格式控制字符串 ( format-control-string)
由双引号括起来的字符串,用于指定输出格式
– 输出表列 ( output-list)
需要输出的数据列表,彼此间用逗号分隔
可以是任意合法的表达式
Formatted outPUT
目 录第三讲 顺序结构
23.5 s 78
output stream
120 f
RAM
格式控制字符串
Format Control String
printf(“n=%5d,f=%5.2f\n”,n,f)
Formatted outPUT
目 录第三讲 顺序结构普通字符原样输出格式说明符(转换规则)
% [修饰符 ] 格式字符指定数据的输出格式
printf的格式字符
Format Character
Formatted outPUT
目 录第三讲 顺序结构格式字符 功 能
d,i 以十进制有符号形式输出整数(正数不输出符号)
o 以八进制无符号形式输出整数(不输出前缀)
x,X 以十六进制无符号形式输出整数(不输出前缀)
u 以十进制无符号形式输出整数
f 以小数形式输出单、双精度实数
e,E 以指数形式输出单、双精度实数
g,G 选用 %f和 %e格式中输出宽度较短的一种,不输出无意义的零
c 以字符形式输出,输出一个字符
s 输出字符串
printf的修饰符
Qualifier Character
Formatted outPUT
目 录第三讲 顺序结构修饰符 意 义
l 用于长整型和双精度实型数据,可加在格式字符 d,o、
x,u,f 前面。
m(正整数) 数据最小宽度。
n(正整数) 对于实数,表示输出 n位小数;
对于字符串,表示截取的字符个数。
- 输出的数字或字符在域内向左靠,右边填空格。
# 当整数以八进制或十六进制形式输出时,输出前缀。
可加在格式字符 o,x前面。
printf的格式说明符小结
Format Specification String Summary
Formatted outPUT
目 录第三讲 顺序结构格式字符 形 式
d,i %d,%md,%-md,%ld,%mld,%-mld,%i,……
o %o,%mo,%-mo,%lo,%mlo,%-mlo,%#o,……
x,X %x,%mx,%-mx,%lx,%mlx,%-mlx,%#x,……
u %u,%mu,%-mu,%lu,%mlu,%-mlu
f %f,%mf,%m.nf,%lf,……
e,E %e,%me,%m.ne,……
g,G %g
c %c
s %s,%ms,%m.ns,……
例 3-3:格式输出
Formatted Output
Example 3-3,printf
Formatted outPUT
目 录第三讲 顺序结构
main()
{ int a=97,b=-1;
float f=123.4;
printf(“%d,%c\n”,a,a);
printf(“%d,%o,%x,%u\n”,b,b,b,b);
printf(“%f,%e,%gEND”,f,f,f);
} /*CW03-03.C*/
97,a
-1,177777,ffff,65535
123.400002,1.234000e+02,123.4END
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
例 3-4:格式输出
Formatted Output
Example 3-4,printf
Formatted outPUT
目 录第三讲 顺序结构
main()
{ int a=1,b=2,c=3;
printf(“%d,%d,%d,%d\n”,a,b,c);
printf(“%d,%d,%d\n”,a,b,c,a+b+c);
} /*CW03-04.C*/
1,2,3,898
1,2,3 格式说明符和输出项在数量和类型上应该一一对应。
例 3-5:格式输出
Formatted Output
Example 3-5,printf
Formatted outPUT
目 录第三讲 顺序结构
main()
{ int i=3;
printf("%d,%d\n",i,i++);
} /*CW02-12.C*/
4,3
不同的编译系统对输出表列中的求值顺序不一定相同。
格式输入
Formatted Input
scanf
scanf(format-control-string,address-list);
– 按格式控制字符串规定的格式,从指定的输入设备输入数据,并存放到地址表列中的各地址项指定的变量中使用说明
– 格式控制字符串 ( format-control-string)
由双引号括起来的字符串,用于指定输入格式
– 地址表列 ( address-list)
由若干个变量的地址组成
Formatted INPUT
目 录第三讲 顺序结构
23.5 s 78
input stream
RAM
格式输入
Formatted Input
scanf(“%d,%d”,&a,&b)
取地址运算符,&
– &<变量 >
– 得到变量在内存中的地址。
Formatted INPUT
目 录第三讲 顺序结构
FF00
FF02
a
b
scanf的格式字符
Format Characters
Formatted INPUT
目 录第三讲 顺序结构格式字符 功 能
d,i 以十进制形式输入有符号整数
o 以八进制形式输入无符号整数
x,X 以十六进制形式输入无符号整数
u 以十进制形式输入无符号整数
f 以小数形式或指数形式输入实数
e,E,g,G 同 f,它们之间可以互换
c 输入单个字符
s 输入字符串
scanf的修饰符
Qualifier Characters
Formatted INPUT
目 录第三讲 顺序结构修饰符 意 义
l 用于输入长整型和双精度实型数据,可加在格式字符 d、
o,x,u,f,e 前面。
h 用于输入短整型数据。
m(正整数) 域宽,指定输入数据所占的宽度。
* 表示本输入项读入后不赋给相应的变量,即跳过该输入值。
scanf的格式说明符小结
Format Specification Characters Summary
Formatted INPUT
目 录第三讲 顺序结构格式字符 形 式
d,i %d,%md,%ld,%mld,%i,……
o %o,%mo,%lo,%mlo
x,X %x,%mx,%lx,%mlx
u %u,%mu,%lu,%mlu
f %f,%mf,%lf,%mlf
e,E,g,G %e,%me,%le,%mle,%g,……
c %c
s %s,%ms
格式输入
Formatted Input
输入数据时采用的分隔符应与格式控制中的分隔符一致。
– 例 1,scanf("%d%f%d",&a,&b,&c);
格式符中无普通字符时,可用空格,Tab键、回车键作分隔符。
如,12 3.45 678↙ 或 12<Tab>3.45<Tab>678↙
– 例 2,scanf("%d,%f,%d",&a,&b,&c);
必须采用格式,12,3.45,678↙
– 例 3,scanf("a=%d,b=%d",&a,&b);
必须采用格式,a=12,b=345↙
Formatted INPUT
目 录第三讲 顺序结构格式输入
Formatted Input
无符号整数可用 %d,%o,%x 格式输入。
输入格式符带有 *,表示该数据不赋值。
– 例,scanf("%d%*d%d",&a,&c);
键入,12 34 567↙
则 a=12,c=567,而 34 未赋值。
数据输入时不可规定精度,但可确定宽度。
– 例 1,scanf(“%3f%3c”,&a,&b); 合法。
– 例 2,scanf(”%3.2f%3c”,&a,&b); 非法。
Formatted INPUT
目 录第三讲 顺序结构格式输入
Formatted Input
Example 3-6,scanf
Formatted INPUT
目 录第三讲 顺序结构
main()
{ char a,b,c;
scanf(“%c%c%c”,&a,&b,&c);
printf(“a=%c,b=%c,c=%c",a,b,c);
} /*CW03-06.C*/
abc
a=a,b=b,c=c
a b c
a=a,b=,c=b
a b
a=a,b=,c=
a
b
a=a,b=
,c=b
1 2
3 4
用 c 格式字符输入字符时,若格式控制字符串中无普通字符,
那么认为所有输入的字符(包括空格、制表符、换行符)均为有效字符。
深入分析输入流
Deep Into Input Stream
Formatted INPUT
目 录第三讲 顺序结构
a<nl>b<nl>2,3.4
输入缓冲区
scanf();
getchar();

输入流输入流格式输入
Formatted Input
用 c格式字符输入字符时,若格式控制字符串中加入空格作为分隔符,那么输入时各数据之间可以加任意多个空格(或回车换行)。
– 例,scanf(,%c %c %c”,&a,&b,&c);
输入,a b c↙
则 a=a,b=b,c=c
在下列情况下可认为数据输入结束:
– 遇空格、回车、跳格键( Tab)时
– 按指定的宽度结束
– 遇非法输入
Formatted INPUT
目 录第三讲 顺序结构例 3-7:顺序结构
Sequence Structure
问题:输入圆柱体的截面圆半径和高,求其体积。
– 设截面圆半径 r,高 h,那么根据几何知识得到
– 圆柱体的体积 v=πr2h
Formatted INPUT
目 录第三讲 顺序结构
#define PI 3.14
main()
{ float r,h,v;
printf(“Input r and h:\n");
scanf("%f%f",&r,&h);
v=PI*r*r*h;
printf(“v=%.2f\n“,v);
} /*CW03-07.C*/
Input r and h:
1 1
v=3.14
第四讲 选择结构
Selection Structures
PROGRAM DESIGN IN C LANGUAGE
目 录
4.2 if选择结构
if Selection Structure
4.3 if-else选择结构
if-else Selection Structure
4.4 逻辑运算
Logical Calculation
4.5 多重选择结构
Multiple-Selection Structure
4.1 关系运算
Relational Calculation
关系运算
Relational Calculation
关系运算(比较运算)
– 比较两个值,结果为“真”或“假”
– 举例,a>3
如果 a=8,则结果为“真”
如果 a=1,则结果为“假”
用关系运算进行条件判断
– 关系表达式表示一个条件,根据其结果判断条件是否满足
– 举例,a>3
如果 a=8,结果为“真”,即条件满足
如果 a=1,结果为“假”,即条件不满足
ReLATIONAL CALCULATION
目 录第四讲 选择结构关系运算符
Relational Operators
ReLATIONAL CALCULATION
目 录第四讲 选择结构运算符 含 义 优先级 结合性
< 小于 6 左结合
<= 小于或等于
> 大于
>= 大于或等于
== 等于 7
!= 不等于关系表达式
Relational Expressions
关系表达式 ( Relational Expressions)
<表达式 1> <关系运算符 > <表达式 2>
– 表达式 1和表达式 2可以是任何表达式
– 举例
ReLATIONAL CALCULATION
目 录第四讲 选择结构
a>b
m+n<=20
c!=?y?
(x>z)==(y>z)
关系表达式
Relational Expressions
关系表达式的值是一个逻辑值:,真,或,假,
– C语言没有逻辑类型,因此
用整数 1 表示“真”
用整数 0 表示“假”
– 即关系表达式的值是整数 1 或 0
– 举例
若 a=1,b=2,c=3
ReLATIONAL CALCULATION
目 录第四讲 选择结构
a>b
a+b<=c
(a>c)==(b>c)
Y?!=?y?
0
1
1
1
关系表达式的使用
Use Of Relational Expressions
问题:写出下面各条件的关系表达式
– x为不小于 -5 的整数
– x为非零的数
– x的平方大于 m与 n的和
ReLATIONAL CALCULATION
目 录第四讲 选择结构
x>=-5
x!=0
x*x>(m+n)
if选择结构
The if Selection Structure
选择结构 ( Selection Structure)
– 用于在可选择的几个操作之间进行选择
– 伪代码语句举例
If student’s grade is greater than or equal to 60
Print,Passed”
– 如果条件为真(学生分数大于等于 60)
那么就打印或显示,Passed”,然后程序按顺序执行下一条伪代码语句
– 如果条件为假
就忽略打印或显示操作,顺序执行下一条伪代码语句
SELECTION STRUCTURES
目 录第四讲 选择结构
if选择结构
The if Selection Structure
选择结构是一个单入 /单出结构
SELECTION STRUCTURES
目 录
True Print,Passed”
grade >= 60 False
if Selection Structure
if (grade>=60)
printf(“Passed”);
条件判断可以是任何表达式
0( zero),false
非 0( nonzero),true
第四讲 选择结构
if-else选择结构
The if-else Selection Structure
if Selection Structure
– 只有在条件为真时,才会执行一个操作;否则就会跳过这个操作
if-else Selection Structure
– 条件为真时所执行的操作与条件为假时所执行的操作不同
– 伪代码语句举例
If student’s grade is greater than or equal to 60
Print,Passed”
Else
Print,Failed”
SELECTION STRUCTURES
目 录第四讲 选择结构
if-else选择结构
The if-else Selection Structure
if-else Selection Structure
– 伪代码转换成 C代码
SELECTION STRUCTURES
目 录
Print,Passed”
True
Print,Failed”
grade >= 60 False
if-else Selection Structure
第四讲 选择结构
if (grade>=60)
printf(“Passed”);
else
printf(“Failed”);
条件运算符
Conditional Operator
条件运算符,?,
– 三目运算符
– 右结合条件表达式
<expression-1>?<expression-2>:<expression-3>
– 举例
SELECTION STRUCTURES
目 录第四讲 选择结构
printf(“%s”,(grade>=60)?,Passed”:“Failed”);
(grade>=60)?printf(“Passed”):printf(“Failed”);
嵌套选择结构
Nested Selection Structure
嵌套的 if-else结构 ( Nested If-else Structure)
– 对多种情况进行测试
– 伪代码语句举例
If 学生的分数大于等于 90
打印,A”
else
If 学生的分数大于等于 80
Print,B”
else
If 学生的分数大于等于 70
Print,C”
else
If 学生的分数大于等于 60
Print,D”
else
Print,E”
SELECTION STRUCTURES
目 录第四讲 选择结构嵌套的选择结构
Nested Selection Structure
嵌套的 if-else结构 ( Nested if-else Structure)
– 伪代码转换成 C语言
SELECTION STRUCTURES
目 录第四讲 选择结构
if (grade>=90)
printf(“A”);
else
if (grade>=80)
printf(“B”);
else
if (grade>=80)
printf(“C”);
else
if (grade>=60)
printf(“D”);
else
printf(“E”);
if (grade>=90)
printf(“A”);
else if (grade>=80)
printf(“B”);
else if (grade>=80)
printf(“C”);
else if (grade>=60)
printf(“D”);
else
printf(“E”);
选择结构中的复合语句
Compound Statement Nested In if/else
选择结构的 if或 else体可以是复合语句
SELECTION STRUCTURES
目 录第四讲 选择结构
if (grade>=60)
printf(“Passed”);
else {
printf(“Failed\n”);
printf(“You must take the course again!”);
}
复合语句可以放在程序中单一语句能够放置的任何位置关系运算的不足
Shortage Of Relational Calculation
关系表达式只能表达一些简单的条件
– grade>=60
– total>1000
– 每个判断只是对一个条件进行测试
– 如果要对多个条件进行测试就要在独立的语句或嵌套的 if或 if-else结构中进行测试
– 例 1,10>y>5
– 例 2,x<-10或者 x>0
LOGICAL CALCULATION
目 录第四讲 选择结构
if (y>5)
if (y<10)
…;
if (x<-10) …;
if (x>0) …;
逻辑运算
Logical Calculation
逻辑运算
– 通过逻辑运算符把简单的条件组合起来,能够形成更加复杂的条件
– 例 1,10>y>5 的逻辑表达式
(y>5)&&(y<10)
– 例 2,x<-10或者 x>0 的逻辑表达式
(x<-10)||(x>0)
逻辑运算符
– !(逻辑非,logical NOT)
– &&(逻辑与,logical AND)
– ||(逻辑或,logical OR)
LOGICAL CALCULATION
目 录第四讲 选择结构逻辑表达式
Logical Expression
逻辑表达式
[<表达式 1>] <逻辑运算符 > <表达式 2>
– 表达式 1和表达式 2可以是任何表达式
– 举例
LOGICAL CALCULATION
目 录第四讲 选择结构
(x>5)||(x<-5)
!(a<b)&&(m!=n)
(a+b>c)&&(a+c>b)&&(b+c>a) 逻辑表达式的值
1,true
0,false
整数逻辑运算
Logical Calculation
逻辑运算真值表
LOGICAL CALCULATION
目 录第四讲 选择结构
a !a
1 0
0 1
a b a&&b
1 1 1
1 0 0
0 1 0
0 0 0
a b a||b
1 1 1
1 0 1
0 1 1
0 0 0
!
&&
||
逻辑运算
Logical Calculation
运算符运算优先级小结
LOGICAL CALCULATION
目 录第四讲 选择结构算术运算关系运算逻辑运算与

或赋值运算逻辑非从高到低逻辑表达式的使用
Use Of Logical Expression
将下面的条件用 C语言的逻辑表达式表达
– 例 1,1≤x≤10且 x≠7
x>=1&&x<=10&&x!=7
– 例 2,y能被 4整除,但不能被 100整除
(y%4==0)&&(y%100!=0)
逻辑与和逻辑非具有短路能力
– 例 1,gender==?F?&&age>65
如果 gender不等于’ F?,整个表达式的值就是假,求值过程将停止
– 例 2,average>=90||finalExam>=90
如果 average大于等于 90,整个表达式的值就是真,求值过程将停止
LOGICAL CALCULATION
目 录第四讲 选择结构例 4-1:逻辑表达式的使用
Use Of Logical Expression
问题,任意输入一个字符,判断它是字母还是数字。
LOGICAL CALCULATION
目 录第四讲 选择结构
void main() {
char c;
c=getchar();
if ((c>=?A?&&c<=?Z?)||(c>=?a?&&c<=?z?))
printf(“%c is a letter.”,c);
else if (c>=?0?&&c<=?9?)
printf(“%c is a digit.”,c);
else
printf(“%c is neither a letter nor a digit.”,c);
} /*CW04-01.C*/
多重选择结构
Multiple-Selection Structure
switch
– 在判断过程中,一个变量或表达式会分别针对其可能会取的每个整型常量值进行测试,并采取不同的动作
MULTIPLE-SELECTION STRUCTURE
目 录第四讲 选择结构
switch(expression)
{ case <constant_expression_1>,action_1; [break;]
case <constant_expression_2>,action_2; [break;]
……
case <constant_expression_n-1>,action_n-1; [break;]
[default,action_n; [break;]]
}
例 4-2:多重选择结构
Multiple-Selection Structure
问题
– 根据考试成绩的等级打印相应的分数段
MULTIPLE-SELECTION STRUCTURE
目 录第四讲 选择结构
grade=getchar();
switch(grade)
{ case?A?,printf(“85~100\n”);
case?B?,printf(“70~84\n”);
case?C?,printf(“60~69\n”);
case?D?,printf(“<60\n”);
default,printf(“error\n”);
}
若 grade=?A?
85~100
70~84
60~69
<60
error
例 4-2:多重选择结构
Multiple-Selection Structure( cont.)
分析例 4-2的结果
– 流程图
MULTIPLE-SELECTION STRUCTURE
目 录第四讲 选择结构
print
“60~69”
print
“70~84”
print
“85~100”
print
“<60”
print
“error”
grade
ABCD? default
例 4-3:多重选择结构
Multiple-Selection Structure
改进例 4-2
– 改进后的流程图
MULTIPLE-SELECTION STRUCTURE
目 录第四讲 选择结构
print
“60~69”
print
“70~84”
print
“85~100”
print
“<60”
print
“error”
grade
ABCD? default
例 4-3:多重选择结构
Multiple-Selection Structure( cont.)
switch中的 break语句
– 改进后的代码
MULTIPLE-SELECTION STRUCTURE
目 录第四讲 选择结构
switch(grade)
{ case?A?,printf(“85~100\n”); break;
case?B?,printf(“70~84\n”); break;
case?C?,printf(“60~69\n”); break;
case?D?,printf(“<60\n”); break;
default,printf(“error\n”);
} 若 grade=?A?
85~100
break语句终止 switch语句的执行例 4-4:多重选择结构
Multiple-Selection Structure
问题
– 任意输入两个数,和一个运算符,输出运算结果。
MULTIPLE-SELECTION STRUCTURE
目 录第四讲 选择结构
print
op1*op2
print
op1-op2
print
op1+op2
print
op1/op2
print
“error”
operator
+-*/? default
例 4-4:多重选择结构
Multiple-Selection Structure
代码 ( cw04-04.c)
MULTIPLE-SELECTION STRUCTURE
目 录第四讲 选择结构
main()
{ int op1,op2,operator;
scanf("%d%d",&op1,&op2); operator=getchar();
switch(operator)
{ case?+?,printf(“=%d”,op1+op2); break;
case?-?,printf(“=%d”,op1-op2); break;
case?*?,printf(“=%d”,op1*op2); break;
case?/?,printf(“=%d”,op1/op2); break;
default,printf(“operator is invalid!”);
}
}
例 4-4:多重选择结构
Multiple-Selection Structure( cont.)
改进代码
MULTIPLE-SELECTION STRUCTURE
目 录第四讲 选择结构
main()
{ int op1,op2,operator,result,done=1;
scanf("%d%d",&op1,&op2); operator=getchar();
switch(operator)
{ case?+?,result=op1+op2; break;
case?-?,result=op1-op2; break;
case?*?,result=op1*op2; break;
case?/?,result=op1/op2; break;
default,done=0;
}
if (done) printf(“%d%c%d=%d”,op1,operator,op2,result);
else printf(“operator is invalid!”);
} /*CW04-04.C*/
标记变量( flag)
例 4-5:多重选择结构
Multiple-Selection Structure
问题
– 根据输入的月份,给出当月的天数。
MULTIPLE-SELECTION STRUCTURE
目 录第四讲 选择结构
main()
{ int m,d;
scanf("%d",&m);
switch (m) {
case 1,case 3,case 5,case 7,case 8,case 10,case 12,d=31; break;
case 4,case 6,case 9,case 11,d=30; break;
case 2,d=28; break;
default,d=0;
}
d>0? printf("%d",d),printf("invalid input!");
} /*CW04-05.C*/
小结
Summary
Relational Calculation
– Simple Condition
Logical Calculation
– Compound Condition
if Selection Structure
if-else Selection Structure
switch Multiple-Selection Structure
– break
SELECTION STRUCTURE
目 录第四讲 选择结构第五讲 循环结构
Repetition Structures
PROGRAM DESIGN IN C LANGUAGE
目 录
5.2 计数器控制的循环
Counter-controlled structure
5.3 标记控制的循环
Flag-controlled stucture
5.4 嵌套的控制结构
Nested control structures
5.5 do-while循环结构
The do-while repetition
5.1 while循环结构
The while repetition structure
5.6 for循环结构
The for repetition structure
5.7 结构化程序设计小结
Structured programming summary
5.8 程序设计举例
Examples
while循环结构
The while Repetition Structure
循环结构 ( Repetition Structure)
– 程序员指定当某个条件一直为真时重复执行某个动作
– Example in Pseudocode:
While there are more items on my shopping list
Purchase next item and cross it off my list
如果条件“购物单上还有其他商品”为真时,就执行动作“购买下一个商品,并把它从购物单上划掉”
如果该条件一直为真,这个动作就会重复执行
最终,该条件为假,循环过程就会终止,程序将执行这个循环结构之后的第一个伪代码语句
– while 循环重复执行,直到条件为假
THE While REPETITION STRUCTURE
目 录第五讲 循环结构
while循环结构
The while Repetition Structure
while 语句
while (condition) action;
– Example in C:
THE While REPETITION STRUCTURE
目 录第五讲 循环结构
int product=2;
while (product<=1000)
product=2*product;
product<=1000 product=2*product
Y
N
可以是两种语句单语句复合语句
while 循环结构是单入 /单出结构计数器控制的循环
Counter-Controlled Repetition
计数器控制的循环 ( Counter-controlled Repetition)
– 循环重复执行,直到计数器达到一个特定的值
– 确定循环 ( Definite repetition)
循环的次数是已知的
Example 5-1
– 1个班有 10个学生,参加了一次考试,成绩( 0~100内的整数)已知。
计算这次考试的班级平均成绩。
– 算法
输入每个学生的成绩,累计总成绩,计算平均分,显示结果
采用计数器控制的循环来输入学生的成绩
每输入一个成绩就进行累加
COUNTER-CONTROLLED REPETITION
目 录第五讲 循环结构计数器控制的循环
Counter-Controlled Repetition
Example 5-1
– Pseudocode:
设置总分( total)为 0
设置分数计数器( counter)为 1
While 分数计数器 <=10
输入下一个分数( grade)
把该分数加到总分上对分数计数器加 1
班级平均分( average)为总分除以 10
显示班级平均分
COUNTER-CONTROLLED REPETITION
目 录第五讲 循环结构计数器控制的循环
Counter-Controlled Repetition
Example 5-1( cw05-01.c)
COUNTER-CONTROLLED REPETITION
目 录第五讲 循环结构
#include <stdio.h>
void main() {
int counter,grade,total,average;
total=0;
counter=1;
while (counter<=10) {
printf("Enter grade:");
scanf("%d",&grade);
total+=grade;
counter++;
}
average=total/10;
printf("Class average is %d\n",average);
}
初始化
( initialization)
执行循环
( execute loop)
输入累加结束
( termination)
最后的计算输出结果计数器控制的循环
Counter-Controlled Repetition
Example 5-1
– Result
COUNTER-CONTROLLED REPETITION
目 录第五讲 循环结构
Enter grade:60
Enter grade:70
Enter grade:65
Enter grade:76
Enter grade:73
Enter grade:56
Enter grade:78
Enter grade:64
Enter grade:89
Enter grade:76
Class average is 70
标记控制的循环
Flag-Controlled Repetition
Example 5-2
– 开发出一个班级平均分计算程序,每次执行该程序,都能够处理任意数量的学生分数。
– 思考:学生人数未知,何时结束输入?
标记控制的循环 ( Flag-controlled Repetition)
– 使用标记 ( flag) 指定“数据输入的结束”
其他名称:信号值 ( signal value),哨兵 ( sentinel)
标记值不应与正常的用户输入混淆
– 本例可以采用 -1
但同时标记值也是合法的输入
– 当用户输入标记值时,循环结束
– 不确定的循环 ( indefinite repetition)
循环次数未知
FLAG-CONTROLLED REPETITION
目 录第五讲 循环结构标记控制的循环
Flag-Controlled Repetition
自上而下,逐步求精 ( top-down,stepwise refinement)
– 算法的顶部(描述程序整体功能)
计算本次考试的班级平均分
– 划分成一系列较小的任务初始化变量输入考试的分数,求分数总和,并计数(统计分数个数)
计算并显示班级平均分许多程序都有三个阶段 ( phase)
– 初始化 ( initialization)
初始化变量
– 处理 ( process)
输入数据,并相应的调整相关变量的值
– 结束 ( termination)
计算并输出最终结果
FLAG-CONTROLLED REPETITION
目 录第五讲 循环结构标记控制的循环
Flag-Controlled Repetition
进一步细化
– 初始化变量
– 输入考试的分数,求分数总和,并计数(计算分数个数)
FLAG-CONTROLLED REPETITION
目 录第五讲 循环结构设置总分( total)为 0
设置计数器( counter)为 0
输入第一个分数( grade)(可能是标记值)
While 用户还没有输入标记值把当前分数加到总分中分数的个数加 1
输入下一个标记值(可能是标记值)
标记控制的循环
Flag-Controlled Repetition
进一步细化 (续)
– 计算并显示班级平均分
FLAG-CONTROLLED REPETITION
目 录第五讲 循环结构
If 计数器不等于 0
总分除以计数器的结果就是班级平均分显示班级平均分
Else
显示“没有输入成绩”
被 0 除
,致命,错误会导致程序,崩溃,
标记控制的循环
Flag-Controlled Repetition
Example 5-2( cw05-02.c)
FLAG-CONTROLLED REPETITION
目 录第五讲 循环结构
#include <stdio.h>
void main() {
float average;
int counter,grade,total;
total = 0;
counter = 0;
printf("Enter grade,-1 to end:");
scanf("%d",&grade);
while (grade != -1) {
total += grade;
counter++;
printf("Enter grade,-1 to end:");
scanf("%d",&grade);
}
新的类型初始化处理结束判断标记控制的循环
Flag-Controlled Repetition
Example 5-2( cw05-02.c)
FLAG-CONTROLLED REPETITION
目 录第五讲 循环结构
if (counter != 0) {
average = (float)total / counter;
printf("Class average is %.2f\n",average);
}
else
printf("No grades were entered\n");
}
Enter grade,-1 to end:70
Enter grade,-1 to end:60
Enter grade,-1 to end:65
Enter grade,-1 to end:-1
Class average is 65.00
结束嵌套的控制结构
Nested Control Structures
构造程序的方式
– 堆叠控制结构 ( stacking)
– 嵌套控制结构 ( nesting)
Example 5-3
– 每班 10个学生期末考试结果的清单( 1-通过,2-没有通过)
– 开发出一程序对结果进行分析
如果有 8个学生通过,显示“优秀班级”
分析
– 程序每次执行处理 10个考试结果
采用计数器控制的循环
– 使用两个统计计数器
一个统计通过的人数,另一个统计没通过的人数
– 每一个考试结果要么是 1,要么是 2
只对 1进行测试,不是 1的其他数就假定为 2
NESTED CONTROL STRUCTURES
目 录第五讲 循环结构嵌套的控制结构
Nested Control Structures
算法的顶部
– 分析考试结果,判断是否评为优秀班级细化
– 初始化变量
– 输入 10个考试结果,并计算通过考试和未通过考试的学生数目
– 显示考试结果的汇总,并判断是否应该评为优秀班级进一步细化
– 初始化变量
NESTED CONTROL STRUCTURES
目 录第五讲 循环结构通过数初始化为 0
未通过数初始化为 0
循环控制计数器初始化为 1
嵌套的控制结构
Nested Control Structures
进一步细化 (续)
– 输入 10个考试结果,并计算通过考试和未通过考试的学生数目
NESTED CONTROL STRUCTURES
目 录第五讲 循环结构
While 循环控制计数器的值 <=10
输入一个考试结果
if 考试结果为 1
通过计数器加 1
else
未通过计数器加 1
循环控制计数器加 1
嵌套的控制结构
Nested Control Structures
进一步细化 (续)
– 显示考试结果的汇总,并判断是否应该评为优秀班级
NESTED CONTROL STRUCTURES
目 录第五讲 循环结构显示通过考试的学生数目显示未通过考试的学生数目
If 8个以上的学生通过了考试显示“优秀班级”
嵌套的控制结构
Nested Control Structures
Example 5-3( cw05-03.c)
NESTED CONTROL STRUCTURES
目 录第五讲 循环结构
#include <stdio.h>
void main() {
int passed=0,failed=0,counter=1,result;
while (counter<=10) {
printf("Enter result (1=pass,2=fail):");
scanf("%d",&result);
if (result==1)
passed++;
else
failed++;
counter++;
}
嵌套的控制结构
Nested Control Structures
Example 5-3( cw05-03.c)
NESTED CONTROL STRUCTURES
目 录第五讲 循环结构
printf("Passed %d\n",passed);
printf("Failed %d\n",failed);
if (passed>8)
printf("Excellent Class\n");
}
Enter result (1=pass,2=fail):1
Enter result (1=pass,2=fail):1
Enter result (1=pass,2=fail):1
Enter result (1=pass,2=fail):2
Enter result (1=pass,2=fail):1
Enter result (1=pass,2=fail):1
Enter result (1=pass,2=fail):1
Enter result (1=pass,2=fail):1
Enter result (1=pass,2=fail):1
Enter result (1=pass,2=fail):1
Passed 9
Failed 1
Excellent Class
do-while循环结构
The do-while Repetition Structure
do-while 语句
do
action
while (condition);
THE do-While REPETITION STRUCTURE
目 录第五讲 循环结构
condition
action
Y
N do-while 循环结构是单入 /单出结构先执行循环体语句,再判断循环条件
do-while循环结构
The do-while Repetition Structure
Example 5-4( cw05-04.c)
– 计算 1+2+…+100
THE do-While REPETITION STRUCTURE
目 录第五讲 循环结构
#include <stdio.h>
void main() {
int s,i;
s=0;
i=1;
do {
s = s + i;
i++;
} while (i<=100);
printf("1+2+...+100=%d\n",s);
}
do-while与 while
do-while and while
比较 do-while与 while( cw05-05.c)
THE do-While REPETITION STRUCTURE
目 录第五讲 循环结构
main()
{ int s=0,n;
scanf(“%d”,&n);
while (n<=2)
{ s += n; n++; }
printf(“s=%d,n=%d”,s,n);
}
main()
{ int s=0,n;
scanf(“%d”,&n);
do { s += n; n++; }
while (n<=2);
printf(“s=%d,n=%d”,s,n);
}
1
s=3,n=3
3
s=0,n=3
1
s=3,n=3
3
s=3,n=41 2 1 2
for循环结构
The for Repetition Structure
for 语句
for (expression1; expression2; expression3)
action;
THE FOR REPETITION STRUCTURE
目 录第五讲 循环结构没有分号
expression2 action
Y
N
expression3
expression1
for循环结构
The for Repetition Structure
for 循环结构能够自动处理计数器控制的循环的细节
THE FOR REPETITION STRUCTURE
目 录第五讲 循环结构
#include <stdio.h>
void main() {
int counter;
for (counter = 1; counter <= 10; counter++)
printf("%d ",counter);
} /*cw05-06b.c*/
循环条件 控制变量增 1
对控制变量进行初始化
1 2 3 4 5 6 7 8 9 10
for循环结构
The for Repetition Structure
for 语句使用说明
for ([expression1]; [expression2]; [expression3])
action;
– Notes:
三个表达式都是可选的(都可以为空)
如果表达式 2为空,那么就假定该循环条件为真
– 因此会创建一个无限循环
THE FOR REPETITION STRUCTURE
目 录第五讲 循环结构
for (i=0;;i++)
printf(“%2d”,i);
for (i=0;1;i++)
printf(“%2d”,i);
=
for循环结构
The for Repetition Structure
for 语句使用说明
for ([expression1]; [expression2]; [expression3])
action;
– Notes:
表达式 1和表达式 2可以是任何合法的表达式
– 常用逗号表达式
THE FOR REPETITION STRUCTURE
目 录第五讲 循环结构
for (s=0,i=1;i<=100;i++)
s+=i;
for (s=0,i=1;i<=100;s+=i,i++);
对多个变量初始化 修改多个变量的值
break语句
The break Statement
break 语句
break;
– 当在 while,do-while,for或 switch结构中执行 break语句时,
break语句会造成程序从该结构中退出
– 程序接着执行该结构之后的第一条语句
– 常规应用:
提前从循环结构中退出
跳过 switch结构的剩余部分
THE BREAK AND CONTINUE STATEMENTS
目 录第五讲 循环结构
break语句
The break Statement
Example,break (cw05-07.c)
THE BREAK AND CONTINUE STATEMENTS
目 录第五讲 循环结构
#include <stdio.h>
void main() {
int x;
for (x = 1; x <= 10; x++) {
if (x == 5)
break;
printf("%d ",x);
}
printf("\nBroke out of loop at x == %d\n",x);
}
1 2 3 4
Broke ot of loop at x == 5
break语句
The break Statement
Example,break in switch and for structure
THE BREAK AND CONTINUE STATEMENTS
目 录第五讲 循环结构
for (i=1;i<=3;i++)
{ switch(i)
{ case 1,printf(“*\n”);
break;
case 2,printf(“**\n”);
break;
case 3,printf(“***\n”);
break;
}
} *
**
***
for (i=1;i<=3;i++)
{ if (i==1) {printf(“*\n”);
break;}
if (i==2) {printf(“**\n”);
break;}
if (i==3) {printf(“***\n”);
break;}
}
}
*
continue语句
The continue Statement
continue 语句
continue;
– 当在 while,do-while或 for结构中执行 continue语句时,
continue语句能够跳过该结构中剩余语句
– 执行下一个循环过程
Notes:
在 while和 do-while结构中
– 在 continue语句被执行之后立即进行循环条件的测试
在 for结构中
– 表达式 3被执行之后,然后进行循环条件的测试
THE BREAK AND CONTINUE STATEMENTS
目 录第五讲 循环结构
continue语句
The continue Statement
Example,continue (cw05-08a.c,cw05-08b.c)
THE BREAK AND CONTINUE STATEMENTS
目 录第五讲 循环结构
#include <stdio.h>
void main() {
int x;
x = 1;
while (x <= 10) {
if (x == 5)
continue;
printf("%d ",x);
x++;
}
}
1 2 3 4
#include <stdio.h>
void main() {
int x;
for (x = 1; x <= 10; x++) {
if (x == 5)
continue;
printf("%d ",x);
}
}
1 2 3 4 6 7 8 9 10
goto语句
The goto Statement
goto 语句
goto statement-label;
– 改变程序正常的流程控制
– 立即执行语句标号指向的语句
– 合理的使用:
与 if语句一起构成循环结构
从循环体内跳到循环体外
– 特别是从多层嵌套循环的内部调到外层循环,或者直接跳出
THE GOTO STATEMENTS
目 录第五讲 循环结构语句标号是一个标识符放在可执行语句前面结构化编程技术限制使用 goto 语句滥用 goto语句使得程序无结构可言,可读性差,
调试和维护困难
goto语句
The goto Statement
Example,goto (cw05-09.c)
THE GOTO STATEMENTS
目 录第五讲 循环结构
#include <stdio.h>
void main() {
int s=0,i=1;
Loop:
s = s + i;
i++;
if (i<=100) goto Loop;
printf("1+2+...+100=%d\n",s);
}
1 2 3 4
Broke ot of loop at x == 5
语句标号结构化程序设计
Structured Programming
Structured programming
– Disciplined approach to writing programs
– Easier than unstructured programs to understand,test,debug,
and modify programs
Rules for structured programming
– Only single-entry/single-exit control structures are used
– Rules,
1,Begin with the ―simplest flowchart‖
2,Any rectangle (action) can be replaced by two rectangles (actions) in
sequence
3,Any rectangle (action) can be replaced by any control structure
4,Rules 2 and 3 can be applied in any order and multiple times
STRUCTURED PROGRAMMING SUMMARY
目 录第五讲 循环结构控制结构
Control Structures (1/2)
C语言的控制结构
STRUCTURED PROGRAMMING SUMMARY
目 录第五讲 循环结构
Sequence Structure
T
F
TF
T
F
break
T
F
break
T
F
break
Selection Structures
switch
if
if-else
控制结构
Control Structures (2/2)
C语言的控制结构
STRUCTURED PROGRAMMING SUMMARY
目 录第五讲 循环结构
T
F
Repetition Structures
while
T
F
T
F
do-while
for
结构化程序设计规则
Rules for Structured Programming (1/2)
Rule 1 and 2
STRUCTURED PROGRAMMING SUMMARY
目 录
Rule 1,Begin with the
simplest flowchart
Rule 2,Any rectangle can be
replaced by two rectangles in
sequence
第五讲 循环结构
Rule 2 Rule 2
Rule 2
结构化程序设计规则
Rules for Structured Programming (2/2)
Rule 3,Any rectangle can be replaced by any control structure
STRUCTURED PROGRAMMING SUMMARY
目 录
Rule 3
Rule 3
Rule 3
第五讲 循环结构非结构化程序
Unstructured Program
Unstructured flowchart
STRUCTURED PROGRAMMING SUMMARY
目 录第五讲 循环结构
satcking
nesting
overlaping
goto
结构化程序设计小结
Structured Programming Summary
All programs can be broken down into 3 control
structures:
– Sequence,handled automatically by compiler
– Selection,if,if-else or switch
– Repetition,while,do-while or for
Can only be combined in two ways:
Stacking (rule 2)
Nesting (rule 3)
Any selection can be rewritten as an if statement,
and any repetition can be rewritten as a while statement
STRUCTURED PROGRAMMING SUMMARY
目 录第五讲 循环结构结构化程序设计举例
Example 5-10
问题
– 求下面公式的前 n项之和分析
– 累加求和,s = s + an
– 关键在于写出 an 的表达式
– 用计数器控制的循环实现
...7151311
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
12
1)1( 1

na
nn
初始化累计和变量 s 为 0
初始化计数器变量 i 为 1
输入要累加的项数,放入变量 n
While i <= n
计算第 n项的值,结果放入 an
累计,s = s + an
修改计数器变量,i++
输出结果 s
结构化程序设计举例
Example 5-10
第一种实现 ( cw05-10a.c)
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
#include <stdio.h>
#include <math.h>
void main() {
int i=1,n;
float s=0,an;
scanf(“%d”,&n);
while (i<=n)
{ an=pow(-1,i-1)/(2*i-1);
s+=an;
i++;
}
printf(“sum=%.3f\n”,s);
}
不划算
1
sum=1.000
2
sum=0.667
5
sum=0.835
0
sum=0.000
结构化程序设计举例
Example 5-10
第二种实现 ( cw05-10b.c)
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
#include <stdio.h>
void main() {
int i=1,n,sign=1;
float s=0,an;
scanf(“%d”,&n);
while (i<=n) {
an=1.0/(2*i-1);
s+=sign*an;
sign*=-1;
i++;
}
printf(“sum=%.3f\n”,s);
}
1
sum=1.000
2
sum=0.667
5
sum=0.835
0
sum=0.000
结构化程序设计举例
Example 5-11
问题
– 用下面的公式求 π的近似值( 直到最后一项的绝对值小于 10-6为止 ):
分析
– 先计算等式右边的和
– 累加求和,s = s + an
– 当 |an|<10-6时,停止累加
– 用标记控制的循环实现
...71513114π
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构初始化累计和变量 s 为 0
初始化计数器变量 i 为 1
第 1项的值 an = 1
While |an| >= 10-6
累计,s = s + an
计算第 n项的值,结果放入 an
计算 π=s*4
输出结果 π
结构化程序设计举例
Example 5-11
实现 ( cw05-11.c)
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
#include <stdio.h>
void main() {
int i=1,n,sign=1;
double s=0,an;
an=1;
while (!(an<1e-6)) {
s+=sign*an;
i++;
sign*=-1;
an=1.0/(2*i-1);
}
printf("pi=%.8lf\n",s*4);
}
pi=3.14153162
an 保存的是第 i
项的绝对值结构化程序设计举例
Example 5-11
另一种实现 ( cw05-11b.c)
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
#include <stdio.h>
void main() {
int i=1,n,sign=1;
double s=0,an;
for (;;) {
an=1.0/(2*i-1);
if (an<1e-6) break;
s+=sign*an;
sign*=-1;
i++;
}
printf(“pi=%.8lf\n",s*4);
}
pi=3.14153162
使用 break 语句违背了结构化程序设计的原则
continue语句也有类似的问题
T
F T
F
结构化程序设计举例
Example 5-12
问题
– 任意输入 10个数,找出最大数和最小数分析
– 用计数器控制的循环实现
– 数的范围无法确定
– 把输入的第一个数作为最大数和最小数
– 将其余的数与最大数、最小数分别比较
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构结构化程序设计举例
Example 5-12
实现 ( cw05-12.c)
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
#include <stdio.h>
void main() {
int i,d,max,min;
printf("Input 10 integers:\n");
scanf("%d",&d);
max=min=d;
for (i=2;i<=10;i++) {
scanf("%d",&d);
if (d>max) {max=d; continue;}
if (d<min) min=d;
}
printf("max=%d\nmin=%d\n",max,min);
}
结构化程序设计举例
Example 5-13
问题
– 判断整数 m 是否素数实现 ( cw05-13.c)
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
#include <stdio.h>
#include <math.h>
void main() {
int m,k,i;
scanf("%d",&m);
k=sqrt(m);
for (i=2;i<=k;i++) if (m%i==0) break;
if (i>k) printf("%d is a prime number.\n",m);
else printf("%d is not a prime number.\n",m);
}
结构化程序设计举例
Example 5-14
问题
– 找出 1-100间的全部素数实现 ( cw05-14.c)
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
#include <stdio.h>
#include <math.h>
void main() {
int m,k,i;
for (m=1;m<=100;m++) {
k=sqrt(m);
for (i=2;i<=k;i++)
if (m%i==0) break;
if (i>k) printf("%4d",m);
}
}
Example 5-13
nesting
结构化程序设计举例
Example 5-15
问题
– 输出图形分析
– 共有 10行
– 第 n行有 n个星号
– 用计数器控制的循环实现
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
*
**
***
****
*****
******
*******
********
*********
**********
结构化程序设计举例
Example 5-15
实现 ( cw05-15.c)
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
#include <stdio.h>
void main() {
int m,n;
for (n=1;n<=10;n++) {
for (m=1;m<=n;m++)
printf("*");
printf("\n");
}
}
结构化程序设计举例
Example 5-16
问题
– 输出图形分析
– 共有 10行
– 第 n行先输出 n-1个空格,再输出 10-(n-1)个星号
– 用计数器控制的循环实现
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
**********
*********
********
*******
******
*****
****
***
**
*
结构化程序设计举例
Example 5-16
实现 ( cw05-16.c)
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
#include <stdio.h>
void main() {
int m,n;
for (n=1;n<=10;n++) {
for (m=1;m<=n-1;m++)
printf(" ");
for (;m<=10;m++)
printf("*");
printf("\n");
}
}
结构化程序设计举例
Example 5-17
问题
– 输出图形
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
*
***
*****
*******
*********
*
***
*****
*******
*********
*******
*****
***
*图 1
图 2
结构化程序设计举例
Example 5-17
实现 ( cw05-17a.c)
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
main()
{ int m,n;
for (n=1;n<=5;n++)
{ for (m=1;m<=5-n;m++) printf(" ");
for (m=1;m<=2*n-1;m++) printf("*");
printf("\n");
}
}
结构化程序设计举例
Example 5-17
实现 ( cw05-17b.c)
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
main() {
int m,n;
for (n=1;n<=5;n++) {
for (m=1;m<=5-n;m++)
printf(" ");
for (m=1;m<=2*n-1;m++)
printf("*");
printf("\n");
}
for (n=4;n>=1;n--) {
for (m=1;m<=5-n;m++)
printf(" ");
for (m=1;m<=2*n-1;m++)
printf("*");
printf("\n");
}
}
结构化程序设计举例
Example 5-18
问题
– 用二分法求下面方程在区间 [-10,10]上的根:
2x3-4x2+3x-6=0
二分法
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构近似计算
x1
x2
f(x1)
f(x2)
y
x
f(x)
0 x0
f(x0)
x0=(x1+x2)/2
结构化程序设计举例
Example 5-18
二分法
– 确定有根的区间
指定一个区间 [x1,x2],如果函数 f(x)在此区间是单调变化的,则可以根据
f(x1)和 f(x2)是否同号来确定方程 f(x)=0在区间 [x1,x2]内是否有一个实根
– 把区间一分为二
若 f(x1)和 f(x2)不同号,则 f(x)=0在区间 [x1,x2]内有一个(且只有一个)
实根;
如果 f(x1)和 f(x2)同号,则 f(x)=0在区间 [x1,x2]内没有实根,要重新改变
x1和 x2的值
– 重复
当确定 f(x)=0在区间 [x1,x2]内有实根后,可采用二分法将 [x1,x2]区间一分为二,再判断在哪一个小区间中有实根
– 循环
如此不断进行下去,直到小区间足够小为止
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构结构化程序设计举例
Example 5-18
算法设计
– 输入并确定有根的初始区间
输入两个数放入 x1 和 x2,表示区间 [x1 x2]
判断区间被是否有根
否则,重复上面两步,直到的到合法的区间
– 二分法求近似根
计算当前近似根 x0 = (x1+x2)/2
把当前区间一分为二 [x1 x0]和 [x0 x2]
判断根在哪一个小区间
更新当前区间 [x1 x2]
判断当前近似根是否达到精度要求
否则,重复上述步骤,直到满足要求
– 输出近似根
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
do-while
do-while
if-else
process
output
input
结构化程序设计举例
Example 5-18
算法设计 (细化)
– 输入并确定有根的初始区间
输入两个数放入 x1 和 x2,表示区间 [x1 x2]
计算 fx1 和 fx2
判断区间被是否有根,即 fx1 和 fx2 是否同号
否则,重复上面两步,直到的到合法的区间
– 二分法求近似根
计算当前近似根 x0 = (x1+x2)/2
计算 fx0
把当前区间一分为二 [x1 x0]和 [x0 x2]
判断根在哪一个小区间
更新当前区间 [x1 x2],和相应的 fx#
判断当前近似根是否达到精度要求
否则,重复上述步骤,直到满足要求
– 输出近似根
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
do-while
do-while
if-else
process
output
input
结构化程序设计举例
Example 5-18
实现 ( cw05-18.c)
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
do-while
do-while
if-else
process
output
input#include <math.h>
main() {
float x0,x1,x2,fx0,fx1,fx2;
do {
printf("Input x1,x2:");
scanf("%f,%f",&x1,&x2);
fx1 = x1*(x1*(2*x1-4)+3)-6;
fx2 = x2*(x2*(2*x2-4)+3)-6;
} while (fx1*fx2>0);
结构化程序设计举例
Example 5-18
实现 ( cw05-18.c)
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
do-while
do-while
if-else
process
output
inputdo {
x0=(x1+x2)/2;
fx0=x0*(x0*(2*x0-4)+3)-6;
if (fx0*fx1<0) {
x2=x0; fx2=fx0; }
else {
x1=x0; fx1=fx0; }
} while (fabs(fx0)>=1e-5);
printf("x=%.2f",x0);
}
结构化程序设计举例
Example 5-18
思考
–,计算 fx#” 的代码能重用吗?
自定义函数 fx
用宏
– 那么,“判断区间 [x1 x2]内是否有根”这个功能呢?
自定义函数 check
STRUCTURED PROGRAMMING EXAMPLES
目 录第五讲 循环结构
fx1 = x1*(x1*(2*x1-4)+3)-6;
fx2 = x2*(x2*(2*x2-4)+3)-6;
fx0 = x0*(x0*(2*x0-4)+3)-6;
fx1 = fx(x1);
fx2 = fx(x2);
fx0 = fx(x0);
第六讲 函数
Functions
目录
PROGRAM DESIGN IN C LANGUAGE
目 录
6.2 C语言的程序模块
Program modules in c
6.3 函数的定义
Function definitions
6.4 函数原型
Function prototypes
6.5 头文件
Head files
6.1 简介
Introduction
6.7 递归
Recursion
6.8 存储类别
Storage classes
6.9 作用范围
Scope
6.10 编译多源文件的程序
Compiling multiple-source-file programs
6.6 函数调用
Function call
简介
Introduction
分而治之 ( divide and conquer)
– 从较小的程序片段或组件来构建程序
这些小片段被称为模块 ( module)
– 这些小片段或组件比原始程序更容易管理
Functions
目 录第六讲 函数
main
fun_a fun_b fun_c
fun_c fun_d fun_e fun_f
fun_d
C语言的程序模块
Program Modules in C
函数 ( function)
– C语言中的模块
一个 C程序由一个主函数和若干个函数构成
由主函数调用其他函数,其他函数也可以互相调用
同一个函数可以被一个或多个函数调用任意多次
– 程序把用户定义的函数和标准库 ( standard libary) 函数组合在一起
C标准库提供了丰富的函数
– 数学计算,sqrt
– 字符串处理
– 输入 /输出,printf,scanf
程序员可以编写函数来定义特定的任务应该熟悉 ANSI C中的丰富的函数集合应该避免从头开始构建一切
Program modules in c
目 录第六讲 函数函数调用
Function Call
函数调用 ( function call)
– 激发函数 ( invoking functions)
提供函数名和参数 ( argument)
函数完成指定的任务
函数可以返回结果 ( result)
– 类比
老板命令工人去完成一项任务
– 工人获取信息,完成任务,返回报告
–,隐藏” ( hiding),老板不知道细节
Program modules in c
目 录第六讲 函数
Boss
Worker1 Worker2 Worker3
Worker4 Worker5
主调函数函数调用被调函数数学库函数
Math Library Functions
数学库函数
– 执行常用的数学计算
– #include <math.h>
函数调用的格式
function-name(argument)
如果有多个参数,则参数之间用逗号隔开
参数可以是常量、变量和表达式
– 举例
printf(“%.2f”,sqrt(900.0));
调用函数 sqrt,返回其参数 900.0的平方根
所有的数学函数返回 double型的
Program modules in c
目 录第六讲 函数函数
Functions
函数
– 使程序模块化 ( modulization)
– 在函数内声明的变量都是局部变量 ( local variable)
– 参数是函数间交流信息的途径,它们也是局部变量函数的好处
– 分而治之
使程序的开发易于管理 ( managable program development)
– 软件重用 ( software reusability)
使用现有的函数作为构件来创建程序
抽象 ( abstraction),隐藏了实现的细节(库函数)
– 避免代码重复 ( repetition)
Program modules in c
目 录第六讲 函数举例:函数
Example,Function
举例:函数 ( cw06-01.c)
– 写一个程序,使用 square函数计算从 1到 10所有整数的平方
Function definitions
目 录第六讲 函数
#include <stdio.h>
int square(int);
void main() {
int x;
for (x=1; x<=10; x++)
printf("%d ",square(x));
}
int square(int y) {
return y*y;
}
函数原型函数调用函数定义
1 4 9 16 25 36 49 64 81 100
函数的定义
Function Definitions
函数定义的格式
return-value-type function-name(parameter-list)
{
declarations and statements
}
– function-name(函数名):任何有效的标识符
– return-value-type(返回值类型):结果的数据类型
缺省是 int
void —— 表示函数不返回任何值
– parameter-list(参数列表):声明参数,用逗号分隔
必须为每个参数指定数据类型
但 int 可以省略
Function definitions
目 录第六讲 函数函数的定义
Function Definitions
函数定义的格式
return-value-type function-name(parameter-list)
{
declarations and statements
}
– declarations and statements(声明和语句):函数体
在函数体内可以声明变量,即局部变量
不能定义函数,即函数的定义不允许嵌套
– Returning control:把程序的控制返回到调用函数的位置
}
return;
return expression;
Function definitions
目 录第六讲 函数不返回结果返回结果举例:函数的定义
Example,Function Definitions
举例:函数定义 ( cw06-02.c)
Function definitions
目 录第六讲 函数
#include <stdio.h>
int maximum(int,int,int);
void main() {
int a,b,c;
printf("enter three integers,");
scanf("%d%d%d",&a,&b,&c);
printf("Maximum is,%d",maximum(a,b,c));
}
int maximum(int x,int y,int z) {
int max = x;
if (y>max) max = y;
if (z>max) max = z;
return max;
}
maximum
int int int
int
函数原型函数原型
Function Prototypes
函数原型
return-value-type function-name(parameter-list);
函数名
参数(类型、数量、顺序)
返回值类型编译程序使用函数原型来测试函数调用
– 函数原型要与函数的定义匹配
– 如果函数的定义在函数调用的后面就需要函数原型
– 例如
int maximum(int,int,int);
Function prototypes
目 录第六讲 函数函数原型
Function Prototypes
函数原型在程序文件中的位置不同,作用范围不同
– 在所有函数的外面
函数原型将应用于所有出现在文件中函数原型之后的函数调用中
– 在函数内部
函数原型只能用于该函数中的函数调用
Function prototypes
目 录第六讲 函数
main() {
}
void funcA() {
int funcB(int);
}
int funcB(int) {
}
函数 funcB只能在 funcA
中被使用函数原型
Function Prototypes
函数原型强迫参数采用正确的数据类型
– 举例
printf(“%.3f”,sqrt(4) );
函数原型使编译程序把整数值 4转换为 double型的值 4.0
没有与函数原型中的参数类型完全对应的参数值会在调用函数之前被转换成合适的数据类型
遵守 C语言的提升规则
Function prototypes
目 录第六讲 函数
double sqrt(double);
函数原型
Function Prototypes
如果程序中没有包含函数原型
– 编译程序会使用该函数第一次出现的情形来形成自己的函数原型
函数的定义
函数的调用默认情况下,编译程序假定函数返回 int型的结果,但不会对参数进行任何假定
如果传递给函数的参数不正确,编译程序不会检测到这些错误
Function prototypes
目 录第六讲 函数头文件
Head Files
头文件
– 每个标准库函数都有对应的头文件
– 包含了标准库中所有函数的函数原型,以及那些函数所需的数据类型和常量的定义
stdio.h,math.h,string.h
– 使用 #include命令把头文件包含到程序文件中
#include <filename>
例如,#include <math.h>
程序员可以创建自己的头文件
– 使用,h扩展名
– 使用下面的命令格式包含头文件
#include,filename”
Head files
目 录第六讲 函数函数调用
Function Call
函数调用的执行过程
Function call
目 录第六讲 函数
main() {
int a,b,c;
scanf("%d%d",&a,&b);
c = max(a,b);
printf("the larger is %d",c);
}
1
2
6
int max(int a,int b) {
int c;
c=a>=b?a:b;
return c;
}
3
4
5
1,……
2、主调函数暂停,
3、把实参的值拷贝给形参,控制权传给函数 max 。
4,……
5、结束被调函数,把函数值返回给主调函数,同时把控制权还给主调函数。
6,……
参数传递
Passing Parameters
函数间的数据传递
– 参数(传递)
– 结果(返回)
Function call
目 录第六讲 函数
int max(int a,int b) {
…… return c;
}
main() {
…… c=max(a,b);
}
max()
a
b
c
main()
参数传递返回值传递按值调用和按引用调用
Call By Value And Call By Reference
调用函数的两种途径按值调用
– 把参数的值的副本传递给函数
– 在函数内改变参数的值不会影响调用函数中的参数的原始值
– 如果函数不需要修改参数的值,就采用这种调用方式按引用调用
– 把参数传递给函数
– 在函数内改变参数的值将改变参数的原始值
– 用于可信的函数在 C语言中,所有调用都是按值调用
Function call
目 录第六讲 函数形参和实参
Formal Parameter and Actual Parameter
形参和实参
Function call
目 录第六讲 函数
int max(int a,int b)
{ int c=a>=b?a:b;
return c;
}
main()
{ int a,b,c;
scanf(“%d%d”,&a,&b);
c=max(a,b);
}
形式参数简称“形参”。在函数定义时表示可以接受实际参数的值实际参数简称“实参”。在函数调用时给出形参
Formal Parameter
形参
Function call
目 录第六讲 函数
int max(int a,int b)
{ int c=a>=b?a:b;
return c;
}
main()
{ int a,b,c;
scanf(“%d%d”,&a,&b);
c=max(a,b);
}
只有在函数被调用、启动后,
才临时为其分配存储单元,并接受主调函数传来的数据。
在函数调用结束后,形参所占存储单元被释放。
实参
Actual Parameter
实参
Function call
目 录第六讲 函数
int max(int a,int b)
{ int c=a>=b?a:b;
return c;
}
main()
{ int a,b,c;
scanf(“%d%d”,&a,&b);
c=max(a,b);
}
实参是函数调用时主调函数传送给被调函数的参数的实际值。
实参可以是常量、变量和表达式。
实参必须有确定的值。
参数传递
Passing Parameters
实参和形参应该一一对应
Function call
目 录第六讲 函数
int max(int a,int b)
{ int c=a>=b?a:b;
return c;
}
main()
{ int x=6,y;
y=max(x,x++);
printf(“%d”,y);
}
当实参表列中有多个实参时,
对实参的求值顺序并不确定。
Turbo C是按从右往左的顺序求值。
b=x++;
a=x;
7
在参数传递时参数传递
Passing Parameters
值传递
Function call
目 录第六讲 函数
int max(int a,int b)
{ int c=a>=b?a:b;
a++; b++;
return c;
}
main()
{ int x=6,y=5,z;
z=max(x,y);
printf(“%d,%d,%d”,x,y,z);
}
实参与形参不共用存储单元。
参数传递时,把实参的值复制一份给形参。
形参值的变化不影响实参的值。
所以,形参和实参可以同名。6,5,6
6x
5y
6 a
5 b
参数传递
Passing Parameters
实参和形参的类型应该相同或赋值兼容
Function call
目 录第六讲 函数
int max(int a,int b)
{ int c=a>=b?a:b;
return c;
}
main()
{ int x=6,y=5,z;
z=max(x,y);
printf(“%d”,z);
}
如果 a,b是整型,则调用合法;
如果 a,b是字符型,因为字符型与整型可以互换,所以也是合法的;
如果 a,b是短整型,则进行类型自动转换,
结果也正确;
如果 a或 b是实数,则结果有可能不正确。
b=y;
a=x;
在参数传递时函数返回值
Returning Results
函数返回值的类型应该与函数的类型一致
– 如果不一致,以函数类型为准,对返回值进行类型转换
Function call
目 录第六讲 函数
int max(int a,int b)
{ float c=a>=b?a:b;
return c;
}
main()
{ int x=6,y=5,z;
z = 2*max(x,y);
printf(“%d”,z);
}
c 的类型?
返回值的类型?
max(x,y) 的类型?
2*max(x,y) 的类型?
函数的嵌套调用
Nested Function Call
嵌套调用
– 在调用一个函数的过程中又调用另一个函数
Function call
目 录第六讲 函数主函数调用函数 1
函数 1
调用函数 2
函数 2
1 2 3 4
5
6789
函数的嵌套调用
Nested Function Call
举例:计算圆环的面积 ( cw06-03.c)
– 分析
圆环的面积 = 外圆的面积 – 内圆的面积
可以定义两个函数
– circleArea 计算圆的面积
– ringArea 计算圆环的面积
Function call
目 录第六讲 函数
r1
r2
circleArea
double
double
ringArea
double double
double
double circleArea(double r);
double ringArea(double r1,double r2);
函数的嵌套调用
Nested Function Call
举例:计算圆环的面积 ( cw06-03.c)
Function call
目 录第六讲 函数
#include <stdio.h>
#define PI 3.14
double circleArea(double r);
double ringArea(double r1,double r2);
void main() {
double r1,r2,s;
printf("\tInput r1,r2,");
scanf("%lf%lf",&r1,&r2);
s = ringArea(r1,r2);
printf("\n\tThe area is:%.2lf\n",s);
}
函数的嵌套调用
Nested Function Call
举例:计算圆环的面积 ( cw06-03.c)
Function call
目 录第六讲 函数
double circleArea(double r) {
return PI*r*r;
}
double ringArea(double r1,double r2) {
if (r1<=r2)
return circleArea(r2)-circleArea(r1);
else
return circleArea(r1)-circleArea(r2);
}
Input r1,r2,1 2
The area is,9.42
递归函数
Recursive Functions
递归函数( Recursive Functions)
– 直接或间接调用自己的函数
Recursion
目 录第六讲 函数函数 1
调用函数 1
函数 1
调用函数 2
函数 2
调用函数 1
递归
Recursion
用递归(函数)解决问题
– 递归函数只知道如何去解最简单的情形(基本情形)
简单的返回一个值
– 把复杂的问题分成两部分:
函数知道如何去做的部分
函数不知道如何去做的部分
– 这一部分与原问题相似,且更简单
– 函数可以调用自己的新形式来解决这个更小的问题(递归调用)
– 最终遇到基本情形
函数识别出基本情形,将结果返回给前一个情形
一系列的结果按顺序返回
直到把最终结果返回给原始的调用者(可能是 main)
Recursion
目 录第六讲 函数递归
Recursion
举例:用递归方法计算 n!
– 分析
5! = 5 * 4 * 3 * 2 * 1
5! = 5 * 4!
4! = 4 * 3!...
– 递归公式
Recursion
目 录第六讲 函数
n ! =
1 ( n=0或 1)
n*(n-1)! ( n>1)
基本情形简化问题递归
Recursion
举例:用递归方法计算 n!( cw06-05.c)
Recursion
目 录第六讲 函数
#include <stdio.h>
long fac(int n) {
long f;
if (n==0||n==1)
f=1;
else
f=n*fac(n-1);
printf("\t%d!=%ld\n",n,f);
return f;
}
void main( ) {
printf("\n\t5!=%ld\n",fac(5));
}
1!=1
2!=2
3!=6
4!=24
5!=120
5!=120
递归调用递归
Recursion
举例:用递归方法计算 n!
– 分析递归过程
Recursion
目 录第六讲 函数
5!
5*4!
4*3!
3*2!
2*1!
1
120
5*24
4*6
3*2
2*1
1
递归调用从递归调用返回值递归
Recursion
举例:用递归方法计算斐波拉契数列
0 1 1 2 3 5 8?
– 分析
每个数是前两个数的和
– 递归公式
fib(n) = fib(n-1) + fib(n-2)
fib(1) = 0
fib(2) = 1
Recursion
目 录第六讲 函数递归与迭代
Recursion vs,Iteration
循环
– 迭代:明确使用了循环结构
– 递归:重复调用递归函数终止条件
– 迭代:循环条件不满足
– 递归:遇到基本情形都有可能出现无限循环选择
– 迭代:性能好
– 递归:可读性好
Recursion
目 录第六讲 函数汉诺塔问题
Towers Of Hanoi
递归问题举例:汉诺塔
– 问题
假设有三个分别命名为 X,Y和 Z的塔座,在塔座 X上插有 n个直径大小个不相同、依从小到大编号为 1,2,…,n的圆盘。现要求将 X轴上的 n个圆盘移到塔座 Z上,并按同样的顺序叠放。
移动时必须遵循以下规则:
– 每次只能移动一个圆盘;
– 圆盘可以插在 X,Y和 Z中的任一塔座上;
– 任何时候都不能将一个较大的圆盘压在较小的圆盘之上。
Recursion
目 录第六讲 函数
X Y Z
汉诺塔问题
Towers Of Hanoi
递归问题举例:汉诺塔
– 分析
n=1时
– 将圆盘 1从塔座 X移到塔座 Z。
Recursion
目 录第六讲 函数
X Y Z
X Y Z
基本情形汉诺塔问题
Towers Of Hanoi
递归问题举例:汉诺塔
– 分析
n>1时
Recursion
目 录第六讲 函数
X Y Z
X Y Z
X Y Z
X Y Z递归调用
1,利用塔座 Y为辅助塔座,将压在圆盘 n之上的 n-1个盘从塔座 X移到塔座 Y;
( ——与原问题类似)
2,将圆盘 n从塔座 X移到塔座 Z;
3,利用塔座 X为辅助塔座,将塔座
Y上的 n-1个圆盘移动到塔座 Z。
( ——与原问题类似)
汉诺塔问题
Towers Of Hanoi
递归问题举例:汉诺塔
– 设计
move 函数:移动一个盘
– 把盘 n 从 s 塔移到 d 塔
hanoi 函数:移动 n个盘的汉诺塔问题
– 把 n 个盘从 x 塔移到 z 塔,y 塔作为辅助塔
Recursion
目 录第六讲 函数
void move(int n,char s,char d);
void hanoi(int n,char x,char y,char z);
汉诺塔问题
Towers Of Hanoi
递归问题举例:汉诺塔
– 实现( cw06-06.c)
Recursion
目 录第六讲 函数
#include <stdio.h>
void move(int n,char s,char d);
void hanoi(int n,char x,char y,char z);
void main() {
int n;
printf("\t Input the number of disks:");
scanf("%d",&n);
hanoi(n,'X','Y','Z');
}
汉诺塔问题
Towers Of Hanoi
递归问题举例:汉诺塔
– 实现( cw06-06.c)
Recursion
目 录第六讲 函数
void hanoi(int n,char x,char y,char z) {
if (n==1) move(n,x,z);
else {
hanoi(n-1,x,z,y);
move(n,x,z);
hanoi(n-1,y,x,z);
}
}
void move(int n,char s,char d) {
printf("\t%d\t%c-->%c\n",n,s,d);
}
存储类别
Storage Classes
变量定义的完整格式存储类别 数据类型 变量名
– 数据类型
占据存储空间的大小
取值范围
– 存储类别
在内存中持续的时间(生存期)
在硬件中存放的位置
– 其它属性
作用范围
– 可以被引用的程序部分(可见性)
Storage classes
目 录第六讲 函数
int a;
void main() {
int b;

}
int max(int x,int y) {

}
全局变量局部变量局部变量存储类别
Storage Classes
四种存储类别说明符
– auto
– register
– extern
– static
两种存储持续时间
– 自动存储持续时间
auto
register
– 静态存储持续时间
extern
static
Storage classes
目 录第六讲 函数自动存储类别
Automatic Storage
自动存储
– 变量在它所在的程序块内被创建和销毁
– auto(自动变量):局部变量的缺省类别
函数体中声明的变量,函数的参数,程序块中声明的变量
– register(寄存器变量):建议编译器把变量放进高速的寄存器
只适用于自动变量
Storage classes
目 录第六讲 函数
auto int a,b;
register int count = 1;
静态存储类别
Static Storage
静态存储
– 在程序执行期间,变量存在
系统给定缺省初值,0 或 ‘ \0’
– static(静态变量):用于在函数体中声明的变量
函数结束后依然存在,并保留值
但不改变其作用范围,即只能在所在的程序块内被使用
– extern(外部变量):在函数外声明的变量(全局变量)的缺省类别
在所有函数中都可以被使用
Storage classes
目 录第六讲 函数
static int a,b;
extern int total;
自动变量与静态变量
Automatic Variables and Static Variables
举例:存储类别 ( cw06-07.c)
Storage classes
目 录第六讲 函数
void func(int a) {
auto int b=10;
static int c=10;
b++; c++;
printf("a=%d\tb=%d\tc=%d\n",a,b,c);
}
void main() {
int i;
for (i=1;i<=3;i++)
func(i);
}
a=1 b=11 c=11
a=2 b=11 c=12
a=3 b=11 c=13
自动变量与静态变量
Automatic Variables and Static Variables
举例:存储类别
Storage classes
目 录第六讲 函数
c
a
b
a
b
a
b
1 2 3
动态存储区静态存储区
FF00
2208
2206
2206
2204
2204
2202
a=1 b=11 c=11
a=2 b=11 c=12
a=3 b=11 c=13
自动变量与静态变量
Automatic Variables and Static Variables
C语言程序的内存映像
Storage classes
目 录第六讲 函数存放全局变量和标明为静态类的局部变量。
栈,保存函数调用时的返回地址、函数的形参、局部变量,
以及 CPU的当前状态。
堆,自由内存区域。
程序代码全局变量堆栈程序可以访问的内存区域。
数据段代码段动态存储区用户区静态存储区作用范围
Scope
标识符的作用范围
– 能够引用该标识符的程序部分
– 四种作用范围:
函数作用范围 ( function scope)
文件作用范围 ( file scope)
程序块作用范围 ( block scope)
函数原型作用范围 ( function prototype scope)
Scope
目 录第六讲 函数文件作用范围
File Scope
文件作用范围
– 在函数外声明的标识符,在所有函数中可以被引用
– 全局变量,函数定义,函数原型
Scope
目 录第六讲 函数
int total;
int max(int,int);
void main() {

}
int limit;
int max( int x,int y) {

}
作用范围从声明的位置开始,到文件的末尾函数作用范围
Function Scope
函数作用范围
– 在函数体内定义的标识符,只能在函数体内被引用
– 语句标号
Scope
目 录第六讲 函数
void main() {

loop:

goto loop;
}
程序块作用范围
Block Scope
程序块作用范围
– 在程序块内声明的变量,在程序块内被引用
– 函数体内声明的变量,函数的参数,程序块内的变量
Scope
目 录第六讲 函数
int max(int x,int y) {

}
void main() {
int a;

{ int a;

}

}
作用范围从声明的位置开始,到程序块的右大括号隐藏同名变量,内部变量
“隐藏了”外部变量函数原型作用范围
Function Prototype Scope
函数原型作用范围
– 函数原型中的参数
Scope
目 录第六讲 函数
int max(int x,int y);
void main() {

}
int max(int x,int y) {

}
存储类别与作用范围
Storage Classes And Scope
举例:存储类别与作用范围 ( cw06-08.c)
Scope
目 录第六讲 函数
#include <stdio.h>
void a(void); /*function prototype*/
void b(void); /*function prototype*/
void c(void); /*function prototype*/
int x = 1; /*global variable*/
void main() {
int x = 5;
printf("local x in outer scope of main is %d\n",x);
{ /*start new scope*/
int x = 7;
printf("local x in inner scope of main is %d\n",x);
} /*end new scope*/
printf("\nlocal x in outer scope of main is %d\n",x);
存储类别与作用范围
Storage Classes And Scope
举例:存储类别与作用范围 ( cw06-08.c)
Scope
目 录第六讲 函数
a();
b();
c();
a();
b();
c();
printf("local x in main is %d\n",x);
}
void a() {
int x = 25; /*initialized each time a is called*/
printf("\nlocal x in a is %d after entering\n",x);
x++;
printf("local x in a is %d before exiting\n",x);
}
存储类别与作用范围
Storage Classes And Scope
举例:存储类别与作用范围 ( cw06-08.c)
Scope
目 录第六讲 函数
void b() {
static int x = 50; /*static initialization only*/
/*first time b is called*/
printf("\nlocal x in b is %d after entering\n",x);
x++;
printf("local x in b is %d before exiting\n",x);
}
void c() {
printf("\nglobal x is %d on entering c\n",x);
x*=10;
printf("global x is %d on exiting c\n",x);
}
存储类别与作用范围
Storage Classes And Scope
举例:存储类别与作用范围 ( cw06-08.c)
Scope
目 录第六讲 函数
local x in outer scope of main is 5
local x in inner scope of main is 7
local x in outer scope of main is 5
local x in a is 25 after entering a
local x in a is 26 before exiting a
local x in b is 50 after entering b
local x in b is 51 before exiting b
global x is 1 on entering c
global x is 10 on exiting c
存储类别与作用范围
Storage Classes And Scope
举例:存储类别与作用范围 ( cw06-08.c)
Scope
目 录第六讲 函数
local x in a is 25 after entering a
local x in a is 26 before exiting a
local x in b is 51 after entering b
local x in b is 52 before exiting b
global x is 10 on entering c
global x is 100 on exiting c
local x in main is 5
包含多个源文件的程序
Programs With Multiple Source Files
包含多个源文件的程序
– 每个函数的定义必须在一个文件内,不能被分割
– 全局变量可以被同一文件内的函数访问
如果需要被其他文件内的函数访问,则必须在其他文件内声明
– extern
表示该变量是在另一个文件内定义的
– 在一个文件内定义的函数,也可以被其他文件内的函数调用
在每个文件内加入该函数的原型(声明为外部函数)
函数的原型不需要 extern
Programs multiple source files
目 录第六讲 函数
int myGlobal; extern int myGlobal;
包含多个源文件的程序
Programs With Multiple Source Files
Example,programs with multiple source files
Programs with multiple source files
目 录第六讲 函数
int a,b;
extern int max(void);
void main() {
scanf("%d%d",&a,&b);
printf("%d",max());
}
extern int a,b;
int max() {
return (a>b?a:b);
}
A Bcw06-09a.c cw06-09b.c
包含多个源文件的程序
Programs With Multiple Source Files
包含多个源文件的程序
– static
限制全局变量只能被同一文件内的函数访问
限制函数只能被同一文件内的函数调用
Programs with multiple source files
目 录第六讲 函数
static int myGlobal;
static void myFunc() {

}
编译多个源文件的程序
Compiling Multiple-Source-File Programs
编译多个源文件的程序
– 每个源文件必须被编译,然后链接成一个可执行文件
– 如果有一个文件作了改动,则必须重新编译所有相关的文件
– 一般会提供 make 工具用来管理和编译多源文件的程序
创建 makefile 文件记录编译规则
自动查找必须编译的源文件
– 可以创建工程 ( project) 文件来管理多源文件的程序
Programs with multiple source files
目 录第六讲 函数程序设计举例
Examples
Example,Functions(cw06-11.c)
– 问题
每个玩家掷两个骰子。每个骰子都有 6个面。这些面中包含了 1点,2点,3
点,4点,5点和 6点。当骰子静止下来之后,计算两个朝上的面中的点数和。
如果第一次投掷的结果是 7 或 11,那么这个玩家就获胜。
如果第一次投掷的结果是 2,3或 12,那么这个玩家就输了(即庄家获胜)。
如果第一次投掷的结果是 4,5,6,8,9或 10,那么这个和就是该玩家的
“点数”。
为了获胜,玩家必须继续掷骰子,直到“掷出了点数”。在掷出点数之前,
如果玩家掷出了 7,那么玩家就输了。
Examples
目 录第六讲 函数程序设计举例
Examples
Example,Functions(cw06-11.c)
– 设计
定义一个函数 rollDice,用来模拟掷一次骰子
– 产生两个随机数,返回它们的和(点数)
算法
Examples
目 录第六讲 函数掷第一次胜 输 掷一次胜 输

程序设计举例
Examples
Example,Functions(cw06-11.c)
– 设计
定义一个变量保存游戏进展的状态 gamestatus
– 0:失败
– 1:胜利
– 2:第一次掷就失败
算法
Examples
目 录第六讲 函数
rollDice
End?
rollDice
End?
N N
Y
Y
Win or fail
程序设计举例
Examples
Example,Functions(cw06-11.c)
Examples
目 录第六讲 函数
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int rollDice(void);
void main() {
int gameStatus,sum,myPoint;
srand(time(NULL));
sum = rollDice();
程序设计举例
Examples
Example,Functions(cw06-11.c)
Examples
目 录第六讲 函数
switch(sum) {
case 7,case 11:
gameStatus = 1;
break;
case 2,case 3,case 12:
gameStatus = 2;
break;
default:
gameStatus = 0;
myPoint = sum;
printf("Point is %d\n",myPoint);
break;
}
程序设计举例
Examples
Example,Functions(cw06-11.c)
Examples
目 录第六讲 函数
while (gameStatus == 0) {
sum = rollDice();
if (sum == myPoint)
gameStatus = 1;
else
if (sum == 7)
gameStatus = 2;
}
if (gameStatus == 1)
printf("You wins!");
else
printf("You loses!");
}
程序设计举例
Examples
Example,Functions(cw06-11.c)
Examples
目 录第六讲 函数
int rollDice() {
int dice1,dice2,sum;
dice1 = rand()%6 + 1;
dice2 = rand()%6 + 1;
sum = dice1 + dice2;
printf("You rolled %d + %d = %d\n",dice1,dice2,sum);
return sum;
}
第七讲 数组与字符串
Arrays and Strings
PROGRAM DESIGN IN C LANGUAGE
目 录
7.2 数组
Arrays
7.3 查找与排序
Searching and sorting
7.4 多维数组
Multiplr subscripted arrays
7.5 字符串
Strings
7.1 简介
Introduction
简介
Introduction
Arrays(数组)
– Data Structures of related data items
– Static entity(静态实体)
same size throughout program
Introduction
目 录第七讲 数组与字符串
65 72 83 79 97 87 79 57 … 78
数组
Arrays
数组( Array)
– 在内存中数组占有一段连续的存储空间
– 保存一组有序数据
数组中的每一个数称为 数组元素 ( element)
数组元素都属于同一个数据类型
数组元素的数目是固定且有限的
– 引用数组元素的格式
arrayname[position-number]
第一个位置编号( 下标 )是 0
数组 c 的 n 个元素如图所示
Ayrrays
目 录第七讲 数组与字符串
-45
6
0
72
1543
-89
0
62
-3
1
6453
78
c[6]
c[0]
c[1]
c[2]
c[3]
c[11]
c[10]
c[9]
c[8]
c[7]
c[5]
c[4]
c
数组
Arrays
数组( Array)
– 数组元素都是普通变量
– 下标可以是整型常量和整型表达式
Ayrrays
目 录第七讲 数组与字符串
-45
6
0
72
1543
-89
0
62
-3
1
6453
78
c[6]
c[0]
c[1]
c[2]
c[3]
c[11]
c[10]
c[9]
c[8]
c[7]
c[5]
c[4]
c
c[0] = 3;
scanf(“%d”,&c[1]);
printf(“%d”,c[1]);
若 x = 3,那么
c[5-2] == c[3] == c[x]
定义数组
Defining Arrays
定义数组的格式
arrayType arrayName[numberOfElements]
数组类型 数组名 元素个数(数组长度)
– 数组长度必须是一个整型常量或常量表达式
Ayrrays
目 录第七讲 数组与字符串
#define MAX 200;
int c[12];
float f[1000];
int b[MAX],c[MAX*10];
int n,m=5,d[m];
scanf(“%d”,&n);
int c[n];
数组的初始化
Arrays Inilialization
数组的初始化
arrayType arrayName[numberOfElements] = {valueList};
初值表
如果数据表中的数据太多,产生语法错误( syntax error)
剩下的元素的初值是 0
数组的长度就是初值表中数值的个数
Ayrrays
目 录第七讲 数组与字符串
int a[5] = {1,2,3,4,5};
int a[5] = {1};
int a[ ] = {1,2,3,4,5};
数组的初始化的说明
Notes For Arrays Inilialization
数组的初始化说明
– 初值表不能为空
– 没有初始化的数组,其元素的值不确定
Ayrrays
目 录第七讲 数组与字符串
int a[5] = { };
int a[5]={1};
for (i=0;i<5;i++)
printf(,%d”,a[i]);
int a[5];
for (i=0;i<5;i++)
printf(,%d”,a[i]);
1 0 0 0 0 872 0 1492 4160 186
不可预知使用数组
Using Arrays
Example,Using Arrays(cw07-01.c)
– 从一个数组中读取数字,并以直方图的形式显示信息
Ayrrays
目 录第七讲 数组与字符串
#include <stdio.h>
#define SIZE 10
void main() {
int n[SIZE] = {19,2,15,7,11,9,13,5,17,1};
int i,j;
用一系列 ‘ *’ 来代替长方形
**************
***
*******
使用数组
Using Arrays
Example,Using Arrays(cw07-01.c)
Ayrrays
目 录第七讲 数组与字符串
printf("%s%13s%17s\n","Element","Value","Histogram");
for (i=0; i<=SIZE-1; i++) {
printf("%7d%13d",i,n[i]);
for (j=1; j<=n[i]; j++)
printf("%c",'*');
printf("\n");
}
}
使用数组
Using Arrays
Example,Using Arrays(cw07-01.c)
– 运行结果
Ayrrays
目 录第七讲 数组与字符串
Element Value Histogram
0 19 *******************
1 3 ***
2 15 ***************
3 7 *******
4 11 ***********
5 9 *********
6 13 *************
7 5 *****
8 17 *****************
9 1 *
使用数组
Using Arrays
Example,Using Arrays(cw07-02a.c)
– 统计全班 32名同学某门功课的平均成绩,找出最高分
把学生成绩保存到数组 score
Ayrrays
目 录第七讲 数组与字符串
#include <stdio.h>
#define MAX 10
void main()
{ float score[MAX],sum,best;
int i;
printf("Input %d scores:\n",MAX);
for (i=0; i<MAX; i++)
scanf("%f",&score[i]);
保存最好成绩使用数组
Using Arrays
Example,Using Arrays(cw07-02a.c)
Ayrrays
目 录第七讲 数组与字符串
sum=best=score[0];
for (i=1;i<MAX;i++)
{ sum+=score[i];
if (best<score[i])
best=score[i];
}
printf("The average:%.1f\n",sum/MAX);
printf("The best:%.1f\n",best);
}
#include <stdio.h>
#define MAX 10
void main()
{ float score[MAX],sum;
int i,best;
printf("Input %d scores:\n",MAX);
for (i=0; i<MAX; i++)
scanf("%f",&score[i]);
使用数组
Using Arrays
Example,Using Arrays(cw07-02b.c)
– 统计全班 32名同学某门功课的平均成绩,找出最高分
使用位置指针
Ayrrays
目 录第七讲 数组与字符串保存最好成绩在数组中的位置
65 72 83 79 97 87 79 57 91 78
位置指针使用数组
Using Arrays
Example,Using Arrays(cw07-02b.c)
Ayrrays
目 录第七讲 数组与字符串
sum=score[0];
best=0;
for (i=1; i<MAX; i++)
{ sum+=score[i];
if (score[best]<score[i])
best=i;
}
printf("The average:%.1f\n",sum/MAX);
printf("The best:%.1f\n",score[best]);
}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 7
void main() {
int face,roll,frequency[SIZE]={0};
srand(time(NULL));
使用数组
Using Arrays
Example,Using Arrays(cw07-03.c)
– 把一个六面的骰子掷 6000次,统计每一面出现的次数
用 frequency[6]数组保存六个面出现的次数
Ayrrays
目 录第七讲 数组与字符串初始化数组,为所有指定初值 0
frequency[1],…,frequency[6]
for (roll=1; roll<=1000; roll++) {
face = rand()%6+1;
frequency[face]++;
}
printf("%s%17s\n","Face","Frequency");
for (face=1; face<=SIZE-1; face++)
printf("%4d%17d\n",face,frequency[face]);
}
使用数组
Using Arrays
Example,Using Arrays(cw07-03.c)
Ayrrays
目 录第七讲 数组与字符串使用数组
Using Arrays
Example,Using Arrays(cw07-04.c)
– 把一个任意的正整数 N 转换成 d 进制数
用 N 除以 d,
如果商不为 0,继续用商除以 d,直到商为 0
用数组 remainder 保存每一步的余数
Ayrrays
目 录第七讲 数组与字符串
N N/8 N%8
1348 168 4
168 21 0
21 2 5
2 0 2
#include <stdio.h>
#define MAX 10
void main() {
int N,d,len;
int remainder[MAX];
printf("Input a decimal integer and a base:");
scanf("%d%d",&N,&d);
printf("Converting...\n");
使用数组
Using Arrays
Example,Using Arrays(cw07-04.c)
Ayrrays
目 录第七讲 数组与字符串
len=0;
while (N) {
len++;
remainder[len]=N%d;
N=N/d;
}
printf("equals ");
for (;len>0;len--) printf("%d",remainder[len]);
}
使用数组
Using Arrays
Example,Using Arrays(cw07-04.c)
Ayrrays
目 录第七讲 数组与字符串把数组传递给函数
Passing Arrays to Functions
把数组作为参数传递给函数
实参用数组名
通常要把数组的长度传递给函数
– 对应的函数定义
实参与形参的类型相同
可以不指定形参数组长度
– 函数原型的特殊形式
Passing Ayrrays To Functions
目 录第七讲 数组与字符串
int myArray[20];
myFunction(myArray,20);
void myFunction(int array[],int arraySize) {
}
void myFunction(int [],int);
把数组传递给函数
Passing Arrays to Functions
把数组作为实参传递给函数
– 数组的传递模拟了引用传递( call-by-reference)
Passing Ayrrays To Functions
目 录第七讲 数组与字符串
void bubble_sort(int array[ ],int len) {…}
main() {
int list[10];

bubble_sort(list,10);
}
list[0]
list[1]
list[2]

list[9]
FF00
FF00
list
FF00
array
数组名是数组第一个元素的地址所以,依然是按值传递(传递的是地址)
把数组传递给函数
Passing Arrays to Functions
把数组作为实参传递给函数
– 数组名是一个指针变量,保存的是数组第一个元素的地址 ( cw07-05.c)
Passing Ayrrays To Functions
目 录第七讲 数组与字符串
#include <stdio.h>
void main() {
int array[10];
printf("array = %p\n"
"&array[0] = %p\n",
array,&array[0]);
}
array = 19b8
&array[0] = 19b8
%p
输出地址的格式说明字符
printf的格式控制字符串可以分多行写,
但每一行必须用“”
括起来把数组传递给函数
Passing Arrays to Functions
把数组元素传递给函数
– 数组元素就是一个普通的变量
– 按值传递( call-by-value)
Example,Passing arrays and elements to functions
– ( cw07-06.c)
Passing Ayrrays To Functions
目 录第七讲 数组与字符串
#include <stdio.h>
void modifyArray(int [],int);
void modifyElement(int);
void main() {
int a[] = {0,1,2,3,4},i;
把数组传递给函数
Passing Arrays to Functions
Example:( cw07-06.c)
Passing Ayrrays To Functions
目 录第七讲 数组与字符串
printf("\nThe values of the original array are:\n");
for (i=0;i<SIZE;i++)
printf(" %d",a[i]);
modifyArray(a,5);
printf("\nThe values of the modified array are:\n");
for (i=0;i<5;i++)
printf(" %d",a[i]);
printf("\nThe value of a[3] is %d",a[3]);
modifyElement(a[3]);
printf("\nThe value of a[3] is %d",a[3]);
}
把数组传递给函数
Passing Arrays to Functions
Example:( cw07-06.c)
Passing Ayrrays To Functions
目 录第七讲 数组与字符串
void modifyArray(int array[],int size) {
int j;
for (j=0;j<size;j++)
array[j] *= 2;
}
void modifyElement(int e) {
printf("\nValue in modifyElement is %d",e *= 2);
}
把数组传递给函数
Passing Arrays to Functions
Example:( cw07-06.c)
Passing Ayrrays To Functions
目 录第七讲 数组与字符串
The values of the original array are:
0 1 2 3 4
The values of the modified array are:
0 2 4 6 8
The value of a[3] is 6
Value in modifyElement is 12
The value of a[3] is 6
查找
Searching
查找
– 查找数组中的特定元素( key value)
– 常用方法
顺序查找( sequential searching)
折半查找( binary searching)
Searching Arrays
目 录第七讲 数组与字符串顺序查找
Sequential Searching
顺序查找
– 用关键字与数组的每个元素进行比较
– 适用于小型和(或)没有排序的数组
平均而言,要与数组的一半元素进行比较
Sequential Searching
目 录第七讲 数组与字符串
65 72 83 79 97 87 79 57 91 78
87
顺序查找
Sequential Searching
Example,Sequential searching( cw07-07.c)
Sequential Searching
目 录第七讲 数组与字符串
#define N 10
void main() {
int list[N+1]={0,65,72,83,79,97,87,75,57,91,78};
int key,i;
printf("Input search key:");
scanf("%d",&key);
for (i=1;(list[i]!=key)&&(i<=N);i++);
if (i>N) printf("Not found!");
else printf("Success! The position is %d.",i);
}
折半查找
Binary Searching
折半查找
– 用于已经排好序的数组
– 用数组的中间元素与关键字比较
如果相等,则查找成功
如果 key<middle,则查找前半部分
如果 key>middle,则查找后半部分
重复上述步骤
Binary Searching
目 录第七讲 数组与字符串
57 65 72 75 78 79 83 87 91 97
83
low mid high
折半查找
Binary Searching
Example,Binary searching( cw07-08.c)
Binary Searching
目 录第七讲 数组与字符串
#include <stdio.h>
#define N 10
void main()
{ int i,low,mid,high,key,found;
int list[N+1]={0,57,65,72,75,78,79,83,87,91,97};
printf("Sorted list:\n");
for (i=1;i<=N;i++) printf("%-4d",list[i]); printf("\n");
printf("Input search key:");
scanf("%d",&key);
折半查找
Binary Searching
Example,Binary searching( cw07-08.c)
Binary Searching
目 录第七讲 数组与字符串
low=1;
high=N;
found=0;
while ((low<=high) && (! found)) {
mid=(low+high)/2;
if (key>list[mid]) low=mid+1;
else if (key==list[mid]) found=1;
else high=mid-1;
}
if (found) printf("Success! The position is %d.",mid);
else printf("Not found!");
}
排序
Sorting
排序
– 数据排序(按特定的顺序来安排数据)是最重要的计算应用之一
– 实际上,每个组织都必须排列某些数据
– 常用方法
直接插入排序( directive insert sorting)
简单选择排序( simple selection sorting)
冒泡排序( bubble sorting)
Sorting Arrays
目 录第七讲 数组与字符串数据插入
Insert Data
数据插入
– 把一个数据插入到已排好序的有序表中,从而得到一个新的、长度增 1
的有序表
Directive Insert Sorting
目 录第七讲 数组与字符串
57 65 72 75 78 79 87 91 97
83
57 65 72 75 78 79 83 87 91 97
57 65 72 75 78 79 87 91 97
数据插入
Insert Data
Example,Inserting data
– ( cw07-09.c)
Directive Insert Sorting
目 录第七讲 数组与字符串
#include <stdio.h>
#define N 20
void main()
{ int i,j,x,len=9;
int list[N]={57,65,72,75,78,79,87,91,97};
printf("Sorted list:\n");
for (i=0;i<len;i++) printf("%-4d",list[i]); printf("\n");
printf("Input a integer to be inserted into the list:");
scanf("%d",&x);
数据插入
Insert Data
Example,Inserting data
– ( cw07-09.c)
Directive Insert Sorting
目 录第七讲 数组与字符串
for (i=0;(x>list[i])&&(i<len);i++);
for (j=len;j>i;j--) list[j]=list[j-1];
list[i]=x;
len++;
printf("The new list:\n");
for (i=0;i<len;i++) printf("%-4d",list[i]); printf("\n");
}
找到插入点
“腾出位子”
插入数据直接插入排序
Directive Insert Sorting
直接插入排序
Directive Insert Sorting
目 录第七讲 数组与字符串
(78) 45 25 31 13 66 92 8初始状态
(45 78) 25 31 13 66 92 8插入第 2个数
(25 45 78) 31 13 66 92 8插入第 3个数
(8 13 25 31 45 66 78 92)插入最后一个数
……
直接插入排序
Directive Insert Sorting
Example,directive insert sorting
– ( cw07-10.c)
Directive Insert Sorting
目 录第七讲 数组与字符串
#include <stdio.h>
#define N 10
void main()
{ int i,j,k,len;
int list[N],x;
printf("Input several integers to construct a list:");
scanf("%d",&len);
for (i=0;i<len;i++) scanf("%d",&list[i]);
printf("OK! The list has been constructed:\n");
for (i=0;i<len;i++) printf("%-4d",list[i]);
直接插入排序
Directive Insert Sorting
Example,directive insert sorting
– ( cw07-10.c)
Directive Insert Sorting
目 录第七讲 数组与字符串
printf("\nTo sort...\n");
for (i=1;i<len;i++) {
x=list[i];
for (j=0;(list[i]>list[j])&&(j<i);j++);
for (k=i;k>j;k--) list[k]=list[k-1];
list[j]=x;
}
printf("Finished! The list has been sorted:\n");
for (i=0;i<len;i++) printf("%-4d",list[i]);
}
冒泡排序
Bubble Sorting
冒泡排序
– 将相邻两个数比较,把小的调到前面,大数放到后面。
Bubble Sorting
目 录第七讲 数组与字符串
78
45
32
10
29
80
92
8
61
55
45
78
32
10
29
80
92
8
61
55
45
32
78
10
29
80
92
8
61
55
45
32
10
78
29
80
92
8
61
55
45
32
10
29
78
80
92
8
61
55
45
32
10
29
78
80
92
8
61
55
45
32
10
29
78
80
92
8
61
55
45
32
10
29
78
80
8
92
61
55
45
32
10
29
78
80
8
61
92
55
45
32
10
29
78
80
8
61
55
92
32
10
29
45
78
8
61
55
80
92
10
29
32
45
8
61
55
78
80
92

8
10
29
32
45
55
61
78
80
92
小数大数
N-1 趟冒泡排序
Bubble Sorting
Example,Bubble sorting
– ( cw07-11.c)
Bubble Sorting
目 录第七讲 数组与字符串
#include <stdio.h>
#define N 10
void main()
{ int i,j,len;
int list[N],tmp;
printf("Input several integers to construct a list:");
scanf("%d",&len);
for (i=0;i<len;i++) scanf("%d",&list[i]);
printf("OK! The list has been constructed:\n");
for (i=0;i<len;i++) printf("%-4d",list[i]);
冒泡排序
Bubble Sorting
Example,Bubble sorting
– ( cw07-11.c)
Bubble Sorting
目 录第七讲 数组与字符串
printf("\nTo sort...\n");
for (i=0;i<len-1;i++)
for (j=0;j<len-i-1;j++)
if (list[j]>list[j+1]) {
tmp=list[j]; list[j]=list[j+1]; list[j+1]=tmp;
}
printf("Finished! The list has been sorted:\n");
for (i=0;i<len;i++) printf("%-4d",list[i]);
}
简单选择排序
Simple Selection Sorting
简单选择排序
Simple Selection Sorting
目 录第七讲 数组与字符串
78 45 25 31 13 66 92 8初始状态
(8) 78 45 31 25 66 92 13找到最小数
(8 13) 78 45 31 66 92 25找到第二小的数
(8 13 25 31 45 66 78 92)最大数被找到
……
一趟简单选择排序的操作:通过 n-i次数据间的比较,从 n-i+1个记录中选出最小的数,并和第 i个数交换。
简单选择排序
Simple Selection Sorting
Example,Simple selection sorting
– ( cw07-12.c)
Simple Selection Sorting
目 录第七讲 数组与字符串
#include <stdio.h>
#define N 10
void main()
{ int i,j,len,min;
int list[N],tmp;
printf("Input several integers to construct a list:");
scanf("%d",&len);
for (i=0;i<len;i++) scanf("%d",&list[i]);
printf("OK! The list has been constructed:\n");
for (i=0;i<len;i++) printf("%-4d",list[i]);
简单选择排序
Simple Selection Sorting
Example,Simple selection sorting
– ( cw07-12.c)
Simple Selection Sorting
目 录第七讲 数组与字符串
printf("\nTo sort...\n");
for (i=0;i<len-1;i++) {
min=i;
for (j=i+1;j<len;j++)
if (list[min]>list[j]) min=j;
tmp=list[i]; list[i]=list[min]; list[min]=tmp;
}
printf("Finished! The list has been sorted:\n");
for (i=0;i<len;i++) printf("%-4d",list[i]);
}
多维数组
Multiple-Subscripted Arrays
多维数组
– 一个有行号和列号的表
矩阵或行列式
– Example
int a[3][4];
MULTIPLE-SUBSCRIPTED ARRAYS
目 录第七讲 数组与字符串
Row 0
Row 1
Row 2
Column 0 Column 1 Column 2 Column 3
a[0][0]
a[1][0]
a[2][0]
a[0][1]
a[1][1]
a[2][1]
a[0][2]
a[1][2]
a[2][2]
a[0][3]
a[1][3]
a[2][3]
Row subscript
Array name
Column subscript
多维数组的定义
Multiple-Subscripted Arrays? Definition
定义多维数组的格式
type-name array-name[row-number][column-number];
类型名 数组名 常量表达式 常量表达式
– Example
MULTIPLE-SUBSCRIPTED ARRAYS
目 录第七讲 数组与字符串
int a[3][3],b[30][3];
char name[30][20];
float score[30][5];
a[3][3]
二维数组可以看作是由一维数组组成的数组,即数组元素是一维数组的一维数组。
a[0] a[0][0] a[0][1] a[0][2]
a[1] a[1][0] a[1][1] a[1][2]
a[2] a[2][0] a[2][1] a[2][2]
引用多维数组的元素
Referencing Multiple-Subscripted Arrays? Elements
引用多维数组的元素的格式
array-name[row-subscript][column-subscript];
数组名 行下标 列下标
– Example
MULTIPLE-SUBSCRIPTED ARRAYS
目 录第七讲 数组与字符串
int a[3][4];
for (m=0;m<3;m++)
for (n=0;n<4;n++)
a[m][n]=m*n;
多维数组的存储形式
Multiple-Subscripted Arrays? Storage
二维数组的存储形式
– 二维数组的元素是按行顺序存放的
– Example
int a[2][3];
MULTIPLE-SUBSCRIPTED ARRAYS
目 录第七讲 数组与字符串
a[0][0] a[0][1] a[0][2]
a[1][0] a[1][1] a[1][2]
12
32
-1
87
0
53
a[0][0]
a[0][1]
a[0][2]
a[1][0]
a[1][1]
a[1][2]
a
数组 a 的存储形式多维数组的初始化
Multiple-Subscripted Arrays? Initialization
二维数组的初始化
– 四种方式:
给全部元素赋初值
给部分元素赋初值
给全部元素赋初值时,不指定第一维的长度,但要指定第二维的长度
给部分元素赋初值时,不指定第一维的长度,但要指定第二维的长度
MULTIPLE-SUBSCRIPTED ARRAYS
目 录第七讲 数组与字符串多维数组的初始化
Multiple-Subscripted Arrays? Initialization
二维数组的初始化
– 给全部元素赋初值
MULTIPLE-SUBSCRIPTED ARRAYS
目 录第七讲 数组与字符串
int a[2][3]={{10,11,12},{13,14,15}};
int a[2][3]={10,11,12,13,14,15};
a[0][0] a[0][1] a[0][2]
10 11 12
a[1][0] a[1][1] a[1][2]
13 14 15
用括号按行分组多维数组的初始化
Multiple-Subscripted Arrays? Initialization
二维数组的初始化
– 给部分元素赋初值
MULTIPLE-SUBSCRIPTED ARRAYS
目 录第七讲 数组与字符串
int a[2][3]={{10,11},{13}};
a[0][0] a[0][1] a[0][2]
10 11 0
a[1][0] a[1][1] a[1][2]
13 0 0
int a[2][3]={10,11,13};
a[0][0] a[0][1] a[0][2]
10 11 13
a[1][0] a[1][1] a[1][2]
0 0 0
没有明确初始化的元素被自动初始化多维数组的初始化
Multiple-Subscripted Arrays? Initialization
二维数组的初始化
– 给全部元素赋初值时,不指定第一维的长度,但要指定第二维的长度
MULTIPLE-SUBSCRIPTED ARRAYS
目 录第七讲 数组与字符串
int a[ ][3]={{10,11,12},{13,14,15}};
int a[ ][3]={10,11,12,13,14,15};
a[0][0] a[0][1] a[0][2]
10 11 12
a[1][0] a[1][1] a[1][2]
13 14 15
多维数组的初始化
Multiple-Subscripted Arrays? Initialization
二维数组的初始化
– 给部分元素赋初值时,不指定第一维的长度,但要指定第二维的长度
MULTIPLE-SUBSCRIPTED ARRAYS
目 录第七讲 数组与字符串
int a[ ][3]={{10,11},{13}};
a[0][0] a[0][1] a[0][2]
10 11 0
a[1][0] a[1][1] a[1][2]
13 0 0
多维数组的应用举例
Examples,Multiple-Subscripted Arrays
Example,Multiple-Subscripted Arrays
– 将一个二维数组行和列元素互换,存到另一个二维数组中
MULTIPLE-SUBSCRIPTED ARRAYS
目 录第七讲 数组与字符串
654 321a
63
52
41
b
b的第 i行第 j列的元素等于
a的第 j行第 i列的元素
for(i=0;i<3;i++)
for(j=0;j<2;j++)
b[i][j] = a[j][i]
多维数组的应用举例
Examples,Multiple-Subscripted Arrays
Example,Multiple-Subscripted Arrays
– ( ca07-13.c)
MULTIPLE-SUBSCRIPTED ARRAYS
目 录第七讲 数组与字符串
#include <stdio.h>
void main() {
int a[2][3]={1,2,3,4,5,6},b[3][2];
int i,j;
printf("matrix a is:\n");
for (i=0; i<2; i++) {
for (j=0; j<3; j++) {
b[j][i] = a[i][j];
printf("%3d",a[i][j]);
}
printf("\n");
}
多维数组的应用举例
Examples,Multiple-Subscripted Arrays
Example,Multiple-Subscripted Arrays
– ( ca07-13.c)
MULTIPLE-SUBSCRIPTED ARRAYS
目 录第七讲 数组与字符串
printf("matrix b is:\n");
for (i=0; i<3; i++) {
for (j=0; j<2; j++)
printf("%3d",b[i][j]);
printf("\n");
}
}
matrix a is:
1 2 3
4 5 6
matrix b is:
1 4
2 5
3 6
多维数组的应用举例
Examples,Multiple-Subscripted Arrays
Example,Multiple-Subscripted Arrays
– 有一个 3× 4的矩阵,找出每行元素中的最大值,并使该值成为该行的首列元素
– 分析
对每行元素从右往左相邻两数作比较,大数调到左边
MULTIPLE-SUBSCRIPTED ARRAYS
目 录第七讲 数组与字符串
3579
6857
4321
利用从冒泡法排序算法中得到的经验多维数组的应用举例
Examples,Multiple-Subscripted Arrays
Example,Multiple-Subscripted Arrays
– ( ca07-14.c)
MULTIPLE-SUBSCRIPTED ARRAYS
目 录第七讲 数组与字符串
……
for (i=0; i<3; i++)
for (j=3; j>0; j--)
if (num[i][j]>num[i][j-1]) {
tmp = num[i][j];
num[i][j] = num[i][j-1];
num[i][j-1] = tmp;
}
……
把多维数组传递给函数
Passing Multiple-Subscripted Arrays To Functions
把多维数组传递给函数
– 数组元素作为函数的实参
值传递
– 多维数组名作为函数的实参
模拟引用传递
MULTIPLE-SUBSCRIPTED ARRAYS
目 录第七讲 数组与字符串
void exchange(int a[][3],int b[][2],int m,int n);
void main() {
int a[2][3],b[3][2];

exchange(a,b);

}
第 1括号可以为空,其他下标必须指定字符串
Strings
Characters(字符)
– Character constant
An int value represented as a character in single quotes
'z' represents the integer value of z
Strings(字符串)
– Series of characters treated as a single unit
Can include letters,digits and special characters (*,/,$)
– String constant
written in double quotes
"Hello"
STRINGS
目 录第七讲 数组与字符串字符串的定义
Strings? Definition
在 C语言中,字符串是用空字符( ’ \0’)结束的字符数组
STRINGS
目 录第七讲 数组与字符串
char name[20];
char names[30][20];

name
字符串名就是该字符数组第一个元素的地址字符数组的初始化
Character Arrays? Initialization
给字符数组的全部元素赋初值
STRINGS
目 录第七讲 数组与字符串
char a[5]={?C?,?h?,?i?,?n?,?a?};
a[0] a[1] a[2] a[3] a[4]
China?
字符数组的初始化
Character Arrays? Initialization
给字符数组的部分元素赋初值
STRINGS
目 录第七讲 数组与字符串
char a[5]={?C?,?h?,?i?};
a[0] a[1] a[2] a[3] a[4]
Chi\0\0?
缺省的初值为 ‘ \0?
字符数组的初始化
Character Arrays? Initialization
给全部元素赋初值时,可以不指定长度
STRINGS
目 录第七讲 数组与字符串
char a[ ]={?C?,?h?,?i?,?n?,?a?};
a[0] a[1] a[2] a[3] a[4]
China?
char a[5]={?C?,?h?,?i?,?n?,?a?};
char a[ ] = {“China”};
char a[ ] =,China”;
字符数组的初始化
Character Arrays? Initialization
用字符串常量给字符数组赋初值
STRINGS
目 录第七讲 数组与字符串
char a[6] = {“China”};
char a[6] =,China”;
a[0] a[1] a[2] a[3] a[4] a[5]
China\0? 来自字符串常量的结束字符 ‘ \0? 。
字符串的输入输出
Strings? Input/Output
有以下方式:
– 逐个字符输入输出
%c
– 作为整体一次输入输出
%s
– 用字符串输入输出函数
gets
puts
STRINGS
目 录第七讲 数组与字符串字符串的输入输出
Strings? Input/Output
用 %c逐个字符的输入输出
– ( cw07-15.c)
STRINGS
目 录第七讲 数组与字符串
#include <stdio.h>
#define MAX 5
void main() {
int n;
char c[MAX];
printf("Input %d characters:\n",MAX);
for (n=0;n<MAX;n++)
scanf("%c",&c[n]);
printf("Show the %d characters:\n",MAX);
for (n=0;n<MAX;n++)
printf("%c",c[n]);
}
字符串的输入输出
Strings? Input/Output
用 %s实现字符串作为整体一次性的输入输出
– ( cw07-16.c)
STRINGS
目 录第七讲 数组与字符串
#include <stdio.h>
#define MAX 5
void main() {
char c[MAX];
printf("Input c[%d]:\n",MAX);
scanf("%s",c);
printf("Show c:\n");
printf("%s",c);
}
输入和输出项都是数组名
在输入时,空格、制表符和换行符都被作为字符串的分隔符,不被读入
在输出时,一旦遇到 ‘ \0?
就结束字符串的输入输出
Strings? Input/Output
用标准库提供的输入输出函数
– ( cw07-17.c)
STRINGS
目 录第七讲 数组与字符串
#include <stdio.h>
#define MAX 5
void main() {
char c[MAX];
printf("Input c[%d]:\n",MAX);
gets(c);
printf("Show c:\n");
puts(c);
}
在输入时,换行符被作为数据的分隔符,不被读入
但是,空格和制表符可以被读入字符和字符串处理库
Character And String Handling Library
字符处理库,<ctype.h>
– 字符的检测和处理函数字符串处理库,<string.h>
– 字符串处理函数
strcat(string1,string2)
strcpy(string1,string2)
strcmp(string1,string2)
strlen(string)
strlwr(string)
strupr(string)
字符串转换库,<stdlib.h>( general utilities lib)
– 把数字字符串转换成整数和浮点数
STRINGS
目 录第七讲 数组与字符串字符串应用举例
Examples,String Handling
Example,String Handling
– 输入一行字符,统计其中有多少个单词,单词之间用空格隔开
STRINGS
目 录第七讲 数组与字符串
I a m f r o m … \0
算法:
逐一检测字符,遇到第一个非空格字符即为一个单词的开始,再次遇到空格就表示最新的单词结束定义一个标记变量记住当前字符的前一个字符(最近检测的)是否是空格字符串应用举例
Examples,String Handling
Example,String Handling
定义标记变量 word
– 0
最近检测的字符是空格
期待新单词出现
– 1
最近检测的字符不是空格
正在检测单词
期待单词的结束
STRINGS
目 录第七讲 数组与字符串
i=0
word=0
c=s[i]!=?\0?
c==
word=0
i++
word==0
word=1
num++
N
Y
N
YN
Y
字符串应用举例
Examples,String Handling
Example,String Handling
– ( cw07-18.c)
STRINGS
目 录第七讲 数组与字符串
#include <stdio.h>
void main()
{ char c,s[81];
int i,num,word;
printf("Input a sentence:\n");
gets(s);
字符串应用举例
Examples,String Handling
Example,String Handling
– ( cw07-18.c)
STRINGS
目 录第七讲 数组与字符串
num=word=i=0;
while ((c=s[i])!='\0') {
if (c==' ') word=0;
else if (word==0) {
word=1;
num++;
}
i++;
}
printf("There are %d words in this sentence.\n",num);
}
扩展:
输出这些单词
统计每个单词出现的次数字符串应用举例
Examples,String Handling
Example,String Handling
– 任意输入两个字符串,将它们连接成一个字符串,不使用 strcat函数
STRINGS
目 录第七讲 数组与字符串
a b c \0 x y z \0
a b c x y z \0
字符串应用举例
Examples,String Handling
Example,String Handling
– ( cw07-19.c)
STRINGS
目 录第七讲 数组与字符串
#include <stdio.h>
void main() {
char str1[81],str2[81],str[161];
int i,j;
printf("Input two strings:\n");
gets(str1);
gets(str2);
for(i=0;str1[i]!='\0';i++) str[i]=str1[i];
for(j=0;str2[j]!='\0';i++,j++) str[i]=str2[j];
str[i]='\0';
printf("\nNow,you get a new string:\n%s\n",str);
}
字符串应用举例
Examples,String Handling
Example,String Handling
– 输入一字符串,内有若干个字符,再输入一个字符,要求程序将字符串中该字符删去
STRINGS
目 录第七讲 数组与字符串
w u h a n d a \0
w u h a n d a \0
读写
char str[81]
字符串应用举例
Examples,String Handling
Example,String Handling
– ( cw07-20.c)
STRINGS
目 录第七讲 数组与字符串
#include <stdio.h>
void main() {
void delLetter(char str[],char c);
char str[81],c;
printf("Input a string:\n"); gets(str);
printf("Input a letter:\n"); c=getchar();
delLetter(str,c);
printf("Delete all \'%c\' from the string.\n",c);
printf("The string:\n");
puts(str);
}
字符串应用举例
Examples,String Handling
Example,String Handling
– ( cw07-20.c)
STRINGS
目 录第七讲 数组与字符串
void delLetter(char str[81],char c) {
int i,j;
for (i=j=0;str[i]!='\0';i++)
if (str[i]!=c) {
str[j]=str[i];
j++;
}
str[j]='\0';
}
程序设计举例
Programming Examples
Example,TicTacToe
– 写程序实现“井”字棋游戏。
–,井”字棋游戏规则:
每次一方只能在某一个空格处下一颗棋子
胜负判断:
– 若棋盘的某一行,或某一列,抑或某一对角线上的三个格子被某一方的棋子占据,则该方胜利;
– 否则,为平局
PROGRAMMING EXAMPLES
目 录第七讲 数组与字符串程序设计举例
Programming Examples
Example,TicTacToe
– 过程分析:
PROGRAMMING EXAMPLES
目 录第七讲 数组与字符串玩家胜利计算机胜利初始化棋盘玩家下一颗棋子胜利?
计算机下一颗棋子胜利?
Y
Y
N
N
怎么表示?
怎么判断?
计算机如何决策?
程序设计举例
Programming Examples
Example,TicTacToe
– 功能分解:
PROGRAMMING EXAMPLES
目 录第七讲 数组与字符串玩家胜利计算机胜利初始化棋盘玩家下一颗棋子胜利?
计算机下一颗棋子胜利?
Y
Y
N
N
初始化棋盘显示棋盘玩家走一步判断胜负计算机走一步判断胜负程序设计举例
Programming Examples
Example,TicTacToe
– 模块划分:
PROGRAMMING EXAMPLES
目 录第七讲 数组与字符串初始化棋盘,init_matrix()
显示棋盘,disp_matrix()
玩家走一步,get_player_move()
判断胜负,check()
计算机走一步,get_computer_move()
main
程序设计举例
Programming Examples
Example,TicTacToe
– 数据结构:
棋盘
PROGRAMMING EXAMPLES
目 录第七讲 数组与字符串
3*3的二维字符数组:
char matrix[3][3];
全局变量。
玩家的棋子用‘ X?表示;
计算机的棋子用‘ O?表示;
‘ ’表示空。
一步棋棋子的位置:一对坐标程序设计举例
Programming Examples
Example,TicTacToe
– ( tictac.c)
PROGRAMMING EXAMPLES
目 录第七讲 数组与字符串
char matrix[3][3]; /* the ticktacktoe matrix */
void main(void) {
char done;
printf("This is the game of ticktacktoe.\n");
printf("You will be playing against the computer.\n");
done = ' ';
init_matrix(); done
保存当前游戏的状态和结局程序设计举例
Programming Examples
Example,TicTacToe
– ( tictac.c)
PROGRAMMING EXAMPLES
目 录第七讲 数组与字符串
do {
disp_matrix();
get_player_move();
done = check(); /* see if winner */
if (done != ' ') break; /* winner! */
get_computer_move();
done = check(); /* see if winner */
} while (done == ' ');
if (done == 'X') printf("You won!\n");
else printf("I won!!!!\n");
disp_matrix(); /* show final positions */
}
程序设计举例
Programming Examples
Example,TicTacToe
– ( tictac.c)
PROGRAMMING EXAMPLES
目 录第七讲 数组与字符串
/* Initialize the matrix,*/
void init_matrix(void) {
int i,j;
for (i=0; i<3; i++)
for (j=0; j<3; j++)
matrix[i][j] = ' ';
}
程序设计举例
Programming Examples
Example,TicTacToe
– ( tictac.c)
PROGRAMMING EXAMPLES
目 录第七讲 数组与字符串
/* Get a player's move,*/
void get_player_move(void) {
int x,y;
printf("Enter X,Y coordinates for your move,");
scanf("%d%*c%d",&x,&y);
x--; y--;
if (matrix[x][y] != ' ') {
printf("Invalid move,try again.\n");
get_player_move();
}
else matrix[x][y] = 'X';
}
程序设计举例
Programming Examples
Example,TicTacToe ( tictac.c)
PROGRAMMING EXAMPLES
目 录第七讲 数组与字符串
/* Get a move from the computer,*/
void get_computer_move(void) {
int i,j;
for (i=0; i<3; i++) {
for (j=0; j<3; j++)
if (matrix[i][j] == ' ') break;
if (matrix[i][j] == ' ') break;
}
if (i*j == 9) {
printf("draw\n");
exit(0);
}
else
matrix[i][j] = 'O';
}
程序设计举例
Programming Examples
Example,TicTacToe
– ( tictac.c)
PROGRAMMING EXAMPLES
目 录第七讲 数组与字符串
/* Display the matrix on the screen,*/
void disp_matrix(void) {
int t;
for (t=0; t<3; t++) {
printf(" %c | %c | %c",
matrix[t][0],matrix[t][1],matrix[t][2]);
if (t != 2) printf("\n---|---|---\n");
}
printf("\n");
}
程序设计举例
Programming Examples
Example,TicTacToe
– ( tictac.c)
PROGRAMMING EXAMPLES
目 录第七讲 数组与字符串
/* See if there is a winner,*/
char check(void) {
int i;
for (i=0; i<3; i++) /* check rows */
if (matrix[i][0] == matrix[i][1] &&
matrix[i][0] == matrix[i][2])
return matrix[i][0];
for (i=0; i<3; i++) /* check colums */
if (matrix[0][i] == matrix[1][i] &&
matrix[0][i] == matrix[2][i])
return matrix[0][i];
程序设计举例
Programming Examples
Example,TicTacToe
– ( tictac.c)
PROGRAMMING EXAMPLES
目 录第七讲 数组与字符串
/* test disgonals */
if (matrix[0][0] == matrix[1][1] &&
matrix[1][1] == matrix[2][2])
return matrix[0][0];
if (matrix[0][2] == matrix[1][1] &&
matrix[1][1] == matrix[2][0])
return matrix[0][2];
return ' ';
}
第八讲 指针
Pointers
PROGRAM DESIGN IN C LANGUAGE
目 录
8.2 指针变量
Pointer variables
8.7 指针数组
Arrays of pointers
8.8 指针的指针
Pointers to pointers
8.9 函数指针
Pointers to functions
8.1 简介
Introduction
8.4 指针参数
Pointer arguments
8.3 指针运算符
Pointer operators
8.6 指针与数组
Pointers and arrays
8.5 指针表达式和运算
Pointer expressions and arithmetic
8.10 指针函数
Pointer functions
简介
Introduction
Pointers
– Powerful,but difficult to master
– Simulate call-by-reference
– Close relationship with arrays and strings
– Create and control dynamic data structures
List,queue,stack and tree
THE POINTERS
目 录第八讲 指针指针和地址
Pointers and Addresses
指针就是变量的地址
THE POINTERS
目 录第八讲 指针
int x;
x=23;
内存单元的地址一个常量,就是指向变量的指针。
变量名其实就是符号化的内存单元地址。
内存单元的内容就是变量的值。
FF00 x23
直接引用
Direct reference
通过变量名直接引用变量的值指针变量
Pointer Variables
指针变量就是包含内存地址的变量
THE POINTERS
目 录第八讲 指针
int x=23;
int *x_pointer;
x_pointer=&x;
FF00 x23
FFF0 x_pointerFF00
指针变量
保存变量的地址。
变量 x_pointer 的值是变量
x 的地址(指针)。
目前,指针 x_pointer 指向变量 x 。
间接引用
Indirect reference
通过指针间接引用变量的值指针变量的声明
Pointer Variable Declarations
指针变量的声明
type-name * pointer-variable-name;
* 表示 x_pointer 是一个指针变量
x_pointer 是 int* 类型的指针,读作:
– 指向 int 的指针
– 指向整数类型的对象
指针可以声明为指向任何数据类型的对象
– 声明多个指针时,每个变量前都必须有 *
THE POINTERS
目 录第八讲 指针
int *x_pointer;
int *x_pointer,*y_pointer;
char *charPtr;
指针变量的初始化
Pointer Variable Initializations
指针变量的初始化
– 在声明或赋值语句中初始化指针
– 指针变量可以被初始化为 0,NULL 或 地址
0 和 NULL 是等价的(用 NULL更好)
– NULL 是在 <stdio.h>(和几个其他头文件)中定义的符号常量
THE POINTERS
目 录第八讲 指针
int x,*p=&x;
int x,*p=0xffe; int x,*p=(int *)0xffe;
强制类型转换
int x,*p=NULL; 空指针:不指向任何对象指针运算符
Pointer Operators
&( address operator,地址运算符)
– Returns address of operand
THE POINTERS
目 录第八讲 指针
int y,*yPtr;
y = 5;
yPtr = &y;
5
yPtr
fff0
y
ff00yPtr
y
5
Address of y is
value of yPtryPtr,points to” y
ff00
指针运算符
Pointer Operators
*( indirective operator,间接运算符,指针运算符)
– Returns a alias of what its operand points to
*yPtr returns y (because yPtr points to y)
– 可以用在赋值语句中
THE POINTERS
目 录第八讲 指针
int y=5,*yPtr;
yPtr = &y;
int y,*yPtr;
yPtr = &y;
*yPtr = 5;
指针运算符举例
Example,Pointer Operators
Example,Pointer operators ( cw08-01.c)
THE POINTERS
目 录第八讲 指针
#include <stdio.h>
void main() {
int a,*aPtr;
a = 7;
aPtr = &a;
printf("The address of a is %p"
"\nThe value of aPtr is %p",&a,aPtr);
printf("\n\nThe value of a is %d"
"\nThe value of *aPtr is %d",a,*aPtr);
printf("\n\nShowing that * and & are inverses of each other."
"\n&*aPtr = %p"
"\n*&aPtr = %p",&*aPtr,*&aPtr);
}
指针运算符举例
Example,Pointer Operators
Example,Pointer operators ( cw08-01.c)
– 运行结果
THE POINTERS
目 录第八讲 指针
The address of a is 1A58
The value of aPtr is 1A58
The value of a is 7
The value of *aPtr is 7
Showing that * and & are inverses of each other.
&*aPtr = 1A58
*&aPtr = 1A58 * 和 & 是互反的指针参数
Pointer Arguments
用指针参数模拟引用调用
– 用指针作为函数的形式参数
– 调用函数时,用 & 运算符把实际参数的地址传递给函数
– 在被调用函数中,用 * 运算符间接引用实际参数
THE POINTERS
目 录第八讲 指针指针参数举例
Example,Pointer Arguments
Example,call by value
– ( cw08-02a.c)
THE POINTERS
目 录第八讲 指针
#include <stdio.h>
int callByValue(int);
void main() {
int number = 5;
printf("The original value of number is %d",number);
number = callByValue(number);
printf("\nThe new value of number is %d",number);
}
int callByValue(int n) {
return n*n*n;
}
The original value of number is 5
The new value of number is 125
指针参数举例
Example,Pointer Arguments
Example,call by reference with pointer arguments
– ( cw08-02b.c)
THE POINTERS
目 录第八讲 指针
#include <stdio.h>
void callByReference(int*);
void main() {
int number = 5;
printf("The original value of number is %d",number);
callByReference(&number);
printf("\nThe new value of number is %d",number);
}
void callByReference(int *nPtr) {
*nPtr = *nPtr**nPtr**nPtr;
}
The original value of number is 5
The new value of number is 125
指针参数举例
Example,Pointer Arguments
Example,call by reference with pointer arguments
– 分析
THE POINTERS
目 录第八讲 指针
void main() {
int number = 5;
callByReference(&number);
}
void callByReference(int *nPtr) {
*nPtr = *nPtr**nPtr**nPtr;
}
void main() {
int number = 5;
callByReference(&number);
}
void callByReference(int *nPtr) {
*nPtr = *nPtr**nPtr**nPtr;
}
void main() {
int number = 5;
callByReference(&number);
}
void callByReference(int *nPtr) {
*nPtr = *nPtr**nPtr**nPtr;
}
nPtr
5 number
nPtr
125 number
nPtr
125 number
调用前调用后返回指针参数举例
Example,Pointer Arguments
Example,swap the values of two arguments
THE POINTERS
目 录第八讲 指针
void swap(int x,int y) {
int tmp;
tmp=x; x=y; y=tmp;
}
void main() {
int a=4,b=6;
swap(a,b);
printf("a=%d,b=%d",a,b);
}
a=4,b=6
void swap(int *x,int *y) {
int tmp;
tmp=*x; *x=*y; *y=tmp;
}
void main() {
int a=4,b=6;
swap(&a,&b);
printf("a=%d,b=%d",a,b);
}
a=6,b=4
指针表达式和算术运算
Pointer Expressions and Arithmetic
指针可以进行以下运算:
– 赋值运算
给指针变量赋值
– 关系运算
两个指针之间的比较
– 算术运算
加(减)一个整数
两个指针相减
THE POINTERS
目 录第八讲 指针指针表达式和算术运算
Pointer Expressions and Arithmetic
指针的赋值运算:
– 可以把同类型的指针赋给指针变量
THE POINTERS
目 录第八讲 指针
int x=10,*p,*q;
p = &x;
q = p;
printf(“*q=%d",*q);
*q=10
10
x
2000
p
2000
q
2000
指针表达式和算术运算
Pointer Expressions and Arithmetic
指针的赋值运算:
– 把类型不同的指针赋值给指针变量时要进行类型转换
– 但 void * 类型的指针是一个例外
THE POINTERS
目 录第八讲 指针
int a,*intPtr=&a;
char *charPtr;
charPtr = (char*)intPtr;
int a,*intPtr=&a;
char *charPtr;
void *voidPtr;
voidPtr = intPtr;
charPtr = voidPtr;
void*
通用指针,代表任何指针类型不能间接引用指针表达式和算术运算
Pointer Expressions and Arithmetic
指针的关系运算:
– 比较两个指针包含的内存地址
THE POINTERS
目 录第八讲 指针
p1 < p2
p1 <= p2
p1 > p2
p1 >= p2
p1 == p2
p1 != p2
2000p1
2002p2
char *charPtr;

charPtr >= (char*)2000 与同类型的常量指针比较常常与 0 比较指针表达式和算术运算
Pointer Expressions and Arithmetic
指针的算术运算:
– 自增自减 ( ++,--)
– 加上一个整数 ( +,+=,-,-=)
– 两个指针相减
– 在数组上执行才有意义
THE POINTERS
目 录第八讲 指针指针表达式和算术运算
Pointer Expressions and Arithmetic
指针的算术运算
– 举例
vPtr + 2
THE POINTERS
目 录第八讲 指针
int v[4],*vPtr;
vPtr = v;
vPtr = vPtr + 2;
2000
2002
2004
2006
数组 vvPtr
2000 + 2 = 2002
2000 + 2*2 = 2004
vPtr
基类型的长度

指针表达式和算术运算
Pointer Expressions and Arithmetic
指针的算术运算
– 举例
vP2 – vP1
= 2
THE POINTERS
目 录第八讲 指针
int v[4],*vP1,*vP2;
vP1 = v;
vP2 = &v[2];
2000
2002
2004
2006
数组 vvP1
vP2
vP2和 vP1之间元素的个数

指针的算术运算在数组上使用才有意义指针与数组的关系
The Relationship Between Pointers and Arrays
数组和指针是密切相关的
– 数组名可以认为是常量指针
– 指针可以用来完成任何涉及数组下标的操作
将 bPtr 设置为等于数组 b 中的地一个元素的地址
bPtr = b;
等价于
bPtr = &b[0];
THE POINTERS
目 录第八讲 指针
int b[5];
int *bPtr;
指针与数组的关系
The Relationship Between Pointers and Arrays
数组和指针是密切相关的
– 引用数组元素的表达式
数组元素 b[3] 可以用 *(bPtr + 3) 来引用
– 3是偏移量( offset)
– 这种表示法称为指针 /偏移量表示法
还可以用 bPtr[3] 来引用
– 称为指针 /下标表示法
– 与 b[3] 相同
还可以用 *(b + 3) 来引用
– 把数组本身作为指针处理
THE POINTERS
目 录第八讲 指针指针与数组的关系
The Relationship Between Pointers and Arrays
引用数组元素的方法小结
– 数组和指针几乎可以互换使用
THE POINTERS
目 录第八讲 指针
main() {
int i,a[5]={1,2,3,4,5};
for (i=0; i<5; i++)
printf("%2d",a[i]);
}
下标法
main() {
int i,a[5]={1,2,3,4,5};
for (i=0; i<5; i++)
printf("%2d",*(a+i));
}
地址法
main() {
int a[5]={1,2,3,4,5},*p;
for (p=a; p<(a+5); p++)
printf("%2d",*p);
}
指针法指针与数组的关系
The Relationship Between Pointers and Arrays
数组和指针互换使用中的注意事项
THE POINTERS
目 录第八讲 指针因为 a是数组名,即数组的首地址,它的值在程序运行期间是固定不变的!
是一个常量指针。

main() {
int a[5]={1,2,3,4,5},*p;
for ( p=a; a<(p+5); a++ )
printf("%2d",*a);
}
指针与数组的关系
The Relationship Between Pointers and Arrays
数组和指针互换使用中的注意事项
THE POINTERS
目 录第八讲 指针要注意指针变量的当前值。
p
p
a[0]
a[1]
a[2]
a[3]
a[4]
数组 a
main() {
int i,a[5],*p;
p=a;
for ( i=0; i<5; i++ )
scanf( "%d",p++ );
for ( i=0; i<5; i++,p++ )
printf( "%d ",*p );
}

p = a;
指针与数组的关系
The Relationship Between Pointers and Arrays
数组和指针互换使用中的注意事项
– 注意运算符的优先级
THE POINTERS
目 录第八讲 指针
* aPtr ++ * (aPtr ++)等价考虑:
*(aPtr++) 与 *(++aPtr)
int a=0,*aPtr=&a;
printf("a=%d,aPtr=%p\n",a,aPtr);
printf("%d\n",*aPtr++);
printf("a=%d,aPtr=%p\n",a,aPtr);
a=0,aPtr=1BCC
0
a=0,aPtr=1BCE
指针与数组的关系
The Relationship Between Pointers and Arrays
举例:数组和指针的互换使用
– 按引用调用的冒泡排序
THE POINTERS
目 录第八讲 指针
void sort( int *x,int n) {

}
void main() {
int a[10];


sort( a,10);

}
a,x a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
a[8]
a[9]
地址字符串指针
Pointers Point To Strings
字符串指针
– 让字符指针指向字符串(字符数组)
THE POINTERS
目 录第八讲 指针
char str[20]=“China”,*p=str;
printf(“%s”,p);
C
h
i
n
a
\0
str,p
char *p=“China”;
printf(“%s”,p);
C语言对字符串常量是按字符数组处理的。
char *p;
p=“China”;
printf(“%s”,p);
C
h
i
n
a
\0
p
字符串指针
Pointers Point To Strings
字符串指针
– 让字符指针指向字符串(字符数组)
THE POINTERS
目 录第八讲 指针
char str[20]=“China”,*p=str;
printf(“%s”,p);
C
h
i
n
a
\0
str,p
char *p=“China”;
printf(“%s”,p);
C语言对字符串常量是按字符数组处理的。
char *p;
p=“China”;
printf(“%s”,p);
C
h
i
n
a
\0
p
字符串指针
Pointers Point To Strings
字符数组和字符(串)指针
– 初始化和赋值
THE POINTERS
目 录第八讲 指针
char str[5]=,wuhan”;
char *p=“wuhan”; char *p;p=“wuhan”;
char str[5];
str=,wuhan”;
=

错对字符串指针
Pointers Point To Strings
字符数组和字符(串)指针
– 输入字符串
THE POINTERS
目 录第八讲 指针
char *p;
scanf(“%s”,p);
char str[5],*p;
p=str;
scanf(“%s”,p);
char str[5];
scanf(“%s”,str);
错 对对在编译时为字符串数组分配内存单元,有确定的地址虽然为字符指针变量分配了内存单元,但其值(地址)是不确定的,不可以使用字符串指针
Pointers Point To Strings
举例:字符数组和字符(串)指针的互换使用
– 字符串的复制
THE POINTERS
目 录第八讲 指针
C
h
i
n
a
\0
C
h
i
n
e
s
e
\0
a
frm
b
to Ch
i
n
a
\0
e
\0
bvoid strCopy(char *frm,char *to) {while((*to=*frm)!='\0') {
frm++; to++; }
}
void main() {
char *a="China";
char *b="Chinese";
strCopy(a,b);
printf("%s",b);
}
China
指针数组
Arrays Of Pointers
指针数组
– 数组元素是指针
type-name *array-name[constant-expression];
– 常用来构造字符串数组:
字符串并不在 suit 数组中
suit 数组只包含指向字符串的指针
THE POINTERS
目 录第八讲 指针
char *suit[4] = {“Hearts”,“Diamonds”,“Clubs”,“Spades”};
suit[3]
suit[2]
suit[1]
suit[0]?Hearts\0?
Diamonds\0?
Clubs\0?
Spades\0?
suit 的长度是固定的,但却可以访问任意长度的字符串指针数组
Arrays Of Pointers
举例,洗牌和发牌的模拟
– 定义数据结构
字符串(指针)数组 suit 保存牌的花色名
字符串(指针)数组 face 保存牌的号码
二维数组 deck 表示一副牌,行对应花色,列对应号码
– 保存洗牌后牌的序号
THE POINTERS
目 录第八讲 指针
deck[2][12] represents the King of Clubs
Hearts
Diamonds
Clubs
Spades
0
1
2
3
Ace Two Three Four Five Six Seven Eight Nine Ten Jack Queen King
0 1 2 3 4 5 6 7 8 9 10 11 12
Clubs King
指针数组
Arrays Of Pointers
举例,洗牌和发牌的模拟
– 设计算法(自顶向下,逐步求精)
– 第一次细化
THE POINTERS
目 录第八讲 指针对 52张牌进行洗牌和发牌初始化 suit 数组初始化 face 数组初始化 deck 数组对 52 张牌洗牌对 52 张牌发牌指针数组
Arrays Of Pointers
举例,洗牌和发牌的模拟
– 设计算法(自顶向下,逐步求精)
– 第二次细化
THE POINTERS
目 录第八讲 指针初始化 suit 数组初始化 face 数组初始化 deck 数组对 52 张牌中的每张在随机选择的纸牌空位上放置纸牌序号对 52 张牌中的每张查找 deck 数组中纸牌的序号,并显示纸牌的花色和号码指针数组
Arrays Of Pointers
举例,洗牌和发牌的模拟
– 设计算法(自顶向下,逐步求精)
– 第三次细化
THE POINTERS
目 录第八讲 指针初始化 suit 数组初始化 face 数组初始化 deck 数组对 52 张牌中的每张随机选择纸牌位置当所选纸牌位置已经被选过(有序号)
随机选择纸牌位置在所选纸牌位置中放置纸牌序号对 52 张牌中的每张对于 deck 数组的每个位置如果该位置包含期望的纸牌序号显示纸牌的花色和号码指针数组
Arrays Of Pointers
举例,洗牌和发牌的模拟
– 实现 ( cw08-05.c)
THE POINTERS
目 录第八讲 指针
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void shuffle(int[][13]);
void deal(int[][13],char*[],char*[]);
void main() {
char *suit[]={"Hearts","Diamonds","Clubs","Spades"};
char *face[]={"Ace","Two","Three",
"Four","Five","Six",
"Seven","Eight","Nine",
"Ten","Jack","Queen","King"};
int deck[4][13]={0};
指针数组
Arrays Of Pointers
举例,洗牌和发牌的模拟
– 实现 ( cw08-05.c)
THE POINTERS
目 录第八讲 指针
srand(time(0));
shuffle(deck);
deal(deck,face,suit);
}
指针数组
Arrays Of Pointers
举例,洗牌和发牌的模拟
– 实现 ( cw08-05.c)
THE POINTERS
目 录第八讲 指针
void shuffle(int wDeck[][13]) {
int row,column,card;
for (card=1; card<=52; card++) {
do {
row = rand()%4;
column = rand()%13;
} while(wDeck[row][column]!=0);
wDeck[row][column]=card;
}
}
指针数组
Arrays Of Pointers
举例,洗牌和发牌的模拟
– 实现 ( cw08-05.c)
THE POINTERS
目 录第八讲 指针
void deal(int wDeck[][13],char *wFace[],char *wSuit[]) {
int card,row,column;
for (card=1; card<=52; card++)
for (row=0; row<4; row++)
for (column=0; column<13; column++)
if (wDeck[row][column]==card)
printf("%5s of %-8s%c",
wFace[column],wSuit[row],
card%2==0?'\n':'\t');
}
第九讲 结构
Structures
PROGRAM DESIGN IN C LANGUAGE
目 录
9.2 结构定义
Structure definitions
9.3 初始化结构
Initializing structures
9.5 在函数中使用结构
Using structures with functions
9.6 结构数组
Arrays of structures
9.1 简介
Introduction
9.7 链表
Linked list
9.4 访问结构成员
Accessing structure members
简介
Introduction
Structures(结构)
– Collections of related variables
Can contain variables of different data types
– Commonly used to define records to be stored in files
– Combined with pointers,can create linked lists,stacks,queues,
and trees
STRUCTURES
目 录第九讲 结构结构定义
Structure Definitions
结构是派生的数据类型
– 使用其他类型的对象来构造它们结构定义举例
– struct,引入了结构定义
– card,结构的名称,必须与 struct 一起使用
– struct card 结构包含两个 char * 类型的成员( member),
face
suit
STRUCTURE DEFINITIONS
目 录第九讲 结构
struct card {
char *face;
char *suit;
};
为程序创建了一个新的数据类型
struct card
结构定义
Structure Definitions
结构定义说明
– 相同结构的成员名不可以相同
– 不同结构的成员名可以相同,不互相冲突
STRUCTURE DEFINITIONS
目 录第九讲 结构
struct date { int year,month,day; };
struct Book {
char title[50],writer[20],publisher[50];
int year,month;
};
int year,month,day;
结构定义
Structure Definitions
结构定义说明
– 结构的成员可以使基本类型和构造类型(数组和其他结构)
STRUCTURE DEFINITIONS
目 录第九讲 结构
struct date {
int year,month,day;
};
struct StuRec {
int num;
char name[20];
struct date birthday;
};
结构定义
Structure Definitions
结构定义说明
– 结构不能包含自身的实例
– 但可以包含指向自身的指针
STRUCTURE DEFINITIONS
目 录第九讲 结构
struct student {
char name[20];
char gender;
float scores[4];
struct student next; /*error*/
struct student *nextPtr; /*correct*/
};
结构变量
Structure Variables
结构定义说明
– 结构定义只是创建了新的数据类型,并不能保留内存空间
必须声明结构变量声明结构变量
– 定义结构后,像声明普通变量一样声明结构变量
STRUCTURE DEFINITIONS
目 录第九讲 结构
struct date {
int year,month,day;
};
struct date birth;
year
month
day
FF00
FF02
FF04
birth
birth 的存储形式结构变量
Structure Variables
声明结构变量
– 在定义结构的同时,声明结构变量
– 直接(只)声明结构变量
STRUCTURE DEFINITIONS
目 录第九讲 结构
struct date {
int year,month,day;
} birth,days[4],*bPtr;
struct {
int year,month,day;
} birth,days[4],*bPtr;
没有结构名,
无法再次使用结构操作
Structures Operations
在结构(变量)上可以执行的操作
– 将结构变量赋给相同类型的结构变量
– 得到结构变量的地址
– 访问结构变量的成员
– 使用 sizeof 确定结构变量的大小
STRUCTURE DEFINITIONS
目 录第九讲 结构初始化结构
Initializing Structures
初始化结构(变量)
– 给全部成员赋初值
INITIALIZING STRUCTURES
目 录第九讲 结构
struct StuRec {
int num;
char name[20];
struct date { int year,month,day; } birthday;
float score;
} student={101,“WangHai”,1982,5,21,80};
num
(2B)
name
(20B)
birthday(6B) score
(4B)year month day
101 WangHai 1982 5 21 80.0
初始化结构
Initializing Structures
初始化结构(变量)
– 给部分成员赋初值
INITIALIZING STRUCTURES
目 录第九讲 结构
struct StuRec {
int num;
char name[20];
struct date { int year,month,day; } birthday;
float score;
} student={101,“WangHai”};
num
(2B)
name
(20B)
birthday(6B) score
(4B)year month day
101 WangHai 0 0 0 0.0
访问结构成员
Accessing Structure Members
访问结构成员的两种方式
– 结构成员运算符,.
用于结构变量
– 结构指针运算符,->
用于指向结构的指针
等价于 (*cardPtr).face
ACCESSING MEMBERS OF STRUCTURES
目 录第九讲 结构
struct card myCard;
printf(“%s”,myCard.face);
struct card *cardPtr;
printf(“%s”,cardPtr->face);
访问结构成员
Accessing Structure Members
Example,Accessing structure members
– ( cw09-01.c)
ACCESSING MEMBERS OF STRUCTURES
目 录第九讲 结构
#include <stdio.h>
struct card {
char *face;
char *suit;
};
void main() {
struct card a,*aPtr;
a.face = "Ace";
a.suit = "Spades";
aPtr = &a;
与数组的不同:
结构变量名不是指针访问结构成员
Accessing Structure Members
Example,Accessing structure members
– ( cw09-01.c)
ACCESSING MEMBERS OF STRUCTURES
目 录第九讲 结构
printf("%s%s%s\n%s%s%s\n%s%s%s\n",
a.face," of ",a.suit,
aPtr->face," of ",aPtr->suit,
(*aPtr).face," of ",(*aPtr).suit);
}
Ace of Spades
Ace of Spades
Ace of Spades 注意:
结构不能作为整体输入输出必须逐个成员进行输入输出在函数中使用结构
Using Structures With Functions
把结构的单个成员传递给函数
– 按值调用传递
– 被调用函数不能修改调用函数中的结构成员把整个结构传递给函数
– 按值调用传递
– 被调用函数不能修改调用函数中的结构把结构指针传递给函数
– 按引用调用传递
– 被调用函数能修改调用函数中的结构
USING STRUCTURES WITH FUNCTIONS
目 录第九讲 结构在函数中使用结构
Using Structures With Functions
Example,Passing structures to functions
– 编写函数实现结构的复制( cw09-02.c)
USING STRUCTURES WITH FUNCTIONS
目 录第九讲 结构
#include <stdio.h>
struct date {
int year,month,day;
};
void show(char *,struct date);
void copy(struct date,struct date);
void clone(struct date,struct date *);
void main() {
struct date d1,d2,d3,d4;
d1.year = 2004;
d1.month = 5;
d1.day = 1;
show("d1",d1);
在函数中使用结构
Using Structures With Functions
Example,Passing structures to functions
– 编写函数实现结构的复制( cw09-02.c)
USING STRUCTURES WITH FUNCTIONS
目 录第九讲 结构
d2 = d1;
show("d2",d2);
copy(d1,d3);
show("d3",d3);
clone(d1,&d4);
show("d4",d4);
}
void show(char *name,struct date d) {
printf("%s,%d-%d-%d\n",name,d.year,d.month,d.day);
}
在函数中使用结构
Using Structures With Functions
Example,Passing structures to functions
– 编写函数实现结构的复制( cw09-02.c)
USING STRUCTURES WITH FUNCTIONS
目 录第九讲 结构
void copy(struct date s,struct date d) {
d = s;
}
void clone(struct date s,struct date *dPtr) {
*dPtr = s;
}
d1,2004-5-1
d2,2004-5-1
d3,0-0-24
d4,2004-5-1
在函数中使用结构
Using Structures With Functions
把整个结构返回
– 因为结构变量之间可以赋值按值调用把数组传递给函数
– 把数组作为结构的成员,然后把结构传递给函数
– 被调用函数不能修改调用函数中的数组
USING STRUCTURES WITH FUNCTIONS
目 录第九讲 结构定义类型的别名
typedef
typedef
– 为已经定义的数据类型创建一个别名(或同义词)
– 举例
创建了一个新的类型名 Date,它是 struct date 的别名
注意:并没有创建新的类型
– 可以简化程序代码,提高程序的可移植性
TYPEDEF
目 录第九讲 结构
typedef struct date Date;
void show(char *,Date d);
void copy(Date s,Date d);
typedef int Integer;
结构数组
Arrays Of Structures
结构数组
– 数组的元素是结构
– 常用结构来表示记录,那么结构数组就可以表示一组记录
– 举例
全班 N 个学生,每个学生有学号、姓名、四门课的成绩
ARRAYS OF STRUCTURES
目 录第九讲 结构学号 姓名 成绩 1 成绩 2 成绩 3 成绩 4
101 WangHai 80 78 76 81
102 ZhaoFei 68 66 71 75
…… …… …… …… …… ……
130 LiRui 82 76 81 84
结构数组
Arrays Of Structures
结构数组
– 举例
全班 N 个学生,每个学生有学号、姓名、四门课的成绩
那么,可以定义结构数组来保存 N 个学生的数据
这样,每个学生的数据就对应一个结构(一条记录),便于编程处理
ARRAYS OF STRUCTURES
目 录第九讲 结构
struct student {
int num;
char name[20];
float scores[4];
};
struct student students[30];
结构数组
Arrays Of Structures
举例:高性能洗牌和发牌仿真程序
– 修改原来的数据结构
用一个纸牌结构数组保存一副牌
纸牌的花色和号码名依然保存在字符串数组中
– 这样,数组中的纸牌俨然已有一个顺序了,则可以改进算法
洗牌:随机打乱纸牌在数组中的位置
– 不存在无限延期
发牌:按纸牌在数组中的顺序显示输出
– 数组遍历一次
ARRAYS OF STRUCTURES
目 录第九讲 结构结构数组
Arrays Of Structures
举例:高性能洗牌和发牌仿真程序
– 实现 ( cw09-03.c)
ARRAYS OF STRUCTURES
目 录第九讲 结构
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct card {
char *face;
char *suit;
};
typedef struct card Card;
void fillDeck(Card*,char*[],char*[]);
void shuffle(Card*);
void deal(Card*);
结构数组
Arrays Of Structures
举例:高性能洗牌和发牌仿真程序
– 实现 ( cw09-03.c)
ARRAYS OF STRUCTURES
目 录第九讲 结构
void main() {
Card deck[52];
char *face[] = {"Ace","Deuce","Three",
"Four","Five",
"Six","Seven","Eight",
"Nine","Ten",
"Jack","Queen","King"};
char *suit[] = {"Hearts","Diamonds","Clubs","Spades"};
srand(time(NULL));
fillDeck(deck,face,suit);
shuffle(deck);
deal(deck);
}
结构数组
Arrays Of Structures
举例:高性能洗牌和发牌仿真程序
– 实现 ( cw09-03.c)
ARRAYS OF STRUCTURES
目 录第九讲 结构
void fillDeck(Card *wDeck,char *wFace[],char *wSuit[]) {
int i;
for (i=0; i<=51; i++) {
wDeck[i].face = wFace[i%13];
wDeck[i].suit = wSuit[i/13];
}
}
结构数组
Arrays Of Structures
举例:高性能洗牌和发牌仿真程序
– 实现 ( cw09-03.c)
ARRAYS OF STRUCTURES
目 录第九讲 结构
void shuffle(Card *wDeck) {
int i,j;
Card temp;
for (i=0; i<=51; i++) {
j = rand()%52;
temp = wDeck[i];
wDeck[i] = wDeck[j];
wDeck[j] = temp;
}
}
结构数组
Arrays Of Structures
举例:高性能洗牌和发牌仿真程序
– 实现 ( cw09-03.c)
ARRAYS OF STRUCTURES
目 录第九讲 结构
void deal(Card *wDeck) {
int i;
for (i=0; i<=51; i++) {
printf("%5s of %-8s%c",
wDeck[i].face,
wDeck[i].suit,
(i+1)%2? '\t','\n');
}
}
结构数组
Arrays Of Structures
举例:检索
– 某班有 n 个学生,每个学生的数据包括学号、姓名、年龄和性别。要求给定任意一个学号,程序能输出检索的结果,并显示对应的学生的数据。 ( cw09-04.c)
– 分析
用结构体数组保存学生数据
采用顺序查找法
ARRAYS OF STRUCTURES
目 录第九讲 结构输入学生信息输入查询条件查找学生信息,报告结果结构数组
Arrays Of Structures
举例:检索
– 实现 ( cw09-04.c)
ARRAYS OF STRUCTURES
目 录第九讲 结构
#include <stdio.h>
#define MAX 20
void main() {
struct StuRec {
int num;
char name[20];
char gender;
int age;
} student[MAX];
int i,N,num;
结构数组
Arrays Of Structures
举例:检索
– 实现 ( cw09-04.c)
ARRAYS OF STRUCTURES
目 录第九讲 结构
printf("\tInput a integer as the number of students:");
scanf("%d",&N);
printf("\tInput %d students' information:\n",N);
printf("\n\tNo.\tName\tGender\tAge\n");
for (i=0;i<N;i++) {
printf("student %d:\n\t",i+1);
scanf("%d %s %c %d",
&student[i].num,
student[i].name,
&student[i].gender,
&student[i].age);
}
结构数组
Arrays Of Structures
举例:检索
– 实现 ( cw09-04.c)
ARRAYS OF STRUCTURES
目 录第九讲 结构
printf("\n\tInput a number:");
scanf("%d",&num);
printf("\n\tPlease wait,Searching...\n");
for (i=0;i<N;i++) if (num==student[i].num) break;
if (i<N) {
printf("\n\tNo.:%d\n\tName:%s\n\tGender:%c\n\tAge:%d\n",
student[i].num,
student[i].name,
student[i].gender,
student[i].age);
}
else
printf("\n\tNot found!\n");
}
输入查找条件查找结构数组
Arrays Of Structures
举例:检索
– 增加要求:可以多次查找 ( cw09-04m.c)
ARRAYS OF STRUCTURES
目 录第九讲 结构输入学生信息输入查询条件查找学生信息,报告结果是否继续查询 Y
N
结构数组
Arrays Of Structures
举例:检索
– 修订后的部分代码 ( cw09-04m.c)
ARRAYS OF STRUCTURES
目 录第九讲 结构
do {
scanf("%d",&num);
for (i=0;i<N;i++) if (num==student[i].num) break;
if (i<N) { /* Found! */ }
else printf("\n\tNot found!\n");
printf("\n\tContinue?(y/n)");
c=getchar(); c=getchar();
} while (c=='y'||c=='Y');
结构数组
Arrays Of Structures
举例:点票程序
– 有三个候选人,N个选举人,每次输入一个得票的候选人的名字,要求最后输出各人的得票结果。
– 定义数据结构
ARRAYS OF STRUCTURES
目 录第九讲 结构
struct candidate {
char name[20]; /*姓名 */
int count; /*得票数 */
} cand[3];
结构数组
Arrays Of Structures
举例:点票程序
– 算法
ARRAYS OF STRUCTURES
目 录第九讲 结构输入候选人信息输入选票查找得票人信息找到否?
得票人的票数增一输出点票结果点完否?
Y
N
N
Y
结构数组
Arrays Of Structures
举例:点票程序
– 实现 ( cw09-05.c)
ARRAYS OF STRUCTURES
目 录第九讲 结构
……
do {
printf("Vote:\t"); gets(name);
for (i=0;i<M;i++)
if (strcmp(name,cand[i].name)==0) {
cand[i].count++; vote++; break;
}
printf("\tContinue?(y/n)"); c=getchar(); i=getchar();
} while (c=='y'||c=='Y');
……
结构数组
Arrays Of Structures
举例:改进点票程序
– 假设选举人都可以是候选人
– 分析点票过程中数组的变化
ARRAYS OF STRUCTURES
目 录第九讲 结构
litao
litao wanghai litao zhaofei ……
litao wanghai
litao wanghai zhaofei
结构数组
Arrays Of Structures
举例:改进的点票程序
– 数据结构和算法
ARRAYS OF STRUCTURES
目 录第九讲 结构
struct candidate {
char name[20];
int count;
} cand[M];
输入选票查找得票人信息找到否?
得票人的票数增一输出点票结果点完否?
Y
N
N
Y
加入新的候选人;
其得票数赋值,1”。
结构数组
Arrays Of Structures
举例:改进的点票程序
– 实现 ( cw09-06.c)
ARRAYS OF STRUCTURES
目 录第九讲 结构
。。。
printf("Vote:\t"); gets(name); found=0;
for (i=0;i<len;i++)
if (strcmp(name,cand[i].name)==0) {
cand[i].count++; found=1; break;
}
if (!found) {
strcpy(cand[i].name,name);
cand[i].count=1; len++;
}
。。。
出现新的候选人结构数组
Arrays Of Structures
举例:增强点票程序
– 要求按候选人得票数
– 从高到低顺序输出结果。
– 修改算法
ARRAYS OF STRUCTURES
目 录第九讲 结构输入选票查找得票人信息找到否?
得票人的票数增一输出点票结果点完否?
Y
N
N
Y
加入新的候选人;
其得票数赋值,1”。
按得票数进行排序结构数组
Arrays Of Structures
举例:增强点票程序
– 实现 ( cw09-07.c)
ARRAYS OF STRUCTURES
目 录第九讲 结构

for (i=0;i<len-1;i++)
for (j=0;j<len-1-i;j++)
if (cand[j].count<cand[j+1].count) {
tmp=cand[j];
cand[j]=cand[j+1];
cand[j+1]=tmp;
}

结构数组
Arrays Of Structures
举例:优化点票程序
– 如果候选人的信息较多,为了提高排序过程中数据交换的性能,增设一数组 order,用来保存排序结果。
– 分析
ARRAYS OF STRUCTURES
目 录第九讲 结构
0 1 2 3 4 5
3 0 5 1 4 2
20 Wanghai M 43 P …
12 Zhaofei F 41 P …
6 Lilan F 38 N …
35 Huangjin M 52 P …
9 Wuma M 29 N …
15 Hecheng M 36 P …
order的初态
order的末态从高到低
0
1
2
3
4
5
结构数组
Arrays Of Structures
举例:优化点票程序
– 实现 ( cw09-08.c)
ARRAYS OF STRUCTURES
目 录第九讲 结构
for (i=0;i<len;i++) order[i]=i;

for (i=0;i<len-1;i++)
for (j=0;j<len-1-i;j++)
if (cand[order[j]].count<cand[order[j+1]].count) {
tmp=order[j];
order[j]=order[j+1];
order[j+1]=tmp;
}
交换序号排序数组赋初值结构数组
Arrays Of Structures
举例:优化点票程序
– 实现 ( cw09-08.c)
ARRAYS OF STRUCTURES
目 录第九讲 结构
for (i=0;i<len;i++)
printf("\t%s\t%d\n",cand[order[i]].name,
cand[order[i]].count);
按照 order保存的顺序输出候选人信息。
数据结构
Data Structures
Dynamic data structures( 动态数据结构 )
– Data structures that grow and shrink during execution
Linked lists( 链表 )
– Allow insertions and removals anywhere
Stacks( 栈 )
– Allow insertions and removals only at top of the stack
Queues( 对列 )
– Allow insertions at the back and removals from the front
LINKED LISTS
目 录第九讲 结构自引用的结构
Self-Referenial Structures
自引用的结构
– 包含指向相同结构类型的指针成员
– 可以链接到一起,构成有用的数据结构,链表、栈、队列和树
LINKED LISTS
目 录第九讲 结构
struct node {
int data;
struct node nextPtr;
};
20 42
数据成员 指针结点( node)
空指针链头指针动态内存分配
Dynamic Memory Allocation
动态内存分配
– 在程序执行期间获取或释放内存
– 相关的函数
malloc
free
sizeof
LINKED LISTS
目 录第九讲 结构动态内存分配
Dynamic Memory Allocation
malloc
– 把要分配的字节数作为参数
用 sizeof 确定对象的大小
– 返回指向分配内存的 void* 类型的指针
void* 类型的指针可以被赋值给任何类型的指针变量
如果没有可用内存,则返回 NULL
free
– 释放用 malloc 分配的内存
用指向要被释放的内存区的指针作为参数
LINKED LISTS
目 录第九讲 结构
newPtr = malloc(sizeof(struct node));
free(newPtr);
链表
Linked Lists
链表
– 用指针链接连接的自引用结构的线性集合,这些结构称为 结点
– 通过指向链表的第一个结点的指针访问链表
– 后续的结点通过存储在每个结点中的链接指针成员来访问
– 链表中最后一个结点的链接指针被设置为 NULL,以标志链表的结尾什么时候用链表替代数组
– 数据成员的数目无法事先确定
– 对数据进行快速的排序
LINKED LISTS
目 录第九讲 结构
20 42
链表
Linked Lists
Example,Linked list
– 输入任意个整数创建链表
– 实现常用的操作:遍历,插入,删除,空表判断
– ( cw09-11.c)
LINKED LISTS
目 录第九讲 结构
#include <stdio.h>
#include <stdlib.h>
struct listNode {
int data;
struct listNode *nextPtr;
};
typedef struct listNode ListNode;
typedef ListNode* ListNodePtr;
链表
Linked Lists
Example,Linked list
– 主函数
LINKED LISTS
目 录第九讲 结构
void insert(ListNodePtr*,int);
int delete(ListNodePtr*,int);
int isEmpty(ListNodePtr);
void printList(ListNodePtr);
void menu(void);
void main() {
ListNodePtr listPtr = NULL;
int choice;
int item;
menu();
printf("? ");
scanf("%d",&choice);
链表
Linked Lists
Example,Linked list
– 主函数
LINKED LISTS
目 录第九讲 结构
while (choice != 3) {
switch (choice) {
case 1:
printf("Enter an integer,");
scanf("%d",&item);
insert(&listPtr,item);
printList(listPtr);
break;
链表
Linked Lists
Example,Linked list
– 主函数
LINKED LISTS
目 录第九讲 结构
case 2:
if (!isEmpty(listPtr)) {
printf("Enter an integer to be deleted,");
scanf("%d",&item);
if (delete(&listPtr,item)) {
printf("%d deleted.\n",item);
printList(listPtr);
}
else
printf("%d not found.\n",item);
}
else
printf("List is Empty!\n");
break;
链表
Linked Lists
Example,Linked list
– 主函数
LINKED LISTS
目 录第九讲 结构
default:
printf("Invalid choice.\n\n");
menu();
break;
}
printf("? ");
scanf("%d",&choice);
}
printf("Bye-bye!\n");
}
链表
Linked Lists
Example,Linked list
– 显示菜单函数
LINKED LISTS
目 录第九讲 结构
void menu(void) {
printf("Enter your choice:\n"
"1 to insert an element into the list.\n"
"2 to delete an element from the list.\n"
"3 to ent.\n");
}
链表
Linked Lists
Example,Linked list
– 插入结点函数
LINKED LISTS
目 录第九讲 结构
20 42
listPtr
35
newPtr
prePtr curPtr
链表
Linked Lists
Example,Linked list
– 插入结点函数
LINKED LISTS
目 录第九讲 结构
void insert(ListNodePtr *sPtr,int data) {
ListNodePtr newPtr,prePtr,curPtr;
newPtr = malloc(sizeof(ListNode));
if (newPtr != NULL) {
newPtr->data = data;
newPtr->nextPtr = NULL;
prePtr = NULL;
curPtr = *sPtr;
while (curPtr != NULL && data > curPtr->data) {
prePtr = curPtr;
curPtr = curPtr->nextPtr;
}
链表
Linked Lists
Example,Linked list
– 插入结点函数
LINKED LISTS
目 录第九讲 结构
if (prePtr == NULL) {
newPtr->nextPtr = curPtr;
*sPtr = newPtr;
}
else {
prePtr->nextPtr = newPtr;
newPtr->nextPtr = curPtr;
}
}
else
printf("%d not inserted,No memory available.\n",data);
}
如果新结点是第一个节点,则必须调整链表的头指针链表
Linked Lists
Example,Linked list
– 删除结点函数
LINKED LISTS
目 录第九讲 结构
tempPtr
prePtr curPtr
20 42
listPtr
35
链表
Linked Lists
Example,Linked list
– 删除结点函数
LINKED LISTS
目 录第九讲 结构
int delete(ListNodePtr *sPtr,int data) {
ListNodePtr prePtr,curPtr,tempPtr;
if (data == (*sPtr)->data) {
tempPtr = *sPtr;
*sPtr = (*sPtr)->nextPtr;
free(tempPtr);
return 1;
}
else {
prePtr = *sPtr;
curPtr = (*sPtr)->nextPtr;
如果删除的是第一个节点,必须调整链表的头指针链表
Linked Lists
Example,Linked list
– 删除结点函数
LINKED LISTS
目 录第九讲 结构
while (curPtr != NULL && curPtr->data != data) {
prePtr = curPtr;
curPtr = curPtr->nextPtr;
}
if (curPtr != NULL) {
tempPtr = curPtr;
prePtr->nextPtr = curPtr->nextPtr;
free(tempPtr);
return 1;
}
}
return 0;
}
链表
Linked Lists
Example,Linked list
– 判空和输出(遍历)函数
LINKED LISTS
目 录第九讲 结构
int isEmpty(ListNodePtr listPtr) {
return listPtr == NULL;
}
void printList(ListNodePtr curPtr) {
if (curPtr == NULL)
printf("List is Empty.\n\n");
else {
printf("The list is:\n");
while (curPtr != NULL) {
printf("%d --> ",curPtr->data);
curPtr = curPtr->nextPtr;
}
printf("NULL\n\n");
}
}
第十讲 文件处理
File Processing
PROGRAM DESIGN IN C LANGUAGE
目 录
10.2 文件和流
Files and streams
10.3 顺序存取文件
Sequential access files
10.4 随机存取文件
Random access files
10.5 举例
Examples
10.1 简介
Introduction
简介
Introduction
Data files( 数据文件 )
– Can be created,updated,and processed by C programs
– Are used for permanent storage of large amounts of data
Storage of data in variables and arrays is only temporary
FILE PROCESSING
目 录第十讲 文件处理第十一讲 预处理器
The Preprocessor
PROGRAM DESIGN IN C LANGUAGE
目 录
11.2 文件包含
The #include preprocessor directive
11.3 符号常量
The #define preprocessor directive,symbolic constants
11.4 宏
The #define preprocessor directive,macro
11.5 条件编译
Conditional compilation
11.1 简介
Introduction
简介
Introduction
预处理 ( preprocessing)
– Occurs before a program is compiled
– Inclusion of other files
– Definition of symbolic constants and macros
– Conditional compilation of program code
– Conditional execution of preprocessor directives
预处理命令 ( preprocessor directive) 的格式
– Lines begin with #
– Only whitespace characters before directives on a line
The Preprocessor
目 录第十一讲 预处理器文件包含
The #include Preprocessor Directive
#include
– Copy of a specified file included in place of the directive
– #include <filename>
Searches standard library for file
Use for standard library files
– #include "filename"
Searches current directory,then standard library
Use for user-defined files
– Used for:
Programs with multiple source files to be compiled together
Header file – has common declarations and definitions (classes,
structures,function prototypes)
– #include statement in each file
The Preprocessor
目 录第十一讲 预处理器符号常量
The #define Preprocessor Directive,symbolic constants
#define
– Preprocessor directive used to create symbolic constants and
macros
Symbolic constants
When program compiled,all occurrences of symbolic constant
replaced with replacement text
– Format
#define identifier replacement-text
– Example
Everything to right of identifier replaces text
Cannot redefine symbolic constants once they have been created
The Preprocessor
目 录第十一讲 预处理器
#define PI 3.14159 #define PI = 3.14159