C语言基本语法归纳_图文

C语言基本语法归纳 及实例介绍
计算机教学中心 李雪飞

提 纲
C语言概况 ? C程序的结构 ? 数据类型、运算符与表达式 ? 最简单的C程序设计—顺序程序设计 ? 选择结构程序设计 ? 循环控制 ? 数组 ? 函数 ? 指针
?

C语言概况
? C的优点

?1)、高效 ?2)、可移植

?3)、灵活
? C的缺点
?可读性差,学习应用较难。

[例1.1] main( ) { printf("This is a C program.\n"); } 该程序的作用:在屏幕上输出一行信息: This is a C program. 1、main( ) 表示“主函数”,每一个C程序都必须有 且只有一个主函数。 2、main函数体由大括号{ }括起来。 3、语句后面有一个分号。. 4、printf( )是C语言的输出函数。双引号内的字符 被原样输出。 5、“\n”是换行符,即在输出This is a C program 之后换行。

C语言概况--简单的C程序

[例1.2]求两数之和。

main( )
{ int a, b, sum; /*定义三个整型变量。(int = integer)。*/ a = 123;b = 456; /*把常数123赋给变量a,把常数456赋给变量b*/ sum = a + b; /*计算a、b之和,并把和值赋变量给sum*/ printf(“Sum is %d\n”, sum);/*输出sum的值*/
}
? ?

程序的输出信息为: sum is 579 /* */中间的内容表示“注释”。注释是程序员对程序某部分的功能和作用所做的 说明,是给人看的,对编译和运行不起作用。 %d表示输出的数据类型是十进制整数类型。在输出时,该位置用对应变量sum 的值代替。

[例1.3]输入两个整数,输出其中的最大值。
int max(int x,int y) /*求两数最大值函数max*/ { int z; if(x>y) z=x; else z=y; return (z); /*将z的值返回给主函数main*/ } /*返回值通过函数名max带回main函数调用处*/ main ( ) /*主函数*/ { int a,b,c; scanf(“%d,%d”,&a,&b); /*输入a,b的值*/ c=max(a,b); /*调用max函数,将实参a,b的值给形参x,y*/ printf(“max=%d”,c); /*输出最大值*/ }

C程序的结构
?

1、C 程序是由函数构成的。一个C源程序至少 包括一个函数(main函数:它代表程序开始执行 的起始位置),也可以包括一个main函数和若干 其它函数。因此,函数是C程序的基本单位。

?

C程序的结构
C程序中有三种类型的函数: 1).main():主函数,每一个C程序必须且只有一个main() 函数。 2).开发系统提供的特殊函数,如printf( )、scanf( )等。 Turbo C开发系统提供三百多个函数。 3).程序员自己设计的函数,如例1.3中的函数max()。 C的函数相当于其它语言中的子程序。用函数来实现 特定的功能。可以说C是函数式的语言。程序全部工 作都是由函数来完成的。C的这种特性很容易实现模

块化。

C程序的结构
?

2、一个函数由两部分组成: (1)函数的说明部分。包括函数名、函数类型、函数 属性、函数参数(形参)名、形式参数类型。 如int max (int x, int y)

?

函数类型 函数名 函数参数类型 函数参数名 函数参数类型 函数参数名 ?

(2)函数体。即函数说明部分下面的大括弧{...}内的 部分。如果一个函数内有多个大括弧,则最外层的一对 { }为函数体的范围。

C程序的结构
函数体一般包括: ① 变量定义。如[例1.3]中main函数中的“int a,b,c;” ② 执行部分。由若干个语句组成。 当然,在某些情况下也可以没有变量定义部分(例如 [例1.1])。甚至可以既无变量定义也无执行部分,如: dump()

{} 它是一个空函数,什么也不干,但这是合法的。

C程序的结构
3、一个C程序总是从main函数开始执行的,而不论 main函数在整个程序中的位置如何(main函数可以放 在程序最前头,也可以放在程序最后,或在一些函数之

前在另一些函数之后)。
4、 C程序书写格式自由,一行内可以写几个语句,

一个语句可以分写在多行上。C程序没有行号,也不象 fortran或cobol那样严格规定书写格式(语句必须从某 一列开始书写)。

C程序的结构
5、每个语句和数据定义的最后必须有一个分号。分号 是C语句的必要组成部分。例如:c=a+b; 分号不可少。 即使是程序中最后一个语句也应包含分号(这是和

pascal语言不同的)。 6、C语言本身没有输入输出语句。输入和输出的操作 是由库函数scanf和printf等函数来完成的。C对输入输 出实行“函数化”。 7、可以用/*……*/对C程序中的任何部分作注释。可以 增加程序的可读性。

程序开发过程
编 译 C源代 码 程 …… 序 C源代 码 编 译 程 序 目标 代码 链 接 程 序 可 执 行 代 码

?

?

目标 代码 库

数据类型、运算符与表达式

§3.1 信息在计算机中的存储与表示
计算机的基本功能是进行数据的计算和加工处理, 程序和数据在计算机的存储是用二进制形式表示的。 ? 数与字符是自然信息与计算机二进制信息的中转环 节。 ? 数制:就是用一组固定的数字和一套统一的规则来 表示数据的方法。
?
? 日常使用的十进制(逢十进一)
? 机器内部的二进制(逢二进一) ? 其它常用的数制:八进制,十六进制

不同数制之间的对应表示
十进制 decimal 0 1 二进制 binary 0 1 八进制 octal 0 1 十六进制 hexdecimal 0 1

2
3 4 5 6

10
11 100 101 110

2
3 4 5 6

2
3 4 5 6

7

111

7

7

十进制 decimal 8 9 10 11 12 13 14 15 16

二进制 binary 1000 1001 1010 1011 1100 1101 1110 1111 10000

八进制 octal 10

十六进制 hexdecimal 8 9 A B C D E F 10

11 12 13
14 15 16 17 20

数制间的转换
? 1.二、八、十六进制转换为十进制

按权展开法。 例: (101.11)2=1×22+0×21+1×20+1×2-1+1×2-2 =(5.75) 10 (127.4)8=1×82+2×81+7×80+4×2-1 =(87.5) 10

数制间的转换
2.十进制转换为二、八、十六进制 整数部分:除R取余法(先余为低,后余为高) 小数部分:乘R取整法(先整为高,后整为低) 转换精度问题 例: (4.6875)10=(?) 2 结果: (100.1011) 2
?

(87.5)10=(?) 8 结果: (127.47) 8

数制间的转换
? 3.二进制与八、十六进制之间的转换
?八、十六进制转换为二进制

一分为三、一分为四 例: (23.54)8=(010011.101100) 2 =(10011.1011) 2 (13.B)16=(00010011.1011) 2 =(10011.1011) 2 ?二进制转换为八、十六进制 合三为一、合四为一

§3.2 C的数据类型
? ? ?

数据结构指的是数据的组织形式。 不同的计算机语言所允许定义和使用的数据结构是不同的。 处理同一类问题,如果数据结构不同,算法也会不同。

?

所以,我们应当综合考虑算法和数据结构,选择最佳的数 据结构和算法。
数据结构+算法=程序 对程序当中所用到的所有数据都必须指定其数据类型。 C语言的数据结构是以数据类型形式出现的。

? ?

C的数据类型如下:

§3.2 常量与变量
? 3.2.1 ? 3.2.2

常量和符号常量

变量

3.2.1 常量和符号常量
?
?

在程序运行过程中,其值不能被改变的量称为常量。
常量分为: (1)整型常量;如12,0,-3等; (2)实型常量;如4.6,-1.23等; (3)字符常量;如‘a?,‘d?等;

(将在后面的小节中详细讲解)
?

常量一般从其字面形式即可判别,这种常量称为字面常量 或直接常量。
也可以用一个标识符代表一个常量。如例3.1

?

例 3.1 符号常量的使用。
#define PRICE 30 main() {int num,total; num=10; total=num*PRICE; printf(“total=%d”,total); } 程序中用#define 命令行定义PRICE代表常量30,此后 凡在本文件中出现的PRICE都代表30,可以和常量一样 进行运算。 程序运行结果为:total=300

符号常量
?

用一个标识符代表一个常量的,称为符号常量,即标识 符形式的常量。 注意:符号常量不同于变量。符号常量的值在其作用域 (例3.1中即为main()函数)内不能被改变,也不能被再 次赋值。如:在主函数main中再次用“PRICE=40”语句 对PRICE赋值是错误的。

?

?

为了方便区分符号常量与变量,习惯上符号常量名大写, 变量名小写。

使用符号常量的好处
(1)含义清楚。

定义符号常量名时应考虑“见名知意”,在一个规范的程 序中不提倡使用很多的常数,如:sum=15*30*23.5*43. 在检查程序时搞不清各个常数究竟代表什么。应尽量使 用“见名知意”的变量名和符号常量。
(2)在需要改变一个常量时能够做到“一改全改”。例如, 在程序中多处用到某物品的价格,如果价格用常数表示, 则在价格进行调整时,需要在程序中作多处修改;若使 用符号常量PRICE代表价格,则只需在定义该符号常量 处作一次修改即可。如:#define PRICE=35

3.2.2 变量
?

其值可以改变的量称为变量。一个变量应该有一个名字,

在内存中占据一定的存储单元。在该存储单元中存放该 变量的值。
?

注意:变量名与变量值的区别。 变量名(一个符号地址,在对程序编 译时系统分配给它一个内存地址)

a

3

变量值(在程序中对变量取值,实际上是 通过变量名找到相应内存地址,从其存储 单元中读取数据) 存储单元

?

变量的使用是程序设计的中心环节之一,应掌握:

(1) 变量的定义:某一时刻值是确定的,不同时刻可能取不同的值, 其改变是不连续的。
(2) 变量的两个要素

变量名:它是一个标识符,代表一定的内存存储单元,存储单元有一 个地址。C语言以“&变量名”表示变量的地址。
变量值:它存放在相应的存储单元中,C语言在使用变量名时,实际上

是在使用存储单元中存放的变量的值。

变量的命名规则
?

变量的命名符合一般标识符(名字)的命名规则 。 以字母开头,后边跟以字母或者数字,下划线等同于字

(1)“字母数字串” ;

母。(汉字看作字母,但编程时尽量避免使用汉字,因 为汉字的兼容性不好)
(2) 建议长度不超过8个字符(可移植性要求);

(3) 区分大小写 (一般使用小写字母);
(4) 尽量做到“见名知意”,避免使用代数符号(如 a,b); (5) 不能有空格,不能有小数点。

变量的强制定义
?

在C语言中,要求对所有用到的变量作强制定义,就是 “先定义,后使用”。这样做的目的是:

(1)凡是没有被事先定义的,不作为变量名,这就能保 证程序中变量名使用的正确; (2)每一个变量被指定为一确定类型,在编译时就能为 其分配相应的存储单元;

(3)制定每一变量属于一个类型,这就便于在编译时, 据此检查该变量所进行的运算是否合法。

§3.3 整型数据
?
? ?

3.3.1 整型常量的表示方法
3.3.2 整型变量

3.3.3 整型常量的类型

3.3.1 整型常量的表示方法
?

整形常量即整常数。C整常数可用以下三种形式表示:

(1)十进制整数。如123、-456、0 (2)八进制整数。以0开头的数是八进制数。如0123表

示八进制数123,即(123)8,等于十进制数83(1×82+ 2×81+3×80=83 )。-011表示八进制数-11,即十进 制数-9。 ( 3 ) 十 六 进 制 整 数 。 以 0x 开 头 的 数 是 16 进 制 数 。 如 0x123,代表16进制数123。

3.3.2 整型变量
?
?

1.整型数据在内存中的存放形式
2.整型变量的分类

?
?

3.整型变量的定义
4.整型数据的溢出

整型变量的分类
?

(1)基本型,以int表示。

?
? ?

(2)短整型,以short int表示,或以short表示。
(3)长整型,以long int表示,或以long表示。 (4)无符号型,以存储单元中全部二进位(bit)存放数本身, 而不必空出最高位作为符号位。无符号型中又分为无符号 整型、无符号短整型和无符号长整型,分别以unsigned

int, unsigned short, unsigned long表示。
?

如果整量在内存中占2个字节(16位),则int型变量数 的范围为-32768~32767。而unsigned int型变量数的范围

为0~65535.

各类数据所占内存字节数
?

C标准没有具体规定以上各类数据所占内存的字节数, 只要求long型数据长度不短于int型,short型不长于int型。 具体如何实现,有各计算机系统自行决定。 通常的做法是:把long定为32位,把short定为16位, 而int可以是16位,也可以是32位。
在微机上用long型可以得到大范围的整数,但同时会降 低运算速度,因此不要随便使用long型。

?

?

整型变量的定义
?

