C 语言语法之二程序结构设计

大纲

赋值语句

  1. 注意在变量声明中给变量赋初值和赋值语句的区别,给变量赋初值是变量声明的一部分,赋初值后的变量与其后的其它同类变量之间仍必须用逗号间隔,而赋值语句则必须用分号结尾,例如:int a=5,b,c;
  2. 在变量声明中,不允许连续给多个变量赋初值,而赋值语句则允许连续赋值,如 int a=b=c=5; 声明是错误的,正确的写法必须是:int a=5,b=5,c=5;
  3. 注意赋值表达式和赋值语句的区别,赋值表达式是一种表达式,它可以出现在任何允许表达式出现的地方,而赋值语句则不能,如 if((x=y+5)>0) z=x; 语句是合法的,if((x=y+5;)>0) z=x; 语句是非法的,因为 x=y+5; 是语句,不能出现在表达式中

putchar 函数与 getchar 函数

  1. 使用 putchar 和 getchar 函数前,都必须要用文件包含命令 #include <stdio.h>#include “stdio.h”
  2. putchar 函数是字符输出函数,功能是在显示器上输出单个字符,其一般形式为:putchar (字符变量),如 putchar('A');
  3. getchar 函数的功能是从键盘上输入一个字符,其一般形式为:getchar (),通常把输入的字符赋予一个字符变量来构成赋值语句,如:char c = getchar();

putch 函数与 getch 函数

  1. getch 函数是一个不回显函数,当用户按下某个字符时,函数自动读取,无需按回车;有的 C 语言命令行程序会用到此函数做游戏,但是这个函数并非标准函数,要注意不同平台的移植性
  2. Windows 系统使用 putch 和 getch 函数,需要引入 ‘conio.h’ 头文件;在使用 getch 函数之前要调用 initscr(),结束时要调用 endwin(),否则会出现不输入字符这个函数也会有返回值的情况
  3. 在不同的系统平台,输入回车,getch 函数将返回不同数值,而 getchar 函数统一返回十进制数 10 (即 \n)
  4. Linux 系统不存在 conio.h 头文件,但可以使用 curses 库替代;若在编译的时候不通过,gcc 编译命令需要添加 -l curses 参数来引入 curses 库。Linux 系统下只能使用 getch 函数,而 putch 函数不能使用,因为 curses 库里没有 putch 函数

printf 函数(格式输出函数)

  1. printf 函数称为格式输出函数,其关键字最末一个字母 f 即为 “格式”(format) 之意。其功能是按用户指定的格式,把指定的数据显示到显示器屏幕上。该函数是一个标准库函数,它的函数原型在头文件 stdio.h 中,但作为一个特例,不要求在使用 printf 函数之前必须包含 stdio.h 文件,其调用的一般形式为:printf (“格式控制字符串”,输出表列)
  2. 其中格式控制字符串用于指定输出格式,格式控制串可由格式字符串和非格式字符串两种组成。格式字符串是以 % 开头的字符串,在 % 后面跟有各种格式字符,以说明输出数据的类型、形式、长度、小数位数等,如:%c 表示按字符型输出,%d 表示按十进制整型输出,%f 表示按小数形式输出单精度实数
    1
    2
    3
    4
    i. 类型:具体类型如下表所示
    ii. 长度:长度格式符为h、l两种,h表示按短整型量输出,l表示按长整型量输出
    iii. 输出最小宽度:用十进制整数来表示输出的最少位数,若实际位数多于定义的宽度,则按实际位数输出,若实际位数少于定义的宽度则补以空格或0
    iiii. 输出精度:精度格式符以`.`开头,后面跟十进制整数,本项的意义是如果输出数字,则表示小数的位数;如果输出的是字符,则表示输出字符的个数;若实际位数大于所定义的精度数,则截去超过的部分

c-data-format

1
2
3
4
5
6
7
8
9
10
11
/printf函数使用例子/
int a = 15;
char d = 'p';
int x = 88, y = 89;
float b = 123.1234567;
double c = 12345678.1234567;
printf("%c,%c\n",x,y); // >> X, Y
printf("a=%d,%5d,%o,%x\n",a,a,a,a); // >> a=15, 15,17,f
printf("b=%f,%lf,%5.4lf,%e\n",b,b,b,b); // >> b=123.123459,123.123459,123.1235,1.231235e+02
printf("c=%lf,%f,%8.4lf\n",c,c,c); // >> c=12345678.123457,12345678.123457,12345678.1235
printf("d=%c,%8c\n",d,d); // >> d=p, p

scanf 函数(格式输入函数)

  1. scanf 函数称为格式输入函数,即按用户指定的格式从键盘上把数据输入到指定的变量之中。该函数是一个标准库函数,它的函数原型在头文件 stdio.h 中,与 printf 函数相同,C 语言也允许在使用 scanf 函数之前不必包含 stdio.h 文件。scanf 函数的一般形式为:scanf (“格式控制字符串”,地址表列),其中格式控制字符串的作用与 printf 函数相同,如:int a,b; scanf("%d%d",&a,&b);,但不能显示非格式字符串,也就是不能显示提示字符串。地址表列中给出各变量的地址,地址是由地址运算符 & 后跟变量名组成,例如:&a、 &b 分别表示变量 a 和变量 b 的地址
  2. 格式控制字符串的一般形式为:%[*][输入数据宽度][长度] 类型,其中有方括号 [ ] 的项为任选项,各项的意义如下:
    1
    2
    3
    4
    i. *符号:用以表示该输入项读入后不赋予相应的变量,即跳过该输入值,例如: 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表示输入十进制整数
  3. 使用 scanf 函数必须注意以下几点:
    1
    2
    3
    4
    5
    6
    i. 若输入的数据与输出的类型不一致时,虽然编译能够通过,但输出结果可能不正确
    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也将会被赋予正确的值

