C语言入门教程,C语言学习教程(非常详细)第五章 循环结构与选择结构

C语言if else语句详解

前面我们看到的代码都是顺序执行的,也就是先执行第一条语句,然后是第二条、第三条……一直到最后一条语句,这称为顺序结构。

但是对于很多情况,顺序结构的代码是远远不够的,比如一个程序限制了只能成年人使用,儿童因为年龄不够,没有权限使用。这时候程序就需要做出判断,看用户是否是成年人,并给出提示。

在C语言中,使用ifelse关键字对条件进行判断。请先看下面的代码:

 
  1. #include
  2. int main()
  3. {
  4. int age;
  5. printf("请输入你的年龄:");
  6. scanf("%d", &age);
  7. if(age>=18){
  8. printf("恭喜,你已经成年,可以使用该软件!\n");
  9. }else{
  10. printf("抱歉,你还未成年,不宜使用该软件!\n");
  11. }
  12. return 0;
  13. }

可能的运行结果:

请输入你的年龄:23↙
恭喜,你已经成年,可以使用该软件!

或者:

请输入你的年龄:16
抱歉,你还未成年,不宜使用该软件!

这段代码中,age>=18是需要判断的条件,>=表示“大于等于”,等价于数学中的

如果条件成立,也即 age 大于或者等于 18,那么执行if后面的语句(第8行);如果条件不成立,也即 age 小于 18,那么执行else后面的语句(第10行)。

if 和 else 是两个新的关键字,if 意为“如果”,else 意为“否则”,用来对条件进行判断,并根据判断结果执行不同的语句。总结起来,if else 的结构为:

if(判断条件){
    语句块1
}else{
    语句块2
}

意思是,如果判断条件成立,那么执行语句块1,否则执行语句块2 。其执行过程可表示为下图:
C语言入门教程,C语言学习教程(非常详细)第五章 循环结构与选择结构_第1张图片

所谓语句块(Statement Block),就是由{ }包围的一个或多个语句的集合。如果语句块中只有一个语句,也可以省略{ },例如:

 
  1. if(age>=18) printf("恭喜,你已经成年,可以使用该软件!\n");
  2. else printf("抱歉,你还未成年,不宜使用该软件!\n");


由于if else 语句可以根据不同的情况执行不同的代码,所以也叫分支结构或选择结构,上面的代码中,就有两个分支。

求两个数中的较大值:

 
  1. #include
  2. int main()
  3. {
  4. int a, b, max;
  5. printf("输入两个整数:");
  6. scanf("%d %d", &a, &b);
  7. if(a>b) max=a;
  8. else max=b;
  9. printf("%d和%d的较大值是:%d\n", a, b, max);
  10. return 0;
  11. }

运行结果:
输入两个整数:34 28↙
34和28的较大值是:34

本例中借助变量max,用max来保存较大的值,最后将max输出。

只使用if语句

有的时候,我们需要在满足某种条件时进行一些操作,而不满足条件时就不进行任何操作,这个时候我们可以只使用 if 语句。也就是说,if else 不必同时出现。

单独使用 if 语句的形式为:

if(判断条件){
    语句块
}

意思是,如果判断条件成立就执行语句块,否则直接跳过。其执行过程可表示为下图:
C语言入门教程,C语言学习教程(非常详细)第五章 循环结构与选择结构_第2张图片

只使用 if 语句来求两个数中的较大值:

 
  1. #include
  2. int main()
  3. {
  4. int a, b, max;
  5. printf("输入两个整数:");
  6. scanf("%d %d", &a, &b);
  7. max=b; // 假设b最大
  8. if(a>b) max=a; // 如果a>b,那么更改max的值
  9. printf("%d和%d的较大值是:%d\n", a, b, max);
  10. return 0;
  11. }

运行结果:
输入两个整数:34 28
34和28的较大值是:34

本例程序中,输入两个数a、b。把b先赋予变量max,再用 if 语句判别max和b的大小,如max小于b,则把b赋予max。因此max中总是大数,最后输出max的值。

多个if else语句

if else 语句也可以多个同时使用,构成多个分支,形式如下:

if(判断条件1){
    语句块1
} else  if(判断条件2){
    语句块2
}else  if(判断条件3){
    语句块3
}else  if(判断条件m){
    语句块m
}else{
     语句块n
}

意思是,从上到下依次检测判断条件,当某个判断条件成立时,则执行其对应的语句块,然后跳到整个 if else 语句之外继续执行其他代码。如果所有判断条件都不成立,则执行语句块n,然后继续执行后续代码。

也就是说,一旦遇到能够成立的判断条件,则不再执行其他的语句块,所以最终只能有一个语句块被执行。

例如,使用多个 if else 语句判断输入的字符的类别:

 
  1. #include
  2. int main(){
  3. char c;
  4. printf("Input a character:");
  5. c=getchar();
  6. if(c<32)
  7. printf("This is a control character\n");
  8. else if(c>='0'&&c<='9')
  9. printf("This is a digit\n");
  10. else if(c>='A'&&c<='Z')
  11. printf("This is a capital letter\n");
  12. else if(c>='a'&&c<='z')
  13. printf("This is a small letter\n");
  14. else
  15. printf("This is an other character\n");
  16. return 0;
  17. }