前面已提到,C规定在程序中所有用到的变量都必须在 程序中指定其类型,即“定义”。这和BASIC, FORTRAN不同,而和PASCAL相类似。例如: int a,b;(指定变量a,b为整型) unsigned short c,d; (指定变量c,d为无符号短整型) long e,f (指定变量e,f为长整型)

?

?

对变量的定义,一般是放在一个函数的开头部分的声明 部分,变量的作用域是整个函数;也可以放在函数中的 某一分程序内,但变量的作用域只限于该分程序内(这 将在第8章介绍)。

例3.2 整型变量的定义与使用
main() { int a,b,c,d; /*指定a,b,c,d为整型变量*/ unsigned u; /*指定u为无符号整型变量*/ a=12;b=-24;u=10; c=a+u;d=b+u; printf(“a+u=%d,b+u=%d\n”,c,d); } 运行结果为:a+u=22,b+u=-14 可以看到:不同种类的整型数据可以进行算术运算。在 本例中是int型数据与unsigned int型数据进行加减运算。

§3.4 实型数据
? ? ?

3.4.1 实型常量的表示方法 3.4.2 实型变量 3.4.3 实型常量的类型

3.4.1 实型常量的表示方法
?

实数在C语句中又称为浮点数。实数有两种表示形式:

(1)十进制数形式。它由数字和小数点组成(注意必须有 小数点)。0.123, .123, 123.0, 123., 0.0都是十进制数形 式。 (2)指数形式。如123e3或123E3都代表123×103 。但 注意字母e(或E)之前必须有数字,且e后面指数必须为 整数,如e3, 2.1e3.5, .e3, e等都不是合法的指数形式。

3.4.2 实型变量
? ? ?

1. 实型数据在内存中的存放形式 2. 实型变量的分类 3. 实型数据的舍入误差

3.4.2 实型变量
? ? ?

1. 实型数据在内存中的存放形式 2. 实型变量的分类 3. 实型数据的舍入误差

§3.5 字符型数据
? ? ? ?

3.5.1 字符常量 3.5.2 字符变量 3.5.3 字符数据在内存中的存储形式 3.5.4 字符串常量

3.5.1 字符常量
C的字符常量是用单引号括起来的一个字符。如'a', 'D', '?'等都是字符常量。注意,'a'和'A'是不同的字符的常量。
?

除了以上形式的字符常量外,C还允许用一种特殊的字

符常,就是以一个“\”开关的字符序列。例如,前面已 经遇到过的,在printf函数中的‘\n?,它代表一个“换 行”符,这种非显示字符难以用一般形式的字符表示, 故规定用这种特殊形式表示。
?

这类特殊的字符称为“转义字符”。

转义字符
?

a. 控制字符: \t 水平制表(跳到下一个tab位置); \r 回车; \n 换行; b. 疑难字符: \?单引号字符 \\ 反斜杠字符 c. 指定ASCII码对应的字符: 格式1: \xhh:1到2位十六进制数ASCII码对应的字符 如:\x42表示字符“B”; 格式2:\ddd: 1到3位八进制数ASCII码对应的字符 如:\102同样表示字符“B”;

3.5.2 字符变量
字符型变量用来存放字符常量,注意只能放一个字符, 不要以为在一个字符变量中可以放一个字符串(包括若干 字符)。字符变量的字义如下: char c1,c2; 它表示c1和c2为字符型变量,各可以放一个字符。因此 可以用下面语句对c1,c2赋值: c1='a';c2='b'
?

一般以一个字节来存放一个字符,或者说一个字符变量 在内存中占一个字节。

3.5.3 字符数据在内存中的存储形式
?

将一个字符常量放到一个字符变量中,并不是把该字符 本身放到内存单元中,而是将该字符的ASCII码放到存 储单元中,而且以二进制形式存放。例如:执行赋值语 句c1=?a?;c2=?b?;字符‘a?的ASCII码为97,‘b?为98,在 内存中变量c1,c2的值如图所示: c1 97 c2 98 c1 01100001 c2 01100010

?

既然在内存中,字符数据以ASCII码存放,它的存储形 式就与整数的存储类似,这使得字符型数据和整型数据 之间可以通用。

字符型数据和整型数据的通用性
?

一个字符数据既可以以字符形式输出,也可以以整数形 式输出。 两种通用形式的输出;以字符形式输出时,需要先将存

?

储单元中的ASCII码转换成相应字符,然后输出;以整 数形式输出时,直接将ASCII码作为整数输出。
?

对字符数据进行算术运算;相当于对它们的ASCII码进

行整数的算术运算。
?

相互赋值;字符数据与整型数据可以相互赋值。

程序输出如下: 两种通用形式的输出 a b 97 98 main() {char c1,c2; c1=97;c2=98; (等价于c1=?a?;c2=?b?;) printf(“%c%c\n”,c1,c2); printf(“%d%d\n”,c1,c2); }

将97和98两个整数 直接存放到c1和c2的内 存单元中。

先将字符‘a? 和‘b? 化成ASCII码97和98,然 后放到内存单元中。

两者的作用和结果是完全相同的

对字符数据进行算术运算
例3.7 大小写字母的转换。 main() {char c1,c2; c1=?a?;c2=?b?; c1=c1-32;c2=c2-32; printf(“%c%c”,c1,c2); } 运行结果为: A B ?a?的ASCII码为97,‘A?为65; ‘b?为98,‘B?为66。从ASCII 代码表中可以发现:每一个 小写字母比它相应的大写字母 的ASCII码大32。 C语言允许字符数据与整数 直接进行算术运算。

相互赋值
字符数据与整型数据可以相互赋值。 main() {int i; char c; i=?a?; c=97; printf(“%c,%d\n”,c,c); printf (“%c,%d\n”,i,i); } 运行结果:a,97 a,97
?

3.5.4 字符串常量
前面已提到,字符常量是由一对单引号括起来的单个字 符。C语言除了允许使用字符常量外,还允许使用字符 串常量。
字符串常量是一对双引号括起来的字符序列。如: “How do you do.”, “CHINA”, “$123.45”都是字符串常量。 可以输出一个字符串,如printf("How do you do.");

?

不要将字符常量与字符串常混淆。‘a?是字符常量, “a”是字符串常量,二者不同。 假设C被指定为字符变量: char c; c=?a?; 是正确的; 而 c=“a”; 是错误的。 究竟为什么 c=?a?就是正确的, 而c=“a”就错了 呢?

?

c=“CHINA”, 也是错误的。
?

不能把一个字符串赋给一个字符变量。

§3.6 变量赋初值
?

程序中常需要对一些变量预先设置初值。C语言允许在定 义变量的同时使变量初始化。 int a=3; /*指定a为整型变量,初值为3*/

?

float f=3.56;
char c=?a?;
?

/*指定f为实型变量,初值为3.56*/
/*指定c为字符变量,初值为‘a?*/

也可以使被定义的变量的一部分赋初值。 int a,b,c=5; /*指定a,b,c为整型变量,只对c初始化*/ 如果对几个变量赋予初值3,应写为:int a=3,b=3,c=3;

?

不能写成:int a=b=c=3

?

初始化不是在编译阶段完成的(只有在第8章中介绍 的静态存储变量和外部变量的初始化时在编译阶段完 成的)。 如:int a=3; 相当于:int a; /*指定a为整型变量*/ a=3; /*赋值语句,将3赋给a*/

?

?

如:int a,b,c=5;
相当于:int a,b,c; /*指定a,b,c为整型变量*/ c=5; /*赋值语句,将5赋给c*/

§3.7 算术运算符和算术表达式
? ?

3.7.1 C运算符简介
3.7.2 算术运算符和算术表达式
1. 基本的算术运算符 2. 算术表达式和运算符的优先级与结合性 3. 强制类型转换运算符

4. 自增、自减运算符
5. 有关表达式使用中的问题说明

3.7.1 C运算符简介
?

C语言是表达式语言,除了控制语句和输入输出外几乎 都是表达式。如:赋值符“=”作为赋值运算符,而方 括号“[]”作为下标运算符等。
C的运算符有13类之多。

?

C的运算符
1. 算术运算符(+,-,*,/,%,即加,减,乘,除,求余)

2. 关系运算符( >,<,==,>=,<=,!=)
3. 逻辑运算符(!,&&,||) 4. 位运算符(<<,>>,~,|,^,&)

5. 赋值运算符(=及其扩展赋值运算符)
6. 条件运算符(?,:) 7. 逗号运算符(,) 8. 指针运算符(*和&) 9. 求字节数运算符(sizeof) 10.强制类型转换运算符((类型)) 11.分量运算符(. ->)

运算符详见本 书附录III

12.下标运算符([ ])
13.其他(如函数调用运算符())

基本的算术运算符
?

四则运算: +(加法运算符,或正值运算符。如3+5、+3) -(减法运算符,或负值运算符。如5-2、-2) *( 乘法运算符。如3*5) /(除法运算符。如5/3) %(模运算符,或求余运算符,%两则应均为整型数据)

说明:/运算如果除数或被除数中有一个为负数,则舍入的 方向是不固定的。如-5/3有的机器上结果为-1,有的 为-2。但多数机器采取“向零取整”的方法,即5/3=1,

-5/3=-1,取整后向零靠拢。

算术表达式和运算符的优先级与结合性
?

用算术运算符和括号将运算对象(操作数)连接起来, 符合C语法规则的式子,称C算术表达式。运算对象包括 常量、变量、函数。

? ?

合法的C算术表达式如:a*b/c-1.5+?a? 优先级:若运算对象两侧运算符的优先级不同,则先乘 除后加减。

?

结合性:若一个运算对象两侧的运算符的优先级相同, 则满足结合性规则,自左向右,左结合性(运算对象先 与左面的运算符结合)。

自增、自减运算符
?

有前置和后置两种形式:

前置形式: + +变量名 ,--变量名 后置形式: 变量名++ , 变量名--
? ?

功能:对变量的值进行自加1(自减1)的运算。 例:语句++a; 相当于执行a=a+1; 前置形式运算规则:先对表达式中含有前置自增(减)运

算符的变量进行自加(减)1,然后用这些变量的新值参与 表达式运算。
后置形式运算规则:先用变量原值参与表达式运算,然

后对含有后置自加(减)运算符的变量进行自加(减)1运算。

main() main() {int j,i=3; {int j,i=3; j=++i;(相当于i=i+1;j=i) j=i++;(相当于 j=i;i=i+1) printf(“%d,%d”,i,j);} printf(“%d,%d”,i,j);} 运行结果:4,4 运行结果:4,3 (1)自增运算符(++)和自减运算符(--),只 能用于变量,不能用于常量或表达式; (2)++和--的结合方向为“自右至左”。 考虑:若i的初值为3,那么print(“%d”,-i++)的 结果 应该为多少呢?

§3.8 赋值运算符和赋值表达式
?
?

1. 赋值运算符
2. 类型转换

?
?

3. 复合的赋值运算符
4. 赋值表达式

1. 赋值运算符
?

赋值符号“=”就是赋值运算符,作用是将一个数据 赋给一个变量。
如“a=3”的作用是执行一次赋值操作(或称赋值运 算),把常量3赋给变量a。 也可以将一个表达式的值赋给一个变量。如“a=3+58%5”,相当于把结果值5赋给变量a(“a=5”)。

?

?

2. 类型转换
?

如果赋值运算符两侧的类型不一致,但都是数值型或字 符型时,在赋值时要进行类型转换。

3. 复合的赋值运算符
?

在赋值符“=”之前加上其他运算符,可以构成复合的运 算符。如:a+=3等价于a=a+3,x%=3等价于x=x%3。

?
?

注意:赋值符“=”右边看作一项。
凡是二元运算符,都可以与赋值符一起组成复合赋值符。 C语言规定了10种复合赋值运算符:+=,-=,*=,/=,%=, <<=,>>=,&=,^=,|= 规则:(1)“=”后边先加括号; (2) “=”前边复制到“=”后边 ;

?

4. 赋值表达式
?

由赋值运算符将一个变量和一个表达式连接起来的式子 称为“赋值表达式”。 一般形式为:<变量> <赋值运算符> <表达式> 赋值表达式求解过程:将赋值运算符右侧“表达式”的 值赋给左侧的变量。表达式的值就是被赋值的变量的值。 上述一般形式中的“表达式”还可以是一个赋值表达式。

? ?

?

如:a=(b=5)。所以,C语言允许连续赋值。

?

int a,b,c; a=b=c=0; 连续使用等号时,从右向左顺序赋值: a=(b=(c=0)); 赋值表达式也可以包含复合的赋值运算符。如: a+=a-=a*a也是一个赋值表达式。 若a的初值为12,则:

?

先进行“a-=a*a”,相当于a= a- a*a,a的值为
12-144=-132; 再进行“a+=-132”的运算,相当于“a= a+(-132)”,a的 值为-132-132=-264。

§3.9 逗号运算符和逗号表达式
? ?

