C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C ....

107
http://math.ecnu.edu.cn/~jypan 第三讲 C 语言编程初步

Transcript of C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C ....

Page 1: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

第三讲

C 语言编程初步

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

1

2C 语言基础

选择与循环3 函数4 指针与字符串

5 文件操作

谭浩强C 程序设计第5版2017 Kernighan amp RitchieThe C Programming Language 2nd 1988 Schildt C The Complete Reference 4th 2000

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

C 语言介绍

数据类型

输入输出

数组

1 C 语言基础

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 4

程序设计语言的发展

机器语言

汇编语言

高级语言

面向过程 面向对象 面向应用

效率高编程难

CPU指令系统由 01 构成的指令码组成是计算机唯一能识别并直接执行的语言

用助记符号描述的指令系统如ADD SUB需翻译成机器语言符号化的机器语言

httpmathecnueducn~jypan 5

高级语言典型代表

- FORTRANFormula Translation1956年高级语言诞生的标志简洁高效科学计算主流语言

- C1972年贝尔实验室的 DM Ritchie(哈佛大学数学博士) 在 B 语言的基础上开发是一种通用的过程式的编程语言高效灵活功能丰富主流的系统软件开发和科学计算语言

- C++1983年继承 C 的所有优点增加面向对象功能

httpmathecnueducn~jypan 6

高级语言的发展(部分)52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96

Ada

ALGOL60 ALGOL68Pascal

Modula-2

BCPL B CC++

Java

LISPPROLOG

COBOL

FORTRAN77FORTRANPL1

Simula 67

Smalltalk 80

BASIC ANSI-BASIC QBASIC VB

FORTRAN90

CPL

httpmathecnueducn~jypan 7

C 语言概述

1969-1973由 Dennis M Ritchie 设计并实现

1973UNIX 的内核正式用 C 语言改写

1978B Kernighan 和 D Ritchie《C程序设计语言》

1983-1989ANSI C 标准形成 (C89 C90) 1999ISO 正式发布新的标准 C99 2011C11 标准发布

C 语言发展历史

httpmathecnueducn~jypan

Example calculate the sum of a and b

include ltstdiohgt

main()

int a b sum

a=10 b=24sum=add(ab)printf(sum=dn sum)

int add(int xint y)

int zz=x+yreturn(z)

8

一个简单的 C 程序

主函数

打印语句

预处理

注解语句

C 源程序结构

一个 C 源程序由一个或多个源文件组成

每个源文件可由一个或多个函数组成

一个源程序有且只能有一个 main 函数

程序执行从 main 开始在 main 中结束

源程序中可以有预处理命令通常应放

在源文件或源程序的最前面

httpmathecnueducn~jypan 9

C 程序书写规范

每个说明和每个语句都必须以分号ldquordquo结尾但预处理命令函数

头和花括号ldquordquo之后不能加分号

标识符关键字之间必须至少加一个空格以示间隔若已有明显的间

隔符也可不再加空格来间隔

一行可以写多个语句一个语句可以分几行书写

区分大小写习惯用小写字母

注释 为注释符 不能嵌套

常用锯齿形书写格式

书写规范

书写漂亮的程序

要对齐

一行写一个语句

一个语句写一行

使用 TAB 缩进

有合适的空行

有足够的注释注所有标点符号必须在英文状态下输入

httpmathecnueducn~jypan 10

C 语言编译器

编译器就是将ldquo高级语言rdquo翻译为ldquo机器语言rdquo的程序

编译器

常见的 C 语言编译器

源代码 目标代码 可执行程序编译 链接

一个现代编译器的主要工作流程

Visual C Windows 平台上流行的编译器集成在 Visual Studio 中

GNU C 开源免费LinuxUnix 平台上的首选非常优秀的编译器

Intel C Intel 的编译器对自家硬件的支持很好WinLinux 都有相应版本

httpmathecnueducn~jypan 11

IDE

Integrated Development Environment IDE (集成开发环境)

Windows 下常见的 C++ 集成开发环境

用于程序开发的应用程序软件一般包括代码编辑器

编译器调试器和图形用户界面工具等

- Visual Studio Windows 平台上最流行的商业 CC++ 集成开发环境

- Dev C++ 小巧免费win 下的 gcc非常适合学习 CC++

- CodeBlocks 开放源码的全功能跨平台集成开发环境免费

httpmathecnueducn~jypan 12

字符集

字母(大写和小写共 52 个)

数字(0 到 9 共 10 个)

空白符(空格符制表符换行符)

标点和特殊字符

C 语言字符集

注这里的标点符号都是指在英文状态下的标点

^ amp () [] _ + = - ~ lt gt

httpmathecnueducn~jypan 13

词法记号词汇

标识符用来标识变量名函数名对象名等的字符序列

- 由字母数字下划线组成第一个字符必须是字母或下划线

- 区分大小写不能用关键字

- 不限制标识符长度实际长度与编译器有关

- 命名原则见名知意不宜混淆

运算符(详见后面介绍)

分隔符逗号冒号分号空格(){}

注释符以ldquordquo开头并以ldquordquo结尾或者 (行注释符)

文字直接用字符表示的数据即常量如数字字符串等

关键字具有特定意义的字符串通常也称为保留字

- 类型说明符语句定义符(控制命令)预处理命令等

httpmathecnueducn~jypan 14

代码编写与运行

1) 编写源程序以 c 为扩展名(可使用任何文本编辑器)

2) 编译并连接源文件 (可以一步完成)

gcc [选项] 源代码文件

-o 指定输出文件名缺省为 aout -c 只编译不链接即只生产目标文件(o 文件)

-Ipath 指定或增加包含文件(如 h)的搜索路径

-Lpath 指定(增加)库文件的搜索路径

-lname与库文件 libnamea 链接

-O-O1-O2-O3 优化开关

-g 在目标码中加入更多信息用于程序调试

常用选项

3) 运行生成的可执行文件

httpmathecnueducn~jypan 15

C 语言数据类型

整型

实型

字符型 (char)

整型 (int)短整型 (short)长整型 (long)

单精度 (float)双精度 (double)

基本类型

C数

布尔型 (bool)

无符号 (unsigned)有符号

自定义数据类型或扩展数据类型或派生数据类型或导出数据类型

数组

结构联合

指针

hellip hellip

httpmathecnueducn~jypan 16

基本数据类型

类型 关键字 所占字节数 表示范围

整型 short 2 -215 ~ 215 -1

int 2 4 -215 ~ 215 -1 -231 ~ 231 -1

long 4 8 -231 ~ 231 -1 -263 ~ 263 -1

unsigned short 2 0 ~ 216 -1

unsigned int 24 0 ~ 216 -1 0 ~ 232 -1

unsigned long 48 0 ~ 232 -1 0 ~ 264 -1

实型 float 4 (6-7) 10-38 ~ 1038

double 8 (15-16) 10-308 ~ 10308

long double 16 (18-19) 10-4932 ~ 104932

布尔型 bool 1 true false

字符型 char 1

C 没有规定每种数据类型的字节数和表示范围只规定大小顺序具体长度由

处理器和编译器决定

更长的整型long long unsigned long longex_datatypec

httpmathecnueducn~jypan 17

数据类型转换

printf(12=fn 12)printf(102=fn 102)

ex_datetype_02cpp

charrarrshortrarrintrarr longrarrunsigned longrarrdoublelarrfloat

不同类型的数据进行运算需先转换成同一类型

转换按数据长度增加的方向进行以保证精度不降低

所有的浮点运算都是以双精度进行的

char 型和 short 型参与运算时必须先转换成 int 型

赋值号两边的数据类型不同时右边的类型将转换为左边的

自动转换隐式转换

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 2: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

1

2C 语言基础

选择与循环3 函数4 指针与字符串

5 文件操作

谭浩强C 程序设计第5版2017 Kernighan amp RitchieThe C Programming Language 2nd 1988 Schildt C The Complete Reference 4th 2000

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

C 语言介绍

数据类型

输入输出

数组

1 C 语言基础

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 4

程序设计语言的发展

机器语言

汇编语言

高级语言

面向过程 面向对象 面向应用

效率高编程难

CPU指令系统由 01 构成的指令码组成是计算机唯一能识别并直接执行的语言

用助记符号描述的指令系统如ADD SUB需翻译成机器语言符号化的机器语言

httpmathecnueducn~jypan 5

高级语言典型代表

- FORTRANFormula Translation1956年高级语言诞生的标志简洁高效科学计算主流语言

- C1972年贝尔实验室的 DM Ritchie(哈佛大学数学博士) 在 B 语言的基础上开发是一种通用的过程式的编程语言高效灵活功能丰富主流的系统软件开发和科学计算语言

- C++1983年继承 C 的所有优点增加面向对象功能

httpmathecnueducn~jypan 6

高级语言的发展(部分)52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96

Ada

ALGOL60 ALGOL68Pascal

Modula-2

BCPL B CC++

Java

LISPPROLOG

COBOL

FORTRAN77FORTRANPL1

Simula 67

Smalltalk 80

BASIC ANSI-BASIC QBASIC VB

FORTRAN90

CPL

httpmathecnueducn~jypan 7

C 语言概述

1969-1973由 Dennis M Ritchie 设计并实现

1973UNIX 的内核正式用 C 语言改写

1978B Kernighan 和 D Ritchie《C程序设计语言》

1983-1989ANSI C 标准形成 (C89 C90) 1999ISO 正式发布新的标准 C99 2011C11 标准发布

C 语言发展历史

httpmathecnueducn~jypan

Example calculate the sum of a and b

include ltstdiohgt

main()

int a b sum

a=10 b=24sum=add(ab)printf(sum=dn sum)

int add(int xint y)

int zz=x+yreturn(z)

8

一个简单的 C 程序

主函数

打印语句

预处理

注解语句

C 源程序结构

一个 C 源程序由一个或多个源文件组成

每个源文件可由一个或多个函数组成

一个源程序有且只能有一个 main 函数

程序执行从 main 开始在 main 中结束

源程序中可以有预处理命令通常应放

在源文件或源程序的最前面

httpmathecnueducn~jypan 9

C 程序书写规范

每个说明和每个语句都必须以分号ldquordquo结尾但预处理命令函数

头和花括号ldquordquo之后不能加分号

标识符关键字之间必须至少加一个空格以示间隔若已有明显的间

隔符也可不再加空格来间隔

一行可以写多个语句一个语句可以分几行书写

区分大小写习惯用小写字母

注释 为注释符 不能嵌套

常用锯齿形书写格式

书写规范

书写漂亮的程序

要对齐

一行写一个语句

一个语句写一行

使用 TAB 缩进

有合适的空行

有足够的注释注所有标点符号必须在英文状态下输入

httpmathecnueducn~jypan 10

C 语言编译器

编译器就是将ldquo高级语言rdquo翻译为ldquo机器语言rdquo的程序

编译器

常见的 C 语言编译器

源代码 目标代码 可执行程序编译 链接

一个现代编译器的主要工作流程

Visual C Windows 平台上流行的编译器集成在 Visual Studio 中

GNU C 开源免费LinuxUnix 平台上的首选非常优秀的编译器

Intel C Intel 的编译器对自家硬件的支持很好WinLinux 都有相应版本

httpmathecnueducn~jypan 11

IDE

Integrated Development Environment IDE (集成开发环境)

Windows 下常见的 C++ 集成开发环境

用于程序开发的应用程序软件一般包括代码编辑器

编译器调试器和图形用户界面工具等

- Visual Studio Windows 平台上最流行的商业 CC++ 集成开发环境

- Dev C++ 小巧免费win 下的 gcc非常适合学习 CC++

- CodeBlocks 开放源码的全功能跨平台集成开发环境免费

httpmathecnueducn~jypan 12

字符集

字母(大写和小写共 52 个)

数字(0 到 9 共 10 个)

空白符(空格符制表符换行符)

标点和特殊字符

C 语言字符集

注这里的标点符号都是指在英文状态下的标点

^ amp () [] _ + = - ~ lt gt

httpmathecnueducn~jypan 13

词法记号词汇

标识符用来标识变量名函数名对象名等的字符序列

- 由字母数字下划线组成第一个字符必须是字母或下划线

- 区分大小写不能用关键字

- 不限制标识符长度实际长度与编译器有关

- 命名原则见名知意不宜混淆

运算符(详见后面介绍)

分隔符逗号冒号分号空格(){}

注释符以ldquordquo开头并以ldquordquo结尾或者 (行注释符)

文字直接用字符表示的数据即常量如数字字符串等

关键字具有特定意义的字符串通常也称为保留字

- 类型说明符语句定义符(控制命令)预处理命令等

httpmathecnueducn~jypan 14

代码编写与运行

1) 编写源程序以 c 为扩展名(可使用任何文本编辑器)

2) 编译并连接源文件 (可以一步完成)

gcc [选项] 源代码文件

-o 指定输出文件名缺省为 aout -c 只编译不链接即只生产目标文件(o 文件)

-Ipath 指定或增加包含文件(如 h)的搜索路径

-Lpath 指定(增加)库文件的搜索路径

-lname与库文件 libnamea 链接

-O-O1-O2-O3 优化开关

-g 在目标码中加入更多信息用于程序调试

常用选项

3) 运行生成的可执行文件

httpmathecnueducn~jypan 15

C 语言数据类型

整型

实型

字符型 (char)

整型 (int)短整型 (short)长整型 (long)

单精度 (float)双精度 (double)

基本类型

C数

布尔型 (bool)

无符号 (unsigned)有符号

自定义数据类型或扩展数据类型或派生数据类型或导出数据类型

数组

结构联合

指针

hellip hellip

httpmathecnueducn~jypan 16

基本数据类型

类型 关键字 所占字节数 表示范围

整型 short 2 -215 ~ 215 -1

int 2 4 -215 ~ 215 -1 -231 ~ 231 -1

long 4 8 -231 ~ 231 -1 -263 ~ 263 -1

unsigned short 2 0 ~ 216 -1

unsigned int 24 0 ~ 216 -1 0 ~ 232 -1

unsigned long 48 0 ~ 232 -1 0 ~ 264 -1

实型 float 4 (6-7) 10-38 ~ 1038

double 8 (15-16) 10-308 ~ 10308

long double 16 (18-19) 10-4932 ~ 104932

布尔型 bool 1 true false

字符型 char 1

C 没有规定每种数据类型的字节数和表示范围只规定大小顺序具体长度由

处理器和编译器决定

更长的整型long long unsigned long longex_datatypec

httpmathecnueducn~jypan 17

数据类型转换

printf(12=fn 12)printf(102=fn 102)

ex_datetype_02cpp

charrarrshortrarrintrarr longrarrunsigned longrarrdoublelarrfloat