运行结果:
Input a character:e↙
This is a small letter

本例要求判别键盘输入字符的类别。可以根据输入字符的ASCII码来判别类型。由ASCII码表可知ASCII值小于32的为控制字符。在“0”和“9”之间的为数字,在“A”和“Z”之间为大写字母, 在“a”和“z”之间为小写字母,其余则为其它字符。这是一个多分支选择的问题,用多个 if else 语句编程,判断输入字符ASCII码所在的范围,分别给出不同的输出。例如输入为“e”,输出显示它为小写字符。

在使用 if 语句时还应注意以下两点:

  • 在 if 语句中,判断条件必须用括号括起来。
  • 语句块由{ }包围,但要注意的是在}之后不需要再加分号;(当然加上也没错)。

if语句的嵌套

if 语句也可以嵌套使用,例如:

 
  1. #include
  2. int main(){
  3. int a,b;
  4. printf("Input two numbers:");
  5. scanf("%d %d",&a,&b);
  6. if(a!=b){ //!=表示不等于
  7. if(a>b) printf("a>b\n");
  8. else printf("a
  9. }else{
  10. printf("a=b\n");
  11. }
  12. return 0;
  13. }

运行结果:
Input two numbers:12 68
a
if 语句嵌套时,要注意 if 和 else 的配对问题。C语言规定,else 总是与它前面最近的 if 配对,例如:

 
  1. if(a!=b) // ①
  2. if(a>b) printf("a>b\n"); // ②
  3. else printf("a

③和②配对,而不是和①配对。

C语言关系运算符详解

在上节《C语言if else语句》中看到,if 的判断条件中使用了<=>!=等符号,它们专门用在判断条件中,让程序决定下一步的操作,称为关系运算符(Relational Operators)。

关系运算符在使用时,它的的两边都会有一个表达式,比如变量、数值、加减乘除运算等,关系运算符的作用就是判明这两个表达式的大小关系。注意,是判明大小关系,不是其他关系。

C语言提供了以下关系运算符:

关系运算符 含  义 数学中的表示
< 小于 <
<= 小于或等于
> 大于 >
>= 大于或等于
== 等于 =
!= 不等于


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

在C语言中,有的运算符有两个操作数,例如 10+20,10和20都是操作数,+ 是运算符。我们将这样的运算符称为双目运算符。同理,将有一个操作数的运算符称为单目运算符,将有三个操作数的运算符称为三目运算符。

常见的双目运算符有 +、-、*、/ 等,单目运算符有 ++、-- 等,三目运算符只有一个,就是 ? :,我们将在《C语言条件运算符》中详细介绍。

关系运算符的两边可以是变量、数据或表达式,例如:
1) a+b > c-d
2) x > 3/2
3) 'a'+1 < c
4) -i-5*j == k+1

关系运算符也可以嵌套使用,例如:
1) a > (b > c)
2) a != (c == d)

关系运算符的运算结果只有 0 或 1。当条件成立时结果为 1,条件不成立结果为 0。例如:

  • 5>0 成立,其值为 1;
  • 34-12>100 不成立,其值为 0;
  • (a=3)>(b=5) 由于3>5不成立,故其值为 0。


我们将运算结果 1 称为“真”,表示条件成立,将 0 称为“假”,表示条件不成立。

下面的代码会将关系运算符的结果输出:

 
  1. #include
  2. int main(){
  3. char c='k';
  4. int i=1, j=2, k=3;
  5. float x=3e+5, y=0.85;
  6. int result_1 = 'a'+5
  7. printf( "%d, %d\n", result_1, -i-2*j>=k+1 );
  8. printf( "%d, %d\n", 1
  9. printf( "%d, %d\n", i+j+k==-2*j, k==j==i+5 );
  10. return 0;
  11. }

运行结果:
1, 0
1, 1
0, 0

对于含多个关系运算符的表达式,如 k==j==i+5,根据运算符的左结合性,先计算k==j,该式不成立,其值为0,再计算0==i+5,也不成立,故表达式值为0。

需要提醒的是,==才表示等于,而=表示赋值,大家要注意区分,切勿混淆。

再谈 if 语句的判断条件

if 语句的判断条件中不是必须要包含关系运算符,它可以是赋值表达式,甚至也可以是一个变量,例如:

 
  1. //情况①
  2. if(b){
  3. //TODO:
  4. }
  5. //情况②
  6. if(b=5){ //情况①
  7. //TODO:
  8. }

都是允许的。只要整个表达式的值为非0,条件就成立。

上面两种情况都是根据变量 b 的最终值来判断的,如果 b 的值为非0,那么条件成立,否则不成立。

又如,有程序段:

 
  1. if(a=b)
  2. printf("%d",a);
  3. else
  4. printf("a=0");

意思是,把 b 的值赋予 a,如果为非0则输出该值,否则输出“a=0”字符串。这种用法在后面的程序中会经常出现。

C语言逻辑运算符详解

现在假设有这样一种情况,我们的软件比较特殊,要求使用者必须成年,并且成绩大于等于60,该怎么办呢?

或许你会想到使用嵌套的 if 语句,类似下面这样的代码:

 
  1. #include
  2. int main()
  3. {
  4. int age;
  5. float score;
  6. printf("请输入你的年龄和成绩:");
  7. scanf("%d %f", &age, &score);
  8. if(age >= 18){
  9. if(score >= 60){
  10. printf("你满足条件,欢迎使用该软件\n");
  11. }else{
  12. printf("抱歉,你的成绩不及格,不能使用该软件\n");
  13. }
  14. }else{
  15. printf("抱歉,你还未成年,不能使用该软件!\n");
  16. }
  17. return 0;
  18. }

这种方法虽然能够行得通,但不够简洁和专业,我们可以将其压缩为一条 if else 语句:

 
  1. #include
  2. int main()
  3. {
  4. int age;
  5. float score;
  6. printf("请输入你的年龄和成绩:");
  7. scanf("%d %f", &age, &score);
  8. if(age>=18 && score>=60){
  9. printf("你满足条件,欢迎使用该软件\n");
  10. }else{
  11. printf("抱歉,你还未成年,或者成绩不及格,不能使用该软件!\n");
  12. }
  13. return 0;
  14. }

 

&&是一个新的运算符,称为逻辑运算符,表示age>=18score>=60两个条件必须同时成立才能执行 if 后面的代码,否则就执行 else 后面的代码。

在高中数学中,我们就学过逻辑运算,例如p为真命题,q为假命题,那么“p且q”为假,“p或q”为真,“非q”为真。在C语言中,也有类似的逻辑运算:

运算符 说明 结合性 举例
&& 与运算,双目,对应数学中的“且” 左结合 1&&0、(9>3)&&(b>a)
|| 或运算,双目,对应数学中的“或” 左结合 1||0、(9>3)||(b>a)
! 非运算,单目,对应数学中的“非” 右结合 !a、!(2<5)

逻辑运算的结果

在编程中,我们一般将零值称为“假”,将非零值称为“真”。逻辑运算的结果也只有“真”和“假”,“真”对应的值为 1,“假”对应的值为 0。

1) 与运算(&&)