逗号运算符(又称顺序求值运算符):, 逗号表达式:用逗号运算符把两个表达式连接起来的表 达式。 一般形式为:表达式1,表达式2,…..,表达式n 逗号表达式的值:表达式n的值. 如:逗号表达式“3+5,6+8”的值为14。

? ? ?

?

如:“a=3*5,a*4”,由于赋值运算符的优先级高于逗号 运算符(逗号运算符在所有运算符中级别最低),因此 应先求解a=3*5,再求解a*4,得到逗号表达式的值60。

?

一个逗号表达式又可以与另一个表达式组成一个新的逗

号表达式,如:(a=3*5,a*4),a+5,先计算出a的值为15, 由于a*4的操作并没有改变a的值,所以a+5的值为20。 因此,逗号表达式最终的值为20。
?

在许多情况下,使用逗号表达式的目的只是想分别得到 各个表达式的值。
逗号表达式最常用于循环(for)语句。 注意:并不是任何地方出现的逗号都作为逗号运算符。 例如函数参数也是用逗号来间隔的,如: printf(“%d,%d,%d”,a,b,c);

? ?

课堂作业:
2.1 指出下面哪些是合法的变量名: ①123 ②abc ③a+b ④a_b ⑤pad ⑥?12 ⑦Li_Li ⑧*P
②④⑤⑦

2.2 ?a?在内存中占 个字节.

个字节,“a”在在内存中占
1 2

2.3 写出下面程序的运行结果: main() {char ch; ch=?B?; /*B的ascii码的值为66*/ printf(“%c,%d\n”,ch,ch)
B 66

2.4 写出下面程序的运行结果:

main() { int a=10, b , c , d ; int b,c; a+=6; b = (c=20, 6, a+2 ); printf("a=%d,b=%d,c=%d\n",a,b,c); }

运行结果:a=16,b=18,c=20

2.5写出下面程序的运行结果:
main() { int a=4; int b,c; c=a+(b=2); a+=a-=a*a; printf("%d,%d,%d\n",a,b,c); }

2.6 写出下面程序的运行结果: main() { int a,b,c=9; a=3,b=4; c%= a+b; printf(“%d\n”,c) }

运行结果:-24,2,6

运行结果:2

2.7 写出下面程序的运行结果:

main() { int i,j,m,n; i=8;j=10; m=++i; n=j++; printf("%d,%d,%d,%d\n",i,j,m,n); }
运行结果:9,11,9,10

2.8 写出下面程序的运行结果:

main() { float x=5.4; int i; i=(int)x; printf(”x=%f,i=%d\n",x,i); }
运行结果:x=5.400000,I=5

第四章 最简单的C程序设计 ————顺序程序设计

?
?

§4.1 C语句概述
§4.2 赋值语句

?
?

§4.3 数据输入输出的概念及实现
§4.4 字符数据输入输出函数

?
?

§4.5 格式输入与输出
§4.6 顺序结构程序设计举例

§4.1 C语句概述
?

与其他高级语言一样,C语言的语句用来向计算机系统发 出操作指令。
一个语句经编译后产生若干条机器指令。

?

?
?

一个实际的程序应当包含若干条语句。
C语句都是用来完成一定的操作任务的;声明部分的内容 不应称为语句。如:int a;不是一个C语句,它不产生机 器操作,而只是对变量的定义。

C程序结构
C程序
源程序文件1 源程序文件2 … 源程序文件n

预处理命令

全局变量声明

函数1

…..

函数n

函数首部

函数体

局部变量声明

执行语句

C语句分类
?

C语句可以分为以下5类:
1. 控制语句; 2. 函数调用语句; 3. 表达式语句; 4. 空语句;

5. 复合语句;

1. 控制语句
?

完成一定的控制功能。C只有9种控制语句: if()~else~ (条件语句) for()~ (循环语句) while()~ (循环语句) do~while() (循环语句) continue (结束本次循环语句) break (中止switch或循环语句) switch (多分支选择语句) goto (转向语句) return (从函数返回语句)

( )表示条件,~表示内嵌的语句。

2. 函数调用语句
? ?

由一次函数调用加一个分号构成一个语句。 如:printf(“This is a C statement.”);

一次函数调用

分号

3. 表达式语句
?

由一个表达式构成一个语句;最典型的是,由赋值表达式 构成一个赋值语句(表达式后面加分号即构成语句)。如: a=3是一个赋值表达式,而a=3;是一个赋值语句。 一个语句必须在最后出现分号。
任何表达式都可以加上分号而成为语句。如:x+y;是语句, 但没有意义(没有将相加之和赋给另一个变量)。 表达式能构成语句是C语言的一个重要特色。C中大多数 语句是表达式语句(包括函数调用语句),所以有人称C 语言为?表达式语言?。

?
?

?

4. 空语句
空语句:仅包含一个分号的语句,它什么都不做。 有时用来做被转向点,或是循环语句中的循环体

(循环体是空语句,表示循环体什么也不做。)
如:;

5. 复合语句
由大括号{ }括起来的语句序列,称为复合语句,或 是分程序。 如:{ z = x + y; t = z / 100; printf("%f",t); } 注意:复合语句中最后一个语句最后的分号不能忽略不 写。 C语言允许一行写几个语句,也可以一个语句拆开写在 几行上。

§4.2 赋值语句
?

C语言的赋值语句具有其他高级语言赋值语句的一切特点 和功能,但也有不同之处:
1、C语言中的赋值号?=?是一个运算符,而其它大多数 语言中赋值号?=?不是运算符。 2、关于赋值表达式和赋值语句的概念。其他大多数高级 语言中没有?赋值表达式?这一概念。作为赋值表达式可 以包括在其他表达式之中,如: if((a=b)>0) t=a;(先赋值,将b的值赋给a;再判断a是 否>0,若>0,则执行t=a; )

if((a=b;)>0) t=a;(不合法:if条件不能包含赋值语句)

§4.3 数据输入输出的概念及实现
?

所谓输入输出是以计算机主机为主体而言的。从计算机向 外部输出设备(显屏,打印机)输出数据称为?输出?; 从输入设备(键盘,磁盘)向计算机输入数据称为?输 入?。
C语言本身不提供输入输出语句,输入和输出操作是由函 数来实现的。

?

?

在C的标准函数库中提供了一些输入输出函数,例如, printf函数和scanf函数。在使用它们时,千万不要简单地 认为它们是C语言的?输入输出语句?。printf和scanf不是 C语言的关键字。完全可以不用printf和scanf这两个名字, 而另外编两个函数,另用其它函数名。

?

C提供的函数以库的形式存放在系统中,它们不是C语言 文本中的组成部分。因此各函数的功能和名,在各种不同 的计算机系统所不同。 有些通用的函数(如printf和scanf等),各种计算机系统 都提供,成为各种计算机系统的标准函数(标准输入输出 库的一部分)。在程序编译连接时,用户程序与标准文件 相连,所以在程序中可以直接使用printf和scanf函数。
注意:在源程序中有printf函数,在编译时并不把它翻译 成目标指令,而是在执行阶段中调用已被连接的函数库中 的printf函数。

?

?

?

C语言函数库中有一批?标准输入输出函数?,它是 以标准的输入输出设备(一般为终端设备)为输入输 出对象的。其中有: putchar(输出字符) getchar(输入字符) printf(格式输出) puts(输出字符串) scanf(格式输入) gets(输入字符串)

?

在使用标准I/O库函数时,要用预编译命令?#include”将 ?stdio.h”文件包括到用户源文件中。即 #include “stdio.h”(或#include <stdio.h>)。stdio.h是 standart input & output的缩写,它包括了标准I/O库有关 的变量定义和宏定义(有关预编译命令见第九章)。
在需要使用标准I/O库中的函数时,应在程序前使用上述预 编译命令,但在用printf和scanf函数时,则可以不要(只 有printf和scanf例外)。 预编译命令?#include”都是放在程序的开头,因此这类文 件被称为?头文件?。

?

?

§4.4 字符数据输入输出函数
? ?

4.4.1 putchar函数(字符输出函数) 4.4.2 getchar函数(字符输入函数)

4.4.1 putchar函数
?
?

putchar函数的作用是向终端输出一个字符。
例如:putchar(c) 输出字符串变量C的值。C可以是字符 型变量或整型变量。 例4.1:#include "stdio.h" main() {char a,b,c; a="B"; b="O"; c="Y"; putchar(a); putchar(b); putchar(c); } 运行结果:BOY

?

?

也可以输出控制字符,如putchar(?\n?)输出一个换行符。 如果将例4.1程序最后一行改为: putchar(a);putchar('\n');putchar(b);putchar('\n'); putchar(c);putchar('\n'); 则输出结果为: B O Y

?

也可以输出其它转义字符,如: putchar(?\101?) (输出字符‘A?) putchar(?\??) (输出单引号字符’) putchar(?015?) (输出回车,不换行,使输出的
位置移到本行开头)

4.4.2 getchar函数
?

此函数的作用是从终端(或系统隐含指定的输入设备)输 入一个字符。getchar函数没有参数,其一般形式为: getchar() 函数的值就是从输入设备得到的字符。
例4.2:#include "stdio.h" main() 在运行时,如果从键盘输入字‘a? { char c; a<enter> (输入a后,按“回车” c=getchar(); 键,字符才送到内存) putchar(c); a (输出变量c的值'a') }

? ?

?

请注意,getchar()只能接收一个字符。getchar函数得到 的字符可以赋给一个字符变量或整型变量,也可以不赋 给任何变量,作为表达式的一部分。 例如,例4.2第4、5行可以用下面一行代替: putchar(getchar());
也可以用printf函数:printf("%c",getchar()); 在函数中要用getchar函数,应该在函数的前面(或本文 件开头)用#include "stdio.h”。因为在使用标准I/O库中 的函数时需要用到?stdio.h”文件中包含的一些信息。

?

? ?

§4.5 格式输入与输出
? ?

4.5.1 printf函数(格式输出函数) 4.5.2 scanf函数(格式输入函数)

4.5.1 printf函数
? ?

1. printf函数的一般格式 2. 格式字符

printf函数的一般格式
?

printf函数的作用是:向终端(或系统隐含指定的输 出设备)输出若干个任意类型的数据。 注意:putchar只能输出字符,而且只能是一个字符; 而printf可以输出多个数据,且为任意类型。

?

?
?

一般格式:printf(格式控制,输出列表) 如:printf(“%d , %c \n” , i,c) 普通字符: 即需要原样 输出的字符 (逗号,空 格和换行符) 输出列表:需 要输出的数据, 可以是表达式。

格式说明: 将数据转换 为指定格式输出。

?

例:printf(“a=%d_b=%d”,a,b);
双引号中的字符除了“%d”和“%d”以外,还有非格式 说明的普通字符“a=”、“b=”及空格“_”,它们按原样输 出。若a=3,b=4,则输出为:a=3_b=4

格式字符
? ?

对不同类型的数据用不同的格式字符。
常用的有以下几种格式字符: (1) d格式符 (2) o格式符 (3) x格式符 (6) s格式符 (7) f格式符 (8) e格式符

(4) u格式符
(5) c格式符

(9) g格式符

d格式符:输出十进制整数
?
?

%d:

按整型数据的实际长度 输出;

%md: 输出m位(指定的输出字段宽度); (数据位数 小于m位时左端补空格,大于m位时按实际长度输出); %ld,%mld:l表示输出?长整型?数据,也可以指定输出 字段宽度; 一个int型数据可以用%d或%ld格式输出; 注:%后面的m(位数控制) 对于其它格式符也适用。

?

? ?

例、(□表示空格) int i = 123; long j = 123456; printf("%d,%5d,%ld, %8ld ",i ,i , j, j);

输出: 123, □□123,

123456,

□□ 123456

c格式符:输出一个字符
?

一个整数,只要它的值在0~255之间,也可以用字符形 式输出。在输出前,系统会将该整数作为ASCII码转换成 相应的字符;反之,字符数据也可以用整数形式输出。 例:4.4 main() { char c='a'; 输出: a,97 int i=97; a,97 printf("%c,%d\n",c,c); printf("%c,%d\n",i,i); } 可以指定输出字段宽度:printf(“%3c”,c);则输出:__a

s格式符:输出一个字符串
(1)%s:原样输出字符串;
如:printf(“%s”,“CHINA”)输出:CHINA (2)%ms:输出字符串占m列;>m全输出<m左补空格; (3)%-ms:输出字符串占m列;<m字符串左靠右补空格; (4)%m.ns:输出字符串占m列,但只取串左端n个字符。这 n个字符输出在m列的右侧,左补空格。 (5)%-m.ns:输出字符串占m列,但只取串左端n个字符。这 n个字符输出在m列的左侧,右补空格。若n>m,则m自 动取n值,即保证n个字符正常输出。

例 4.5 m自动取n值,即 main() 等价于:%4.4s { printf("%3s,%7.2s,%.4s,%-5.3s\n", "CHINA","CHINA","CHINA","CHINA"); } 输出: CHINA, □□ □□ □CH,CHIN,CHI □□

f格式符:以小数形式输出实数(单/双精度)
(1)%f:由系统自动指定字段宽度,使整数部分全部输出, 并输出6位小数。 (2)%m.nf:指定输出的数据共占m列,其中由n位小数。若 数值长度<m,则左端补空格。 (3)%-m.nf:同%m.nf,只是输出的数值向左端靠,右端补

空格。
注意:并非全部数字都是有效数字。 单精度实数的有效位数一般为7位,而双精度实数的有效

位数一般为16位(小数6位)。

?

例4.6

main() {float x,y; x=111111.111;y=222222.222; printf(“%f”,x+y);

}
运行结果为:333333.328125 显然,只有前7位数字是有效数字。

?

例4.7

main() {double x,y; x=1111111111111.111111111; y=2222222222222.222222222;

printf(“%f”,x+y);
} 运行结果为:3333333333333.333010

可以看到,最后3位小数(超过16位)是无意义的。

例: 4.8 main() {float f=123.456; printf("%f □□%10f □□ %10.2f □□ %.2f □□ %-10.2f\n",f,f,f,f,f); } 输出: 123.455994 □□ 123.455994 □□ □□ □□123.46 □□123.46 □□ 123.46 □□ □□ 按原样输出的字符 由于格式定义而输出的字符

4.5.2 scanf函数
?

getchar函数只能用来输入一个字符,用scanf函数 可以用来输入任何类型的多个数据。 在前面已初步接触到了scanf函数,在本节中再作详 细介绍。

?

1. 一般形式

2. 格式说明
3. 使用scanf函数时应注意的问题

一般形式
? ?

scanf(格式控制,地址表列) ?格式控制?含义同printf函数。?地址表列?是由

若干个地址组成的表列,可能是变量的地址,或字 符串的首地址。

例4.9:用scanf函数输入数据
?

main() {int a,b,c; scanf("%d%d%d",&a,&b,&c); printf("%d,%d,%d\n",a,b,c); }

?

运行时按以下方式输入a,b,c的值: 3 4 5<enter> (输入a,b,c的值) 3,4,5 (输出a,b,c的值) &a,&b,&c中的?&”是?地址运算符?,&a指a在内存中 的地址。上面scanf函数的作用是:按照a,b,c在内存的地 址将a,b,c的值存进去。

?

?

见下图,a,b,c的地址是在定义a,b,c之后就确定的(在编
译阶段分配的)。 a c b 3 5

4

?

"%d%d%d"表示按十进制整数形式输入数据。输入数 据时,在两个数据之间以一个或多个空格间隔,也可 以用回车键、跳格键tab。 下面输入各法:① 3 4 5<enter> ② 3<enter> 4 5<enter> ③ 3(按tab键)4<enter> 5<enter>
用?%d%d%d”格式输入时,不能用逗号作为两个 数据间的分隔符,如下面输入不合法:3,4,5<enter>

?

?

格式说明
?

和printf函数中的格式说明相似,以%开始,以一个字符结束, 中间可以插入附加的字符。
格式字符 说明

d,i u o x,X c
s f e,E,g,G

用来输入有符号的十进制整数。
用来输入无符号的十进制整数。 用来输入无符号的八进制整数。 用来输入无符号的十六进制整数(大小写作用相同)。 用来输入单个字符。 输入字符串,将字符串送到一个字符数组中,输入以非空白 符开始,以第一个空白符结束,以'\0'作为其最后一个字符。 用来输入实数,可以用小数形式或指数形式输入。 与f作用相同,e与f,g可以互相替换(大小写作用相同)。

?

scanf的附加格式说明字符
字符 l h 域宽 * 说明 用于输入长整型数据(可用%ld, % lo,%lx,%lu), 以及double型数据(用%lf或%le)。 用于输入短整型数据(可用%hd,%ho,%hx)。 指定输入数据所占宽度(列数),域宽应为正整数 表示本输入顶在读入后不赋给相应的变量。

§4.6 顺序结构程序设计举例
?

[例4.10] 输入三角形的三边长,计算其面积。

算法:问题求解的方法与步骤. 算法的表示: 1) 自然语言:

开始 输入a、b、c 计算s

Step1:输入a,b,c Step2:计算s=(a+b+c)/2 Step3:计算面积area Step4:输出面积area
2) 传统流程图

计算面积area
输出面积area

结束

3) 结构化流程图(N-S图) 4)伪代码 (1) (用英语描述) begin(算法开始) input a,b,c s?(a+b+c)/2 area ??s(s-a)(s-b)(s-c) output area end 5)计算机语言