不同类型的数据进行运算需先转换成同一类型

转换按数据长度增加的方向进行以保证精度不降低

所有的浮点运算都是以双精度进行的

char 型和 short 型参与运算时必须先转换成 int 型

赋值号两边的数据类型不同时右边的类型将转换为左边的

自动转换隐式转换

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 3: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

C 语言介绍

数据类型

输入输出

数组

1 C 语言基础

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 4

程序设计语言的发展

机器语言

汇编语言

高级语言

面向过程 面向对象 面向应用

效率高编程难

CPU指令系统由 01 构成的指令码组成是计算机唯一能识别并直接执行的语言

用助记符号描述的指令系统如ADD SUB需翻译成机器语言符号化的机器语言

httpmathecnueducn~jypan 5

高级语言典型代表

- FORTRANFormula Translation1956年高级语言诞生的标志简洁高效科学计算主流语言

- C1972年贝尔实验室的 DM Ritchie(哈佛大学数学博士) 在 B 语言的基础上开发是一种通用的过程式的编程语言高效灵活功能丰富主流的系统软件开发和科学计算语言

- C++1983年继承 C 的所有优点增加面向对象功能

httpmathecnueducn~jypan 6

高级语言的发展(部分)52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96

Ada

ALGOL60 ALGOL68Pascal

Modula-2

BCPL B CC++

Java

LISPPROLOG

COBOL

FORTRAN77FORTRANPL1

Simula 67

Smalltalk 80

BASIC ANSI-BASIC QBASIC VB

FORTRAN90

CPL

httpmathecnueducn~jypan 7

C 语言概述

1969-1973由 Dennis M Ritchie 设计并实现

1973UNIX 的内核正式用 C 语言改写

1978B Kernighan 和 D Ritchie《C程序设计语言》

1983-1989ANSI C 标准形成 (C89 C90) 1999ISO 正式发布新的标准 C99 2011C11 标准发布

C 语言发展历史

httpmathecnueducn~jypan

Example calculate the sum of a and b

include ltstdiohgt

main()

int a b sum

a=10 b=24sum=add(ab)printf(sum=dn sum)

int add(int xint y)

int zz=x+yreturn(z)

8

一个简单的 C 程序

主函数

打印语句

预处理

注解语句

C 源程序结构

一个 C 源程序由一个或多个源文件组成

每个源文件可由一个或多个函数组成

一个源程序有且只能有一个 main 函数

程序执行从 main 开始在 main 中结束

源程序中可以有预处理命令通常应放

在源文件或源程序的最前面

httpmathecnueducn~jypan 9

C 程序书写规范

每个说明和每个语句都必须以分号ldquordquo结尾但预处理命令函数

头和花括号ldquordquo之后不能加分号

标识符关键字之间必须至少加一个空格以示间隔若已有明显的间

隔符也可不再加空格来间隔

一行可以写多个语句一个语句可以分几行书写

区分大小写习惯用小写字母

注释 为注释符 不能嵌套

常用锯齿形书写格式

书写规范

书写漂亮的程序

要对齐

一行写一个语句

一个语句写一行

使用 TAB 缩进

有合适的空行

有足够的注释注所有标点符号必须在英文状态下输入

httpmathecnueducn~jypan 10

C 语言编译器

编译器就是将ldquo高级语言rdquo翻译为ldquo机器语言rdquo的程序

编译器

常见的 C 语言编译器

源代码 目标代码 可执行程序编译 链接

一个现代编译器的主要工作流程

Visual C Windows 平台上流行的编译器集成在 Visual Studio 中

GNU C 开源免费LinuxUnix 平台上的首选非常优秀的编译器

Intel C Intel 的编译器对自家硬件的支持很好WinLinux 都有相应版本

httpmathecnueducn~jypan 11

IDE

Integrated Development Environment IDE (集成开发环境)

Windows 下常见的 C++ 集成开发环境

用于程序开发的应用程序软件一般包括代码编辑器

编译器调试器和图形用户界面工具等

- Visual Studio Windows 平台上最流行的商业 CC++ 集成开发环境

- Dev C++ 小巧免费win 下的 gcc非常适合学习 CC++

- CodeBlocks 开放源码的全功能跨平台集成开发环境免费

httpmathecnueducn~jypan 12

字符集

字母(大写和小写共 52 个)

数字(0 到 9 共 10 个)

空白符(空格符制表符换行符)

标点和特殊字符

C 语言字符集

注这里的标点符号都是指在英文状态下的标点

^ amp () [] _ + = - ~ lt gt

httpmathecnueducn~jypan 13

词法记号词汇

标识符用来标识变量名函数名对象名等的字符序列

- 由字母数字下划线组成第一个字符必须是字母或下划线

- 区分大小写不能用关键字

- 不限制标识符长度实际长度与编译器有关

- 命名原则见名知意不宜混淆

运算符(详见后面介绍)

分隔符逗号冒号分号空格(){}

注释符以ldquordquo开头并以ldquordquo结尾或者 (行注释符)

文字直接用字符表示的数据即常量如数字字符串等

关键字具有特定意义的字符串通常也称为保留字

- 类型说明符语句定义符(控制命令)预处理命令等

httpmathecnueducn~jypan 14

代码编写与运行

1) 编写源程序以 c 为扩展名(可使用任何文本编辑器)

2) 编译并连接源文件 (可以一步完成)

gcc [选项] 源代码文件

-o 指定输出文件名缺省为 aout -c 只编译不链接即只生产目标文件(o 文件)

-Ipath 指定或增加包含文件(如 h)的搜索路径

-Lpath 指定(增加)库文件的搜索路径

-lname与库文件 libnamea 链接

-O-O1-O2-O3 优化开关

-g 在目标码中加入更多信息用于程序调试

常用选项

3) 运行生成的可执行文件

httpmathecnueducn~jypan 15

C 语言数据类型

整型

实型

字符型 (char)

整型 (int)短整型 (short)长整型 (long)

单精度 (float)双精度 (double)

基本类型

C数

布尔型 (bool)

无符号 (unsigned)有符号

自定义数据类型或扩展数据类型或派生数据类型或导出数据类型

数组

结构联合

指针

hellip hellip

httpmathecnueducn~jypan 16

基本数据类型

类型 关键字 所占字节数 表示范围

整型 short 2 -215 ~ 215 -1

int 2 4 -215 ~ 215 -1 -231 ~ 231 -1

long 4 8 -231 ~ 231 -1 -263 ~ 263 -1

unsigned short 2 0 ~ 216 -1

unsigned int 24 0 ~ 216 -1 0 ~ 232 -1

unsigned long 48 0 ~ 232 -1 0 ~ 264 -1

实型 float 4 (6-7) 10-38 ~ 1038

double 8 (15-16) 10-308 ~ 10308

long double 16 (18-19) 10-4932 ~ 104932

布尔型 bool 1 true false

字符型 char 1

C 没有规定每种数据类型的字节数和表示范围只规定大小顺序具体长度由

处理器和编译器决定

更长的整型long long unsigned long longex_datatypec

httpmathecnueducn~jypan 17

数据类型转换

printf(12=fn 12)printf(102=fn 102)

ex_datetype_02cpp

charrarrshortrarrintrarr longrarrunsigned longrarrdoublelarrfloat

不同类型的数据进行运算需先转换成同一类型

转换按数据长度增加的方向进行以保证精度不降低

所有的浮点运算都是以双精度进行的

char 型和 short 型参与运算时必须先转换成 int 型

赋值号两边的数据类型不同时右边的类型将转换为左边的

自动转换隐式转换

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 4: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 4

程序设计语言的发展

机器语言

汇编语言

高级语言

面向过程 面向对象 面向应用

效率高编程难

CPU指令系统由 01 构成的指令码组成是计算机唯一能识别并直接执行的语言

用助记符号描述的指令系统如ADD SUB需翻译成机器语言符号化的机器语言

httpmathecnueducn~jypan 5

高级语言典型代表

- FORTRANFormula Translation1956年高级语言诞生的标志简洁高效科学计算主流语言

- C1972年贝尔实验室的 DM Ritchie(哈佛大学数学博士) 在 B 语言的基础上开发是一种通用的过程式的编程语言高效灵活功能丰富主流的系统软件开发和科学计算语言

- C++1983年继承 C 的所有优点增加面向对象功能

httpmathecnueducn~jypan 6

高级语言的发展(部分)52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96

Ada

ALGOL60 ALGOL68Pascal

Modula-2

BCPL B CC++

Java

LISPPROLOG

COBOL

FORTRAN77FORTRANPL1

Simula 67

Smalltalk 80

BASIC ANSI-BASIC QBASIC VB

FORTRAN90

CPL

httpmathecnueducn~jypan 7

C 语言概述

1969-1973由 Dennis M Ritchie 设计并实现

1973UNIX 的内核正式用 C 语言改写

1978B Kernighan 和 D Ritchie《C程序设计语言》

1983-1989ANSI C 标准形成 (C89 C90) 1999ISO 正式发布新的标准 C99 2011C11 标准发布

C 语言发展历史

httpmathecnueducn~jypan

Example calculate the sum of a and b

include ltstdiohgt

main()

int a b sum

a=10 b=24sum=add(ab)printf(sum=dn sum)

int add(int xint y)

int zz=x+yreturn(z)

8

一个简单的 C 程序

主函数

打印语句

预处理

注解语句

C 源程序结构

一个 C 源程序由一个或多个源文件组成

每个源文件可由一个或多个函数组成

一个源程序有且只能有一个 main 函数

程序执行从 main 开始在 main 中结束

源程序中可以有预处理命令通常应放

在源文件或源程序的最前面

httpmathecnueducn~jypan 9

C 程序书写规范

每个说明和每个语句都必须以分号ldquordquo结尾但预处理命令函数

头和花括号ldquordquo之后不能加分号

标识符关键字之间必须至少加一个空格以示间隔若已有明显的间

隔符也可不再加空格来间隔

一行可以写多个语句一个语句可以分几行书写

区分大小写习惯用小写字母

注释 为注释符 不能嵌套

常用锯齿形书写格式

书写规范

书写漂亮的程序

要对齐

一行写一个语句

一个语句写一行

使用 TAB 缩进

有合适的空行

有足够的注释注所有标点符号必须在英文状态下输入

httpmathecnueducn~jypan 10

C 语言编译器

编译器就是将ldquo高级语言rdquo翻译为ldquo机器语言rdquo的程序

编译器

常见的 C 语言编译器

源代码 目标代码 可执行程序编译 链接

一个现代编译器的主要工作流程

Visual C Windows 平台上流行的编译器集成在 Visual Studio 中

GNU C 开源免费LinuxUnix 平台上的首选非常优秀的编译器

Intel C Intel 的编译器对自家硬件的支持很好WinLinux 都有相应版本

httpmathecnueducn~jypan 11

IDE

Integrated Development Environment IDE (集成开发环境)

Windows 下常见的 C++ 集成开发环境

用于程序开发的应用程序软件一般包括代码编辑器

编译器调试器和图形用户界面工具等

- Visual Studio Windows 平台上最流行的商业 CC++ 集成开发环境

- Dev C++ 小巧免费win 下的 gcc非常适合学习 CC++

- CodeBlocks 开放源码的全功能跨平台集成开发环境免费

httpmathecnueducn~jypan 12

字符集

字母(大写和小写共 52 个)

数字(0 到 9 共 10 个)

空白符(空格符制表符换行符)

标点和特殊字符

C 语言字符集

注这里的标点符号都是指在英文状态下的标点

^ amp () [] _ + = - ~ lt gt

httpmathecnueducn~jypan 13

词法记号词汇

标识符用来标识变量名函数名对象名等的字符序列

- 由字母数字下划线组成第一个字符必须是字母或下划线

- 区分大小写不能用关键字

- 不限制标识符长度实际长度与编译器有关

- 命名原则见名知意不宜混淆

运算符(详见后面介绍)

分隔符逗号冒号分号空格(){}

注释符以ldquordquo开头并以ldquordquo结尾或者 (行注释符)

文字直接用字符表示的数据即常量如数字字符串等

关键字具有特定意义的字符串通常也称为保留字

- 类型说明符语句定义符(控制命令)预处理命令等

httpmathecnueducn~jypan 14

代码编写与运行

1) 编写源程序以 c 为扩展名(可使用任何文本编辑器)

2) 编译并连接源文件 (可以一步完成)

gcc [选项] 源代码文件

-o 指定输出文件名缺省为 aout -c 只编译不链接即只生产目标文件(o 文件)

-Ipath 指定或增加包含文件(如 h)的搜索路径

-Lpath 指定(增加)库文件的搜索路径

-lname与库文件 libnamea 链接

-O-O1-O2-O3 优化开关

-g 在目标码中加入更多信息用于程序调试

常用选项

3) 运行生成的可执行文件

httpmathecnueducn~jypan 15

C 语言数据类型

整型

实型

字符型 (char)

整型 (int)短整型 (short)长整型 (long)

单精度 (float)双精度 (double)

基本类型

C数

布尔型 (bool)

无符号 (unsigned)有符号

自定义数据类型或扩展数据类型或派生数据类型或导出数据类型

数组

结构联合

指针

hellip hellip

httpmathecnueducn~jypan 16

基本数据类型

类型 关键字 所占字节数 表示范围

整型 short 2 -215 ~ 215 -1

int 2 4 -215 ~ 215 -1 -231 ~ 231 -1

long 4 8 -231 ~ 231 -1 -263 ~ 263 -1

unsigned short 2 0 ~ 216 -1

unsigned int 24 0 ~ 216 -1 0 ~ 232 -1

unsigned long 48 0 ~ 232 -1 0 ~ 264 -1

实型 float 4 (6-7) 10-38 ~ 1038

double 8 (15-16) 10-308 ~ 10308

long double 16 (18-19) 10-4932 ~ 104932

布尔型 bool 1 true false

字符型 char 1

C 没有规定每种数据类型的字节数和表示范围只规定大小顺序具体长度由

处理器和编译器决定

更长的整型long long unsigned long longex_datatypec

httpmathecnueducn~jypan 17

数据类型转换

printf(12=fn 12)printf(102=fn 102)

ex_datetype_02cpp

charrarrshortrarrintrarr longrarrunsigned longrarrdoublelarrfloat

不同类型的数据进行运算需先转换成同一类型

转换按数据长度增加的方向进行以保证精度不降低

所有的浮点运算都是以双精度进行的

char 型和 short 型参与运算时必须先转换成 int 型

赋值号两边的数据类型不同时右边的类型将转换为左边的

自动转换隐式转换

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 5: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 5

高级语言典型代表

- FORTRANFormula Translation1956年高级语言诞生的标志简洁高效科学计算主流语言