参与运算的两个表达式都为真时,结果才为真,否则为假。例如:

5&&0

5为真,0为假,相与的结果为假,也就是 0。

(5>0) && (4>2)

5>0 的结果是1,为真,4>2结果是1,也为真,所以相与的结果为真,也就是1。

2) 或运算(||)

参与运算的两个表达式只要有一个为真,结果就为真;两个表达式都为假时结果才为假。例如:

10 || 0

10为真,0为假,相或的结果为真,也就是 1。

(5>0) || (5>8)

5>0 的结果是1,为真,5>8 的结果是0,为假,所以相或的结果为真,也就是1。

3) 非运算(!)

参与运算的表达式为真时,结果为假;参与运算的表达式为假时,结果为真。例如:

!0

0 为假,非运算的结果为真,也就是 1。

!(5>0)

5>0 的结果是1,为真,非运算的结果为假,也就是 0。

输出逻辑运算的结果:

 
  1. #include
  2. int main(){
  3. int a = 0, b = 10, c = -6;
  4. int result_1 = a&&b, result_2 = c||0;
  5. printf("%d, %d\n", result_1, !c);
  6. printf("%d, %d\n", 9&&0, result_2);
  7. printf("%d, %d\n", b||100, 0&&0);
  8. return 0;
  9. }

运行结果:
0, 0
0, 1
1, 0

优先级

逻辑运算符和其它运算符优先级从低到高依次为:

赋值运算符(=) < &&和|| < 关系运算符 < 算术运算符 < 非(!)

&& 和 || 低于关系运算符,! 高于算术运算符。
 
按照运算符的优先顺序可以得出:


另外,逻辑表达式也可以嵌套使用,例如a>b && b || 9>ca || c>d &&  !p

逻辑运算符举例:

 
  1. #include
  2. int main(){
  3. char c='k';
  4. int i=1,j=2,k=3;
  5. float x=3e+5,y=0.85;
  6. printf( "%d,%d\n", !x*!y, !!!x );
  7. printf( "%d,%d\n", x||i&&j-3, i
  8. printf( "%d,%d\n", i==5&&c&&(j=8), x+y||i+j+k );
  9. return 0;
  10. }

运行结果:
0,0
1,0
0,1

本例中!x和!y分别为0,!x*!y也为0,故其输出值为0。由于x为非0,故!!!x的逻辑值为0。对x|| i && j-3式,先计算j-3的值为非0,再求i && j-3的逻辑值为1,故x||i&&j-3的逻辑值为 1。对i

C语言switch case语句详解

C语言虽然没有限制 if else 能够处理的分支数量,但当分支过多时,用 if else 处理会不太方便,而且容易出现 if else 配对出错的情况。例如,输入一个整数,输出该整数对应的星期几的英文表示:

 
  1. #include
  2. int main(){
  3. int a;
  4. printf("Input integer number:");
  5. scanf("%d",&a);
  6. if(a==1){
  7. printf("Monday\n");
  8. }else if(a==2){
  9. printf("Tuesday\n");
  10. }else if(a==3){
  11. printf("Wednesday\n");
  12. }else if(a==4){
  13. printf("Thursday\n");
  14. }else if(a==5){
  15. printf("Friday\n");
  16. }else if(a==6){
  17. printf("Saturday\n");
  18. }else if(a==7){
  19. printf("Sunday\n");
  20. }else{
  21. printf("error\n");
  22. }
  23. return 0;
  24. }

运行结果:
Input integer number:3↙
Wednesday

对于这种情况,实际开发中一般使用 switch 语句代替,请看下面的代码:

 
  1. #include
  2. int main(){
  3. int a;
  4. printf("Input integer number:");
  5. scanf("%d",&a);
  6. switch(a){
  7. case 1: printf("Monday\n"); break;
  8. case 2: printf("Tuesday\n"); break;
  9. case 3: printf("Wednesday\n"); break;
  10. case 4: printf("Thursday\n"); break;
  11. case 5: printf("Friday\n"); break;
  12. case 6: printf("Saturday\n"); break;
  13. case 7: printf("Sunday\n"); break;
  14. default:printf("error\n"); break;
  15. }
  16. return 0;
  17. }

运行结果:
Input integer number:4↙
Thursday

switch 是另外一种选择结构的语句,用来代替简单的、拥有多个分枝的 if else 语句,基本格式如下:

switch(表达式){
    case 整型数值1: 语句 1;
    case 整型数值2: 语句 2;
    ......
    case 整型数值n: 语句 n;
    default: 语句 n+1;
}

它的执行过程是:
1) 首先计算“表达式”的值,假设为 m。