输入a、b、c 计算s 计算面积area 输出面积area

1.设计算法、 设三边长a、b、c, 面积area的算法是:

开始 输入a、b、c 计算s

2.画出流程图。 求平方根函数sqrt() 在math.h中定义。

计算面积area
输出面积area

结束

#include "math.h" main() { float a,b,c,s,area; scanf("%f,%f,%f ",&a,&b,&c);
s = 1.0/2*(a+b+c); area = sqrt(s*(s-a)*(s-b)*(s-c)); printf("a=%7.2f, b=%7.2f, c=%7.2f\n",a,b,c); printf("area = %7.2f\n",area); } 运行情况如下: 3,4,6↙ a=□□□3.00, b=□□□4.00, c=□□□6.00 area =□□□5.33

例4.11输入一个大写字母,改为小写字母输出。
#include<stdio.h> main() {char c1,c2; c1=getchar(); printf(“%c,%d\n”,c1,c1); c2=c1+32; printf(“%c,%d\n”,c2,c2); }运行情况如下:A<enter>
A,65

a,97

第5章 选择结构程序设计

? ?

C语言中选择结构是用if语句实现的。 if语句最常用的形式是:

if (关系表达式) 语句1 else 语句2
例如:if (x>0) y=1;else y=-1; 其中,x>0是一个关系表达式,?>”是一个关系运 算符。

?

§5.1 关系运算符和关系表达式

?
? ? ?

§5.2 逻辑运算
§5.3 if语句 §5.4 switch语句 §5.5 程序举例

§5.1 关系运算符和关系表达式
?
?

关系运算是逻辑运算的一种。
所谓?关系运算?实际上是?比较运算?。将两个值进 行比较,判断比较的结果是否符合给定的条件。 例如,a>3是关系表达式,大于号?>”是一个关系运算 符,如果a的值为5,则满足给定的的?a>3”条件,因 此关系表达式a>3的值为?真?(即?条件满足?); 如果a的值为2,不满足?a>3”条件,则称关系表达式 的值为?假?。

?

? ?

5.1.1 关系运算符及其优先次序

5.1.2 关系表达式

5.1.1 关系运算符及其优先次序
?

C语言有六种关系运算符:
优先级相同(高)
算术运算符 关系运算符

(1)< 小于 (2)<= 小于或等于 (3)> 大于 (4)>= 大于或等于 (5)==(等于) (6)!= 不等于

优先级相同(低) 赋值运算符

5.1.2 关系表达式
?

用关系运算符将两个表达式(算术表达式或关系表达式、 逻辑表达式、赋值表达式、字符表达式)连接起来的式 子,称为关系表达式。

? ?

如:a>b,a+b>b+c,(a=3)>(b=5),?a?<?b?等都是关系表达式。

关系表达式的值是一个逻辑值,即?真?或?假?。C 语言中用1代表?真?,用0代表?假?。
如:a=3,b=2,c=3,则关系表达式?a>b”的值为?真?,

?

表达式的值为1;?b+c<a”的值为?假?,表达式的值 为0。

例、a=3,b=2,c=1;
1). c>a+b 2). a>b==c 3). a!=b<c 等效于c>(a+b) 等效于(a>b)==c 等效于a!=(b<c) 表达式的值为0 表达式的值为1 表达式的值为1

4). a=b>c 等效于a=(b>c)(赋值表达式)表达式的 值为1 例:a=3,b=2,c=1; d=a<b f=a>b>c d的值为0(赋值表达式) f的值为0 (赋值表达式)

§5.2 逻辑运算
? ?

5.2.1 逻辑运算符及其优先次序 5.2.2 逻辑表达式

5.2.1 逻辑运算符及其优先次序
? ?

C语言提供三种逻辑运算符: && || ! ?逻辑与? ?逻辑或? ?逻辑非? 双目(元)运算符(相当于AND) 双目(元)运算符(相当于OR) 一目(元)运算符(相当于NOT)

? ?

如:(a>b)&&(x>y);(a>b)||(x>y);!(a>b);

逻辑运算举例如下:
a&&b 若a,b为真,则a&&b为真。 a||b 若a,b之一为真,则a||b为真。

!a 若a为真,则!a为假。

?

在一个逻辑表达式中如果包含多个逻辑运算符,如 !a&&b||x>y&&c,按以下的优先次序:

(1)!(非)→&&(与)→||(或),即?!?为三者中最高的; (2)逻辑运算符中的?&&”和?||”低于关系运算符, !(逻辑非) ?!?高于算术运算符。如: 算术运算符

(a>b)&&(x>y) 可写成:a>b&&x>y 关系运算符 (a==b)||(x==y) 可写成:a==b||x==y &&和|| (!a)||(a>b) 可写成:!a||a>b 赋值运算符

5.2.2 逻辑表达式
?

用逻辑运算符将关系表达式或逻辑量连接起来的式子就 是逻辑表达式。 逻辑表达式的值是一个逻辑量?真?或?假?。C语言 编译系统在给出逻辑运算结果时,以1代表?真?,以0 代表?假?。但在判断一个量是否为?真?时,以0代 表?假?,以非0代表?真?,即将一个非零的数值认 作为?真?。 ①若a=4,!a的值为0。②若a=4,b=5,a&&b的值为1。 ③a,b值同前,a||b的值为1。 ④a,b值同前,!a||b的值为1。⑤4&&0||2的值为1。

?

?

如果在一个表达式中不同位置上出现数值,应区分哪些 是作为数值运算或关系运算的对象,哪些作为逻辑运算 的对象。如:5>3&&8<4-!0 (结果为0) 逻辑运算符两侧的运算对象不但可以是0和1,或者是0 和非0的整数,也可以是任何类型的数据,可以是字符 型、实型或指针型等。系统最终以0和非0来判断它们 属于?真?或?假?。例如:‘c?&&?d?的值为1 ,因 为‘c?和‘d?的ASCII值都不为0,按?真?处理 。

?

?

在逻辑表达式的求解中,并不是所有的逻辑运算符都被执 行,只是在必须执行下一个逻辑运算符才能求出表达式的 解时,才执行该运算符。 如:(1)a&&b&&c (2)a||b||c 例:(m=a>b)&&(n=c>d),当a=1,b=2,c=3,d=4,m和n的

? ?

原值为1时,由于?a>b”的值为0,m=0,而?n=c>d” 不被执行,因此n的值不是0而仍保持原值1。

用逻辑表达式来表示复杂的条件
?

例如,判别某一年year是否闰年。闰年的条件是符合下 面二者之一:①能被4整除,但不能被100整除。②能 被400整除。逻辑表达式表示为: (year%4==0&&year%100!=0)||year%400==0

上述表达式值为真(1),则year为闰年;否则为非闰年。

还可以加一个?!?来判别非闰年:
!((year%4==0&&year%100!=0)||year%400==0) 若表达式值为真(1),year为非闰年。

§5.3 if语句
? ? ?

5.3.1 if语句的三种形式

5.3.2 if语句的嵌套
5.3.3 条件运算符

5.3.1 if语句的三种形式
?

if语句:判别条件是否满足,来决定程序的流程(执行两路操 作之一)。

?

(1) if(表达式) 语句 例如:if (x>y) printf("%d",x);
表达式 假(0)

真(非0) 语句

(2) if(表达式)语句1 else 语句2 例如:if (x>y) printf("%d",x); else printf("%d",y);
真 表达式 假

语句1

语句2

(3) if (表达式1) 语句1 else if(表达式2)语句2 else if(表达式3)语句3 ….


表达式1

else if(表达式m)语句m else 语句n 例如: if (num>500) cost=0.15; else if (num>300) cost=0.10; else if (num>100) cost=0.075; else if (num>50) cost=0.05; 语句1 else cost=0;



表达式2



表达式4



表达式3





真 语句2 语句3 语句4 语句5

对if语句的三点说明
(1)if后面的?表达式?,一般为逻辑表达式或关系表达

式。
例如:if(a==b&&x==y) printf(“a=b,x=y”); 系统对表达式的值进行判断,若为0,按?假?处理,若 为非0,按?真? 处理,执行指定的语句。
?

表达式可以是任意的数值类型(包括整型、实型、字符型、 指针型数据)。 例如:if(3) printf(“O.K.”);执行结果: O.K. if(?a?) printf(“%d”,?a?);执行结果:97

