710 likes | 860 Views
第九 / 十讲 C 程序设计导引( II ). 北京大学信息科学技术学院. 主要内容. 语句与控制流 标准库函数:输入输出控制 其他标准库函数 程序风格. 1 、语句与控制流. 高级程序设计语言的运行单位是 语句 。 在 C 语言中,诸如表达式: x = 1 、 i++ , … 等之后加上 分号 就构成了 简单的语句 (所有的表达式加上分号之后都可以形成语句,但它们并不都是有效的语句,如: x + 5 )。 C 语言中的语句种类大致包括: 变量定义与初始化语句,如: int x, y = 1; 赋值语句,如: x = y + z;
E N D
第九/十讲 C程序设计导引(II) 北京大学信息科学技术学院
主要内容 • 语句与控制流 • 标准库函数:输入输出控制 • 其他标准库函数 • 程序风格
1、语句与控制流 • 高级程序设计语言的运行单位是语句。 • 在C语言中,诸如表达式:x = 1、i++,… 等之后加上分号就构成了简单的语句(所有的表达式加上分号之后都可以形成语句,但它们并不都是有效的语句,如:x + 5)。 • C语言中的语句种类大致包括: • 变量定义与初始化语句,如:int x, y = 1; • 赋值语句,如:x = y + z; • 函数调用语句,如:scanf(“%d”, &n); • 自增(减)语句,如:i++; - -i; • 程序控制语句 • 空语句 • ……
1、语句与控制流 程序的执行顺序是由程序中的程序控制语句规定的。一般情况下,程序顺序地执行语句,语句出现的顺序就是其执行顺序(顺序程序结构)。 程序控制语句包括循环控制语句,使得程序能够反复执行某些语句(循环程序结构,将n条相同的语句简单地复制会使程序变得不合理的冗长)。此外,还包括分支控制语句,用于控制多路选一的分支情况(分支程序结构)。
1、语句与控制流 • 程序控制语句及其控制说明: • 分支控制语句:if-else, switch-case/default • 循环控制语句:while, do-while, for • 这2种语句都是用大括号({…… })把修饰性描述和语句组合在一起的,称为复合语句。复合语句在语法上和简单语句是一样的。 • 此外,还有一些与程序转移控制有关的语句: break, continue, return, goto
1、语句与控制流 ——分支控制语句 • 对于复杂的实际问题,常常要求依据条件来改变程序的执行顺序,选择所要执行的语句。 • “如果今天不下雨,我就去游泳;否则就在家里读书。” • 分支控制语句包括: • 条件语句:if-else • 多分支语句(开关语句): switch-case/default
假 expression 真 假 exp1 真 假 expression 真 exp2 stmts1 statements1 statements1 statements1 stmts1 … … 1、语句与控制流 ——条件语句 if-else的形式 if (expression1) { statements1; } else { statements2; } if (expression1) { statements1; } else if (expression2) { statements2; } … else if (expressionN) { statementsN; } else { statements(N+1); } if(expression1) { statements1; }
1、语句与控制流 ——条件语句 if-else • 表达式expression的值应该是数值(0表示假,非0表示真)。通常表达式expression是关系表达式或逻辑表达式。如: • x>(y+1),x>y && x>z,x>10 || x<5 • 每个单一语句后面都要有分号。为了增强程序的可读性,应将if或else后的语句用{ }括起来。 • else if和else子句是任选的,不能单独作为语句使用,它必须和if语句配对使用,并且总是与离它最近的if配对。
1、语句与控制流 ——条件语句 if-else示例 //判断一个数是否偶数 int a = 123; if( a%2==0 ) { printf(“%d is an even.”, a); } //求3个数的最大者 int a = 123; int b = 456; int c = 237; if( a>b && a>c ) { printf(“The biggest one is: %d”, a); } else if( b>a && b>c) { printf(“The biggest one is: %d”, b); } else { printf(“The biggest one is: %d”, c); } //求2个数的最大者 int a = 123; int b = 456; if( a>b ) { printf(“The bigger one is: %d”, a); } else { printf(“The bigger one is: %d”, b); } 给定一个年份,判断是否闰年?
1、语句与控制流 ——条件语句 if-else 条件表达式“? :”能够部分替代if-else语句,如: x = (a>b) ? (a-b) : (b-a); ====================== if (a>b) { x = a - b; } else { x = b - a; } 但是,初学者最好不使用条件表达式,而用if-else语句来替代。
1、语句与控制流 ——多分支语句 switch-case/default switch (expression) { casevalue1 : { statements1; break; } …… • casevalueN : • { • statementsN; • break; • } • [default : • { • defaultStatements; • }] • } 另一类问题,通常我们需要将一个表达式的值与多个不同的常量按顺序进行比较,选择其中的匹配项,执行相应部分的语句。这就是多分支语句。
1、语句与控制流 ——多分支语句 switch-case/default • 表达式expression的值类型必须是整型或字符型:char, short, int, long。 • case子句中的值valueI也必须是整型或字符型常量,而且所有case子句中的值应是不同的。 • 执行switch语句时,首先对表达式expression求值,然后与每个case子句中的常量值比较,若找到匹配的常量(相等),程序就执行该分支的语句。
1、语句与控制流 ——多分支语句 switch-case/default • break语句用来在执行完一个case分支后,使程序跳出switch语句,即终止switch语句的执行。 (如果某个case分支后没有break语句,程序将不再做比较而执行下一个分支,直到break语句或该复合语句结束。) • 当没有case子句匹配时,就执行default子句。default子句是任选的(可有可无)。若无default子句,此时switch语句就什么动作也没有做。 • switch语句的功能可以用if-else语句来实现,但某些情况下,使用switch语句更简炼。
1、语句与控制流 ——多分支语句 switch-case/default • int a = 100; • int b = 20; • int c; • char oper; • scanf(“%c”, &oper); • switch(oper) • { • case ‘+’: • { • c = a + b; • break; • } • case ‘-’: • { • c = a - b; • break; • } 输入一个算术运算符,求2个数的运算值。 • case ‘*’: • { • c = a * b; • break; • } • default : • { • if( b==0) • { • c = a; • } • else • { • c = a / b; • } • break; • } • }
1、语句与控制流 ——多分支语句 switch-case/default switch (expression) { casevalue1 : casevalue2 : casevalue3 : { statements1; break; } …… • casevalueN : • { • statementsN; • break; • } • [default : • { • defaultStatements; • }] • } 当多个匹配项做相同的事情时,则可以用这种形式。
1、语句与控制流 ——多分支语句 switch-case/default 计算某年某月的天数。 case4 : case6 : case9 : case11 : { days = 30; break; } • default : // month == 2 • { • if( (year%4==0&&year%100!=0) • || (year%400==0) ) • { • days = 29; • } • else days = 28; • } • } int year, month, days; scanf(“%d”, &year, &month); switch (month) { case1 : case3 : case5 : case7 : case8 : case10 : case12 : { days = 31; break; }
1、语句与控制流 ——多分支语句 switch-case/default int year, month, days; scanf(“%d”, &year, &month); if (month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12 ) { days = 31; } else if (month==4 || month==6 || month==9 || month==11 ) { days = 30; } else //month == 2 { if( (year%4==0&&year%100!=0) || (year%400==0) ) • { • days = 29; • } • else days = 28; } 计算某年某月的天数。
1、语句与控制流 ——循环控制语句 很多实际问题中会遇到具有规律性的重复运算,因此,在程序中就需要将某些语句重复执行。 比如,求1到N的和,如果没有循环,我们该如何编程? 1 + 2 + 3 + … +N ??? 1: int N, i, S = 0; 2: i = 1; 3: if( i<=N ) 4: S = S + i; 5: i = i + 1; 6: 回到3
1、语句与控制流 ——循环控制语句 • 循环控制语句包括: • 当型循环语句:while • 直到型循环语句:do-while • 另一种 当型循环语句:for
init 假 t 真 body itera 1、语句与控制流 ——循环语句 while(当型循环) • 循环语句 while(当型循环) [initialization] //初始化条件 • while (termination){ //循环条件 • body; //循环体 • [iteration] //迭代,变更循环条件 • } • 当表达式termination的值为“真”(非0)时,执行{}中的语句,否则终止循环。
1、语句与控制流 ——循环语句 while(当型循环) while循环 int sum = 0; //注意sum要赋初值 int i = 1; // initialization while ( i<=100 ) // termination { sum = sum + i; i++; // iteration } 求1~100的和
init body itera 真 t 假 1、语句与控制流 ——循环语句 do-while(直到型循环) • 循环语句 do-while(直到型循环) [initialization] //初始化条件 • do{ • body; //循环体 • [iteration] //迭代,变更循环条件 • } while (termination) ; //循环条件 • 首先执行一遍{}中的语句,当表达式termination为“真”(非0)时,继续执行{}中的语句,否则终止循环。
1、语句与控制流 ——循环语句 do-while(直到型循环) do-while循环 int sum = 0; //注意sum要赋初值 int i = 100; // initialization do { sum += i; i--; // iteration }while( i>0); // termination 求1~100的和
init 假 t 真 body itera 1、语句与控制流 ——循环语句 for(另一种当型循环) • 循环语句 for(另一种当型循环) • for (initialization;termination;iteration) • { • body; //循环体 • } • for语句执行时,首先执行初始化操作initialization,然后判断终止条件termination是否满足,如果满足,则执行循环体中的语句(body),最后执行迭代部分iteration。完成一次循环后,重新判断终止条件termination。
1、语句与控制流 ——循环语句 for(另一种当型循环) • for语句中初始化、终止以及迭代部分都可以为空语句(但分号不能省),三者均为空的时候,相当于一个无限循环。 for( ; ; ) { …… } • 在初始化部分和迭代部分可以使用逗号语句,来进行多个操作。逗号语句是用逗号分隔的语句序列。 • for( int i=0, int j=10; i<j; i++, j--) • { • …… • }
1、语句与控制流 ——循环语句 for(另一种当型循环) 求1~100的和 for循环 int sum = 0; //注意sum要赋初值 int i; for( i=1; i<=100; i++ ) // initialization;termination;iteration { sum = sum + i; }
1、语句与控制流 ——循环控制语句 • 在while, do-while, for这三种循环控制语句中,都包括下面三个要素: • initialization //初始化条件 • termination //循环条件 • iteration //迭代,变更循环条件 • 在使用循环控制语句时,要注意正确处理以上三个要素,以避免死循环。 • 要清楚循环的执行次数:往往容易多一次、少一次。
1、语句与控制流 ——循环控制语句 求15! int total = 1; //注意total要赋初值 int i = 1; // initialization while ( i<=15 ) // termination { total = total * i; i++; // iteration }
1、语句与控制流 ——其它控制语句 • 程序转移相关语句包括: • break • continue • return • goto
1、语句与控制流 ——程序转移相关语句 break • 在switch语中,break语句用来终止switch语句的执行,使程序从整个switch语句后的第一条语句开始执行。 • 在循环语句中(while, do-while, for),break用于终止并跳出循环,从紧跟着循环体代码段后的语句执行。 • break语句的格式为: break; int i; for( i= 0; i <10; i++ ) { … if( i == 5 ) { break; } …… } 到第5次循环时, 就不再继续循环了
1、语句与控制流 ——程序转移相关语句 break 寻找一组数中第一个小于0的元素的下标。 int a[10], i; for( i= 0; i <10; i++ ) { scanf(“%d”, &a[i]); } for( i= 0; i <10; i++ ) { if( a[i] < 0 ) { break; } } printf(“The first negative element is %d.”, i);
1、语句与控制流 ——程序转移相关语句 continue • continue语句用来结束本次循环(while, do-while, for) ,跳过循环体中continue之后尚未执行的语句,接着进行终止条件的判断,以决定是否继续循环。注意:在进行终止条件的判断前,都应先保证执行迭代语句。它的格式为: continue; for( int i= 0; i <10; i++ ) { if( i == 5 ) { continue; } …… } 第5次循环时, 什么也不做
1、语句与控制流 ——程序转移相关语句 continue 求1~100之间除7的倍数之外其他数的和? int sum = 0; int i = 1; // initialization while ( i<=100 ) // termination { if( i%7 ==0 ) { i++; // iteration continue; } sum = sum + i; i++; // iteration }
1、语句与控制流 ——程序转移相关语句 return • return语句从当前函数中退出,返回到调用该函数的语句处,并从紧跟该语句的下一条语句继续程序的执行。返回语句有两种格式: • return expression; //当函数需要返回某种类型数据时 • return; //当函数的返回类型为void时 • 单独一条return语句放在函数中间时,会使程序不能正常运行,因为其后的语句将不会执行到。若真需要退出函数,可以通过将return语句嵌入某些语句(如if-else)来使程序在未执行完函数中所有语句时退出。
1、语句与控制流 ——程序转移相关语句 return #include <stdio.h> float getArea(float r); void main() { float area, radius = 3.0f; area = getArea(radius); printf(“Area is %f.”, area); return; } float getArea(float r) { float s; s = 3.14159*r*r; return s; } int main() { … … return 0; } void main() { … … return; }
1、语句与控制流 ——程序转移相关语句 goto 程序跳转控制语句,不提倡使用。 与程序标号(也是一个标识符,其后要跟一个“:”)一起使用: for(…){ … if(…) goto error; … } … error: … … int i=1, sum=0; loop: sum += i; i++; if (i<=100) goto loop; … 也可以用于实现循环控制
1、语句与控制流 ——空语句 仅由一个分号组成的语句为空操作语句。空语句不做任何操作,它在一些特殊情况下是很有用的,如用循环来跳过输入字符开始的空格或制表符: while( ( c = getchar() ) = = ‘’ || c = = ‘\t’ ) ; 不要以为空语句不做任何操作就可以滥用它,有时会造成语法错误: if(d>=0){ x = 1; }; else{ x = 2; } else子句和前面的if子句被空语句分隔开了,这会导致程序语法错误。
1、语句与控制流 • 程序= 函数的集合 • 函数= 语句的集合 • 语句= 简单语句 + 复合语句 • 简单语句= 变量定义与初始化语句、赋值语句、 • 函数调用语句、自增(减)语句、return、空语句,… • 复合语句= if-else、switch-case/default、while、 • do-while、for、break、continue、goto
1、语句与控制流 分支控制语句和循环控制语句中大括号({…… })括起来的语句,可以是简单语句,也可以是这两种复合语句本身。这样,C语言程序中的语句就形成了一种嵌套的层次结构,并且原则上这种嵌套的层次是可以不断扩大的。
1、语句与控制流 ——程序控制语句的嵌套 • if(…) • { • while ( … ) • { • … • if( … ) • { • … • } • else if( … ) • { • … • } • else • { • … • } • … • } • } • else • { • … • }
2、输入输出控制 • 在标准输入输出函数库(stdio.h)中,提供了通过标准输入输出设备(键盘和显示器)进行数据的输入输出函数: • 单个字符输入:int getchar(),返回的是字符的ASCII码 • 格式化输入:int scanf(constrol_string, arg1, arg2, …) • 单个字符输出:int putchar(int) • 格式化输出:int printf(constrol_string, arg1, arg2, …) char c; int n; float f; c = getchar(); scanf(“%d %f %c %s”, &n, &f, &c); putchar(c); printf(“%d %f %c %s \n”, n, f, c);
2、输入输出控制 • scanf() 的基本格式控制符有: • %d:整数(int) • int a; • scanf(“%d”, &a); • %ld:整数(long) • long b; • scanf(“%ld”, &b); • %hd:整数(short) • short d; • scanf(“%hd”, &d); • %c:字符(char) • char c; • scanf(“%c”, &c); • %s:字符串(字符数组),第12讲中介绍 • char s[20]; • scanf(“%s”, s); • %f:单精度浮点数(float) • float x; • scanf(“%f”, &x); • %lf:双精度浮点数(double) • double y; • scanf(“%lf”, &y);