2) 从第一个 case 开始,比较“整型数值1”和 m,如果它们相等,就执行冒号后面的所有语句,也就是从“语句1”一直执行到“语句n+1”,而不管后面的 case 是否匹配成功。

3) 如果“整型数值1”和 m 不相等,就跳过冒号后面的“语句1”,继续比较第二个 case、第三个 case……一旦发现和某个整型数值相等了,就会执行后面所有的语句。假设 m 和“整型数值5”相等,那么就会从“语句5”一直执行到“语句n+1”。

4) 如果直到最后一个“整型数值n”都没有找到相等的值,那么就执行 default 后的“语句 n+1”。

需要重点强调的是,当和某个整型数值匹配成功后,会执行该分支以及后面所有分支的语句。例如:

 
  1. #include
  2. int main(){
  3. int a;
  4. printf("Input integer number:");
  5. scanf("%d",&a);
  6. switch(a){
  7. case 1: printf("Monday\n");
  8. case 2: printf("Tuesday\n");
  9. case 3: printf("Wednesday\n");
  10. case 4: printf("Thursday\n");
  11. case 5: printf("Friday\n");
  12. case 6: printf("Saturday\n");
  13. case 7: printf("Sunday\n");
  14. default:printf("error\n");
  15. }
  16. return 0;
  17. }

运行结果:
Input integer number:4↙
Thursday
Friday
Saturday
Sunday
error

输入4,发现和第四个分支匹配成功,于是就执行第四个分支以及后面的所有分支。这显然不是我们想要的结果,我们希望只执行第四个分支,而跳过后面的其他分支。为了达到这个目标,必须要在每个分支最后添加break;语句。

break 是C语言中的一个关键字,专门用于跳出 switch 语句。所谓“跳出”,是指一旦遇到 break,就不再执行 switch 中的任何语句,包括当前分支中的语句和其他分支中的语句;也就是说,整个 switch 执行结束了,接着会执行整个 switch 后面的代码。

使用 break 修改上面的代码:

 
  1. #include
  2. int main(){
  3. int a;
  4. printf("Input integer number:");
  5. scanf("%d",&a);
  6. switch(a){
  7. case 1: printf("Monday\n"); break;
  8. case 2: printf("Tuesday\n"); break;
  9. case 3: printf("Wednesday\n"); break;
  10. case 4: printf("Thursday\n"); break;
  11. case 5: printf("Friday\n"); break;
  12. case 6: printf("Saturday\n"); break;
  13. case 7: printf("Sunday\n"); break;
  14. default:printf("error\n"); break;
  15. }
  16. return 0;
  17. }

运行结果:
Input integer number:4↙
Thursday

由于 default 是最后一个分支,匹配后不会再执行其他分支,所以也可以不添加break;语句。

最后需要说明的两点是:
1) case 后面必须是一个整数,或者是结果为整数的表达式,但不能包含任何变量。请看下面的例子:

 
  1. case 10: printf("..."); break; //正确
  2. case 8+9: printf("..."); break; //正确
  3. case 'A': printf("..."); break; //正确,字符和整数可以相互转换
  4. case 'A'+19: printf("..."); break; //正确,字符和整数可以相互转换
  5. case 9.5: printf("..."); break; //错误,不能为小数
  6. case a: printf("..."); break; //错误,不能包含变量
  7. case a+10: printf("..."); break; //错误,不能包含变量


2) default 不是必须的。当没有 default 时,如果所有 case 都匹配失败,那么就什么都不执行。

C语言?和:详解,C语言条件运算符详解

如果希望获得两个数中最大的一个,可以使用 if 语句,例如:

 
  1. if(a>b){
  2. max = a;
  3. }else{
  4. max = b;
  5. }

不过,C语言提供了一种更加简单的方法,叫做条件运算符,语法格式为:

表达式1 ? 表达式2 : 表达式3

条件运算符是C语言中唯一的一个三目运算符,其求值规则为:如果表达式1的值为真,则以表达式2 的值作为整个条件表达式的值,否则以表达式3的值作为整个条件表达式的值。条件表达式通常用于赋值语句之中。