?

(2)第二、第三种形式的if语句中,在每个else前面有 一分号,整个语句结束处有一分号。 例如:if (x>0) printf(“%f”,x); else printf("%f",-x); 这个分号是if语句中的内嵌语句所要求的。 如果无此分号,则出现语法错误。

(3)在if和else后面可以只含一个内嵌的操作语句,也可以有

多个操作语句。若有多个操作语句,则用花括号?{ }”将 几个语句括起来成为一个复合语句。
?

例如:if(a+b>c&&b+c>a&&c+a>b)

{ s=0.5*(a+b+c); area=sqrt(s*(s-a)*(s-b)*(s-c)); printf("area=%6.2f",area;} else printf("it is not a trilateral");
?

注意:在{ }外面不需要再加分号。

例5.1:输入两个实数,按代数值由小到大 输出这两个数。
main() { float a,b,t; scanf("%f,%f",&a,&b); if (a>b) { t = a; a = b; b = t; } printf("%5.2f,%5.2f",a,b); } 运行示例: 3.6 ,-3.2↙ -3.20, 3.60



a > b?
真 交换a、b的位置

例5.2:输入三个数a,b,c,按由小到大输出。
main() { float a,b,c,t; scanf("%f,%f,%f",&a,&b,&c); if (a>b) {t = a; a = b; b = t;} if (a>c) {t = a; a = c; c = t;} if (b>c) {t = b; b = c; c = t;} printf("%5.2f,%5.2f,%5.2f",a,b,c); } 运行示例: 3,7,1 ↙ 1.00,3.00,7.00

3
7 1

3

1

7
1

7
3 1 3

7

5.3.2 if语句的嵌套
一般形式:if ( ) if ( ) 语句1 内嵌if else 语句2 else if ( ) 语句3 内嵌if else 语句4 *注意:使用嵌套if语句时,必须特别注意if与else配对: (1)从最内层开始,else总是与它上面最接近的(未曾配对 的)if配对。 (2)避免if与else配对错位的最佳办法是加大括号,同时,为 了便于阅读,使用适当的缩进。(只有大括号能保证if 和else不错位配对,缩进只是为了便于阅读)
?

5.3.3 条件运算符
?

若if语句中,在表达式为?真?和?假?时,且都只执行

一个赋值语句给同一个变量赋值时,可以用简单的条件运 算符来处理。
?

例如: if(a>b) max=a;

else max=b;
可以用下面的条件运算符来处理:max=(a>b)?a:b;其中 ?(a>b)?a:b”是一个?条件表达式?。它是这样执行的: 如果(a>b)条件为真,则条件表达式取值a,否则取值b。

?

条件运算符要求有三个操作对象,称三目(元)运算符。

它是C语言中唯一的三目运算符。条件表达式的一般形 式为:表达式1?表达式2:表达式3

真(非0) 表达式1 条件表达式 取表达式2的值

假(0)

条件表达式 取表达式3的值

§5.4 switch语句
?

switch语句是多分支选择语句。if语句只有两个分支可供 选择,而实际问题中常常需要用多分支的选择。

?

一般形式:switch(表达式) { case 常量表达式1:语句1 case 常量表达式2:语句2 ┋ case 常量表达式n:语句n default :语句n+1 }

例:按照考试成绩的等级打印出百分之分 数段。
grade

输出 “85~100”

输出 “70~84”

输出 “60~69”

输出 “<60”

输出 “error”

用switch语句实现
?

switch(grade) { case 'A':printf("85~100\n"); case 'B':printf("70~84\n"); case 'C':printf("60~69\n");

case 'D':printf("<60\n"); default :printf("error\n");
}
? ?

Default的出现次序 会不会影响结果?和 书中意见不同。

问题1:各个case和default的出现次序影响执行结果吗?
问题2:若grade=?B?,以上程序的输出结果是什么?

?

应该在执行一个case分支后,使流程跳出switch结构, 即终止switch语句的执行。可以用一个break语句来达到 此目的。

?

switch(grade) {case 'A':printf("85~100\n");break; case 'B':printf("70~84\n");break; case 'C':printf("60~69\n");break; case 'D':printf("<60\n");break; default :printf("error\n"); }

?

在case后面,若包含一个以上的执行语句,可以不必用 { }括起来,系统会自动的顺序执行该case后面所有的执 行语句。 多个case可以共用一组执行语句,如: ┋ case 'A': case 'B': case 'C': printf(">60"); break; ┋

?

§5.5 程序举例
习题5-6:判别学生成绩的等级: 小于60分,E级; 小于70分,D级; 小于80分,C级; A 小于90分,B级; B 小于100分,A级; C (1)算法: D 分数/10: E <6 ,E级 <7 ,D级 60 70 <8 ,C级 6 7 <9 ,B级 <10 ,A级

80 8

90 9

100 10

2. 框图:

假 <60



<70 真


假 <80 真 <90 B C 假

<100
B

E

D

#include "stdio.h" main() {int score,s; char grade; printf("请输入学生的成绩:"); scanf("%d\n",&score); s=score/10; switch(s) { case 10: case 9 : grade='A'; break; case 8 : grade='B'; break; case 7 : grade='C'; break; case 6 : grade='D'; break;

case case case case case case

}

5 4 3 2 1 0

: : : : : :grade='E'; break;

printf(“成绩是%d,相应的等级是%c\n",score,grade);

}

? [例5.6]

求方程的解:

1.算法:有以下几种可能性: ? ① a = 0,不是二次方程。 ? ② b2-4ac=0,有两个相等实根。 ? ③ b2-4ac > 0,有两个不等实根。 ? ④ b2-4ac < 0, 有两个共轭复根。 2. N-S流程图: disc= b2-4ac

思考题
1. 写出下面程序在以下情况的输出结果: ①a=10,b=5; ②a=-5,b=-10; ③a=0,b=-3; ④a=6,b=7。 main( ) { int a,b; scanf("%d,%d",&a,&b); if (a>b)(与这个if配对的else是?) if (a>0) printf("A"); else if (b>-5) printf("B"); else printf("C"); printf("\n"); } 1.A 2.C 3.B 4.

2. 本程序的作用是判断year是否闰年,如是闰年则输出

?leap year”字样,闰年的条件是符合下面二者之一:① 能被4整除,但不能被100整除;②能被4整除,又能被 400整除。请对程序填空(填入一个运算符)。 main( ) { int year; scanf("%d",&year); if((year%4==0___year%100=0)___year%400==0) printf("leap year"); }

第5章小结
一、运算符
关系运算符:>、>=、<、<=、== 逻辑运算符: && 逻辑“与”

|| !

逻辑“或” 逻辑“非”

条件运算符:表达式1?表达式2:表达式3 例: max = (a>b) ? a : b; c>(a+b) (a>b)&&(a>c) (a>b) ||(a>b)

二、语句
1. if语句
1) if (表达式) 语句 2) if (表达式) 语句1 else 语句2 3) if (表达式1) 语句1 else if(表达式2)语句2 else if(表达式3)语句3

else if(表达式m)语句m else 语句n if语句的嵌套: if ( ) if ( ) 语句1 else 语句2 else if ( ) 语句3 else 语句4



2

switch语句

switch(表达式) { case 常量表达式1:语句1 case 常量表达式2:语句2 ┆ case 常量表达式n:语句n default:语句n+1 }

第六章 循环控制

§6.1 ? §6.2 ? §6.3 ? §6.4 ? §6.5 ? §6.6 ? §6.7 ? §6.8
?

概述 goto语句以及用goto语句构成循环 while语句 do-while语句 for语句 循环的嵌套 break语句和continue语句 程序举例

§6.1 概述
循环:反复执行称为?循环体?的程序段。 循环控制常用于数学迭代、对象遍历等问题的求解, 几乎所有实用程序都包含循环。
?

C语言中用如下语句实现循环:

1、用goto语句和if语句构成循环。

2、用while语句。
3、用do-while语句。 4、用for语句。

§6.2 goto语句以及用goto语句构成循环
? ? ?

一般形式: goto 语句标号; 作 用: 无条件转向?语句标号?处执行。 ?语句标号?是一个标识符(字母、数字和下划线组成, 第一个字符必须为字母和下划线),它表示程序指令的 地址。不能用整数作为标号。

? ?

结构化程序设计方法主张限制使用goto语句。
goto语句两种用途:(1)与if语句一起构成循环结构; (2)从循环体中跳转到循环体外。

例6.1:用if语句和goto语句构成循环,求? i
i ?1

100

main() {

int i,sum=0; i = 1; loop: if (i <= 100) { sum = sum + i; i++; goto loop; } printf("%d",sum);

i=1,sum=0

i<=100 真 sum=sum+i i=i+1



}

§6.3 while语句
? ?

一般形式:while (表达式) 语句。 作用:实现?当型?循环结构。当表达式为非0值时, 执行while语句中的内嵌语句。?语句?是被循环执行 的程序,称为?循环体?。 特点:
表达式 非0 语句 0

?

(1)先判?表达式?,后执行语句。 (2)循环体如果包含一个以上的语句, 应该以复合语句(加{ })形式出现。

(3)在循环体中应有使循环趋向于结束的语句。

例:求
main() { int i,sum=0; i = 1; while (i <= 100) { sum = sum + i; i++; /* 使循环趋于结束*/

?
i ?1

100

i

i=1,sum=0
i<=100




}

} printf("%d",sum);

sum=sum+i i=i+1

§6.4 do-while语句
? ?

一般形式为:do 语句 while(表达式); 作用:用来实现?直到型(until)?循环结构 。

?

特点:先执行语句,后判断表达式。先执行一次指定的 内嵌语句,然后判别表达式;当表达式的值非零(“真?) 时,返回重新执行语句,如此反复,直到表达式的值等 于0为止,此时循环结束。

例6.3 用do-while语句求
?

?
i ?1

100

i

main() { int i,sum=0; i = 1; do { sum = sum + i; i++; } while (i<=100); printf("%d",sum); }

i=1,sum=0 sum=sum+i i=i+1
直到i<=100

?

对同一个问题,可以用while语句处理,也可以用dowhile语句处理。do-while结构是由一个语句加一个while 结构构成的。
语句
0(假)

语句 非0 条件P 0

表达式

非0(真)
语句