- C1972年贝尔实验室的 DM Ritchie(哈佛大学数学博士) 在 B 语言的基础上开发是一种通用的过程式的编程语言高效灵活功能丰富主流的系统软件开发和科学计算语言

- C++1983年继承 C 的所有优点增加面向对象功能

httpmathecnueducn~jypan 6

高级语言的发展(部分)52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96

Ada

ALGOL60 ALGOL68Pascal

Modula-2

BCPL B CC++

Java

LISPPROLOG

COBOL

FORTRAN77FORTRANPL1

Simula 67

Smalltalk 80

BASIC ANSI-BASIC QBASIC VB

FORTRAN90

CPL

httpmathecnueducn~jypan 7

C 语言概述

1969-1973由 Dennis M Ritchie 设计并实现

1973UNIX 的内核正式用 C 语言改写

1978B Kernighan 和 D Ritchie《C程序设计语言》

1983-1989ANSI C 标准形成 (C89 C90) 1999ISO 正式发布新的标准 C99 2011C11 标准发布

C 语言发展历史

httpmathecnueducn~jypan

Example calculate the sum of a and b

include ltstdiohgt

main()

int a b sum

a=10 b=24sum=add(ab)printf(sum=dn sum)

int add(int xint y)

int zz=x+yreturn(z)

8

一个简单的 C 程序

主函数

打印语句

预处理

注解语句

C 源程序结构

一个 C 源程序由一个或多个源文件组成

每个源文件可由一个或多个函数组成

一个源程序有且只能有一个 main 函数

程序执行从 main 开始在 main 中结束

源程序中可以有预处理命令通常应放

在源文件或源程序的最前面

httpmathecnueducn~jypan 9

C 程序书写规范

每个说明和每个语句都必须以分号ldquordquo结尾但预处理命令函数

头和花括号ldquordquo之后不能加分号

标识符关键字之间必须至少加一个空格以示间隔若已有明显的间

隔符也可不再加空格来间隔

一行可以写多个语句一个语句可以分几行书写

区分大小写习惯用小写字母

注释 为注释符 不能嵌套

常用锯齿形书写格式

书写规范

书写漂亮的程序

要对齐

一行写一个语句

一个语句写一行

使用 TAB 缩进

有合适的空行

有足够的注释注所有标点符号必须在英文状态下输入

httpmathecnueducn~jypan 10

C 语言编译器

编译器就是将ldquo高级语言rdquo翻译为ldquo机器语言rdquo的程序

编译器

常见的 C 语言编译器

源代码 目标代码 可执行程序编译 链接

一个现代编译器的主要工作流程

Visual C Windows 平台上流行的编译器集成在 Visual Studio 中

GNU C 开源免费LinuxUnix 平台上的首选非常优秀的编译器

Intel C Intel 的编译器对自家硬件的支持很好WinLinux 都有相应版本

httpmathecnueducn~jypan 11

IDE

Integrated Development Environment IDE (集成开发环境)

Windows 下常见的 C++ 集成开发环境

用于程序开发的应用程序软件一般包括代码编辑器

编译器调试器和图形用户界面工具等

- Visual Studio Windows 平台上最流行的商业 CC++ 集成开发环境

- Dev C++ 小巧免费win 下的 gcc非常适合学习 CC++

- CodeBlocks 开放源码的全功能跨平台集成开发环境免费

httpmathecnueducn~jypan 12

字符集

字母(大写和小写共 52 个)

数字(0 到 9 共 10 个)

空白符(空格符制表符换行符)

标点和特殊字符

C 语言字符集

注这里的标点符号都是指在英文状态下的标点

^ amp () [] _ + = - ~ lt gt

httpmathecnueducn~jypan 13

词法记号词汇

标识符用来标识变量名函数名对象名等的字符序列

- 由字母数字下划线组成第一个字符必须是字母或下划线

- 区分大小写不能用关键字

- 不限制标识符长度实际长度与编译器有关

- 命名原则见名知意不宜混淆

运算符(详见后面介绍)

分隔符逗号冒号分号空格(){}

注释符以ldquordquo开头并以ldquordquo结尾或者 (行注释符)

文字直接用字符表示的数据即常量如数字字符串等

关键字具有特定意义的字符串通常也称为保留字

- 类型说明符语句定义符(控制命令)预处理命令等

httpmathecnueducn~jypan 14

代码编写与运行

1) 编写源程序以 c 为扩展名(可使用任何文本编辑器)

2) 编译并连接源文件 (可以一步完成)

gcc [选项] 源代码文件

-o 指定输出文件名缺省为 aout -c 只编译不链接即只生产目标文件(o 文件)

-Ipath 指定或增加包含文件(如 h)的搜索路径

-Lpath 指定(增加)库文件的搜索路径

-lname与库文件 libnamea 链接

-O-O1-O2-O3 优化开关

-g 在目标码中加入更多信息用于程序调试

常用选项

3) 运行生成的可执行文件

httpmathecnueducn~jypan 15

C 语言数据类型

整型

实型

字符型 (char)

整型 (int)短整型 (short)长整型 (long)

单精度 (float)双精度 (double)

基本类型

C数

布尔型 (bool)

无符号 (unsigned)有符号

自定义数据类型或扩展数据类型或派生数据类型或导出数据类型

数组

结构联合

指针

hellip hellip

httpmathecnueducn~jypan 16

基本数据类型

类型 关键字 所占字节数 表示范围

整型 short 2 -215 ~ 215 -1

int 2 4 -215 ~ 215 -1 -231 ~ 231 -1

long 4 8 -231 ~ 231 -1 -263 ~ 263 -1

unsigned short 2 0 ~ 216 -1

unsigned int 24 0 ~ 216 -1 0 ~ 232 -1

unsigned long 48 0 ~ 232 -1 0 ~ 264 -1

实型 float 4 (6-7) 10-38 ~ 1038

double 8 (15-16) 10-308 ~ 10308

long double 16 (18-19) 10-4932 ~ 104932

布尔型 bool 1 true false

字符型 char 1

C 没有规定每种数据类型的字节数和表示范围只规定大小顺序具体长度由

处理器和编译器决定

更长的整型long long unsigned long longex_datatypec

httpmathecnueducn~jypan 17

数据类型转换

printf(12=fn 12)printf(102=fn 102)

ex_datetype_02cpp

charrarrshortrarrintrarr longrarrunsigned longrarrdoublelarrfloat

不同类型的数据进行运算需先转换成同一类型

转换按数据长度增加的方向进行以保证精度不降低

所有的浮点运算都是以双精度进行的

char 型和 short 型参与运算时必须先转换成 int 型

赋值号两边的数据类型不同时右边的类型将转换为左边的

自动转换隐式转换

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 6: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 6

高级语言的发展(部分)52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96

Ada

ALGOL60 ALGOL68Pascal

Modula-2

BCPL B CC++

Java

LISPPROLOG

COBOL

FORTRAN77FORTRANPL1

Simula 67

Smalltalk 80

BASIC ANSI-BASIC QBASIC VB

FORTRAN90

CPL

httpmathecnueducn~jypan 7

C 语言概述

1969-1973由 Dennis M Ritchie 设计并实现

1973UNIX 的内核正式用 C 语言改写

1978B Kernighan 和 D Ritchie《C程序设计语言》

1983-1989ANSI C 标准形成 (C89 C90) 1999ISO 正式发布新的标准 C99 2011C11 标准发布

C 语言发展历史

httpmathecnueducn~jypan

Example calculate the sum of a and b

include ltstdiohgt

main()

int a b sum

a=10 b=24sum=add(ab)printf(sum=dn sum)

int add(int xint y)

int zz=x+yreturn(z)

8

一个简单的 C 程序

主函数

打印语句

预处理

注解语句

C 源程序结构

一个 C 源程序由一个或多个源文件组成

每个源文件可由一个或多个函数组成

一个源程序有且只能有一个 main 函数

程序执行从 main 开始在 main 中结束

源程序中可以有预处理命令通常应放

在源文件或源程序的最前面

httpmathecnueducn~jypan 9

C 程序书写规范

每个说明和每个语句都必须以分号ldquordquo结尾但预处理命令函数

头和花括号ldquordquo之后不能加分号

标识符关键字之间必须至少加一个空格以示间隔若已有明显的间

隔符也可不再加空格来间隔

一行可以写多个语句一个语句可以分几行书写

区分大小写习惯用小写字母

注释 为注释符 不能嵌套

常用锯齿形书写格式

书写规范

书写漂亮的程序

要对齐

一行写一个语句

一个语句写一行

使用 TAB 缩进

有合适的空行

有足够的注释注所有标点符号必须在英文状态下输入

httpmathecnueducn~jypan 10

C 语言编译器

编译器就是将ldquo高级语言rdquo翻译为ldquo机器语言rdquo的程序

编译器

常见的 C 语言编译器

源代码 目标代码 可执行程序编译 链接

一个现代编译器的主要工作流程

Visual C Windows 平台上流行的编译器集成在 Visual Studio 中

GNU C 开源免费LinuxUnix 平台上的首选非常优秀的编译器

Intel C Intel 的编译器对自家硬件的支持很好WinLinux 都有相应版本

httpmathecnueducn~jypan 11

IDE

Integrated Development Environment IDE (集成开发环境)

Windows 下常见的 C++ 集成开发环境

用于程序开发的应用程序软件一般包括代码编辑器

编译器调试器和图形用户界面工具等

- Visual Studio Windows 平台上最流行的商业 CC++ 集成开发环境

- Dev C++ 小巧免费win 下的 gcc非常适合学习 CC++

- CodeBlocks 开放源码的全功能跨平台集成开发环境免费

httpmathecnueducn~jypan 12

字符集

字母(大写和小写共 52 个)

数字(0 到 9 共 10 个)

空白符(空格符制表符换行符)

标点和特殊字符

C 语言字符集

注这里的标点符号都是指在英文状态下的标点

^ amp () [] _ + = - ~ lt gt

httpmathecnueducn~jypan 13

词法记号词汇

标识符用来标识变量名函数名对象名等的字符序列

- 由字母数字下划线组成第一个字符必须是字母或下划线

- 区分大小写不能用关键字

- 不限制标识符长度实际长度与编译器有关

- 命名原则见名知意不宜混淆

运算符(详见后面介绍)

分隔符逗号冒号分号空格(){}

注释符以ldquordquo开头并以ldquordquo结尾或者 (行注释符)

文字直接用字符表示的数据即常量如数字字符串等

关键字具有特定意义的字符串通常也称为保留字

- 类型说明符语句定义符(控制命令)预处理命令等

httpmathecnueducn~jypan 14

代码编写与运行

1) 编写源程序以 c 为扩展名(可使用任何文本编辑器)

2) 编译并连接源文件 (可以一步完成)

gcc [选项] 源代码文件

-o 指定输出文件名缺省为 aout -c 只编译不链接即只生产目标文件(o 文件)

-Ipath 指定或增加包含文件(如 h)的搜索路径

-Lpath 指定(增加)库文件的搜索路径

-lname与库文件 libnamea 链接

-O-O1-O2-O3 优化开关

-g 在目标码中加入更多信息用于程序调试

常用选项

3) 运行生成的可执行文件

httpmathecnueducn~jypan 15

C 语言数据类型

整型

实型

字符型 (char)

整型 (int)短整型 (short)长整型 (long)

单精度 (float)双精度 (double)

基本类型

C数

布尔型 (bool)

无符号 (unsigned)有符号

自定义数据类型或扩展数据类型或派生数据类型或导出数据类型

数组

结构联合

指针

hellip hellip

httpmathecnueducn~jypan 16

基本数据类型

类型 关键字 所占字节数 表示范围

整型 short 2 -215 ~ 215 -1

int 2 4 -215 ~ 215 -1 -231 ~ 231 -1

long 4 8 -231 ~ 231 -1 -263 ~ 263 -1

unsigned short 2 0 ~ 216 -1

unsigned int 24 0 ~ 216 -1 0 ~ 232 -1

unsigned long 48 0 ~ 232 -1 0 ~ 264 -1

实型 float 4 (6-7) 10-38 ~ 1038

double 8 (15-16) 10-308 ~ 10308

long double 16 (18-19) 10-4932 ~ 104932

布尔型 bool 1 true false

字符型 char 1

C 没有规定每种数据类型的字节数和表示范围只规定大小顺序具体长度由

处理器和编译器决定

更长的整型long long unsigned long longex_datatypec

httpmathecnueducn~jypan 17

数据类型转换

printf(12=fn 12)printf(102=fn 102)

ex_datetype_02cpp

charrarrshortrarrintrarr longrarrunsigned longrarrdoublelarrfloat

不同类型的数据进行运算需先转换成同一类型

转换按数据长度增加的方向进行以保证精度不降低

所有的浮点运算都是以双精度进行的

char 型和 short 型参与运算时必须先转换成 int 型

赋值号两边的数据类型不同时右边的类型将转换为左边的

自动转换隐式转换

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 7: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 7

C 语言概述

1969-1973由 Dennis M Ritchie 设计并实现

1973UNIX 的内核正式用 C 语言改写

1978B Kernighan 和 D Ritchie《C程序设计语言》

1983-1989ANSI C 标准形成 (C89 C90) 1999ISO 正式发布新的标准 C99 2011C11 标准发布

C 语言发展历史

httpmathecnueducn~jypan

Example calculate the sum of a and b

include ltstdiohgt

main()

int a b sum

a=10 b=24sum=add(ab)printf(sum=dn sum)

int add(int xint y)

int zz=x+yreturn(z)

8

一个简单的 C 程序

主函数

打印语句

预处理

注解语句

C 源程序结构

一个 C 源程序由一个或多个源文件组成

每个源文件可由一个或多个函数组成

一个源程序有且只能有一个 main 函数

程序执行从 main 开始在 main 中结束

源程序中可以有预处理命令通常应放

在源文件或源程序的最前面

httpmathecnueducn~jypan 9

C 程序书写规范

每个说明和每个语句都必须以分号ldquordquo结尾但预处理命令函数

头和花括号ldquordquo之后不能加分号

标识符关键字之间必须至少加一个空格以示间隔若已有明显的间

隔符也可不再加空格来间隔

一行可以写多个语句一个语句可以分几行书写

区分大小写习惯用小写字母

注释 为注释符 不能嵌套

常用锯齿形书写格式

书写规范

书写漂亮的程序

要对齐

一行写一个语句

一个语句写一行

使用 TAB 缩进

有合适的空行

有足够的注释注所有标点符号必须在英文状态下输入

httpmathecnueducn~jypan 10

C 语言编译器

编译器就是将ldquo高级语言rdquo翻译为ldquo机器语言rdquo的程序

编译器

常见的 C 语言编译器

源代码 目标代码 可执行程序编译 链接