上面的 if else 语句等价于:

 
  1. max = (a>b) ? a : b;

该语句的语义是:如a>b为真,则把a赋予max,否则把b 赋予max。

读者可以认为条件运算符是一种简写的  if else,完全可以用 if else 来替换。


使用条件表达式时,还应注意以下几点:
1) 条件运算符的优先级低于关系运算符和算术运算符,但高于赋值符。因此

 
  1. max=(a>b) ? a : b;

可以去掉括号而写为

 
  1. max=a>b ? a : b;


2) 条件运算符?和:是一对运算符,不能分开单独使用。

3) 条件运算符的结合方向是自右至左。例如:

 
  1. a>b ? a : c>d ? c : d;

应理解为:

 
  1. a>b ? a : ( c>d ? c : d );

这也就是条件表达式嵌套的情形,即其中的表达式又是一个条件表达式。

用条件表达式重新编程,输出两个数中的最大值:

 
  1. #include
  2. int main(){
  3. int a, b;
  4. printf("Input two numbers:");
  5. scanf("%d %d", &a, &b);
  6. printf("max=%d\n", a>b?a:b);
  7. return 0;
  8. }

运行结果:
Input two numbers:23 45
max=45

C语言while循环和do while循环详解

在C语言中,共有三大常用的程序结构:

  • 顺序结构:代码从前往后执行,没有任何“拐弯抹角”;
  • 选择结构:也叫分支结构,重点要掌握 if else、switch 以及条件运算符;
  • 循环结构:重复执行同一段代码。


前面讲解了顺序结构和选择结构,本节开始讲解循环结构。所谓循环(Loop),就是重复地执行同一段代码,例如要计算 1+2+3+……+99+100 的值,就要重复进行99次加法运算。

while循环

while循环的一般形式为:

while(表达式){
    语句块
}

意思是,先计算“表达式”的值,当值为真(非0)时, 执行“语句块”;执行完“语句块”,再次计算表达式的值,如果为真,继续执行“语句块”……这个过程会一直重复,直到表达式的值为假(0),就退出循环,执行 while 后面的代码。

我们通常将“表达式”称为循环条件,把“语句块”称为循环体,整个循环的过程就是不停判断循环条件、并执行循环体代码的过程。

用 while 循环计算1加到100的值:

 
  1. #include
  2. int main(){
  3. int i=1, sum=0;
  4. while(i<=100){
  5. sum+=i;
  6. i++;
  7. }
  8. printf("%d\n",sum);
  9. return 0;
  10. }

运行结果:
5050

代码分析:
1) 程序运行到 while 时,因为 i=1,i<=100 成立,所以会执行循环体;执行结束后 i 的值变为 2,sum 的值变为 1。

2) 接下来会继续判断 i<=100是否成立,因为此时 i=2,i<=100 成立,所以继续执行循环体;执行结束后 i 的值变为 3,sum 的值变为3。

3) 重复执行步骤 2)。

4) 当循环进行到第100次,i 的值变为 101,sum 的值变为5050;因为此时 i<=100 不再成立,所以就退出循环,不再执行循环体,转而执行while循环后面的代码。

while 循环的整体思路是这样的:设置一个带有变量的循环条件,也即一个带有变量的表达式;在循环体中额外添加一条语句,让它能够改变循环条件中变量的值。这样,随着循环的不断执行,循环条件中变量的值也会不断变化,终有一个时刻,循环条件不再成立,整个循环就结束了。

如果循环条件中不包含变量,会发生什么情况呢?

1) 循环条件成立时的话,while 循环会一直执行下去,永不结束,成为“死循环”。例如:

 
  1. #include
  2. int main(){
  3. while(1){
  4. printf("1");
  5. }
  6. return 0;
  7. }

运行程序,会不停地输出“1”,直到用户强制关闭。

2) 循环条件不成立的话,while 循环就一次也不会执行。例如:

 
  1. #include
  2. int main(){
  3. while(0){
  4. printf("1");
  5. }
  6. return 0;
  7. }

运行程序,什么也不会输出。

再看一个例子,统计从键盘输入的一行字符的个数:

 
  1. #include
  2. int main(){
  3. int n=0;
  4. printf("Input a string:");
  5. while(getchar()!='\n') n++;
  6. printf("Number of characters: %d\n", n);
  7. return 0;
  8. }

运行结果:
Input a string:c.biancheng.net↙
Number of characters: 15

本例程序中的循环条件为getchar()!='\n',其意义是,只要从键盘输入的字符不是回车就继续循环。循环体n++;完成对输入字符个数计数。

do-while循环

除了while循环,在C语言中还有一种 do-while 循环。

do-while循环的一般形式为:

do{
    语句块
}while(表达式);

do-while循环与while循环的不同在于:它会先执行“语句块”,然后再判断表达式是否为真,如果为真则继续循环;如果为假,则终止循环。因此,do-while 循环至少要执行一次“语句块”。

用do-while计算1加到100的值:

 
  1. #include
  2. int main(){
  3. int i=1, sum=0;
  4. do{
  5. sum+=i;
  6. i++;
  7. }while(i<=100);
  8. printf("%d\n", sum);
  9. return 0;
  10. }