一般情况,while和do-while语句处理同一问题时,若二 者的循环体部分一样,它们的结果也一样。但如果while 后面的表达式一开始就为?假?,两循环的结果是不同 的。 ? main() main() {int sum=0,i; {int sum=0,i; scanf(“%d”,&i); sum=sum+i ; i++; {sum=sum+i; scanf(“%d”,&i); while(i<=10) do {sum=sum+i; {sum=sum+i; i++;} i++;}while(i<=10)
?

§6.5 for语句
? ?

for语句常用于循环次数已知的循环控制; 也可以用于循环次数不确定而只给出循环结束条件的情

况,它完全可以代替while语句。
?

一般形式:for(表达式1;表达式2;表达式3) 语句

循环初始条件 判断循环条件
?

修改循环条件

执行过程

执行过程
求解表达式1 表达式2 语句 求解表达式3

for语句的 下一语句

?

for语句最简单的应用形式也就是最易理解的形式如下: for(循环变量赋值初值;循环条件;循环变量增值) 语句 如:for (i=1;i<=100;i++) sum=sum+i; for语句的一般形式可以改写如下: 表达式1; i=1;

? ?

while(表达式2)
{语句 表达式3;}

while(i<=100)
{ sum=sum+i; i++;}

§6.6 循环的嵌套
一个循环体内包含另一个完整的循环结构,称为循环的 嵌套。while循环、do-while循环和for循环可以互相嵌 套。 while() do do for(;;) while() {┋ for(;;) {┋ { {┋ {┋ {┋ do ┋ do while() for(;;) while() {… } for(;;) {… } {} {… } {┋ } while(); {} while(); ┋ } } } ┋ } } } while(); while();
?

§6.7 break语句和continue语句

? ? ?

6.7.1 break语句

6.7.2 continue语句
6.7.3 break语句与continue语句的区别

6.7.1 break语句
一般形式:break; ? 作用:跳出所在的多分支switch语句,跳出所在 的while, do-while,for循环语句(提前结束循 环)。 ? 如:for(r=1;r<=10;r++) { area=pi*r*r; if(area>100) break; printf("%f",area); } ? break语句不能用于循环语句和switch语句之外 的任何其它语句中。
?

6.7.2 continue语句
? ?

一般形式为: continue; 作用:结束本次循环。即跳过循环体中下面尚未执行的 语句,接着进行下一次是否执行循环的判定。 例5.5:把100~200之间不能被3整除的数输出。 main () { int n; n%3 == 0时,执行 for (n=100; n<=200; n++) continue语句,跳过 { if (n%3 == 0) printf(“%d”,n)语句, continue; 重新判别循环条件 printf("%d",n); } }

?

6.7.3 break语句和continue语句的区别
假 真 假

表达式1

表达式1



表达式2

真 break

表达式2

真 continue





while循环的 下一语句

while循环的 下一语句

§6.8 程序举例
?

例6.6 用 ?
4

? 1?

1 3

?

1 5

?

1 7

? ...

公式求计算л的值,直

到最后一项的绝对值小于1e-6(即约等于0)为止。 算法分析: 1、每项的分母,等于前一项分母加2,用n=n+2实现, n 的初值为1。 2、每项的符号交替变化,用s=-s实现,s的初值为1, (第一项为正)。 3、根据1和2,每一项的值 t = s/n,第一项的值为1。

#include "math.h" main() { int s; t=1,pi=0,n=1,s=1 float n,t,pi; 当|t|>=10-6 t = 1; pi = 0; n = 1.0; s = 1; pi=pi+t while(fabs(t) >= 1e-6) { pi = pi + t; n=n+2 n = n + 2; s=-s s = -s; t=s/n t = s/n; } pi = pi * 4; pi=pi*4 printf("pi=%10.6f\n",pi); 输出pi } 运行结果:pi= 3.141594

例5.7: 求Fibonacci数列前40个数。
Fibonacci数列1,1,2,3,5,8,....的前40个数,即: F1 = 1 (n = 1) F2 = 1 (n = 2) Fn = Fn-1 + Fn-2 (n≥3) 1. 算法:把40个数分为每2个一组,每组中的两个数的计 算方法为: f1 f2

f1 = f2 + f1 f2 = f1 + f2

1 2

1 3

f1=1 f2=1 f1=1+1=2 f2=2+1=3

5

8

f1=2+3=5

f2=5+3=8

2. N-S流程图: 3.程序: main () { long int f1,f2; /* 长整型数 */ int i; f1 = 1; f2 = 1; /* 已知数列的前两个初值 */ for (i=1; i<=20; i++) { printf("%12ld %12ld ",f1,f2); /* 输出长整型数 */ if (i%2 == 0) printf("\n"); /* 控制输出格式 */ f1 = f2 + f1; f2 = f1 + f2; } } 每次循环输出两个数,
每两次循环输出一个换行, 故输出格式为每行4个数。

goto语句 while语句 do-while语句 for语句 break语句 continue语句
1、算法分析是程序设计中的第一个步骤, 也是最重要的步骤。 2、框图:根据算法的要求,列出程序实现 的步骤。 复杂的算法必须画出框图。 3、程序设计的方法(结构化)和风格。





课堂练习
1、输入两个正整数m和n,求其最大公约数和最小公倍数。
2、一球从100m高度自由落下,每次落地后反弹回原来高度 的一半,再落下。求它在第10次落地时,共经过多少m ? 第10次反弹多高? 3、打印出所有的“水仙花数”。所谓“水仙花数”是指一 个三位数,其各位数字的立方和等于该数本身。

例如:153=13+53+33 。

main() {int p,r,n,m,temp; printf(“请输入两个正整数n,m:”); scanf(“%d,%d”,&n,&m); if(n<m) {temp=n;n=m;m=temp; } /把大数放在n中,小数放在m中/ p=n*m; /先将n和m的乘积保存在p中,以便求最小公倍数时用/ while(m!=0) /求n和m的最大公约数/ {r=n%m;n=m;m=r;} printf(“它们的最大公约数为:%d\n”,n); printf(“它们的最小公倍数为:%d\n”,p/n); } /*p是原来两个整数的乘积*/

main() {float sn=100,hn=sn/2; int n; for(n=2;n<=10;n++) {sn=sn+2*hn; /*第n次落地时共经过的米数*/ hn=hn/2; /*第n次反弹的高度*/ } printf(“第10次落地时共经过%f m.\n”,sn); printf(“第10次反弹%f m.\n”,hn); }

main() {int i,j,k,n; printf(“”水仙花”数是:”); for(n=100;n<1000;n++) {i=n/100;j=n/10-i*10;k=n%10; if(n==i*i*i+j*j*j+k*k*k) printf(%4d,n); } printf(“\n”); }

? §7.1 ? §7.2 ? §7.3

一维数组的定义和引用 二维数组的定义和引用 字符数组

§7.1 一维数组的定义和引用
? ?

7.1.1 一维数组的定义 7.1.2 一维数组元素的引用

?
?

7.1.3 一维数组的初始化
7.1.4 一维数组程序举例

7.1.1 一维数组的定义
?
? ? ?

数组:数组是一组类型相同有序数据的集合。
数组中的每一个元素都属于同一个数据类型。 用数组名和下标来唯一确定数组中的元素。 一维数组的定义:类型说明符 数组名[常量表达式]; 例、 int a[10] 10个元素分别用: a[0]、a[1]、a[2]、a[3]、a[4]、....、a[8]、a[9]。 数组名命名规则和变量名相同,遵循标识符命名规则。

说明
1)常量表达式必须用方括弧括起来;int a(10)错;
2)int a[10]表示a数组有10个元素,下标从0开始;不 能使用数组元素a[10];

3)常量表达式中可以包括常量和符号常量,但不能包含 变量;即C不允许对数组的大小作动态定义,即数组的 大小不依赖于程序运行过程中变量的值。 int n; scanf("%d",&n); int a[n]; ┇

7.1.2 一维数组元素的引用
数组元素的表示形式:数组名 [下标] 例: a[0] = a[5] + a[7] - a[2*3] 例7.1:使数组元素a[0]~a[9]的值为0~9,然后逆序输出。 main () { int i,a[10]; for (i=0;i<=9;i++) a[i] = i; for(i=9;i>=0; i--) printf("%d ",a[i]); } 运行输出: 9 8 7 6 5 4 3 2 1 0

7.1.3 一维数组的初始化
?

可以用赋值语句或输入语句使数组中的元素得到值, 但占运行时间。可以使数组在程序运行之前初始化, 即在编译阶段使之得到初值。 对数组元素的初始化可以用以下方法实现:
int a[10] = { 0,1,2,3,4,5,6,7,8,9}; 花括号,后有分号

?

1、一般初始化:

或int array[10] = {1,2,3,4,5,6,7,8,9,10};
2、部分元素初始化, int a[10] = {0,1,2,3,4}; 仅前5个元素赋初值,后5个元素未指定初值。

3、全部元素均初始化为0,
int a[10]={0,0,0,0,0,0,0,0,0,0}; 错误用法:int a[10]={0*10};

4、在对全部数组元素赋初值时,可以不指定数组长度。
int a[5]={1,2,3,4,5};可以写成:int a[ ]={1,2,3,4,5}; 若被定义的数组长度与提供初值的个数不相同,则数组 长度不能省略。 int a[10]={1,2,3,4,5};只初始化前5个元素,后5个元素为 0

7.1.4 一维数组程序举例
[例7.2] 用数组来处理Fibonicci数列的前20项。 main () { int i; int f[20] = {1,1}; /* f1、f2已知 */ for(i=2; i<20; i++) f[i] = f[i-2] + f[i-1]; for(i=0; i<20; i++) { if (i%5 == 0) printf(“\n”); /*打印 5次后换行*/ printf("%12d",f[i]); } }

§7.2 二维数组的定义和引用
? ? ? ?

7.2.1 二维数组的定义 7.2.2 二维数组的引用 7.2.3 二维数组的初始化 7.2.4 二维数组程序举例

7.2.1 二维数组的定义
?

一般形式为: 类型说明符 数组名[常量表达式][常量表达式] ; float b[5][10]; b为5×10(5行10列)的数组 特殊的一维数组:元素又是一个一维数组。 float a[3][4];可以理解为定义了三个一维数组,

例:float a[3][4]; a为3×4(3行4列)的数组

相当于float a[0][4],a[1][4],a[2][4]
二维数组的元素在内存中的存放顺序:按行存放; (最右边的下标变化最快,第一维的下标变化最慢)。

7.2.2 二维数组的引用
?

二维数组的元素的表示形式为:数组名[下标][下标]
a[0][0]、a[0][1]、a[0][2]、 a[1][0]、a[1][1]、a[1][2]

例、float a[2][3]; 有6个元素,按如下方式引用各元素:

注意:数组float a[2][3]中无元素a[2][3]。(下标从0始) 常出现的错误是:int a[3][4]; ┇ a[3][4]=3; /*应为a[2][3]=3;*/ 严格区分定义数组时的 和引用元素时的a[3][4]的区别。

7.2.3 二维数组的初始化
1、分行赋值: int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
1 2 3 4 5 6 7 8 9 10 11 12 2、全部数据写在一个花括号内,按数组排列的顺序对各

元 素 赋 初 值 : int a[3][4] {1,2,3,4,5,6,7,8,9,10,11,12}; 该方法容易遗漏数据,不易检查错误。

=

3、对部分元素赋初值: int a[3][4] = {{1},{5},{9}}; 1 0 0 0 5 0 0 0 9 0 0 0 仅对a[0][0]、a[1][0]、a[2][0]赋值
4、如果对全部元素赋初值,则第一维的长度可 以不指定,但必须指定第二维的长度。 int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};

与下面定义等价: int a[ ][4]={1,2,3,4,5,6,7,8,9,10,11,12};

7.2.4 二维数组程序举例
[例7.4]将二维数组的行列元素互换,存到另一个二维数组中。 main() {int a[2][3]={{1,2,3},{4,5,6}}; int b[3][2],i,j; printf(“array a:\n”); printf(“array b:\n”); for(i=0;i<=1;i++) for(i=0;i<=2;i++) {for(j=0;j<=2;j++) {for(j=0;j<=1;j++) {printf(“%5d”,a[i][j]); printf(“%5d”,b[i][j]); b[j][i]=a[i][j];} printf(“\n”); printf(“\n”); } } /*打印a数组,行列互换*/ } /*打印b数组*/

§7.3 字符数组
? ?

7.3.1 字符数组的定义 7.3.2 字符数组的初始化

?
? ? ? ?

7.3.3 字符数组的引用
7.3.4 字符串和字符串结束标志

7.3.5 字符数组的输入输出
7.3.6 字符串处理函数 7.3.7 字符数组应用举例

7.3.1 字符数组的定义
? ?

用来存放字符数据的数组是字符数组。字符数组中的一个 元素存放一个字符。 char c[10];/*定义c为字符数组,包含10个元素*/ c[0]='I';c[1]=' ';c[2]='a';c[3]='m';c[4]=? ';c[5]='h'; c[6]='a';c[7]='p';c[8]='p';c[9]='y';

字符型与整型可以通用,但有区别: char c[10]; /* 在内存中占10字节 */ int c[10]; /* 在内存中占20字节 */

7.3.2 字符数组的初始化
1、逐个元素初始化 char c[10] = {'I',' ','a','m',' ','h','a','p','p','y'};
c[0] c[1] c[2] c[3] c[4] c[5] c[6] c[7] c[8] c[9]

I

a m

h

a

p

p

y

2、初值个数少于数组长度。 char c[14] = {'I',' ','a','m',' ','h','a','p','p','y'};
I a m h a p p y ? ? ?

初值个数 大于数组 长度:语 法错误。

c[0] c[1] c[2] c[3] c[4] c[5] c[6] c[7] c[8] c[9] c[10]c[11]c[12]c[13]

?

3、指定初值时,未指定数组长度,则长度等于初值 个数。 char c[ ] = {'I',' ','a','m',' ','h','a','p','p','y'}; 10个初值,因此,数组c的长度是10。

?

也可以定义和初始化一个二维字符数组,如 char diamond[5][5]={{' ',' ','*'},{' ','*',' ','*'}, {?*?,? ?,? ?,? ?,?*?},{? ?,?*?,? ?,?*?},{? ?,? ?,?*?}}; 用它代表一个钻石形的平面图形,如下图所示:

*

* *
* * * * *

7.3.3 字符数组的引用(1)
引用一个元素,得到一个字符。 [例7.6] 输出一个字符串。 main () { char c[10]={'I',' ','a','m',' ','a',' ','b','o','y'}; int i; for(i=0;i<10;i++) printf(“%c”,c[i]); /*引用数组元素c[i],得到一个字符*/ printf("\n"); } 输出结果: I am a boy

7.3.3 字符数组的引用(2)
[例7.7]输出一个钻石图形。 系统自动定义这一维的长度 Main() {char diamond[ ][5] ={{' ',' ','*'},{' ','*',' ','*'}, {?*?,? ?,? ?,? ?,?*?},{? ?,?*?,? ?,?*?},{? ?,? ?,?*?}}; int i,j; for(i=0;i<5;i++) {for(j=0;j<5;j++) printf(“%c”,diamond[i][j]); printf(“\n”); } }

7.3.4 字符串和字符串结束标志(1)
?

在C语言中,将字符串作为字符数组来处理。