一个现代编译器的主要工作流程

Visual C Windows 平台上流行的编译器集成在 Visual Studio 中

GNU C 开源免费LinuxUnix 平台上的首选非常优秀的编译器

Intel C Intel 的编译器对自家硬件的支持很好WinLinux 都有相应版本

httpmathecnueducn~jypan 11

IDE

Integrated Development Environment IDE (集成开发环境)

Windows 下常见的 C++ 集成开发环境

用于程序开发的应用程序软件一般包括代码编辑器

编译器调试器和图形用户界面工具等

- Visual Studio Windows 平台上最流行的商业 CC++ 集成开发环境

- Dev C++ 小巧免费win 下的 gcc非常适合学习 CC++

- CodeBlocks 开放源码的全功能跨平台集成开发环境免费

httpmathecnueducn~jypan 12

字符集

字母(大写和小写共 52 个)

数字(0 到 9 共 10 个)

空白符(空格符制表符换行符)

标点和特殊字符

C 语言字符集

注这里的标点符号都是指在英文状态下的标点

^ amp () [] _ + = - ~ lt gt

httpmathecnueducn~jypan 13

词法记号词汇

标识符用来标识变量名函数名对象名等的字符序列

- 由字母数字下划线组成第一个字符必须是字母或下划线

- 区分大小写不能用关键字

- 不限制标识符长度实际长度与编译器有关

- 命名原则见名知意不宜混淆

运算符(详见后面介绍)

分隔符逗号冒号分号空格(){}

注释符以ldquordquo开头并以ldquordquo结尾或者 (行注释符)

文字直接用字符表示的数据即常量如数字字符串等

关键字具有特定意义的字符串通常也称为保留字

- 类型说明符语句定义符(控制命令)预处理命令等

httpmathecnueducn~jypan 14

代码编写与运行

1) 编写源程序以 c 为扩展名(可使用任何文本编辑器)

2) 编译并连接源文件 (可以一步完成)

gcc [选项] 源代码文件

-o 指定输出文件名缺省为 aout -c 只编译不链接即只生产目标文件(o 文件)

-Ipath 指定或增加包含文件(如 h)的搜索路径

-Lpath 指定(增加)库文件的搜索路径

-lname与库文件 libnamea 链接

-O-O1-O2-O3 优化开关

-g 在目标码中加入更多信息用于程序调试

常用选项

3) 运行生成的可执行文件

httpmathecnueducn~jypan 15

C 语言数据类型

整型

实型

字符型 (char)

整型 (int)短整型 (short)长整型 (long)

单精度 (float)双精度 (double)

基本类型

C数

布尔型 (bool)

无符号 (unsigned)有符号

自定义数据类型或扩展数据类型或派生数据类型或导出数据类型

数组

结构联合

指针

hellip hellip

httpmathecnueducn~jypan 16

基本数据类型

类型 关键字 所占字节数 表示范围

整型 short 2 -215 ~ 215 -1

int 2 4 -215 ~ 215 -1 -231 ~ 231 -1

long 4 8 -231 ~ 231 -1 -263 ~ 263 -1

unsigned short 2 0 ~ 216 -1

unsigned int 24 0 ~ 216 -1 0 ~ 232 -1

unsigned long 48 0 ~ 232 -1 0 ~ 264 -1

实型 float 4 (6-7) 10-38 ~ 1038

double 8 (15-16) 10-308 ~ 10308

long double 16 (18-19) 10-4932 ~ 104932

布尔型 bool 1 true false

字符型 char 1

C 没有规定每种数据类型的字节数和表示范围只规定大小顺序具体长度由

处理器和编译器决定

更长的整型long long unsigned long longex_datatypec

httpmathecnueducn~jypan 17

数据类型转换

printf(12=fn 12)printf(102=fn 102)

ex_datetype_02cpp

charrarrshortrarrintrarr longrarrunsigned longrarrdoublelarrfloat

不同类型的数据进行运算需先转换成同一类型

转换按数据长度增加的方向进行以保证精度不降低

所有的浮点运算都是以双精度进行的

char 型和 short 型参与运算时必须先转换成 int 型

赋值号两边的数据类型不同时右边的类型将转换为左边的

自动转换隐式转换

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 8: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

Example calculate the sum of a and b

include ltstdiohgt

main()

int a b sum

a=10 b=24sum=add(ab)printf(sum=dn sum)

int add(int xint y)

int zz=x+yreturn(z)

8

一个简单的 C 程序

主函数

打印语句

预处理

注解语句

C 源程序结构

一个 C 源程序由一个或多个源文件组成

每个源文件可由一个或多个函数组成

一个源程序有且只能有一个 main 函数

程序执行从 main 开始在 main 中结束

源程序中可以有预处理命令通常应放

在源文件或源程序的最前面

httpmathecnueducn~jypan 9

C 程序书写规范

每个说明和每个语句都必须以分号ldquordquo结尾但预处理命令函数

头和花括号ldquordquo之后不能加分号

标识符关键字之间必须至少加一个空格以示间隔若已有明显的间

隔符也可不再加空格来间隔

一行可以写多个语句一个语句可以分几行书写

区分大小写习惯用小写字母

注释 为注释符 不能嵌套

常用锯齿形书写格式

书写规范

书写漂亮的程序

要对齐

一行写一个语句

一个语句写一行

使用 TAB 缩进

有合适的空行

有足够的注释注所有标点符号必须在英文状态下输入

httpmathecnueducn~jypan 10

C 语言编译器

编译器就是将ldquo高级语言rdquo翻译为ldquo机器语言rdquo的程序

编译器

常见的 C 语言编译器

源代码 目标代码 可执行程序编译 链接

一个现代编译器的主要工作流程

Visual C Windows 平台上流行的编译器集成在 Visual Studio 中

GNU C 开源免费LinuxUnix 平台上的首选非常优秀的编译器

Intel C Intel 的编译器对自家硬件的支持很好WinLinux 都有相应版本

httpmathecnueducn~jypan 11

IDE

Integrated Development Environment IDE (集成开发环境)

Windows 下常见的 C++ 集成开发环境

用于程序开发的应用程序软件一般包括代码编辑器

编译器调试器和图形用户界面工具等

- Visual Studio Windows 平台上最流行的商业 CC++ 集成开发环境

- Dev C++ 小巧免费win 下的 gcc非常适合学习 CC++

- CodeBlocks 开放源码的全功能跨平台集成开发环境免费

httpmathecnueducn~jypan 12

字符集

字母(大写和小写共 52 个)

数字(0 到 9 共 10 个)

空白符(空格符制表符换行符)

标点和特殊字符

C 语言字符集

注这里的标点符号都是指在英文状态下的标点

^ amp () [] _ + = - ~ lt gt

httpmathecnueducn~jypan 13

词法记号词汇

标识符用来标识变量名函数名对象名等的字符序列

- 由字母数字下划线组成第一个字符必须是字母或下划线

- 区分大小写不能用关键字

- 不限制标识符长度实际长度与编译器有关

- 命名原则见名知意不宜混淆

运算符(详见后面介绍)

分隔符逗号冒号分号空格(){}

注释符以ldquordquo开头并以ldquordquo结尾或者 (行注释符)

文字直接用字符表示的数据即常量如数字字符串等

关键字具有特定意义的字符串通常也称为保留字

- 类型说明符语句定义符(控制命令)预处理命令等

httpmathecnueducn~jypan 14

代码编写与运行

1) 编写源程序以 c 为扩展名(可使用任何文本编辑器)

2) 编译并连接源文件 (可以一步完成)

gcc [选项] 源代码文件

-o 指定输出文件名缺省为 aout -c 只编译不链接即只生产目标文件(o 文件)

-Ipath 指定或增加包含文件(如 h)的搜索路径

-Lpath 指定(增加)库文件的搜索路径

-lname与库文件 libnamea 链接

-O-O1-O2-O3 优化开关

-g 在目标码中加入更多信息用于程序调试

常用选项

3) 运行生成的可执行文件

httpmathecnueducn~jypan 15

C 语言数据类型

整型

实型

字符型 (char)

整型 (int)短整型 (short)长整型 (long)

单精度 (float)双精度 (double)

基本类型

C数

布尔型 (bool)

无符号 (unsigned)有符号

自定义数据类型或扩展数据类型或派生数据类型或导出数据类型

数组

结构联合

指针

hellip hellip

httpmathecnueducn~jypan 16

基本数据类型

类型 关键字 所占字节数 表示范围

整型 short 2 -215 ~ 215 -1

int 2 4 -215 ~ 215 -1 -231 ~ 231 -1

long 4 8 -231 ~ 231 -1 -263 ~ 263 -1

unsigned short 2 0 ~ 216 -1

unsigned int 24 0 ~ 216 -1 0 ~ 232 -1

unsigned long 48 0 ~ 232 -1 0 ~ 264 -1

实型 float 4 (6-7) 10-38 ~ 1038

double 8 (15-16) 10-308 ~ 10308

long double 16 (18-19) 10-4932 ~ 104932

布尔型 bool 1 true false

字符型 char 1

C 没有规定每种数据类型的字节数和表示范围只规定大小顺序具体长度由

处理器和编译器决定

更长的整型long long unsigned long longex_datatypec

httpmathecnueducn~jypan 17

数据类型转换

printf(12=fn 12)printf(102=fn 102)

ex_datetype_02cpp

charrarrshortrarrintrarr longrarrunsigned longrarrdoublelarrfloat

不同类型的数据进行运算需先转换成同一类型

转换按数据长度增加的方向进行以保证精度不降低

所有的浮点运算都是以双精度进行的

char 型和 short 型参与运算时必须先转换成 int 型

赋值号两边的数据类型不同时右边的类型将转换为左边的

自动转换隐式转换

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 9: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 9

C 程序书写规范

每个说明和每个语句都必须以分号ldquordquo结尾但预处理命令函数

头和花括号ldquordquo之后不能加分号

标识符关键字之间必须至少加一个空格以示间隔若已有明显的间

隔符也可不再加空格来间隔

一行可以写多个语句一个语句可以分几行书写

区分大小写习惯用小写字母

注释 为注释符 不能嵌套

常用锯齿形书写格式

书写规范

书写漂亮的程序

要对齐

一行写一个语句

一个语句写一行

使用 TAB 缩进

有合适的空行

有足够的注释注所有标点符号必须在英文状态下输入

httpmathecnueducn~jypan 10

C 语言编译器

编译器就是将ldquo高级语言rdquo翻译为ldquo机器语言rdquo的程序

编译器

常见的 C 语言编译器

源代码 目标代码 可执行程序编译 链接

一个现代编译器的主要工作流程

Visual C Windows 平台上流行的编译器集成在 Visual Studio 中

GNU C 开源免费LinuxUnix 平台上的首选非常优秀的编译器

Intel C Intel 的编译器对自家硬件的支持很好WinLinux 都有相应版本

httpmathecnueducn~jypan 11

IDE

Integrated Development Environment IDE (集成开发环境)

Windows 下常见的 C++ 集成开发环境

用于程序开发的应用程序软件一般包括代码编辑器

编译器调试器和图形用户界面工具等

- Visual Studio Windows 平台上最流行的商业 CC++ 集成开发环境

- Dev C++ 小巧免费win 下的 gcc非常适合学习 CC++

- CodeBlocks 开放源码的全功能跨平台集成开发环境免费

httpmathecnueducn~jypan 12

字符集

字母(大写和小写共 52 个)

数字(0 到 9 共 10 个)

空白符(空格符制表符换行符)

标点和特殊字符

C 语言字符集

注这里的标点符号都是指在英文状态下的标点

^ amp () [] _ + = - ~ lt gt

httpmathecnueducn~jypan 13

词法记号词汇

标识符用来标识变量名函数名对象名等的字符序列

- 由字母数字下划线组成第一个字符必须是字母或下划线

- 区分大小写不能用关键字

- 不限制标识符长度实际长度与编译器有关

- 命名原则见名知意不宜混淆

运算符(详见后面介绍)

分隔符逗号冒号分号空格(){}

注释符以ldquordquo开头并以ldquordquo结尾或者 (行注释符)

文字直接用字符表示的数据即常量如数字字符串等

关键字具有特定意义的字符串通常也称为保留字

- 类型说明符语句定义符(控制命令)预处理命令等

httpmathecnueducn~jypan 14

代码编写与运行

1) 编写源程序以 c 为扩展名(可使用任何文本编辑器)

2) 编译并连接源文件 (可以一步完成)

gcc [选项] 源代码文件

-o 指定输出文件名缺省为 aout -c 只编译不链接即只生产目标文件(o 文件)

-Ipath 指定或增加包含文件(如 h)的搜索路径

-Lpath 指定(增加)库文件的搜索路径

-lname与库文件 libnamea 链接

-O-O1-O2-O3 优化开关

-g 在目标码中加入更多信息用于程序调试

常用选项

3) 运行生成的可执行文件

httpmathecnueducn~jypan 15

C 语言数据类型

整型

实型

字符型 (char)

整型 (int)短整型 (short)长整型 (long)

单精度 (float)双精度 (double)

基本类型

C数

布尔型 (bool)

无符号 (unsigned)有符号

自定义数据类型或扩展数据类型或派生数据类型或导出数据类型

数组

结构联合

指针

hellip hellip

httpmathecnueducn~jypan 16

基本数据类型

类型 关键字 所占字节数 表示范围

整型 short 2 -215 ~ 215 -1

int 2 4 -215 ~ 215 -1 -231 ~ 231 -1

long 4 8 -231 ~ 231 -1 -263 ~ 263 -1

unsigned short 2 0 ~ 216 -1

unsigned int 24 0 ~ 216 -1 0 ~ 232 -1

unsigned long 48 0 ~ 232 -1 0 ~ 264 -1

实型 float 4 (6-7) 10-38 ~ 1038

double 8 (15-16) 10-308 ~ 10308

long double 16 (18-19) 10-4932 ~ 104932

布尔型 bool 1 true false

字符型 char 1

C 没有规定每种数据类型的字节数和表示范围只规定大小顺序具体长度由

处理器和编译器决定

更长的整型long long unsigned long longex_datatypec

httpmathecnueducn~jypan 17

数据类型转换

printf(12=fn 12)printf(102=fn 102)

ex_datetype_02cpp

charrarrshortrarrintrarr longrarrunsigned longrarrdoublelarrfloat

不同类型的数据进行运算需先转换成同一类型

转换按数据长度增加的方向进行以保证精度不降低

所有的浮点运算都是以双精度进行的

char 型和 short 型参与运算时必须先转换成 int 型

赋值号两边的数据类型不同时右边的类型将转换为左边的

自动转换隐式转换

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 10: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 10

C 语言编译器