运行结果:
5050

注意 while(i<=100);最后的分号 ;,这个必须要有。

while循环和do-while各有特点,大家可以适当选择,实际编程中使用while循环较多。

C语言for循环(for语句)详解

除了while循环,C语言中还有 for 循环,它的使用更加灵活,完全可以取代 while 循环。

上节我们使用 while 循环来计算1加到100的值,代码如下:

 
  1. #include
  2. int main(){
  3. int i, sum=0;
  4. i = 1; //语句①
  5. while(i<=100 /*语句②*/ ){
  6. sum+=i;
  7. i++; //语句③
  8. }
  9. printf("%d\n",sum);
  10. return 0;
  11. }

可以看到,语句①②③被放到了不同的地方,代码结构较为松散。为了让程序更加紧凑,可以使用 for 循环来代替,如下所示:

 
  1. #include
  2. int main(){
  3. int i, sum=0;
  4. for(i=1/*语句①*/; i<=100/*语句②*/; i++/*语句③*/){
  5. sum+=i;
  6. }
  7. printf("%d\n",sum);
  8. return 0;
  9. }

在 for 循环中,语句①②③被集中到了一起,代码结构一目了然。

for 循环的一般形式为:

for(表达式1; 表达式2; 表达式3){
    语句块
}

它的运行过程为:
1) 先执行“表达式1”。

2) 再执行“表达式2”,如果它的值为真(非0),则执行循环体,否则结束循环。

3) 执行完循环体后再执行“表达式3”。

4) 重复执行步骤 2) 和 3),直到“表达式2”的值为假,就结束循环。

上面的步骤中,2) 和 3) 是一次循环,会重复执行,for 语句的主要作用就是不断执行步骤 2) 和 3)。

“表达式1”仅在第一次循环时执行,以后都不会再执行,可以认为这是一个初始化语句。“表达式2”一般是一个关系表达式,决定了是否还要继续下次循环,称为“循环条件”。“表达式3”很多情况下是一个带有自增或自减操作的表达式,以使循环条件逐渐变得“不成立”。


for循环的执行过程可用下图表示:
C语言入门教程,C语言学习教程(非常详细)第五章 循环结构与选择结构_第3张图片

我们再来分析一下“计算从1加到100的和”的代码:

 
  1. #include
  2. int main(){
  3. int i, sum=0;
  4. for(i=1; i<=100; i++){
  5. sum+=i;
  6. }
  7. printf("%d\n",sum);
  8. return 0;
  9. }

运行结果:
5050

代码分析:
1) 执行到 for 语句时,先给 i 赋初值1,判断 i<=100 是否成立;因为此时 i=1,i<=100 成立,所以执行循环体。循环体执行结束后(sum的值为1),再计算 i++。

2) 第二次循环时,i 的值为2,i<=100 成立,继续执行循环体。循环体执行结束后(sum的值为3),再计算 i++。

3) 重复执行步骤 2),直到第101次循环,此时 i 的值为101,i<=100 不成立,所以结束循环。

由此我们可以总结出for循环的一般形式:

for(初始化语句; 循环条件; 自增或自减){
    语句块
}

C语言for循环中的三个表达式

for 循环中的“表达式1(初始化条件)”、“表达式2(循环条件)”和“表达式3(自增或自减)”都是可选项,都可以省略(但分号;必须保留)。

1) 修改“从1加到100的和”的代码,省略“表达式1(初始化条件)”:

 
  1. int i = 1, sum = 0;
  2. for( ; i<=100; i++){
  3. sum+=i;
  4. }

可以看到,将i=1移到了 for 循环的外面。

2) 省略了“表达式2(循环条件)”,如果不做其它处理就会成为死循环。例如:

 
  1. for(i=1; ; i++) sum=sum+i;

相当于:

 
  1. i=1;
  2. while(1){
  3. sum=sum+i;
  4. i++;
  5. }

所谓死循环,就是循环条件永远成立,循环会一直进行下去,永不结束。死循环对程序的危害很大,一定要避免。

3) 省略了“表达式3(自增或自减)”,就不会修改“表达式2(循环条件)”中的变量,这时可在循环体中加入修改变量的语句。例如:

 
  1. for( i=1; i<=100; ){
  2. sum=sum+i;
  3. i++;
  4. }


4) 省略了“表达式1(初始化语句)”和“表达式3(自增或自减)”。例如:

 
  1. for( ; i<=100 ; ){
  2. sum=sum+i;
  3. i++;
  4. }

相当于:

 
  1. while(i<=100){
  2. sum=sum+i;
  3. i++;
  4. }


5) 3个表达式可以同时省略。例如:

for( ; ; )  语句

相当于:

while(1)  语句


6) “表达式1”可以是初始化语句,也可以是其他语句。例如:

 
  1. for( sum=0; i<=100; i++ ) sum=sum+i;


7) “表达式1”和“表达式3”可以是一个简单表达式也可以是逗号表达式。

 
  1. for( sum=0,i=1; i<=100; i++ ) sum=sum+i;

或:

 
  1. for( i=0,j=100; i<=100; i++,j-- ) k=i+j;


8) “表达式2”一般是关系表达式或逻辑表达式,但也可是数值或字符,只要其值非零,就执行循环体。例如:

 
  1. for( i=0; (c=getchar())!='\n'; i+=c );