关系运算符及其优先级

关系运算符都是双目运算符,其结合性均为左结合,分别是 <、<=、>、>=、==、!=。关系运算符的优先级低于算术运算符,高于赋值运算符。在六个关系运算符中,前四个 <、<=、>、>= 的优先级相同,且高于 ==、!= 的优先级、而 ==、!= 的优先级相同。

关系表达式

  1. 关系表达式的一般形式为:表达式 关系运算符 表达式,例如:a+b > c-dx > 3/2-i-5*j == k+1。由于表达式也可以又是关系表达式,因此也允许出现嵌套的情况,例如:a > (b>c)a != (c==d)
  2. 关系表达式的值是” 真” 和 “假”,分别使用 “1” 和 “0” 表示,例如:5 > 0 的值为 “真”,即为 1,又如:(a=3) > (b=5) 由于 3 > 5 不成立,故其值为” 假”,即为 0

逻辑运算符及其优先级

  1. C 语言中提供了三种逻辑运算符:&&(与运算)、||(或运算)、!(非运算),其中与运算符 && 和或运算符 || 均为双目运算符,具有左结合性。非运算符 ! 为单目运算符,具有右结合性。三种逻辑运算符的优先级是如下图(最高处的运算符级别最高)
  2. 逻辑运算的值也分为 “真” 和 “假” 两种,用 “1” 和 “0 ” 来表示。其求值规则如下,与运算符 &&: 参与运算的两个量都为真时,结果才为真,否则为假,例如:5>0 && 4>2,由于 5>0 为真,4>2 也为真,相与的结果也为真。或运算符 ||: 参与运算的两个量只要有一个为真,结果就为真,两个量都为假时,结果为假,例如:5>0 || 5>8 由于 5>0 为真,相或的结果也就为真。非运算符 !: 参与运算量为真时,结果为假,参与运算量为假时,结果为真,例如:!(5>0) 的结果为假

c-luoji-symbol

逻辑表达式

  1. 逻辑表达式的一般形式为:表达式 逻辑运算符 表达式,其中的表达式可以又是逻辑表达式,从而组成了嵌套的情形。例如:(a && b) && c,根据逻辑运算符的左结合性,也可写为:a && b && c

if 语句

if 语句可以构成分支结构,它根据给定的条件进行判断,以决定执行某个分支程序段,C 语言的 if 语句有三种基本形式:

  1. 第一种形式为:if (表达式) 语句,其语义是:如果表达式的值为真,则执行其后的语句,否则不执行该语句
  2. 第二种形式为: if-else
  3. 第三种形式为:if-else-if,前两种形式的 if 语句一般都用于两个分支以下的情况,当有多个分支选择时,可采用 if-else-if 语句
    c-if

使用 if 语句应注意的问题

  1. 为了避免这种二义性,C 语言规定,else 总是与它前面最近的 if 配对
  2. 在 if 语句中,条件判断表达式必须用括号括起来,在语句之后必须加分号
  3. 在 if 语句的三种形式中,所有的语句应为单个语句,如果要想在满足条件时执行一组(多个)语句,则必须把这一组语句用 {} 括起来组成一个复合语句,但是在 } 之后不能再加分号
  4. 在三种形式的 if 语句中,在 if 关键字之后均为表达式,该表达式通常是逻辑表达式或关系表达式,但也可以是其它表达式,如赋值表达式等,甚至也可以是一个变量。例如:if(a=5) 语句if(b) 语句 都是合法的,只要表达式的值为非 0,即为 “真”

条件运算符与条件表达式

  1. 条件运算符为 ?:,它是一个三目运算符,即有三个参与运算的量。由条件运算符组成条件表达式的一般形式为:表达式 1? 表达式 2: 表达式 3,其求值规则为:如果表达式 1 的值为真,则以表达式 2 的值作为条件表达式的值,否则以表达式 3 的值作为整个条件表达式的值
  2. 条件表达式通常用于赋值语句之中,例如条件语句:if(a>b) max=a; else max=b;,可用条件表达式改写为 max=(a>b)?a:b;,执行该语句的语义是:如 a>b 为真,则把 a 赋予 max,否则把 b 赋予 max
  3. 条件运算符的运算优先级低于关系运算符和算术运算符,但高于赋值符,因此 max=(a>b)?a:b 可以去掉括号而写为 max=a>b?a:b。条件运算符?和:是一对运算符,不能分开单独使用,其结合方向是自右至左

switch 语句

  1. C 语言还提供了另一种用于多分支选择的 switch 语句,其一般形式为:
1
2
3
4
5
6
7
switch(表达式){
case 常量表达式: 语句1;
case 常量表达式: 语句2;
...
case 常量表达式: 语句n;
default: 语句n+1;
}
  1. 其语义是计算表达式的值,并逐个与其后的常量表达式值相比较,当表达式的值与某个常量表达式的值相等时,则执行其后的语句,然后不再进行判断,继续执行后面所有 case、default 后的语句(没有使用 break 关键字的时候)
  2. 在使用 switch 语句时还应注意以下几点:
1
2
3
4
5
i. default子句可以省略不用
ii. 在case后的各常量表达式的值不能相同,否则会出现错误
iii. 在case后,允许有多个语句,可以不用{}括起来,但建议使用{}括起来
iiii. 各case和default子句的先后顺序可以变动,而不会影响程序执行结果