编译器就是将ldquo高级语言rdquo翻译为ldquo机器语言rdquo的程序

编译器

常见的 C 语言编译器

源代码 目标代码 可执行程序编译 链接

一个现代编译器的主要工作流程

Visual C Windows 平台上流行的编译器集成在 Visual Studio 中

GNU C 开源免费LinuxUnix 平台上的首选非常优秀的编译器

Intel C Intel 的编译器对自家硬件的支持很好WinLinux 都有相应版本

httpmathecnueducn~jypan 11

IDE

Integrated Development Environment IDE (集成开发环境)

Windows 下常见的 C++ 集成开发环境

用于程序开发的应用程序软件一般包括代码编辑器

编译器调试器和图形用户界面工具等

- Visual Studio Windows 平台上最流行的商业 CC++ 集成开发环境

- Dev C++ 小巧免费win 下的 gcc非常适合学习 CC++

- CodeBlocks 开放源码的全功能跨平台集成开发环境免费

httpmathecnueducn~jypan 12

字符集

字母(大写和小写共 52 个)

数字(0 到 9 共 10 个)

空白符(空格符制表符换行符)

标点和特殊字符

C 语言字符集

注这里的标点符号都是指在英文状态下的标点

^ amp () [] _ + = - ~ lt gt

httpmathecnueducn~jypan 13

词法记号词汇

标识符用来标识变量名函数名对象名等的字符序列

- 由字母数字下划线组成第一个字符必须是字母或下划线

- 区分大小写不能用关键字

- 不限制标识符长度实际长度与编译器有关

- 命名原则见名知意不宜混淆

运算符(详见后面介绍)

分隔符逗号冒号分号空格(){}

注释符以ldquordquo开头并以ldquordquo结尾或者 (行注释符)

文字直接用字符表示的数据即常量如数字字符串等

关键字具有特定意义的字符串通常也称为保留字

- 类型说明符语句定义符(控制命令)预处理命令等

httpmathecnueducn~jypan 14

代码编写与运行

1) 编写源程序以 c 为扩展名(可使用任何文本编辑器)

2) 编译并连接源文件 (可以一步完成)

gcc [选项] 源代码文件

-o 指定输出文件名缺省为 aout -c 只编译不链接即只生产目标文件(o 文件)

-Ipath 指定或增加包含文件(如 h)的搜索路径

-Lpath 指定(增加)库文件的搜索路径

-lname与库文件 libnamea 链接

-O-O1-O2-O3 优化开关

-g 在目标码中加入更多信息用于程序调试

常用选项

3) 运行生成的可执行文件

httpmathecnueducn~jypan 15

C 语言数据类型

整型

实型

字符型 (char)

整型 (int)短整型 (short)长整型 (long)

单精度 (float)双精度 (double)

基本类型

C数

布尔型 (bool)

无符号 (unsigned)有符号

自定义数据类型或扩展数据类型或派生数据类型或导出数据类型

数组

结构联合

指针

hellip hellip

httpmathecnueducn~jypan 16

基本数据类型

类型 关键字 所占字节数 表示范围

整型 short 2 -215 ~ 215 -1

int 2 4 -215 ~ 215 -1 -231 ~ 231 -1

long 4 8 -231 ~ 231 -1 -263 ~ 263 -1

unsigned short 2 0 ~ 216 -1

unsigned int 24 0 ~ 216 -1 0 ~ 232 -1

unsigned long 48 0 ~ 232 -1 0 ~ 264 -1

实型 float 4 (6-7) 10-38 ~ 1038

double 8 (15-16) 10-308 ~ 10308

long double 16 (18-19) 10-4932 ~ 104932

布尔型 bool 1 true false

字符型 char 1

C 没有规定每种数据类型的字节数和表示范围只规定大小顺序具体长度由

处理器和编译器决定

更长的整型long long unsigned long longex_datatypec

httpmathecnueducn~jypan 17

数据类型转换

printf(12=fn 12)printf(102=fn 102)

ex_datetype_02cpp

charrarrshortrarrintrarr longrarrunsigned longrarrdoublelarrfloat

不同类型的数据进行运算需先转换成同一类型

转换按数据长度增加的方向进行以保证精度不降低

所有的浮点运算都是以双精度进行的

char 型和 short 型参与运算时必须先转换成 int 型

赋值号两边的数据类型不同时右边的类型将转换为左边的

自动转换隐式转换

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 11: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 11

IDE

Integrated Development Environment IDE (集成开发环境)

Windows 下常见的 C++ 集成开发环境

用于程序开发的应用程序软件一般包括代码编辑器

编译器调试器和图形用户界面工具等

- Visual Studio Windows 平台上最流行的商业 CC++ 集成开发环境

- Dev C++ 小巧免费win 下的 gcc非常适合学习 CC++

- CodeBlocks 开放源码的全功能跨平台集成开发环境免费

httpmathecnueducn~jypan 12

字符集

字母(大写和小写共 52 个)

数字(0 到 9 共 10 个)

空白符(空格符制表符换行符)

标点和特殊字符

C 语言字符集

注这里的标点符号都是指在英文状态下的标点

^ amp () [] _ + = - ~ lt gt

httpmathecnueducn~jypan 13

词法记号词汇

标识符用来标识变量名函数名对象名等的字符序列

- 由字母数字下划线组成第一个字符必须是字母或下划线

- 区分大小写不能用关键字

- 不限制标识符长度实际长度与编译器有关

- 命名原则见名知意不宜混淆

运算符(详见后面介绍)

分隔符逗号冒号分号空格(){}

注释符以ldquordquo开头并以ldquordquo结尾或者 (行注释符)

文字直接用字符表示的数据即常量如数字字符串等

关键字具有特定意义的字符串通常也称为保留字

- 类型说明符语句定义符(控制命令)预处理命令等

httpmathecnueducn~jypan 14

代码编写与运行

1) 编写源程序以 c 为扩展名(可使用任何文本编辑器)

2) 编译并连接源文件 (可以一步完成)

gcc [选项] 源代码文件

-o 指定输出文件名缺省为 aout -c 只编译不链接即只生产目标文件(o 文件)

-Ipath 指定或增加包含文件(如 h)的搜索路径

-Lpath 指定(增加)库文件的搜索路径

-lname与库文件 libnamea 链接

-O-O1-O2-O3 优化开关

-g 在目标码中加入更多信息用于程序调试

常用选项

3) 运行生成的可执行文件

httpmathecnueducn~jypan 15

C 语言数据类型

整型

实型

字符型 (char)

整型 (int)短整型 (short)长整型 (long)

单精度 (float)双精度 (double)

基本类型

C数

布尔型 (bool)

无符号 (unsigned)有符号

自定义数据类型或扩展数据类型或派生数据类型或导出数据类型

数组

结构联合

指针

hellip hellip

httpmathecnueducn~jypan 16

基本数据类型

类型 关键字 所占字节数 表示范围

整型 short 2 -215 ~ 215 -1

int 2 4 -215 ~ 215 -1 -231 ~ 231 -1

long 4 8 -231 ~ 231 -1 -263 ~ 263 -1

unsigned short 2 0 ~ 216 -1

unsigned int 24 0 ~ 216 -1 0 ~ 232 -1

unsigned long 48 0 ~ 232 -1 0 ~ 264 -1

实型 float 4 (6-7) 10-38 ~ 1038

double 8 (15-16) 10-308 ~ 10308

long double 16 (18-19) 10-4932 ~ 104932

布尔型 bool 1 true false

字符型 char 1

C 没有规定每种数据类型的字节数和表示范围只规定大小顺序具体长度由

处理器和编译器决定

更长的整型long long unsigned long longex_datatypec

httpmathecnueducn~jypan 17

数据类型转换

printf(12=fn 12)printf(102=fn 102)

ex_datetype_02cpp

charrarrshortrarrintrarr longrarrunsigned longrarrdoublelarrfloat

不同类型的数据进行运算需先转换成同一类型

转换按数据长度增加的方向进行以保证精度不降低

所有的浮点运算都是以双精度进行的

char 型和 short 型参与运算时必须先转换成 int 型

赋值号两边的数据类型不同时右边的类型将转换为左边的

自动转换隐式转换

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 12: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 12

字符集

字母(大写和小写共 52 个)

数字(0 到 9 共 10 个)

空白符(空格符制表符换行符)

标点和特殊字符

C 语言字符集

注这里的标点符号都是指在英文状态下的标点

^ amp () [] _ + = - ~ lt gt

httpmathecnueducn~jypan 13

词法记号词汇

标识符用来标识变量名函数名对象名等的字符序列

- 由字母数字下划线组成第一个字符必须是字母或下划线

- 区分大小写不能用关键字

- 不限制标识符长度实际长度与编译器有关

- 命名原则见名知意不宜混淆

运算符(详见后面介绍)

分隔符逗号冒号分号空格(){}

注释符以ldquordquo开头并以ldquordquo结尾或者 (行注释符)

文字直接用字符表示的数据即常量如数字字符串等

关键字具有特定意义的字符串通常也称为保留字

- 类型说明符语句定义符(控制命令)预处理命令等

httpmathecnueducn~jypan 14

代码编写与运行

1) 编写源程序以 c 为扩展名(可使用任何文本编辑器)

2) 编译并连接源文件 (可以一步完成)

gcc [选项] 源代码文件

-o 指定输出文件名缺省为 aout -c 只编译不链接即只生产目标文件(o 文件)

-Ipath 指定或增加包含文件(如 h)的搜索路径

-Lpath 指定(增加)库文件的搜索路径

-lname与库文件 libnamea 链接

-O-O1-O2-O3 优化开关

-g 在目标码中加入更多信息用于程序调试

常用选项

3) 运行生成的可执行文件

httpmathecnueducn~jypan 15

C 语言数据类型

整型

实型

字符型 (char)

整型 (int)短整型 (short)长整型 (long)

单精度 (float)双精度 (double)

基本类型

C数

布尔型 (bool)

无符号 (unsigned)有符号

自定义数据类型或扩展数据类型或派生数据类型或导出数据类型

数组

结构联合

指针

hellip hellip

httpmathecnueducn~jypan 16

基本数据类型

类型 关键字 所占字节数 表示范围

整型 short 2 -215 ~ 215 -1

int 2 4 -215 ~ 215 -1 -231 ~ 231 -1

long 4 8 -231 ~ 231 -1 -263 ~ 263 -1

unsigned short 2 0 ~ 216 -1

unsigned int 24 0 ~ 216 -1 0 ~ 232 -1

unsigned long 48 0 ~ 232 -1 0 ~ 264 -1

实型 float 4 (6-7) 10-38 ~ 1038

double 8 (15-16) 10-308 ~ 10308

long double 16 (18-19) 10-4932 ~ 104932

布尔型 bool 1 true false

字符型 char 1

C 没有规定每种数据类型的字节数和表示范围只规定大小顺序具体长度由

处理器和编译器决定

更长的整型long long unsigned long longex_datatypec

httpmathecnueducn~jypan 17

数据类型转换

printf(12=fn 12)printf(102=fn 102)

ex_datetype_02cpp

charrarrshortrarrintrarr longrarrunsigned longrarrdoublelarrfloat

不同类型的数据进行运算需先转换成同一类型

转换按数据长度增加的方向进行以保证精度不降低

所有的浮点运算都是以双精度进行的

char 型和 short 型参与运算时必须先转换成 int 型

赋值号两边的数据类型不同时右边的类型将转换为左边的

自动转换隐式转换

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 13: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 13

词法记号词汇

标识符用来标识变量名函数名对象名等的字符序列

- 由字母数字下划线组成第一个字符必须是字母或下划线

- 区分大小写不能用关键字

- 不限制标识符长度实际长度与编译器有关

- 命名原则见名知意不宜混淆

运算符(详见后面介绍)

分隔符逗号冒号分号空格(){}

注释符以ldquordquo开头并以ldquordquo结尾或者 (行注释符)

文字直接用字符表示的数据即常量如数字字符串等

关键字具有特定意义的字符串通常也称为保留字

- 类型说明符语句定义符(控制命令)预处理命令等

httpmathecnueducn~jypan 14

代码编写与运行

1) 编写源程序以 c 为扩展名(可使用任何文本编辑器)

2) 编译并连接源文件 (可以一步完成)

gcc [选项] 源代码文件

-o 指定输出文件名缺省为 aout -c 只编译不链接即只生产目标文件(o 文件)

-Ipath 指定或增加包含文件(如 h)的搜索路径

-Lpath 指定(增加)库文件的搜索路径

-lname与库文件 libnamea 链接

-O-O1-O2-O3 优化开关

-g 在目标码中加入更多信息用于程序调试

常用选项

3) 运行生成的可执行文件

httpmathecnueducn~jypan 15

C 语言数据类型

整型

实型

字符型 (char)

整型 (int)短整型 (short)长整型 (long)

单精度 (float)双精度 (double)

基本类型

C数

布尔型 (bool)

无符号 (unsigned)有符号

自定义数据类型或扩展数据类型或派生数据类型或导出数据类型

数组

结构联合

指针

hellip hellip

httpmathecnueducn~jypan 16

基本数据类型

类型 关键字 所占字节数 表示范围

整型 short 2 -215 ~ 215 -1

int 2 4 -215 ~ 215 -1 -231 ~ 231 -1

long 4 8 -231 ~ 231 -1 -263 ~ 263 -1

unsigned short 2 0 ~ 216 -1

unsigned int 24 0 ~ 216 -1 0 ~ 232 -1

unsigned long 48 0 ~ 232 -1 0 ~ 264 -1

实型 float 4 (6-7) 10-38 ~ 1038

double 8 (15-16) 10-308 ~ 10308

long double 16 (18-19) 10-4932 ~ 104932

布尔型 bool 1 true false

字符型 char 1

C 没有规定每种数据类型的字节数和表示范围只规定大小顺序具体长度由

处理器和编译器决定

更长的整型long long unsigned long longex_datatypec

httpmathecnueducn~jypan 17

数据类型转换

printf(12=fn 12)printf(102=fn 102)

ex_datetype_02cpp

charrarrshortrarrintrarr longrarrunsigned longrarrdoublelarrfloat

不同类型的数据进行运算需先转换成同一类型

转换按数据长度增加的方向进行以保证精度不降低

所有的浮点运算都是以双精度进行的

char 型和 short 型参与运算时必须先转换成 int 型

赋值号两边的数据类型不同时右边的类型将转换为左边的

自动转换隐式转换

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 14: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 14

代码编写与运行

1) 编写源程序以 c 为扩展名(可使用任何文本编辑器)

2) 编译并连接源文件 (可以一步完成)

gcc [选项] 源代码文件

-o 指定输出文件名缺省为 aout -c 只编译不链接即只生产目标文件(o 文件)

