C 语言语法之二程序结构设计
大纲
赋值语句
- 注意在变量声明中给变量赋初值和赋值语句的区别,给变量赋初值是变量声明的一部分,赋初值后的变量与其后的其它同类变量之间仍必须用逗号间隔,而赋值语句则必须用分号结尾,例如:
int a=5,b,c;
- 在变量声明中,不允许连续给多个变量赋初值,而赋值语句则允许连续赋值,如
int a=b=c=5;
声明是错误的,正确的写法必须是:int a=5,b=5,c=5;
- 注意赋值表达式和赋值语句的区别,赋值表达式是一种表达式,它可以出现在任何允许表达式出现的地方,而赋值语句则不能,如
if((x=y+5)>0) z=x;
语句是合法的,if((x=y+5;)>0) z=x;
语句是非法的,因为x=y+5;
是语句,不能出现在表达式中
putchar 函数与 getchar 函数
- 使用 putchar 和 getchar 函数前,都必须要用文件包含命令
#include <stdio.h>
或#include “stdio.h”
- putchar 函数是字符输出函数,功能是在显示器上输出单个字符,其一般形式为:putchar (字符变量),如
putchar('A');
- getchar 函数的功能是从键盘上输入一个字符,其一般形式为:getchar (),通常把输入的字符赋予一个字符变量来构成赋值语句,如:
char c = getchar();
putch 函数与 getch 函数
- getch 函数是一个不回显函数,当用户按下某个字符时,函数自动读取,无需按回车;有的 C 语言命令行程序会用到此函数做游戏,但是这个函数并非标准函数,要注意不同平台的移植性
- Windows 系统使用 putch 和 getch 函数,需要引入 ‘conio.h’ 头文件;在使用 getch 函数之前要调用
initscr()
,结束时要调用endwin()
,否则会出现不输入字符这个函数也会有返回值的情况 - 在不同的系统平台,输入回车,getch 函数将返回不同数值,而 getchar 函数统一返回十进制数 10 (即
\n
) - Linux 系统不存在
conio.h
头文件,但可以使用curses
库替代;若在编译的时候不通过,gcc 编译命令需要添加-l curses
参数来引入curses
库。Linux 系统下只能使用 getch 函数,而 putch 函数不能使用,因为curses
库里没有 putch 函数
printf 函数(格式输出函数)
- printf 函数称为格式输出函数,其关键字最末一个字母 f 即为 “格式”(format) 之意。其功能是按用户指定的格式,把指定的数据显示到显示器屏幕上。该函数是一个标准库函数,它的函数原型在头文件
stdio.h
中,但作为一个特例,不要求在使用 printf 函数之前必须包含stdio.h
文件,其调用的一般形式为:printf (“格式控制字符串”,输出表列) - 其中格式控制字符串用于指定输出格式,格式控制串可由格式字符串和非格式字符串两种组成。格式字符串是以
%
开头的字符串,在%
后面跟有各种格式字符,以说明输出数据的类型、形式、长度、小数位数等,如:%c
表示按字符型输出,%d
表示按十进制整型输出,%f
表示按小数形式输出单精度实数1
2
3
4i. 类型:具体类型如下表所示
ii. 长度:长度格式符为h、l两种,h表示按短整型量输出,l表示按长整型量输出
iii. 输出最小宽度:用十进制整数来表示输出的最少位数,若实际位数多于定义的宽度,则按实际位数输出,若实际位数少于定义的宽度则补以空格或0
iiii. 输出精度:精度格式符以`.`开头,后面跟十进制整数,本项的意义是如果输出数字,则表示小数的位数;如果输出的是字符,则表示输出字符的个数;若实际位数大于所定义的精度数,则截去超过的部分
1 | /printf函数使用例子/ |
scanf 函数(格式输入函数)
- scanf 函数称为格式输入函数,即按用户指定的格式从键盘上把数据输入到指定的变量之中。该函数是一个标准库函数,它的函数原型在头文件
stdio.h
中,与 printf 函数相同,C 语言也允许在使用 scanf 函数之前不必包含stdio.h
文件。scanf 函数的一般形式为:scanf (“格式控制字符串”,地址表列),其中格式控制字符串的作用与 printf 函数相同,如:int a,b; scanf("%d%d",&a,&b);
,但不能显示非格式字符串,也就是不能显示提示字符串。地址表列中给出各变量的地址,地址是由地址运算符&
后跟变量名组成,例如:&a、 &b 分别表示变量 a 和变量 b 的地址 - 格式控制字符串的一般形式为:%[*][输入数据宽度][长度] 类型,其中有方括号 [ ] 的项为任选项,各项的意义如下:
1
2
3
4i. *符号:用以表示该输入项读入后不赋予相应的变量,即跳过该输入值,例如: scanf("%d %*d %d", &a, &b),当输入为:1 2 3 时,将把1赋予a,2被跳过,3赋予b
i. 宽度:用十进制整数指定输入的宽度(即字符数),例如:scanf("%5d", &a),当输入为:12345678,只把12345赋予变量a,其余部分被截去;又如:scanf("%4d%4d", &a, &b),当输入为:12345678,将把1234赋予a,而把5678赋予b
iii. 长度:格式符为l和h,h表示输入短整型数据,l表示输入长整型数据(如%ld) 和双精度浮点数(如%lf)
iiii. 类型:表示输入数据的类型,其格式符和意义和printf函数相同,如:d表示输入十进制整数 - 使用 scanf 函数必须注意以下几点:
1
2
3
4
5
6i. 若输入的数据与输出的类型不一致时,虽然编译能够通过,但输出结果可能不正确
ii. scanf函数中没有精度控制,如:scanf("%5.2f", &a) 是非法的,不能企图用此语句输入小数为2位的实数
iii. scanf中要求给出变量地址,如给出变量名则会出错,如 scanf("%d", a) 是非法的,应改为 scanf("%d", &a) 才是合法的
iiii. 在输入多个数值数据时,若格式控制串中没有非格式字符作为输入数据之间的间隔,则可用空格、TAB或回车作间隔;C编译器在碰到空格、TAB、回车或非法数据(如对“%d”输入“12A”,A即为非法数据)时,即认为数据输入结束
iiiii. 如果格式控制串中有非格式字符,则输入时也要输入该非格式字符,例如:scanf("%d,%d,%d", &a, &b, &c),其中用非格式符“,”作间隔符,则输入数据应为:5,6,7,又如:scanf("a=%d,b=%d,c=%d", &a, &b, &c),则输入数据应为:a=5,b=6,c=7
iiiiii. 在输入字符数据时,若格式控制串中无非格式字符,则认为所有输入的字符均为有效字符,如:scanf("%c%c%c", &a, &b, &c),当输入为:d e f,则把'd'赋予a,' '赋予b,'e'赋予c,只有当输入为:def 时,才能把'd'赋于a,'e'赋予b,'f'赋予c。如果在格式控制中加入空格作为间隔,如:scanf("%c %c %c", &a, &b, &c),则输入时各数据之间可加空格,a、b、c也将会被赋予正确的值
关系运算符及其优先级
关系运算符都是双目运算符,其结合性均为左结合,分别是 <、<=、>、>=、==、!=。关系运算符的优先级低于算术运算符,高于赋值运算符。在六个关系运算符中,前四个 <、<=、>、>= 的优先级相同,且高于 ==、!= 的优先级、而 ==、!= 的优先级相同。
关系表达式
- 关系表达式的一般形式为:表达式 关系运算符 表达式,例如:
a+b > c-d
、x > 3/2
、-i-5*j == k+1
。由于表达式也可以又是关系表达式,因此也允许出现嵌套的情况,例如:a > (b>c)
、a != (c==d)
- 关系表达式的值是” 真” 和 “假”,分别使用 “1” 和 “0” 表示,例如:
5 > 0
的值为 “真”,即为 1,又如:(a=3) > (b=5)
由于 3 > 5 不成立,故其值为” 假”,即为 0
逻辑运算符及其优先级
- C 语言中提供了三种逻辑运算符:&&(与运算)、||(或运算)、!(非运算),其中与运算符
&&
和或运算符||
均为双目运算符,具有左结合性。非运算符!
为单目运算符,具有右结合性。三种逻辑运算符的优先级是如下图(最高处的运算符级别最高) - 逻辑运算的值也分为 “真” 和 “假” 两种,用 “1” 和 “0 ” 来表示。其求值规则如下,与运算符
&&
: 参与运算的两个量都为真时,结果才为真,否则为假,例如:5>0 && 4>2
,由于 5>0 为真,4>2 也为真,相与的结果也为真。或运算符||
: 参与运算的两个量只要有一个为真,结果就为真,两个量都为假时,结果为假,例如:5>0 || 5>8
由于 5>0 为真,相或的结果也就为真。非运算符!
: 参与运算量为真时,结果为假,参与运算量为假时,结果为真,例如:!(5>0)
的结果为假
逻辑表达式
- 逻辑表达式的一般形式为:表达式 逻辑运算符 表达式,其中的表达式可以又是逻辑表达式,从而组成了嵌套的情形。例如:
(a && b) && c
,根据逻辑运算符的左结合性,也可写为:a && b && c
if 语句
if 语句可以构成分支结构,它根据给定的条件进行判断,以决定执行某个分支程序段,C 语言的 if 语句有三种基本形式:
- 第一种形式为:if (表达式) 语句,其语义是:如果表达式的值为真,则执行其后的语句,否则不执行该语句
- 第二种形式为: if-else
- 第三种形式为:if-else-if,前两种形式的 if 语句一般都用于两个分支以下的情况,当有多个分支选择时,可采用 if-else-if 语句
使用 if 语句应注意的问题
- 为了避免这种二义性,C 语言规定,else 总是与它前面最近的 if 配对
- 在 if 语句中,条件判断表达式必须用括号括起来,在语句之后必须加分号
- 在 if 语句的三种形式中,所有的语句应为单个语句,如果要想在满足条件时执行一组(多个)语句,则必须把这一组语句用
{}
括起来组成一个复合语句,但是在}
之后不能再加分号 - 在三种形式的 if 语句中,在 if 关键字之后均为表达式,该表达式通常是逻辑表达式或关系表达式,但也可以是其它表达式,如赋值表达式等,甚至也可以是一个变量。例如:
if(a=5) 语句
、if(b) 语句
都是合法的,只要表达式的值为非 0,即为 “真”
条件运算符与条件表达式
- 条件运算符为
?
和:
,它是一个三目运算符,即有三个参与运算的量。由条件运算符组成条件表达式的一般形式为:表达式 1? 表达式 2: 表达式 3,其求值规则为:如果表达式 1 的值为真,则以表达式 2 的值作为条件表达式的值,否则以表达式 3 的值作为整个条件表达式的值 - 条件表达式通常用于赋值语句之中,例如条件语句:
if(a>b) max=a; else max=b;
,可用条件表达式改写为max=(a>b)?a:b;
,执行该语句的语义是:如 a>b 为真,则把 a 赋予 max,否则把 b 赋予 max - 条件运算符的运算优先级低于关系运算符和算术运算符,但高于赋值符,因此
max=(a>b)?a:b
可以去掉括号而写为max=a>b?a:b
。条件运算符?和:是一对运算符,不能分开单独使用,其结合方向是自右至左
switch 语句
- C 语言还提供了另一种用于多分支选择的 switch 语句,其一般形式为:
1 | switch(表达式){ |
- 其语义是计算表达式的值,并逐个与其后的常量表达式值相比较,当表达式的值与某个常量表达式的值相等时,则执行其后的语句,然后不再进行判断,继续执行后面所有 case、default 后的语句(没有使用 break 关键字的时候)
- 在使用 switch 语句时还应注意以下几点:
1 | i. default子句可以省略不用 |