又如:

 
  1. for( ; (c=getchar())!='\n' ; )
  2. printf("%c",c);

C语言break和continue用法详解(跳出循环)

使用while或for循环时,如果想提前结束循环(在不满足结束条件的情况下结束循环),可以使用break或continue关键字。

break关键字

在《C语言switch case语句》一节中,我们讲到了break,用它来跳出 switch 语句。

当 break 关键字用于 while、for 循环时,会终止循环而执行整个循环语句后面的代码。break 关键字通常和 if 语句一起使用,即满足条件时便跳出循环。

使用 while 循环计算1加到100的值:

 
  1. #include
  2. int main(){
  3. int i=1, sum=0;
  4. while(1){ //循环条件为死循环
  5. sum+=i;
  6. i++;
  7. if(i>100) break;
  8. }
  9. printf("%d\n", sum);
  10. return 0;
  11. }

运行结果:
5050

while 循环条件为 1,是一个死循环。当执行到第100次循环的时候,计算完i++;后 i 的值为 101,此时 if 语句的条件 i> 100 成立,执行break;语句,结束循环。

在多层循环中,一个 break 语句只向外跳一层。例如,输出一个4*4的整数矩阵:

 
  1. #include
  2. int main(){
  3. int i=1, j;
  4. while(1){ // 外层循环
  5. j=1;
  6. while(1){ // 内层循环
  7. printf("%-4d", i*j);
  8. j++;
  9. if(j>4) break; //跳出内层循环
  10. }
  11. printf("\n");
  12. i++;
  13. if(i>4) break; // 跳出外层循环
  14. }
  15.  
  16. return 0;
  17. }

运行结果:

1   2   3   4
2   4   6   8
3   6   9   12
4   8   12  16

当 j>4 成立时,执行break;,跳出内层循环;外层循环依然执行,直到 i>4 成立,跳出外层循环。内层循环共执行了4次,外层循环共执行了1次。

continue语句

continue 语句的作用是跳过循环体中剩余的语句而强制进入下一次循环。continue语句只用在 while、for 循环中,常与 if 条件语句一起使用,判断条件是否成立。

来看一个例子:

 
  1. #include
  2. int main(){
  3. char c = 0;
  4. while(c!='\n'){ //回车键结束循环
  5. c=getchar();
  6. if(c=='4' || c=='5'){ //按下的是数字键4或5
  7. continue; //跳过当次循环,进入下次循环
  8. }
  9. putchar(c);
  10. }
  11. return 0;
  12. }

运行结果:
0123456789↙
01236789

程序遇到while时,变量c的值为'\0',循环条件c!='\n'成立,开始第一次循环。getchar() 使程序暂停执行,等待用户输入,直到用户按下回车键才开始读取字符。

本例我们输入的是 0123456789,当读取到4或5时,if 的条件c=='4'||c=='5'成立,就执行 continue 语句,结束当前循环,直接进入下一次循环,也就是说putchar(c);不会被执行到。而读取到其他数字时,if 的条件不成立,continue 语句不会被执行到,putchar(c);就会输出读取到的字符。

break与continue的对比:break 用来结束所有循环,循环语句不再有执行的机会;continue 用来结束本次循环,直接跳到下一次循环,如果循环条件成立,还会继续循环。

C语言循环嵌套详解

在C语言中,if-else、while、do-while、for 都可以相互嵌套。所谓嵌套(Nest),就是一条语句里面还有另一条语句,例如 for 里面还有 for,while 里面还有 while,或者 for 里面有 while,while 里面有 if-else,这都是允许的。

if-else 的嵌套在《C语言if else语句》一节中已经进行了讲解,本节主要介绍循环结构的嵌套。

示例1:for 嵌套执行的流程。

 
  1. #include
  2. int main()
  3. {
  4. int i, j;
  5. for(i=1; i<=4; i++){ //外层for循环
  6. for(j=1; j<=4; j++){ //内层for循环
  7. printf("i=%d, j=%d\n", i, j);
  8. }
  9. printf("\n");
  10. }
  11. return 0;
  12. }

运行结果:
i=1, j=1
i=1, j=2
i=1, j=3
i=1, j=4

i=2, j=1
i=2, j=2
i=2, j=3
i=2, j=4

i=3, j=1
i=3, j=2
i=3, j=3
i=3, j=4

i=4, j=1
i=4, j=2
i=4, j=3
i=4, j=4

本例是一个简单的 for 循环嵌套,外层循环和内层循环交叉执行,外层 for 每执行一次,内层 for 就要执行四次。

在C语言中,代码是顺序、同步执行的,当前代码必须执行完毕后才能执行后面的代码。这就意味着,外层 for 每次循环时,都必须等待内层 for 循环完毕(也就是循环4次)才能进行下次循环。虽然 i 是变量,但是对于内层 for 来说,每次循环时它的值都是固定的。

示例2:输出一个4×4的整数矩阵。

 
  1. #include
  2. int main()
  3. {
  4. int i, j;
  5. for(i=1; i<=4; i++){ //外层for循环
  6. for(j=1; j<=4; j++){ //内层for循环
  7. printf("%-4d", i*j);
  8. }
  9. printf("\n");
  10. }
  11. return 0;
  12. }