-Ipath 指定或增加包含文件(如 h)的搜索路径

-Lpath 指定(增加)库文件的搜索路径

-lname与库文件 libnamea 链接

-O-O1-O2-O3 优化开关

-g 在目标码中加入更多信息用于程序调试

常用选项

3) 运行生成的可执行文件

httpmathecnueducn~jypan 15

C 语言数据类型

整型

实型

字符型 (char)

整型 (int)短整型 (short)长整型 (long)

单精度 (float)双精度 (double)

基本类型

C数

布尔型 (bool)

无符号 (unsigned)有符号

自定义数据类型或扩展数据类型或派生数据类型或导出数据类型

数组

结构联合

指针

hellip hellip

httpmathecnueducn~jypan 16

基本数据类型

类型 关键字 所占字节数 表示范围

整型 short 2 -215 ~ 215 -1

int 2 4 -215 ~ 215 -1 -231 ~ 231 -1

long 4 8 -231 ~ 231 -1 -263 ~ 263 -1

unsigned short 2 0 ~ 216 -1

unsigned int 24 0 ~ 216 -1 0 ~ 232 -1

unsigned long 48 0 ~ 232 -1 0 ~ 264 -1

实型 float 4 (6-7) 10-38 ~ 1038

double 8 (15-16) 10-308 ~ 10308

long double 16 (18-19) 10-4932 ~ 104932

布尔型 bool 1 true false

字符型 char 1

C 没有规定每种数据类型的字节数和表示范围只规定大小顺序具体长度由

处理器和编译器决定

更长的整型long long unsigned long longex_datatypec

httpmathecnueducn~jypan 17

数据类型转换

printf(12=fn 12)printf(102=fn 102)

ex_datetype_02cpp

charrarrshortrarrintrarr longrarrunsigned longrarrdoublelarrfloat

不同类型的数据进行运算需先转换成同一类型

转换按数据长度增加的方向进行以保证精度不降低

所有的浮点运算都是以双精度进行的

char 型和 short 型参与运算时必须先转换成 int 型

赋值号两边的数据类型不同时右边的类型将转换为左边的

自动转换隐式转换

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 15: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 15

C 语言数据类型

整型

实型

字符型 (char)

整型 (int)短整型 (short)长整型 (long)

单精度 (float)双精度 (double)

基本类型

C数

布尔型 (bool)

无符号 (unsigned)有符号

自定义数据类型或扩展数据类型或派生数据类型或导出数据类型

数组

结构联合

指针

hellip hellip

httpmathecnueducn~jypan 16

基本数据类型

类型 关键字 所占字节数 表示范围

整型 short 2 -215 ~ 215 -1

int 2 4 -215 ~ 215 -1 -231 ~ 231 -1

long 4 8 -231 ~ 231 -1 -263 ~ 263 -1

unsigned short 2 0 ~ 216 -1

unsigned int 24 0 ~ 216 -1 0 ~ 232 -1

unsigned long 48 0 ~ 232 -1 0 ~ 264 -1

实型 float 4 (6-7) 10-38 ~ 1038

double 8 (15-16) 10-308 ~ 10308

long double 16 (18-19) 10-4932 ~ 104932

布尔型 bool 1 true false

字符型 char 1

C 没有规定每种数据类型的字节数和表示范围只规定大小顺序具体长度由

处理器和编译器决定

更长的整型long long unsigned long longex_datatypec

httpmathecnueducn~jypan 17

数据类型转换

printf(12=fn 12)printf(102=fn 102)

ex_datetype_02cpp

charrarrshortrarrintrarr longrarrunsigned longrarrdoublelarrfloat

不同类型的数据进行运算需先转换成同一类型

转换按数据长度增加的方向进行以保证精度不降低

所有的浮点运算都是以双精度进行的

char 型和 short 型参与运算时必须先转换成 int 型

赋值号两边的数据类型不同时右边的类型将转换为左边的

自动转换隐式转换

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 16: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 16

基本数据类型

类型 关键字 所占字节数 表示范围

整型 short 2 -215 ~ 215 -1

int 2 4 -215 ~ 215 -1 -231 ~ 231 -1

long 4 8 -231 ~ 231 -1 -263 ~ 263 -1

unsigned short 2 0 ~ 216 -1

unsigned int 24 0 ~ 216 -1 0 ~ 232 -1

unsigned long 48 0 ~ 232 -1 0 ~ 264 -1

实型 float 4 (6-7) 10-38 ~ 1038

double 8 (15-16) 10-308 ~ 10308

long double 16 (18-19) 10-4932 ~ 104932

布尔型 bool 1 true false

字符型 char 1

C 没有规定每种数据类型的字节数和表示范围只规定大小顺序具体长度由

处理器和编译器决定

更长的整型long long unsigned long longex_datatypec

httpmathecnueducn~jypan 17

数据类型转换

printf(12=fn 12)printf(102=fn 102)

ex_datetype_02cpp

charrarrshortrarrintrarr longrarrunsigned longrarrdoublelarrfloat

不同类型的数据进行运算需先转换成同一类型

转换按数据长度增加的方向进行以保证精度不降低

所有的浮点运算都是以双精度进行的

char 型和 short 型参与运算时必须先转换成 int 型

赋值号两边的数据类型不同时右边的类型将转换为左边的

自动转换隐式转换

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 17: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 17

数据类型转换

printf(12=fn 12)printf(102=fn 102)

ex_datetype_02cpp

charrarrshortrarrintrarr longrarrunsigned longrarrdoublelarrfloat

不同类型的数据进行运算需先转换成同一类型

转换按数据长度增加的方向进行以保证精度不降低

所有的浮点运算都是以双精度进行的

char 型和 short 型参与运算时必须先转换成 int 型

赋值号两边的数据类型不同时右边的类型将转换为左边的

自动转换隐式转换

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 18: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 18

数据类型转换

printf(12=fn 12)printf(102=fn 102) printf((double)12=fn (double)(1)2)printf((double)(12)=fn (double)(12))

ex_datetype_02cpp

(类型说明符)表达式 将表达式的值转换成指定的类型

强制转换显式转换

浮点型转整型直接丢掉小数部分

字符型转整型为字符的 ASCII 码 整型转字符型ASCII 码对应的字符

转换规则

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 19: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 19

变量

变量名要求与标识符相同

变量类型整型实型字符型布尔型

变量必须先声明后使用

用于存储数据值可以改变

变量的声明

初始化声明变量时直接赋值

int i j=10double pi=314159char c=0

example

数据类型 变量名列表

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 20: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 20

常量(常数)

整型常量整数后面加 l 或 L 表示长整型

后面加 u 或 U 表示无符号整型

实型常量缺省为双精度实数

后面加 f 或 F 表示单精度加 l 或 L 表示 long double

字符型常量用单引号括起来的单个字符和转义字符

字符串常量用双引号括起来的字符序列

布尔常量true和 false

在程序运行中值不能改变的量

123 -456 123L 456U12 12F 12L 12e8 12e8F 12e-8LM A T H $MATHECNU

example

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 21: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 21

符号常量

符号常量用标识符表示常量

const float PI=31415926

dagger 符号常量在声明时必须初始化

dagger 符号常量的值在程序中不能被修改(不能重新赋值)

example

const 数据类型 标识符 = 常量值

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 22: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 22

运算符

算术运算符+-++ (自增)-- (自减)

赋值运算符=+=-====amp=|=^=gtgt=ltlt=

逗号运算符 (把若干表达式组合成一个表达式)

求字节数运算符sizeof (计算数据类型所占的字节数)

关系运算符用于比较运算gtlt==gt=lt==

逻辑运算符用于逻辑运算ampamp||

条件运算符是一个三目运算符用于条件求值 ( )

指针运算符 (取内容)amp (取地址)

位运算符按二进制位进行运算amp|^ (异或)~ (取反) ltlt (左移)gtgt (右移)

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 23: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 23

赋值运算

标准赋值语句

自增自减(前置和后置)

变量 = 表达式

++--

int i=10 j kj=i++ j=k=++i k=

Example x++

dagger 这种方式不能用于变量初始化

x=3

x=y=3 y=3x=y

++x

y=x++x

y=++xx

x=x+1

x=x+1

y=xx x=x+1

x=x+1 y=xx

前置先自增自减然后使用

后置先使用然后自增自减

不要在同一语句中包含一个变量的多个++或--因为它们的解释在CC++标准中没有规定完全取决于编译器的个人行为

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 24: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 24

赋值与逗号运算

复合赋值运算符

逗号运算符

- 先计算表达式 1 的值再计算表达式 2 的值

并将表达式 2 的值作为整个表达式的结果

注意运算的优先级

+=-====

int a b c d ea = 5b = a + 3a = a + (c=6)d = e = f = ae = df = c - 2

x+=3 x=x+3

x=3 x=x3

表达式 1表达式 2

int a=2 b1 b2b1 = 3a a+10b2 = (3a a+10)

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 25: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 25

sizeof

求字节数运算符

返回指定数据类型所占的字节数

返回存储指定变量所需的字节数

int a b c da = sizeof(int)b = sizeof(a)c = sizeof(3 + 5)d = sizeof(30L + 5)

sizeof(数据类型)

sizeof(变量名)

返回存储表达式结果所需的字节数sizeof(表达式)

Example

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 26: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 26

运算优先级

() ++(后置) --(后置) 强制类型转换

++(前置) ndashndash(前置) +(正号) ndash(负号)

+ ndashlt lt= gt gt=== =ampamp||赋值(= += ndash= = = 等)

逗号运算( )详见课程主页

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 27: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 27

常用数学函数

abs(x) |x|exp(x) ex

log(x) ln xlog10(x) lg xsqrt(x)pow(xy) x y

需加头文件 mathh include ltmathhgt

x

min(xy)

max(xy)

最小值

最大值

取整函数ceil floor round trunc

三角函数sin cos tan asin acos atan双曲三角函数sinhcoshtanhasinhacoshatanh

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 28: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 28

C 语言输出

C 语言的输出函数printf

格式控制字符串普通字符串格式字符串转义字符

普通字符串原样输出

格式字符串以 开头后面跟各种格式说明符

转义字符实现特殊功能

printf(ldquo格式控制字符串rdquo输出变量列表)

int k=5double a=314printf(ldquok=d a=fnrdquok a) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 29: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 29

格式字符串

printf(pi= -126f n pi)

以 开头

flag

精度

格式说明符

- 左对齐+ 输出符号空格

输出最小宽度

小数点后输出位数

[flag][输出最小宽度][精度]格式说明符

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 30: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 30

格式说明符与转义字符常见的格式说明符

c 字符型 g 浮点数(自动)

d 十进制整数 o 八进制

e 浮点数(科学计数法) s 字符串

f 浮点数(小数形式) xX 十六进制

常见转义字符(输出特殊符号)

b 退后一格 t 水平制表符

f 换页 反斜杠

n 换行 双引号

r 回车 百分号

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 31: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 31

C 语言输入

C 语言的输出函数scanf

scanf(ldquo格式控制字符串rdquo地址列表)

int a bprintf(ldquoinput a and b rdquo)scanf(ldquoddrdquo ampa ampb) 一个格式字符串对应一个输出变量

Example

头文件 stdioh

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 32: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 32

数组

一维数组的声明

声明一个长度为 n 的数组(向量)

类型标识符数组元素的数据类型

n数组的长度即元素的个数

一维数组的引用

int x[5] 声明一个长度为 5 的一维数组

example

数组具有一定顺序关系的若干相同类型变量的集合体

类型标识符 变量名[n]

变量名[k] 注下标 k 的取值为 0 到 n-1下标不能越界

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 33: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 33

一维数组

例x[10] 在内存中的存放顺序是

x[0] x[1] x[2] x[3] x[4] x[5] x[6] x[7] x[8] x[9]

int m=2 n=3int x[mn+2]

exampleint n=5int x[n]

example

类型标识符 变量名[n]

n 必须是一个确定的正整数 n 可以用表达式代替但表达式的值必须是正整数

几点注意

只能逐个引用数组元素而不能一次引用整个数组 数组元素在内存中顺序存放它们的地址是连续的 数组名代表数组存放在内存中的首地址

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 34: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 34

一维数组

一维数组的初始化在声明时可以同时赋初值

也可以只给部分元素赋初值

全部元素赋初值时可以不指定数组长度

int x[5]=02468example

int x[5]=024 只能依次赋初值example

int x[]=02468 example

int x[5] x=6 ERROR

example

dagger 注意只能对数组元素赋值不能对数组名赋值

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 35: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 35

二维数组

二维数组的声明

声明一个 m X n 的二维数组(矩阵)

二维数组的引用

类型标识符 变量名[m][n]

变量名[i][j] 注意下标的取值范围不要越界

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 36: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 36

二维数组

二维数组的存储按行存储

例x[2][3] 在内存中的存放顺序是

x[0][0] x[0][1] x[0][2] x[1][0] x[1][1] x[1][2]

x[0] x[1]

x

dagger 在 C 语言中二维数组被看成是一维数组的数组

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 37: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 37

二维数组

二维数组的初始化

分组初始化

部分初始化

全部初始化

int x[2][3]=1352610

int x[][3]=1352610 注只能省第一维的长度

example

int x[2][3]=135 2610example

int x[2][3]=1 26example

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 38: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 38

多维数组

多维数组的声明

多维数组的赋值引用初始化与二维数组类似

类型标识符 变量名[n1][n2][n3]

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 39: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 39

编译预处理

加入头文件

include lt文件名gt 按标准方式导入头文件

即在系统目录中寻找指定的文件

include ldquo文件名rdquo 先搜索当前目录然后再搜索系统目录

宏定义

define PI 314159 定义符号常量

undef PI 删除由 define 定义的符号常量

define S 31415926rr 可以是表达式

define MAX(ab) (agtb)ab 带参数的宏

dagger 编译时直接替换

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 40: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 40

条件编译

ifdef 标识符

程序正文 当 ldquo标识符rdquo 已由 define 定义时编译

else

程序正文 否则编译这段程序

endif

ifndef 标识符

程序正文 当 ldquo标识符rdquo 没有定义时编译

else

程序正文 否则编译这段程序

endif

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 41: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

关系运算与逻辑运算

选择结构

循环结构

2 选择与循环

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 42: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 42

关系运算比较大小

gt 大于 gt= 大于等于 == 等于

lt 小于 lt= 小于等于 = 不等于

比较大小结论是真 则返回 true否则返回 false C 语言中用 1表示 true0表示 false bool型变量赋值 0时表示 false其他它值都表示 true

bool x1=15 x1=truebool x2=0 x2=falsebool x3=-11 x3=true

dagger 注意 ==与 =的区别