?

有时,人们关心的是有效字符串的长度而不是字符数 组的长度。
例如,定义一个字符数组长度为100,实际有效字符只 有40个。为了测定字符串的实际长度,C语言规定了一 个?字符串结束标志?,用字符‘\0?表示。

?

?

若有一个字符串,其第10个字符为‘\0?,则此字符串 的有效字符为9个。即遇到字符‘\0?时,表示字符串结 束,由它前面的字符组成字符串。

7.3.4 字符串和字符串结束标志(2)
?
?

系统对字符串常量也自动加‘\0’作为结束符。
如:?C Program?共9个字符,但在内存中占10个字节, 最后一个字节放‘\0’。

?
?

字符串作为一维数组来存放。
程序中往往依靠检测‘\0’来判定字符串是否结束,而 不是根据数组长度来决定字符串长度。但应在定义字符 数组时估计实际字符串长度,使数组长度始终保证大于 字符串实际长度。 如果在一个字符数组中先后存放多个不同长度的字符串, 则应使数组长度大于最长的字符串的长度。

?

7.3.4 字符串和字符串结束标志(3)
?

说明:‘\0’代表ASCII码为0的字符。该字符不显示, 而是一个?空操作符?,即它什么也不干。用它来作 字符结束标志不会产生任何附加的操作或增加有效字 符,只是一个供辨别的标志。

?

语句:printf(“How do you do?\n”);输出一个字符串。 系统在执行语句时如何知道输出到哪里结束呢?实际 上,在内存存放时,系统会自动在最后一个字符‘\n’ 后面加一个‘\0’作为字符结束标志。在执行printf函 数时,每输出一个字符检查一次,看下一个字符是否 ‘\0’。遇‘\0’就停止输出。

7.3.4 字符串和字符串结束标志(4)
(1)字符数组可以用字符串常量来初始化。 如:char c[ ] = {"I am happy"}; 或: char c[ ] = "I am happy";
c[0] c[1] c[2] c[3] c[4] c[5] c[6] c[7] c[8] c[9] c[10]

I

a m

h

a

p

p

y

\0

注意:(1)字符串两端是双引号而不是单引号。 (2)数组c的长度不是10,而是11。字符串常量的 后面由系统自动加上一个‘\0?。

7.3.4 字符串和字符串结束标志(5)
(2)字符串常量在存储时,系统自动在其后加上结束标志
‘\0’(占一个字节,其值为二进制0) 如:char c[14 ] = {"I am happy”};
c[0] c[1] c[2] c[3] c[4] c[5] c[6] c[7] c[8] c[9] c[10]c[11]c[12]c[13]

I
?

a m

h

a

p

p

y

\0 \0

\0 \0

已明确指定字符数组的长度为14,但只给10个初值, 不足部分全部补'\0'。

7.3.5 字符串处理函数(1)
(1)puts(字符数组) 输出字符串(以‘\0?结尾)。

char c[6]=“China”; /*printf、puts均以‘\0’结尾.*/ printf("%s\n",c); /*printf需要格式控制符%s */ puts(c); /*puts不需要格式控制符*/ puts(c)执行输出:China 用puts函数输出的字符串中可以包含转义字符。 China char str[ ]={"China\nBeijing"}; Beijing puts(str); 在输出时将字符串结束标志‘\0?转换成‘\n?,即输出完 字符串后换行。Beijing后也换行。

7.3.5 字符串处理函数(2)
(2)gets(字符数组)
从终端输入一个字符串到字符数组,并且得到一个函数值, 该函数值是字符组的起始地址。

如:执行函数 : gets(c)
从键盘输入:Computer 将包括‘\0’在内的9个字符送到字符数组c。 注意:1) gets()、puts()一次只能输入输出一个字符串。 2) scanf()、printf()则可以输入输出多个字符串。

7.3.5 字符串处理函数(3)
(3)strcat(字符数组1,字符数组2)
把字符串2连接到字符串1的后面,结果放到数组1中。 如:main()
{char str1[15]={“I am ”}; /*I am后有一个空格*/

char str2[ ]={"Chinese."};
printf("%s",strcat(str1,str2)); }输出: I am Chinese. 注意:1) 数组1必须足够大,一般容纳连接后的新字符串。 2)连接时将串1后面的‘\0?取消,只在新串后保留一个’\0?。

7.3.5 字符串处理函数(4)
(4)strcpy(字符数组1,字符数组2)
把字符串2的值拷贝到字符串1中。 如:main() {char str1[10]; char str2[ ]="Chinese"; strcpy(str1,str2); puts(str1); } 输出: Chinese 注意:1)字符数组1的长度不应小于字符串2的长度。 2)?字符数组1”必须写成数组名形式,?字符串2” 可 以是一个字符串常量。如:strcpy(str1,“China”);

3)字符串后面的‘\0?一起拷贝到字符数组1中。 4)不能用赋值语句将一个字符串常量或字符数组直接 赋给一个字符数组。如:str1={“China”}; str2=str1; 不合法 只能用strcpy函数处理。用赋值语句只能将一个字符 赋给一个字符型变量或字符数组元素。 如下面是合法的: char a[5],c1,c2; c1=?A?;c2=?B?; c[0]='C';a[1]='h';a[2]='i';a[3]='n';a[4]='a'; 5)用strcpy函数可以将字符串2中前面若干字符拷贝到字符 数组1中去。例如:strcpy(str1,str2,2); 作用:将str2中前面2个字符拷贝到str1中去,然后再加 一个‘\0?。

(5)strcmp(字符串1,字符串2)

作用:比较?字符串1?、?字符串2?。 例: strcmp(str1,str2); strcmp("China", "Korea"); strcmp(str1, "Beijing"); 比较规则:逐个字符比较ASCII码,直到遇到不同字符或‘\0?, 比较结果是该函数的返回值。

①字符串1 < 字符串2 ,函数的返回值:负整数 ②字符串1 == 字符串2,函数的返回值=0 ③字符串1 > 字符串2, 函数的返回值:正整数
注意:字符串只能用strcmp函数比较,不能用关系运算符 ?= =”比较。 if (strcmp(str1,str2) == 0) printf("yes"); if (str1 == str2) printf("yes");

7.3.5 字符串处理函数(5)
(6)strlen(字符数组)测字符串实际长度的函数。 如: char str[10]={“China”}; printf("%d",strlen(str))}; 输出结果:5 也可以直接测字符串常量的长度。如:strlen(“China”); (7)strlwr(字符串) 将字符串中大写字母转换成小写字母。 例如:char str1[ ]=“ABCDEF"; strupr(str1); (8)strupr(字符串) 将字符串中的小写字母转换成大写字母。 例如:char str2[ ]="abcdef"; strupr(str2); 注意:以上函数均是库函数,使用时必须用#include语句 包含头文件stdio.h。

7.3.6 字符数组应用举例
[例7.9] 输入三个字符串,并找出其中最大者。 分析:用strcmp( )函数比较字符串的大小。 首先比较前两个,把较大者拷贝给字符数组变量string(用 strcpy()函数拷贝),再比较string和第三个字符串。 0 1 2 3 4 5 6 7 8 9 10 … 19 Str[0] Str[1] C h i n a \0 J a p a n \0

I n d i a \0 Str[2] 程序:设字符串最长为19个字符(加上’\0?为20个字符)。

#include "string.h” /* strcmp、strcpy函数均在string.h中定义 */ main() { char string[20]; /* 存最大字符串 */ char str[3][20]; /* 三个字符串 */ int i; for(i=0;i<3;i++) gets(str[i]); /* 输入三个字符串 */ if (strcmp(str[0],str[1]) > 0) strcpy(string,str[0]); else strcpy(string,str[1]); if (strcmp(str[2],string) > 0) strcpy(string,str[2]); printf("\nthe largest string is: \n%s\n",string); }

课堂练习
1.以下对一维数组a的正确说明是: A) char a(10) ; B) int a[10] ; C) int k=5,a[k]; D) char a[ ]={?a?,?b?,?c?}; 2.以下对二维数组a的正确说明是: A) char a[10][5] ; B) int a[2][3] ; C) int k=5,a[k][k-2]; D) char a[4][3]={{“abc”},{“bcd”},{“cde”}}; E) int a[3][4] = {{1},{5},{9}};

3、以下程序是否正确?如果错了,怎么改?

程序1:对两个字符串进行比较。 #include <stdio.h> main( ) { char str1[ ]={"abcdefg"}; char str2[ ]={"abcdefg"}; if (str1 == str2) printf("yes"); If(strcmp(str1,str2)= =0) else printf("no"); }
程序2: 输出一个字符串。 main () { char c[10]={'I',' ','a','m',' ','a',' ','b','o','y'}; int i; for(i=0;i<10;i++) printf(“%c”,c[i]); printf("\n"); }

程序3: main() { int i; char c1[ ] = {"How are you?"}; printf("%s", c1[ ] ); } printf("%s", c1 ); 程序4: main( ) { char c[6]=“China”; printf("%s\n",c); puts(c); }

第八章 函数
一、概述
编程中常遇到完成某个功能的程序段出现多次,为使程序更简 化;常遇到大家均要用到的功能,为了减少不必要的重复编程 使程序质量提高。在计算机高级语言中,引入函数(或子程 序、过程),称为标准函数,C中称库函数。

C 中库函数按功能分类:

函数
输入、输出函数 数学函数 字符和字符串函数 动态分配函数 图形函数

头文件
stdio.h math.h string.h malloc.h graphics.h

标准库函数一般均是系统提供,因此程序质量应是最高的,即速 度快、精度高且占内存少,调用方便。

例:程序中出现3次求某数阶乘,这时可将求某数阶乘编制成 函数,而主函数三次调用,主函数和子函数关系如下:
主函数 子函数(求某数阶乘)

C程序就是由若干函数组成, 但必有一个是main( ), 顺序不定, 但执行一定从main( )开始
也允许子函数嵌套调用: 主函数 子函数1 子函数2

C中函数:

有参函数 无参函数 空函数

二、函数定义与调用
1、定义:无参函数 类型标识符 { 说明部分 语句 } 函数名( ) 起名规则符合标识符要求 函数返回值的类型 函数体

例: main( ) { prn1( ); printf(“\n”); prn2( ); printf(“\n”); prn1( ); } prn1( ) { printf(“*****\n”); } prn2( ) { printf(“*BBI*\n”); }

运行结果: ***** *BBI* *****

空函数: 类型说明符

函数名( ) { }

例: dummy( ) { } 该空函数什么也不做,常用 于设计程序时在扩充函数。

有参函数 : 类型标识符 { 说明部分 语句 }

函数名( 参数表)

二、函数调用
1. 调用格式: 函数名(实参列表) int min(int a,int b) 例:main( ) { int c; ( int x1, x2, minum; if (a < b) scanf(“%d,%d”,&x1, &x2); c=a; minum=min(x1,x2); else c=b; printf(“ min=%d\n”, minum); return (c); } } 2. 三种调用方式: 函数调用语句 如: printf(“ %s \n”, “BBI”); 函数调用出现在表达式中: y= max(a,b) + 100; 函数调用是另一个函数调用的实参:printf(“ %d \n”,max(s,b)); 或y=max(max(a,b),c); 3. 函数参数及返回值: 返回值: 一般通过 return(表达式)仅返回一个值; 若不 返回任何值可不要 return ( ); 若表达式的类型与函数返回值规定 类型不一致, 应以函数返回值类型为准; 凡函数未说明返回值 类型均以 int 处理; 形参:在未被调用时,形参不占内存单元;在调用时形 参才被分配单元,调用结束,释放;

4. 实参: 是表达式,调用时将其值相应传送给形参。 值调用:实参传送给形参是值,既实参将值直接赋给形参 (是变量),这称做单方向值调用。这时函数中形 参变量值发生改 变,带不回主调函数。 地址调用:实参传给形参是地址,表示被调函数和主调函 数操作的是同一批内存单元内容,形参的值发 生改变,带回主调函数。 例: main( ) { int i=10; printf(“ i=%d \n”, change(i) ); 调用前:ii不分配单元 printf(“ i=%d \n”, i); 调用时: } 10 ii int change(int ii) { ii=ii+100; return(ii); } 返回时:

ii

110

返回后:ii释放,不可访

运行结果:i=110 i=10

数组作函数参数 例:将键入的10个实数按升序排序后输出,要求排序用函数调 用实现. float sort (float array[ ], int n) { int i, y ; float temp; for (i=0; i< n -1; i++) for (j=i+1; j< n; j++) if (array[i] > array[j]) a { temp = array[i]; array[i] = array[j]; array a[0] a[1] array[j] = temp; a[2] } : } : a[9]

a 是指向10个元素在内存存放的首地 址,调用 sort 函数时,将array a, 则主调和被调操作的是同一批内存单 元的内容。这样速度快,占内存少。 被调函数对参数改变在主调中可见。 这称地址调用(双向)。