运行结果:

1   2   3   4
2   4   6   8
3   6   9   12
4   8   12  16

外层 for 第一次循环时,i为1,内层 for 要输出四次 1*j 的值,也就是第一行数据;内层  for 循环结束后执行 printf("\n"),输出换行符;接着执行外层 for 的 i++ 语句。此时外层 for 的第一次循环才算结束。

外层 for 第二次循环时,i为2,内层 for 要输出四次 2*j 的值,也就是第二行的数据;接下来执行 printf("\n") 和 i++,外层 for 的第二次循环才算结束。外层 for 第三次、第四次循环以此类推。

可以看到,内层 for 每循环一次输出一个数据,而外层 for 每循环一次输出一行数据。

示例3:输出九九乘法表。

 
  1. #include
  2. int main(){
  3. int i, j;
  4. for(i=1; i<=9; i++){ //外层for循环
  5. for(j=1; j<=i; j++){ //内层for循环
  6. printf("%d*%d=%-2d ", i, j, i*j);
  7. }
  8. printf("\n");
  9. }
  10.  
  11. return 0;
  12. }

运行结果:

1*1=1
2*1=2   2*2=4
3*1=3   3*2=6   3*3=9
4*1=4   4*2=8   4*3=12  4*4=16
5*1=5   5*2=10  5*3=15  5*4=20  5*5=25
6*1=6   6*2=12  6*3=18  6*4=24  6*5=30  6*6=36
7*1=7   7*2=14  7*3=21  7*4=28  7*5=35  7*6=42  7*7=49
8*1=8   8*2=16  8*3=24  8*4=32  8*5=40  8*6=48  8*7=56  8*8=64
9*1=9   9*2=18  9*3=27  9*4=36  9*5=45  9*6=54  9*7=63  9*8=72  9*9=81

和示例2一样,内层 for 每循环一次输出一条数据,外层 for 每循环一次输出一行数据。

需要注意的是,内层 for 的结束条件是j<=i。外层 for 每循环一次,i 的值就会变化,所以每次开始内层 for 循环时,结束条件是不一样的。具体如下:

  • 当 i=1 时,内层 for 的结束条件为 j<=1,只能循环一次,输出第一行。
  • 当 i=2 时,内层 for 的结束条件是 j<=2,循环两次,输出第二行。
  • 当 i=3 时,内层 for 的结束条件是 j<=3,循环三次,输出第三行。
  • 当 i=4、5、6... 时,以此类推。


九九乘法表还有更多输出方式,请查看:C语言输出九九乘法表(5种解法)

页 > C语言入门 > 循环结构和选择结构

对C语言选择结构和循环结构的总结

c语言中常用的编程结构有三种(其它编程语言也是如此),它们分别是:

  • 顺序结构:代码从前往后依次执行,没有任何“拐弯抹角”,不跳过任何一条语句,所有的语句都会被执行到。
  • 选择结构:也叫分支结构。代码会被分成多个部分,程序会根据特定条件(某个表达式的运算结果)来判断到底执行哪一部分。
  • 循环结构:程序会重新执行同一段代码,直到条件不再满足,或者遇到强行跳出语句(break 关键字)。

选择结构

选择结构(分支结构)涉及到的关键字包括 if、else、switch、case、break,还有一个条件运算符? :(这是C语言中唯一的一个三目运算符)。其中,if...else 是最基本的结构,switch...case 和? :都是由 if...else 演化而来,它们都是为了让程序员书写更加方便。

你可以只使用 if,也可以 if...else 配对使用。另外要善于使用 switch...case 和? :,有时候它们看起来更加清爽。

if...else 可以嵌套使用,原则上嵌套的层次(深度)没有限制,但是过多的嵌套层次会让代码结构混乱。

循环结构

C语言中常用的循环结构有 while 循环和 for 循环,它们都可以用来处理同一个问题,一般可以互相代替。

除了 while 和 for,C语言中还有一个 goto 语句,它也能构成循环结构。不过由于 goto 语句很容易造成代码混乱,维护和阅读困难,饱受诟病,不被推荐,而且 goto 循环完全可以被其他循环取代,所以后来的很多编程语言都取消了 goto 语句,我们也不再讲解。

国内很多大学仍然讲解 goto 语句,但也仅仅是完成教材所设定的课程,goto 语句在实际开发中很难见到。

对于 while 和 do-while 循环,循环体中应包括使循环趋于结束的语句。

对于 while 和 do-while 循环,循环变量的初始化操作应该在 while 和 do-while 语句之前完成,而 for 循环可以在内部实现循环变量的初始化。

for 循环是最常用的循环,它的功能强大,一般都可以代替其他循环。

最后还要注意 break 和 continue 关键字用于循环结构时的区别:

  • break 用来跳出所有循环,循环语句不再有执行的机会;
  • continue 用来结束本次循环,直接跳到下一次循环,如果循环条件成立,还会继续循环。


此外,break 关键字还可以用于跳出 switch...case 语句。所谓“跳出”,是指一旦遇到 break,就不再执行 switch 中的任何语句,包括当前分支中的语句和其他分支中的语句;也就是说,整个 switch 执行结束了,接着会执行整个 switch 后面的代码。

 

你可能感兴趣的:(c语言,c语言)