dagger 对浮点数进行比较运算时尽量不要使用 ==

pow(sqrt(20)2)==2 true or false

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 43: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 43

逻辑运算

逻辑运算

ampamp 逻辑与 || 逻辑或 逻辑非

运算对象 与 或 非

A B AampampB A||B A0 0 0 0 1

0 1 0 1 1

1 0 0 1 0

1 1 1 1 0

运算法则

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 44: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 44

逻辑运算两点注意

(表达式1) ampamp (表达式2)

先计算表达式1 的值若是 true则计算表达式2 的值

若表达式1 的值是 false则不再计算表达式2 的值

(表达式1) || (表达式2)

先计算表达式1 的值若是 false则计算表达式2 的值

若表达式1 的值是 true则不再计算表达式2 的值

i=3

i=4

i=3 (igt3) ampamp (i++)

i=3 (igt3) || (i++)

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 45: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 45

条件运算符

条件表达式 表达式1 表达式2

先计算条件表达式的值

若是 true则用表达式1 作为整个表达式的值

否则就用表达式2 的值作为整个表达式的值

Example

y = xgt0 1 -1

z = xgty x y

dagger 条件运算符是 C 中唯一的三目运算符

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 46: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

if (表达式) 语句

46

选择结构if 语句

if (表达式) 语句

else 语句

if (表达式) 语句

else if (表达式) 语句

hellip hellipelse if (表达式) 语句

else 语句 else 语句可以省略

表达式可以是任意表达式

(关系逻辑算术等)

语句可以是复合语句

(用大括号括起来)

条件判断表达式两边的小括

号不能省略

else if 中间必须留空

if 语句可以嵌套嵌套时

每一层的 if 要与 else 配套否则要加大括号

几点说明

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 47: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

switch (表达式) case 常量表达式1语句

case 常量表达式2 语句

hellip hellipcase 常量表达式n 语句

default 语句

可以是整型字符型枚举型

47

选择结构switch语句

dagger 先计算ldquo表达式rdquo的值然后依次与每

个 case 后面的ldquo常量表达式rdquo进行匹配

一旦匹配成功则开始执行后面的语句

包括后面所有 case 以及 default 的语句

dagger 如果没有匹配的则执行 default 后面

的语句

dagger default 不是必需的可以没有

dagger 每个 case 分支最后一般需加 breakdagger 每个 case 后面的常量表达式的值不能相

dagger 每个 case 后面可以有多个语句(复合语

句)但可以不用

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 48: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

NOTE

while (条件表达式) 循环体语句

48

循环结构while 循环

执行过程

表达式

循环体语句

(1) 判断条件表达式的值

(2) 如果是 ldquo真rdquo则执行循环体语句 否则退出循环

(3) 返回第一步

dagger 如果循环体语句是复合语句别忘了大括号

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 49: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

do 循环体语句

while (条件表达式)

49

循环结构do while 循环

表达式

循环体语句

执行过程

(1) 执行循环体语句

(2) 判断条件表达式的值

(3) 如果是 ldquo真rdquo返回第一步 否则退出循环

NOTE

dagger 与 while 循环的区别无论条件是否成立循环体语句至少执行一次

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 50: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

for (初始化语句 表达式1 表达式2)

循环体语句

50

for 循环

表达式1

初始化语句

表达式2

循环体语句

假执行过程

(1) 执行初始化语句

(2) 计算表达式1 的值

如果是ldquo真rdquo则执行循环体语句

否则退出循环

(3) 执行表达式2返回第二步

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 51: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

for (循环变量赋初值 循环条件 循环变量增量)

循环体语句

51

for 循环

上面程序中的变量 i有时也称为循环变量

NOTE

dagger 初始化语句表达式1表达式2 均可省略但分号不能省

dagger 表达式1 是循环控制语句如果省略的话就构成死循环

dagger 循环体可以是单个语句也可以是复合语句(大括号)

dagger 初始化语句与表达式2 可以是逗号语句

s=0for (i=1 ilt=10 i++)s=s+i

example

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 52: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 52

循环的终止

break 语句

跳出循环体只用在循环语句和 switch 语句中

break 只能跳出一层循环

continue 语句

结束本轮循环执行下一轮循环一般只用在循环语句中

goto 语句

跳转到由语句标号所指定的语句

语句标号为标记符后面跟冒号即 标记符语句 goto 语句破坏程序的结构性尽量少用

goto 语句标号

break

continue

NOTE

dagger breakcontinue 和 goto通常是与 if语句配合使用

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 53: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

函数的定义与调用

参数传递

函数嵌套内联函数

局部变量与全局变量

3 函 数

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 54: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

类型标识符 函数名(形式参数表)

语句

54

函数的定义

函数是程序设计中对功能的抽象是 C 语言的基本模块

C 语言程序是由函数构成的(一个或多个函数)

C 语言程序必须有且只能有一个 main 函数

函数头

函数体

函数的定义

dagger 类型标识符指明函数返回值的类型若没有返回值可用 void

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 55: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 55

形式参数表

形式参数(简称 形参)需要指定数据类型

有多个形参时用逗号隔开每个形参需单独指定数据类型

如果函数不带参数则形参可以省略但小括号不能省

形参只在函数内部有效

类型标识符 变量 类型标识符 变量

函数返回值

通过 return语句给出如 return x若没有返回值可以不写也可以写不带表达式的 return

形式参数列表

int my_max(int x int y) OK

int my_max(int x y) ERROR

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 56: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 56

函数的调用

函数调用前须先声明

类型标识符 函数名(形式参数表)

可以在主调函数中声明也可以在所有函数之外声明

有时也称为函数原型

主调函数与被调函数

被调函数在主调函数后定义须在调用前声明

被调函数在主调函数前定义则主调函数中可以直接调用

函数的调用方式

函数名(实参数列表)

被调函数可以出现在表达式中此时必须要有返回值

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 57: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 57

函数的调用过程

int main()

fun1()

fun2()

int fun1()fun3()

int fun2()

int fun3()

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 58: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

思 考

dagger 如何生成 [a b] 之间的随机整数

dagger 如何生成 [0 1] 之间的随机小数

58

举例随机数

例随机数的生成

seed=11 srand(seed) 设置种子

x=rand() 返回一个随机整数

rand()返回一个 0 ~ RAND_MAX 之间的伪随机整数

srand(seed)设置种子如不设定默认种子为 1相同的种子对应相同的伪随机整数

每次执行 rand()后种子会自动改变 但变化规律是固定的

头文件 stdlibh

ex_rand_01c

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 59: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

NOTE

dagger clock()返回进程启动后所使用的 cpu 总滴答数(毫秒)

59

举例计时函数

include lttimehgt

clock_t t0 t1

double totaltime

t0 = clock()

t1 = clock()totaltime=(double)(t1 - t0) CLOCKS_PER_SEC

头文件 timeh例计时函数clock

ex_time_01c

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 60: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 60

举例计时函数

include lttimehgt

time_t t0 t1

t0 = time(NULL) t0 = time(0)

t1 = time(NULL)t = t1 - t0

例计时函数time头文件 timeh

NOTE

dagger time(NULL)返回从 1970 年 1 月 1 日 0 时 0 分 0 秒至今的总秒数

dagger clock以滴答(毫秒)为单位time以秒为单位

ex_time_02c

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 61: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

传递方式一值传递

61

参数传递

形参只在函数被调用时才分配存储单元调用结束即被释放

实参可以是常量变量表达式函数(名)等但它们必须

要有确定的值以便把这些值传送给形参

实参和形参在数量类型顺序上应严格一致

传递时是将实参的值传递给对应的形参即单向传递

形参获得实参传递过来的值后便与实参脱离关系

即此后形参的值的改变不会影响实参的值

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 62: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

double my_power(double x int k)

int main()

x = 30n = 2y = my_power(x n)

62

举例

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 63: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 63

数组元素作为参数

数组中的单个元素作实参

void my_swap(int a int b)

int tt = a a = b b = t

int main()

int x[2]=13 my_swap(x[0] x[1])

exampledagger 与单个变量一样(值传递)

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 64: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 64

数组名作为参数

dagger 在函数中对形参数组元素的改变会直接影响到实参数组即实参与形参

代表的是同一个数组

形参和实参都应该是数组名类型要一样

形参后面要加中括号

传递的是数组首地址也可以看作是传递数组的引用

数组名作参数

传递方式二地址传递

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 65: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

void my_swap(int a[] int b[] int n)

int t ifor (i=0 iltn i++) t=a[i] a[i]=b[i] b[i]=t

int main() const int n=3

int i x[n]=123 y[n]=246 my_swap(xyn)

65

数组作为函数的参数

用数组作形参一定要加中括号

但可以不指定第一维的大小

ex_array_swapc

dagger 数组作为形参时一般不指定大小(长度)此时通常需要加一个参数用来传递实参数组的大小这样函数才能知道实参数组有多少个元素

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 66: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

include ltstdiohgt

const int m=3 n=4 常量矩阵维数

void sum_col(double A[][n] double s[]) int i j

for(j=0 jltn j++) s[j]=00 赋初值

for(j=0 jltn j++)for(i=0 iltm i++) s[j] = s[j] + A[i][j]

int main() double H[m][n] s[n]

for(int i=0 iltm i++)for(int j=0 jltn j++) H[i][j]=10(i+j+1) sum_col(H s)printf(s[0]=f s[n-1]=fn s[0] s[n-1])return 0

66

数组举例

例计算矩阵各列的和

只能省略第一维的大小

ex_array_func

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 67: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 67

数组作为函数的参数

在定义函数时须指定数组的大小(常量表达式)

形参中含数组名的函数定义与调用注意事项

函数调用时只需输入数组名即可

void sum_col(double A[10][10] double s[10])

void sum_col(double A[][10] double s[])

const int n=10void sum_col(double A[][n] double s[])

sum_col(A s)

可以省略第 1 维的大小

若数组的大小中含有变量则必须是常量(全局)

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 68: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 68

函数的嵌套

函数可以嵌套调用但不能嵌套定义

函数也可以递归调用(函数可以直接或间接调用自己)

例利用右边的公式计算阶乘1 ( 0)

( 1) ( 0)

nn

n n n=

= minus gt

NOTE

dagger 对同一个函数的多次不同调用中编译器会给函数的形参和局部变量分配

不同的存储空间它们互不影响

ex_factorialc

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 69: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 69

递归

return 1

factorial(4)

return 4 factorial(3)

return 3 factorial(2)

return 2 factorial(1)

return 1 factorial(0)

Step 9 return 24 Step 0 executes factorial(4)

Step 1 executes factorial(3)

Step 2 executes factorial(2)

Step 3 executes factorial(1)

Step 5 return 1

Step 6 return 1

Step 7 return 2

Step 8 return 6

Step 4 executes factorial(0)

Step 4 executes factorial(0)13

13

Step 8 return 613

13

Step 7 return 213

13

Step 6 return 113

13

Step 5 return 113

13

Step 3 executes factorial(1)13

13

Step 2 executes factorial(2)13

13

Step 1 executes factorial(3)13

13

Step 0 executes factorial(4)13

13

Step 9 return 2413

13

return 113

13

return 1 factorial(0)13

13

return 2 factorial(1)13

13

return 3 factorial(2)13

13

return 4 factorial(3)13

13

factorial(4)13

13

13

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 70: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 70

内联函数

定义与普通函数一样只需加关键字 inline 编译时在调用处用函数体进行替换

使用内联函数能节省参数传递控制转移等开销

从而提高代码的执行效率

内联函数声明与使用

NOTE

dagger 内联函数通过应该功能简单规模小使用频繁

dagger 内联函数体内不建议使用循环语句和 switch 语句

dagger 有些函数无法定义成内联函数如递归调用函数等

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 71: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 71

局部变量与全局变量

每个变量都有作用域即在程序中哪些地方可以使用该变量

函数定义时的形参和函数中定义的变量均为局部变量只在该函数内有效

语句块中定义的变量是局部变量只在该语句块中有效

for 循环初始语句中定义的变量是局部变量只在 for循环中有效

extern 类型名 变量名

在所有函数外定义的变量为全局变量在它后面定义的函

数中均可以使用若要在它前面定义的函数中使用该全局变

量则需声明其为外部变量即

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 72: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

include ltstdiohgt int k = 2 全局变量

int main()

int i=5 x 局部变量x=i+k printf(x=dn x)

int k=16 局部变量x=i+kprintf(x=dn x)

x=i+k printf(x=dn x)

72

局部变量与全局变量

若局部变量与全局变量同名则优先使用局部变量

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 73: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

指针的定义与使用

指针与数组

指针与函数

字符串

4 指针与字符串

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 74: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 74

指针

指针极大地丰富了 C 语言的功能

运用指针编程是 C 语言最主要的风格之一

运用指针可以很方便地使用数组和字符串

指针能使 C 语言象汇编语言一样处理内存地址提高效率

指针是 C 语言中最重要的一环也是最为困难的一部分

能否正确理解和使用指针是掌握 C 语言的一个标志

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 75: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 75

指针定义

指针的定义

声明一个指针类型的变量

类型标识符表示该指针可指向的对象的数据类型即该指针所代表

的内存单元所存放的数据的类型

指针变量简称指针用来存放其它变量的内存地址

什么是指针

类型标识符 指针变量名

Tips变量为什么要声明

1) 分配内存空间 2) 限定变量能参与的运算及运算规则

Tips内存空间的访问方式1) 变量名 2) 内存地址即指针

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 76: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 76

指针运算

地址运算符amp

此时我们通常称 px是指向 x的指针

注意指针的类型必须与其指向的对象的类型一致

提取变量的内存地址amp引用指针所指向的变量

指针的两个基本运算

amp变量名 提取变量在内存中的存放地址

int x=3 int px 定义指针 pxpx=ampx 将 x 的地址赋给指针 px

example

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 77: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 77

指针运算

指针运算符指针变量 引用指针变量所指向的对象

int x int px 声明指针变量星号后面可以有空格

px=ampx px = 3 等价于 x = 3星号后面不能有空格

dagger 在使用指针时我们通常关心的是指针指向的元素

int x = 3 int px = ampx 初始化指针的值只能是某个变量的地址

Example指针的初始化

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 78: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 78

指针赋值

指针可能的取值

dagger 没有初始化或赋值的指针是无效的指针

dagger 引用无效指针会带来难以预料的问题

(1) 一个对象的地址

(2) 指向某个对象后面的对象

(3) 值为 0 或 NULL(空指针)

有效指针的三种取值

(1) 0 或者值为 0 的常量表示空指针

(2) 类型匹配的对象的地址

(3) 同类型的另一有效指针

(4) 类型匹配的对象的下一个地址(相对位置)

指针赋值只能用以下四种类型的值