main( ) { float a[10]; int i; for (i=0; i<10; i++) scanf(“%f”, &a[i]); for (i=0; i<10; i++) printf(“%f ”, a[i]); sort (a, 10); for (i=0; i<10; i++) printf(“ \n %f ”,a[i]); }

5、被调函数的说明:
库函数:该函数相应的头文件,应用 include 命令,放在程序 首部。 用户定义函数:返回值是非整型和字符型且函数定义在主调 函数之后时,均须在主调函数里加说明。 格式: 类型标识符 函数名( ); (与函数定义不同) ( 被调函数返回值是 int 或 char;被调函数 定 义在主调前;或在所有函数定义之前, 则主调函数均不加说明 ) float max(float,float ); main( ) {/* 对被调函数说明, 被调函数定义在主调后 */ float a, b, c; scanf(“%f,%f”, &a, &b); c=max(a,b); printf(“max=%f\n”,c); } float max(float x,float y) { return((x>y) ? x : y); }

float max (float x, float y) { return ( x>y ? x : y ); }

main( ) { float a, b, c; /* 主调不要对被调说明 */ scanf(“ %f, %f ”, &a, &b); c=max (a,b); printf(“max=%f \n”, c); }

第九章 指 针
一、概念
指针是 c 的特色之一,也是难点。 使用指针能有效地表示复杂的数据结构;动态分配内存; 方便地使用数组,字符串;实现双向地址调用;使 c能直接处 理单元地址,具有低级语言的特点。这对设计系统软件很重要。 对变量访问方式: 单元地址: 单元地址: 1000 1002 10 20

a b

pa pb

1000 1002

1 2

a b

p

x

main() main() { int a, b; { int a=1; b=2; a=10; int *pa, *pb; b=20; pa=&a; pb=&b; printf (“%d,%d\n”,a, b); *pa=100; *pb=200; } printf (“%d,%d\n”, *pa,*pb ); }

通过变量名访问: 直接访问 给变量赋值; 将变量值输出

通过指针变量来访问: 间接访问 即由指针变量存放的地址来 得到变量的值。

二、指针变量
指针——就是变量在内存中的地址。 指针变量——存放指针的变量,即用来存放 变量地址的变量。 指针类型由其所指向的数据类型决定 指针变量定义: 类型标识符 *变量名 int *pa, *pb; /* 定义pa, pb分别指向整型类型 */ float *pf1, *pf2; /* 定义pf1, pf2分别指向实型变量 */ char *pc1, *pc2; /* 定义pc1,pc2分别指向字符型变量 */ pa 和 pb 只可指向整型变量, 不可指向其他类型变量; pf1, pf2 只可指向实型; pc1, pc2 只可指向字符型;

1、运算符 *:间接引用运算符 *p表示指针变量p所指内容 *p可用于左值 *p=2; & 取地址符 int x,*p; p=&x ; 则 *p=x; *&x=x; *p?*&x?x 注意:不允许将任何非地址类型的数据赋给指针变量 例:int a,*p; a=4; p=&a; scanf(“%d”,p); ?scanf(“%d”,&a); printf(“%d”,*p); ? printf(“%d”,a);

2、指针变量的加法和减法运算包括+ +和- p=p+1; int *p;

指针运算是地址的运算: 取决于指针指向的数据类型(T)。 px+n, px-n ——将指针从当前位置 向前或向后移动n个数据单位。 px?n的结果为: px?n?sizeof(T) px-py:两指针位置之间的数据个数,不是地址差。 px-py的结果为:( px-py) / sizeof(T) y= ?px++ —— y= ? ( px++ ),注意优先级和结合性 y= ? ++ px —— y= ?( ++ px) 问题:y= ?px++和y= (?px)++的意义?

指针变量引用
main( ) { int a,b; pa int *pa,*pb; &a a=10; b=20; pb pa=&a; pb=&b; &b printf(“%d,%d\n”,a,b); printf(“%d,%d\n”,*pa,*pb); }
a 10 b 20 pa 1000 pb 1002 10 20 a b

&、*、++、--均是单目运算:结合性左 *&a 等价 a或*pa &*pa 等价 pa 或&a (*pa)++ 等价 a++ *(++pa) 等价 pa pa+1, *pa



pa++——pa是指向整型指针变量,增1表示增加 2bytes. pf1++——pf是指向实型指针变量,增1表示增加 4bytes. pc1++——pc是指向字符型指针变量,增1表示增加 1byte.

例1:输入a,b两个整数,按从大到小顺序输出

main ( ) &a 3 { int a,b,*pa,*pb,*p; pa a scanf(“%d,%d”,&a,&b); pa=&a; pb=&b; &b 30 if (a<b) { p=pa; pa=pb; pb=p;} pb b printf(“a=%d,b=%d\n”,a,b); printf(“max=%d,min=%d\n”,*pa,*pb); &b 3 }
pa 在程序中若a<b,则将两个指针变量的值交换, 原pa a, 现在pa b(大数) a

&a
pb pb

30
b b

例2 用函数实现两数交换 void swap(int *pa, int *pb) { int temp; temp=*pa; *pa=*pb; *pb=temp; } main ( ) { int a, b; int *pa1, *pb1; scanf(“%d,%d\n”,&a, &b); pa1=&a; pb1=&b; if (a< b) swap(pa1, pb1); printf(“%d,%d \n”,a, b); 参数传递 函数中实现a b } a pa1 &a pa1 &a a 3 30 pa1 a pa &a pa &a &a 3 pb1 &b b 30 pb1 &b pb &b b 30 pb &b pb1 &b b 3

例3:在函数中交换指针值。是不行的 void swap(int *pa, int *pb ) main( ) { int a, b; { int *p; /* 交换指针的值 int *pa,*pb; p=pa; scanf(“%d,%d”,&a, &b); 返回时,pa,pb pa=pb; pa1=&a; pb1=&b; 均释放,达不 pb=p; printf(“%d,%d\n”,a,b); 到交换a,b的目 } if (a<b) swap(pa1,pa2); 的 */ printf(“%d,%d\n”,a, b); } void swap(int *pa, int *pb) { int *p; /* 指针变量 p 未赋值,是随机值,可能会使系统不 *p=*p1; 正常 */ *p1=*p2; *p=*p2; }

例4 main( ) { static int a[2][5]={{1,2,3,4,5},{6,7,8,9,10}}; int i, (*pa)[5]=a, *p; p=*pa++; /*先p *pa, 后pa pa+1指下一行*/ for (i=0; i<5; i++) printf(“%d”, *p++); /* 输出第0行5个元素值 */ printf(“\n”); p=*pa; for (i=0; i<5; i++) printf(“%d”, *p++); /* 输出第1行5个元素值 */ } 三、数组与指针 1、概念:数组名就是指针,是数组的首地址,是常量。 一维数组:int a[10] 二维数组:int b[3][4] 1000 1002 a[0] a[1] a[2] : : a[9] b *(b+0)/b[0] *(b+1)/b[1] *(b+2)/b[2] b[0]+1 b[0]+2 b[0]+3

1004
1010

第i个元素: a[i] 第i个元素地址: &a[i] 指针: main( ) { int a[10], i; int *p; p=a; for (i=0; i<10; i++) { printf(“%u”, p+i); } 指针:

第i行第 j列元素:b[i][j] 第i行第 j列元素地址:&b[i][j]

printf(“%d “, *(p+i));

/* 每个元素首地址,与 printf(“%u”, &a[i]);等价 */ /* 每个元素值,与 printf(“%d”, a[i]);等价 */

main( ) {static int b[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; int *p, i; p=b[0]; /* 或 p=*(b+0) */ for(; p<b[0]+12; p++) {printf(“%u”,p); printf(“%d “,*p); } }

二维数组也可通过定义指向几个元素的一维数组指针变量来处理。 main( ) { static int b[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; int (*p)[4]; /* p是指向有四个元素一维数组 int i, j; 指针变量,p+1指向下一行首地址 */ p=b; scanf(“%d,%d”,&i,&j); printf(“b[%d][%d]=%d\n”,i, j, *(*(p+i)+j)); } 用数组名访问元素,不直观,速度较快 对数组元素操作方式: 用常规下标法,直观,速度慢 main( ) main( ) { int a[10],i; { int a[10];i; for(i=0;i<10;i++) for (i=0;i<10;i++); scanf(“%d”, a+i ); scanf(“%d:, &a[i]); printf(“\n”); printf(“\n”); for(i=0;i<10;i++) for (i=0;i<10; i++) printf(“%d ”, *(a+i) ) printf(“%d ”,a[i]); } }

用指针变量指向元素,不直观,但速度快 main( ) { int a[10], i, *p; p=a; for (i=0; i<10; i++) scanf(“%d”, p+i ); printf(“\n”); for (i=0; i<10; i++) printf(“%d ”, *(p+i) ); } main( ) {int a[10],i,*p; p=a; for (i=0;i<10;i++, p++ ) scanf(“%d”, p ); printf(“\n”); p=a; for (i=0;i<10;i++, p++ ) printf(“%d ”, *p ); } main( ) { int a[10], i, *p; for (p=a; p<a+10; p++) scanf(“%d”,p); printf(“\n”); for (p=a; p<a+10; p++) printf(“%d ”,*p); }

例5:输入10个整数,将其中最小的与第一个数对换,最大数与最后 一个数对换.(函数中用指针处理) 形参、实参均用数组名

main( ) { int num[10], i; for (i=0; i<10; i++) scanf(“%d”, &num[i]); maxmin(num); for (i=0; i<10; i++) printf(“%d ”, num[i]); } void maxmin(int array[ ]) { int *pmax, *pmin, *p; pmax=pmin=array; for (p=array+1; p < array+10; p++) if (*p > *pmax) pmax=p; else if (*p < *pmin) pmin=p; *p=array[0]; array[0]=*pmin; *pmin=*p; *p=array[9]; array[9]=*pmax; *pmax=*p; }

方案二:形参、实参均用指针

main( ) { int num[10], i; int *pnum; pnum=num; for (i=0; i<10; ++) scanf(“%d”, &num[i]); maxmin(pnum); for (i=0; i<10; i++) printf(“%d ”, num[i]); } void maxmin(int *pa) { int *pmax, *pmin, *p; p=pmax=pmin=pa; for (; p < pa+10; p++) if (*p > *pmax) pmax=p; else if (*p<*pmin) pmin=p; *p=*pa; *pa=pmin; *pmin=*p; *p=*(pa+9); *(pa+9)=*pmax; *pmin=*(p+9); }

四、字符数组与指针
main( ) { static char str1[ ]=“I Love China!”; char *str=“I Love China!” ; /* 可不加static,此两句等价 */ char *ps; int i; for (i=0; str1[i] != ?\0?; i++) printf(“%c”, str1[i]); /*下标处理 */ for (i=0; *(str+i) != ?\0?; i++) printf(“%c”,*(str+i)); ps=str; /* 指针处理 */ for (; *ps; ps++)` printf(“%c”,*ps); } str . . I L o : : ?\0? str[0]/*(str+0) str[1]/*(str+1) str[2]/*(str+2) str[3]/*(str+3) : :

.
. .

二 维字符数组(处理多个字符串) #include <stdio.h>
main( ) { static char week[ ][10]={“ ”,“Monday”, “Tuesday”, “Wednesday”, “Thursday”, “Friday”, “saturday”, “Sunday” }; int no; while (1) { printf(“Enter week No:”); Week[1] Monday scanf(“%d”, &no); if (no < 1 || no > 7) Tuesday Week[2] { printf(“Input Error!”); wednesday Week[3] continue; : } : else printf(“%d----%s\n”, no, week[no]); printf(“Continue(Y/N)?”); if (getchar( )= =?N? || getchar( )= =?n?) break; }

例6:用函数实现字符串复制
形参、实参均用数组名:

void copystr(char from[ ], char to[ ]) { int i=0; while(from[i] != ?\0?) { to[i]=from[i]; i++; } to[i]=?\0?; } main( ) { static char a[ ]=“I am a teacher.”; static char b[ ]=“You are a student.”; printf(“string a=%s, string b=%s \n”,a, b); copystr(a, b); printf(“string a=%s, string b=%s \n”,a, b); }

形参、实参均用指针: void copystr(char *from, char *to) { while(*from != ?\0?) *to++=*from++; *to=?\0?; }
main( ) { char *a=“I am a tercher.”; char *b=“You are a student.”; copystr(a, b); printf(“sting a=%s, sting b%s\n”,a, b); }


相关文档

C语言基本语法
C语言基本语法知识
第2章 C语言基本语法
第4章 C语言基本语法
C语言基本语法元素
第2章_C语言基本语法元素
Java语言基本语法总结
C语言基本语法成分
C语言概述与基本语法
C语言基本语法知识习题
电脑版