int x=3 int px=ampxInt py=ampx+1

int pipi=0 OKpi=NULL OK

Example

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 79: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

const int a = 3 int b = 5 const int cpa = ampa OKcpa = 5 ERRORcpa = ampb OKcpa = 9 ERRORb = 9 OK

79

指针与常量

指向常量的指针

指向 const 对象(常量)的指针必须用 const 声明

这里的 const 限定了指针所指对象的属性不是指针本身的属性

允许把非 const 对象的地址赋给指向 const 的指针

但不允许使用指向 const 的指针来修改它所指向的对象的值

指向常量的指针所指对象的值并

不一定不能修改

const 类型标识符 指针名

const int a = 3 int pa = ampa ERRORconst int cpa = ampa OK

ex_pointer_constc

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 80: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 80

指针与常量

常量指针简称常指针

常量指针指针本身的值不能修改

指向 const 对象的 const 指针

指针本身的值不能修改也不能通过它来修改其指向的对象

类型标识符 const 指针名

int a = 3 b = 5 int const pa = ampa OKpa = ampb ERROR

const 类型标识符 const 指针名

Example

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 81: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 81

指针算术运算

在指针上加上或减去一个整型数值 k等效于获得一个新指针该

指针指向原来的元素之后或之前的第 k 个元素

指针的算术运算通常是与数组的使用相联系的

一个指针可以加上或减去 0其值不变

指针可以和整数或整型变量进行加减运算且运算规则与

指针的类型有关

int pa int kpa + k pa 所指的当前位置之后第 k 个元素的地址pa - k pa 所指的当前位置之前第 k 个元素的地址

Example

int pa int kpa++ pa 所指的当前位置之后的元素的地址pa-- pa 所指的当前位置之前的元素的地址

Example

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 82: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 82

指针算术运算

pa

pa-2

pa-1

pa+1

pa+2

pa+3

(pa-2)

pa

(pa+1)

(pa+2)

(pa+3)

(pa-1)

short pa 每个元素占两个字节

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 83: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 83

指针算术运算

pb

pb-1

pb+1

pb+2

pb

(pb+1)

(pb+2)

(pb-1)int pb 每个元素占四个字节

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 84: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 84

指针与数组

在 C 语言中数组名就是数组的首地址

当数组名出现在表达式中时会自动转化成指向第一个数组元素的指针

C 语言中指针与数组密切相关由于数组元素在内存中是连

续存放的因此使用指针可以非常方便地处理数组元素

int a[]=0248int pa pa = a OKpa = ampa[0] OK 与上式等价pa = 3 OK等价于 a[0]=3(pa+2) = 5 OK等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5

Example

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 85: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 85

一维数组与指针

在 C 语言中引用一维数组元素有以下三种方式

(1) 数组名与下标如a[0](2) 数组名与指针运算如(a+1)(3) 指针如int pa=a pa

指针的值可以随时改变即可以指向不同的元素

数组名等价于常量指针值不能改变

int a[]=0248int pa = a pa = 1 等价于 a[0]=1(pa+2) = 5 等价于 a[2]=5(a+2) = 5 OK等价于 a[2]=5(pa++) = 3 OK等价于 a[0]=3 pa = pa+1(a++) = 3 ERROR a代表数组首地址是常量指针

(pa+1) = 10 思考修改了哪个元素的值

example

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 86: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

第三种方式指针

for (int pa=a palta+n pa++)printf(d pa)

第三种方式指针

for (int pa=a i=0 iltn i++)printf(d pa[i])

86

举例

例使用三种方法输出一个数组的所有元素

第一种方式数组名与下标

for (int i=0 iltn i++)printf(d a[i])

第二种方式数组名与指针运算

for (int i=0 iltn i++)printf(d (a+i))

ex_pointer_array02c

若pa是指针k是整型数值则

(pa+k) 可以写成 pa[k]

(pa-k) 可以写成 pa[-k]

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 87: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 87

一维数组与指针

数组名 a 是地址常量数组名 a 与 ampa[0] 等价

a+i 是 a[i] 的地址a[i] 与 (a+i) 等价

数组元素的下标访问方式也是按地址进行的

可以通过指针 pa 访问数组的任何元素且更加灵活

pa++ 或 ++pa 合法但 a++ 不合法

(pa+i) 与 pa[i] 等价表示第 i+1 的元素

一维数组 a[n] 与指针 pa=a

a[i] lt=gt pa[i] lt=gt (pa+i) lt=gt (a+i)

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 88: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 88

二维数组

例int A[2][3]=123789

A[0] mdashmdash A00 A01 A02A[1] mdashmdash A10 A11 A12

A可以理解为

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]

A[0] A[1](第一行的首地址) (第二行的首地址)

C++中二维数组是按行顺序存放在内存中的可以理解为

一维数组组成的一维数组

dagger A[0] A[1]有时也称为行数组

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 89: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 89

二维数组与指针

int A[2][3]=123789int pa = A[0] 行数组A[0]的首地址 等价于 pa=ampA[0][0]int pa1 = A[1] 行数组A[1]的首地址即 ampA[1][0]pa = 11 等价于 A[0][0]=11(pa+2) = 12 等价于 A[0][2]=12(pa+4) = 13 等价于 A[1][1]=13

Example

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 90: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 90

二维数组与指针

对于二维数组 A虽然 AA[0]都是数组首地址但二者指向的对象不同

而 A是一个二维数组的名字它指向的是它的首元素即 A[0]

A[0]是一维数组的名字它指向的是行数组 A[0]的首元素即 A[0][0]

A[0] A[0][0]

(A[0]+1) A[0][1]

A A[0]

(A+1) A[1]

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 91: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 91

二维数组与指针

当 int p声明指针时p指向的是一个 int型数据而不是一个地址

因此用 A[0]对 p赋值是正确的而用 A对 p赋值是错误的

如何用普通指针引用二维数组的元素

int A[2][3]=123789int p = A ERRORint p = A[0] OK

Example

设指针 p=ampA[0][0]则 A[i][j] lt==gt (p+ni+j)

ex_pointer_array2Dc

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 92: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 92

指针作为函数参数

以地址方式传递数据

形参是指针时实参可以是指针或地址

指针作为函数参数

void split(double x int n double f)

double x x2int x1 split(x ampx1 ampx2)

example

dagger 当函数间需要传递大量数据时开销会很大此时如果数据是连续存放

的则可以只传递数据的首地址这样就可以减小开销提高执行效率

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 93: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 93

指针作为函数参数

使形参和实参指向共同的内存地址

减小函数间数据传递的开销

可以传递函数代码的首地址(后面介绍)

指针作为函数参数的作用

Tips如果在被调函数中不需要改变指针所指向的对象的值则可以将形参中

的指针声明为指向常量的指针以保护原始数据

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 94: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 94

指针型函数

指针型函数的定义

当函数的返回值是地址时该函数就是指针型函数

数据类型 函数名(形参列表)

函数体

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 95: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 95

指向函数的指针

函数指针的定义

这里的数据类型和形参列表应与其指向的函数相同

在程序运行过程中不仅数据要占用内存空间函数也要在

内存中占用一定的空间函数名就代表函数在内存空间中的

首地址用来存放这个地址的指针就是指向该函数的指针

数据类型 ( 函数指针名)(形参列表)

dagger 注函数名除了表示函数的首地址外还包括函数的返回值类型形参

个数类型顺序等信息

Tips可以象使用函数名一样使用函数指针

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 96: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 96

函数指针

函数指针需要赋值后才能使用

int Gcd(int x int y)int Lcm(int x int y)

int ( pf)(int int) 声明函数指针

pf=Gcd pf 指向函数 Gcdprintf(最大公约数dn pf(ab) )

pf=Lcm pf 指向函数 Lcm printf(最小公倍数dn pf(ab) )

ex_pointer_fun02c

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 97: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

97

字符串

字符串的表示一维字符数组

字符串以 0 为结束标志

使用双引号时会自动在最后添加结束标志

char str[5] str = Math ERROR一维数组不能直接赋值

字符串赋值逐个赋值循环实现

m a t h 0str

char str[5]=math0 OK只能用于初始化

char str[5]=math OK只能用于初始化

char str[]=math OK只能用于初始化

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 98: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 98

字符串输入输出

字符串的输入

字符串的输出

scanf(ldquosrdquo str)

gets(str)

printf(ldquosrdquo str)

puts(str)

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 99: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 99

字符串操作

字符串相关函数(头文件 stringh 和 stdlibh )

函数 描述 用法

strlen 求字符串长度 strlen(str)

strcat 字符串连接 strcat(destsrc)

strcpy 字符串复制 strcpy(destsrc)

strcmp 字符串比较 strcmp(str1str2)

atoi 将字符串转换为整数 atoi(str)

atol 将字符串转换为long atol(str)

atof 将字符串转换为double atof(str)

(更多函数可参见 httpwwwcppreferencecom)

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 100: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 100

字符检测

函数 描述 用法

isdigit 是否为数字 isdigit(3)isalpha 是否为字母 isalpha(a)isalnum 是否为字母或数字 isalnum(c)islower 是否为小写 islower(b)isupper 是否为大写 isupper(B)isspace 是否为空格 isspace( )

tolower 将大写转换为小写 tolower(A)toupper 将小写转换为大写 toupper(a)

更多字符检测函数参见相关资料

头文件 ctypeh

dagger 注以上检测和转换函数只针对单个字符而不是字符串

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 101: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

目录页

Contents

华东师范大学 数学科学学院School of Mathematical Sciences ECNU

httpmathecnueducn~jypan

文件了类型

打开与关闭

读写文本文件

读写二进制文件

5 文件操作

1

2

C 语言基础

选择与循环

3 函数

4 指针与字符串

5 文件操作

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 102: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 102

文件分类

文件的分类

按存储介质

普通文件存储介质文件(磁盘磁带等)

设备文件非存储介质(键盘显示器打印机等)

按数据的组织形式

文本文件ASCII 文件每个字节存放一个字符的 ASCII 码

二进制文件数据按其在内存中的存储形式原样存放

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 103: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 103

打开文件

文件指针

文件打开

文件名普通字符串

打开方式读写文本文件二进制文件

rtwtatrbwbabrt+wt+at+rb+wb+ab+

(r为读w为写+为读写t为文本b为二进制)

FILE pf

pf=fopen(文件名打开方式)

dagger 注若文件打开成功返回指向文件的指针

若打开失败则返回一个空指针(NULL)

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 104: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 104

关闭文件

文件关闭

正常关闭返回值为 0 出错时返回值为非0

fclose(pf)

FILE pfpf=fopen(out1txtwt)if (pf==NULL)

printf(ERROR Can not open the filen)exit(1)

fprintf(pfThis is my first filen)fclose(pf)

example

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 105: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 105

读写文本文件写文本文件

用法与 printf 类似

读文本文件

fprintf(pf 格式控制字符串输出变量列表)

FILE pfpf=fopen(out1txtwt)double pi=31415926fprintf(pfpi=-126fnpi)fclose(pf)

ex_fprintfc

fscanf(pf 格式控制字符串地址列表)

fscanf(fpdf ampi ampt)

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 106: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan 106

读写二进制文件

写二进制文件

读二进制文件

将 count 个长度为 size 的连续数据写入到 pf 指向的文件中buffer是这些数据的首地址(可以是指针或数组名)

从 pf 指向的文件中读取 count 个长度为 size 的连续数据buffer 是

存放这些数据的首地址(可以是指针或数组名)

fwrite(buffer sizecountpf)

fread(buffer sizecountpf)

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件
Page 107: C 语言编程初步 - East China Normal Universityjypan/Teaching/ParaComp/lect03_C.pdf · C . 语言概述. . 1969-1973,由Dennis M. Ritchie 设计并实现. . 1973,UNIX 的内核正式用C

httpmathecnueducn~jypan

int A[3][3]=111213212223313233FILE pfpf=fopen(data1datwb) fwrite(Asizeof(int)9pf)fclose(pf)

int B[3][3]pf=fopen(data1datrb) fread(Bsizeof(int)9pf)fclose(pf)

107

二进制文件

ex_fwrite_freadc

fwrite(Asizeof(A)1pf)

  • 第三讲
  • 幻灯片编号 2
  • 幻灯片编号 3
  • 程序设计语言的发展
  • 高级语言典型代表
  • 高级语言的发展(部分)
  • C 语言概述
  • 一个简单的 C 程序
  • C 程序书写规范
  • C 语言编译器
  • IDE
  • 字符集
  • 词法记号词汇
  • 代码编写与运行
  • C 语言数据类型
  • 基本数据类型
  • 数据类型转换
  • 数据类型转换
  • 变量
  • 常量(常数)
  • 符号常量
  • 运算符
  • 赋值运算
  • 赋值与逗号运算
  • sizeof
  • 运算优先级
  • 常用数学函数
  • C 语言输出
  • 格式字符串
  • 格式说明符与转义字符
  • C 语言输入
  • 数组
  • 一维数组
  • 一维数组
  • 二维数组
  • 二维数组
  • 二维数组
  • 多维数组
  • 编译预处理
  • 条件编译
  • 幻灯片编号 41
  • 关系运算比较大小
  • 逻辑运算
  • 逻辑运算两点注意
  • 条件运算符
  • 选择结构if 语句
  • 选择结构switch语句
  • 循环结构while 循环
  • 循环结构do while 循环
  • for 循环
  • for 循环
  • 循环的终止
  • 幻灯片编号 53
  • 函数的定义
  • 形式参数表
  • 函数的调用
  • 函数的调用过程
  • 举例随机数
  • 举例计时函数
  • 举例计时函数
  • 参数传递
  • 举例
  • 数组元素作为参数
  • 数组名作为参数
  • 数组作为函数的参数
  • 数组举例
  • 数组作为函数的参数
  • 函数的嵌套
  • 递归
  • 内联函数
  • 局部变量与全局变量
  • 局部变量与全局变量
  • 幻灯片编号 73
  • 指针
  • 指针定义
  • 指针运算
  • 指针运算
  • 指针赋值
  • 指针与常量
  • 指针与常量
  • 指针算术运算
  • 指针算术运算
  • 指针算术运算
  • 指针与数组
  • 一维数组与指针
  • 举例
  • 一维数组与指针
  • 二维数组
  • 二维数组与指针
  • 二维数组与指针
  • 二维数组与指针
  • 指针作为函数参数
  • 指针作为函数参数
  • 指针型函数
  • 指向函数的指针
  • 函数指针
  • 字符串
  • 字符串输入输出
  • 字符串操作
  • 字符检测
  • 幻灯片编号 101
  • 文件分类
  • 打开文件
  • 关闭文件
  • 读写文本文件
  • 读写二进制文件
  • 二进制文件