C语言第二章分支与循环(上)

一.C语言结构

在日常生活中,会有三种结构的语句:顺序结构、循环结构、选择结构。这三种语句结构广泛运用在日常生活中。作为解决日常生活问题的编程语言,自然也会有相同与生活中的语句结构,下面我们就来探索一下吧!

二.选择结构:if语句

1.语法形式

if语句的语法形式如下:

if(表达式)

语句

具体含义是:如果表达式成立,即为真,则执行下面的语句,否则就不执行。在C语言中,语句结果:非0表示真,0表示为假。下面给出一个例子来进一步认识if语句。

cpp 复制代码
#include <stdio.h>
int main()
{
     int num = 0;
     scanf("%d", &num);
     if(num % 2 == 1)
         printf("%d 是奇数\n", num);
     return 0;
}

上述代码的意思是:先定义一个整型变量num,获取键盘输入值赋予num。如果num除以2余数为1,则打印:num时奇数这句话。整体代码的功能是判断输入的值是否为奇数。

左边图片是if语句的流程图,右边图片是判断是否为奇数的流程图。

2.else

(1)语句介绍

一个数字不是奇数,那么就是偶数了。上面我们实现了:判断一个数字是否为奇数,如果是则打印"是奇数",那如果不是呢?如果不是奇数的情况下,我们还想实现一些事情该怎们办?这时候就该用if-else语句了。下面展示if-else语句的语法形式:

if(表达式)

语句一

else

语句二

上述语句的意思是,如果表达式为真,则执行语句一。如果为假,则执行语句二。下面举例子熟悉if-else语句:

(2)代码练习

<1>判断奇偶数

题目介绍:输入一个整数,判断是否为奇数,如果是奇数打印是奇数,否则打印偶数。

cpp 复制代码
#include <stdio.h>
int main()
{
 int num = 0;
 scanf("%d", &num);
 if(num % 2 == 1)
     printf("%d 是奇数\n", num);
 else
     printf("%d 是偶数\n", num);
 return 0;
}

根据if-else 语句写出的判断奇偶数代码的解析:先定义一个整型变量num,用于接收输入的值,从而进行判断奇偶数。如果num除以2余数是1即num是奇数,则打印num是奇数;否则打印num是偶数。

<2>判断年龄

题目介绍:输入一个年龄,大于18岁就输出:成年,否则就输出:未成年。

cpp 复制代码
#include <stdio.h>
int main()
{
 int age = 0;
 scanf("%d", &age);
 if(age>=18)
     printf("成年\n");
 else
     printf("未成年\n");
 return 0;
}

(3)分支包含多条语句

if-else语句默认只能控制一条语句,比如下方代码:

cpp 复制代码
#include <stdio.h>
int main()
{
 int age = 0;
 scanf("%d", &age);
 if(age >= 18)
     printf("你变成大人了\n");
 printf("你开心吗\n");
 return 0;
}

上述代码中if语句下有两句语句。且无论age是否大于18,都会打印在屏幕上。这说明了if语句只能控制一条语句。下面对上面代码进行解释:先定义一个整型变量age,用于接收键盘输入的值,然后进入进行判断的if语句,如果age大于等于18,则打印"你变成大人了",然后出if 语句,遇到printf函数,便打印内部的参数:"你开心吗"。

因为if语句只能控制一条语句,所以当其包含多条语句时,就需要大括号把多条语句括起来。else语句也是相同的道理。下面给出代码示例:

cpp 复制代码
#include <stdio.h>
int main()
{
 int age = 0;
 scanf("%d", &age);
 if(age >= 18) 
 {
     printf("成年了\n");
     printf("可以谈恋爱了\n");
 }
 else  
 {
     printf("未成年\n");
     printf("不可以早恋哦\n");
 }
 return 0;
}

上述代码的解释:先定义一个整型变量age,用于接收键盘的输入值从而进行判断:如果age大于等于18,则打印:"成年了 可以谈恋爱了";如果没有满足age大于等于18这个条件,则打印:"未成年 不可以早恋哦"。

这里需要知道的是:当一些语句被大括号括起来,作为分支的结构,那么这些被括号括起来的语句就可以叫做:程序块或者复合语句。

(4)嵌套if语句

在日常生活中,往往不仅仅只有两层判断,有可能有多重判断。那么简单的单层if语句就不能满足需求。这时候就需要嵌套if语句。下面给出例子用于了解嵌套if语句:

<1>例子一

题目介绍:要求输入一个整数,判断输入的整数是0,还是正数或者负数。

cpp 复制代码
#include <stdio.h>
int main()
{
 int num = 0;
 scanf("%d", &num);
 if(num == 0)
     printf("输⼊的数字是0\n");
 else//起始
 if(num > 0) //这⾥的if 相当于嵌套在else语句中,形成了嵌套结构 
     printf("输⼊的数字是正数\n");
 else
     printf("输⼊的数字是负数\n");
//终止
 return 0;
}

上面代码中从注释可以看出,起始和终止 之间的部分就是嵌套的if语句。

上述代码的解释:先定义一个整型变量num,用于接收键盘输入的值。然后进行判断:num是否等于0,等于0则打印:"输入的数字是0";如果不是0,则进入嵌套的if语句,判断是否大于0,如果大于0,则打印:"输入的数字是正数"。如果不大于0,也不等于0,则进入else语句打印:"输入的数字是负数"。

<2>例子二

题目介绍:输入一个整数,如果是正数,再判断是奇数还是偶数,并输出;如果不是正数则输出:非正数。

cpp 复制代码
#include <stdio.h>
int main()
{
 int num = 0;
 scanf("%d", &num);
 if(num>0)
 {
     if(num%2 == 0)
         printf("偶数\n");
     else
         printf("奇数\n");
 }
 else
 {
     printf("⾮正数\n");
 }
 return 0;
}

上述代码第一个if语句后面大括号内的程序块为嵌套的if语句。

上述代码的解释:先定义一个整型变量num,用于接受键盘输入的值。从而进行判断:如果num不满足大于0,则打印非正数;如果满足,则进入嵌套的if语句,继续判断num除以2,余数是否为0,如果余数为0,则打印偶数;如果余数不为0,则打印奇数。

以上就是嵌套if语句的语法,有了嵌套if语句,就可以完成更多复杂逻辑的判断。下面来练习一个习题吧。

<3>练习题

题目介绍:输入一个人的年龄,如果年龄为18岁,打印"少年" ;如果年龄在18岁-44岁打印"青年"; 如果年龄在45岁-59岁打印"中老年" ;如果年龄在60岁*-89岁打印"老年" ;如果90岁及以上打印"老寿星"。下面是代码实践:

cpp 复制代码
//⽅法1 
#include <stdio.h>
int main()
{
 int age = 0;
 scanf("%d", &age);
 if(age<18)
     printf("少年\n");
 else if(age<=44)
     printf("⻘年\n");
 else if(age<=59)
     printf("中⽼年\n");
 else if(age<=89)
     printf("⽼年\n");
 else
     printf("⽼寿星\n");
 return 0;
}
cpp 复制代码
//方法二
#include <stdio.h>
int main()
{
 int age = 0;
 scanf("%d", &age);
 if(age<18)
 {
     printf("少年\n");
 }
 else 
 {
     if(age<=44)
     {
         printf("⻘年\n");
     }
     else 
     {
         if(age<=59)
         {
             printf("中⽼年\n");
         }
         else 
         {
             if(age<=89)
                 printf("⽼年\n");
             else
                 printf("⽼寿星\n");
         }
     }
 }
 return 0;
}

上述两个代码的解释:先定义一个整型变量age,用于接收键盘输入的值。从而进行判断:如果age小于18,则打印:"少年:;然后进入第一个嵌套if 语句,判断age是否小于等于44,如果满足则打印:"青年"······以此类推。

(5)悬空else问题

在正常写C语言代码的过程中,难免会遇到很多复杂的if-else语句在一个程序内部这种情况,这时候就会出现if-else语句配对问题,所以我们时刻应该记住else总是和最近的if语句匹配。下面给出例子来练习一下:

cpp 复制代码
#include <stdio.h>
int main()
{
 int a = 0;
 int b = 2;
 if(a == 1)
     if(b == 2)
         printf("hehe\n");
     else
         printf("haha\n");
 return 0;
}
//上述代码的打印结果使空内容(什么也不打印)

上述代码有很多的if-else语句,所以会有if-else语句配对问题。下面用大括号对代码进行处理:

cpp 复制代码
#include <stdio.h>
int main()
{
 int a = 0;
 int b = 2;
 if(a == 1)
 {
     if(b == 2)
         printf("hehe\n");
     else
         printf("haha\n");
 }
 return 0;
}

这样便可以更容易地看出if-else语句的配对情况。所以可以得出else语句总和距离最近的if语句配对,但也告诉了我们一个道理:在写代码的时候不要吝啬大括号,写的大括号可以提高代码的阅读性。

三.关系操作符

1.关系操作符的介绍

C语言用于比较关系的表达式,称为"关系表达式",里面使用的运算符就称为"关系运算符",主要有下面6个:

> 大于运算符

< 小于运算符

>= 大于等于运算符

<= 小于等于运算符

== 相等运算符

!= 不相等运算符

下面分别举六个运用了关系操作符的表达式的例子 :

a > b;

a < b;

a >= b;

a <= b;

a == b; //这里注意==和=是不一样的符号,前者是关系操作符,用于判断前后操作数是否相等;后者是赋值操作符,用于把后面操作数的值赋值给前面的操作数。

a != b;

2.关系操作符的原理

关系表达式通常返回0或者1,用于表示表达式的真假。在C语言中,0表示假,非0表示真。关系操作符常常用于if或者while语句中。

3.关系操作符注意事项

(1)分析

关系操作符需要避免的是:多个关系操作符不可以连用。例如下方代码:

i < j < k //左边示例的代码没有问题,编译器不会报错,但是使用起来不会达到预想的效果。因为关系表达式的运算顺序是从左至右。所以表达式可以化成(i<j)<k;又因为关系操作符运算时,返回值是0或者1,所以i<j如果为真,则该表达式的值就会变成1;为假就会变成0;剩下的运算就是k和0或者1比较大小了。

这样看来连写的表达式看起来的效果往往是词不达意,所以在今后书写代码时应该避免写连续的关系操作表达式。

那么我们怎样实现数学上的i < j < k 表达式呢?我们可以尝试下面的写法:

i < j && j < k //&&是并且的意思,这样就可以实现数学表达式i < j < k同样的效果了。

(2)证明

下面给出例题进行验证:

题目描述:我们输入一个年龄,如果年龄在18岁~36岁之间,我们输出青年。

cpp 复制代码
#include <stdio.h>
int main()
{
 int age = 0;
 scanf("%d", &age);
 if(18<=age<=36)
 {
     printf("⻘年\n");
 }
 return 0;
}

上述代码运行结果在我们输入10也会输出青年,我们可以改正代码 :

cpp 复制代码
#include <stdio.h>
int main()
{
 int age = 0;
 scanf("%d", &age);
 if(age>=18 && age<=36)
 {
     printf("⻘年\n");
 }
 return 0;
}

三.条件操作符

1.分析

条件操作符也叫做三目操作符(有三个操作数),形式如下:

表达式1 ?表达式2 :表达式3 //左边代码的意思是:当表达式1为真则整个表达式返回表达式2的值,否则返回表达式3的值。这个三目表达式像是把if语句缩短成了一句话。

下面给出例子:

cpp 复制代码
#include<stdio.h>
int main()
{
 int a = 0;
 int b = 0;
 scanf("%d", &a);
 if (a > 5)
     b = 3;
 else
     b = -3;
 printf("%d\n", b);
 return 0;
}
cpp 复制代码
改造后:
#include <stdio.h>
int main()
{
 int a = 0;
 int b = 0;
 scanf("%d", &a);
 b = a>5 ? 3:-3;
 printf("%d\n", b);
 return 0;
}

两种代码的效果是相同的,但是代码2比代码1更简洁。

2.练习题

下面给出一个练习题:

题目描述:使用条件表达式实现找两个数中较大值

代码实践:

cpp 复制代码
#include <stdio.h>
int main()
{
 int a = 0;
 int b = 0;
 scanf("%d %d", &a, &b);
 int m = a>b ? a : b;
 printf("%d\n", m);
 
 return 0;
}

四.逻辑操作符

逻辑运算符提供逻辑判断功能,用于构建更复杂的表达式,主要有下面三个运算符。

! :逻辑取反运算符(改变单个表达式的真假)。

&& :逻辑与运算符,就是并且的意思(两侧的表达式都为真,则为真,否则为假)。

|| :逻辑或运算符,就是或者的意思(两侧至少有⼀个表达式为真,则为真,否则为假)。

1.逻辑取反操作符:!

逻辑取反操作符的作用是把一个语句的真假取反,把本身为真命题的句子进行取反。比如flag为非0值,在C语言中为真命题,那么!falg为0值,在C语言中为假命题。下面给出代码验证:

cpp 复制代码
#include <stdio.h>
int main()
{
 int flag = 0;
 if(!flag)
 {
 printf("do something\n");
 }
 return 0;
}

上述代码的解释:先定义了一个变量flag,并且初始化为0.下面进入if语句,如果!flag为真则打印:"do something"因为falg为0,所以!flag为非0值,在C语言中为真,所以代码的结果是打印出来:"do something"

2.逻辑与运算符:&&

&& 就是逻辑与运算符,也是并且的意思, && 是⼀个双目操作符,使用的方式是 a&&b , && 两边的表达式都是真的时候,整个表达式才为真,只要有⼀个是假,则整个表达式为假。

代码例子:月份是3月到5月是春天,那使用代码怎么体现呢?

cpp 复制代码
int month = 0;
scanf("%d", &month);
if(month >= 3 && month <= 5)
{
 printf("春季\n");
}

上述代码的解释:当输入的月份介于3和5之间时,打印春季。

上述代码的month >= 3 && month <= 5和5>=month>=3,两句代码的效果是不一样的!!!

3.逻辑或操作符||

|| 就是或运算符,也就是或者的意思, || 也是⼀个双目操作符,使用的方式是 a || b , || 两边的表达式只要有⼀个是真,整个表达式就是真,两边的表达式都为假的时候才为假。

代码例子:月份是12月或者1月或者2月是冬天,那么我们怎么使用代码体现呢?

cpp 复制代码
int month = 0;
scanf("%d", &month);
if(month == 12 || month==1 || month == 2)
{
 printf("冬季\n");
}

4.逻辑运算符练习

输入⼀个年份year,判断year是否是闰年

闰年判断的规则:

  1. 能被4整除并且不能被100整除是闰年

  2. 能被400整除是闰年

cpp 复制代码
#include <stdio.h>
//代码1 
int main()
{
 int year = 0;
 scanf("%d", &year);
 if(year%4==0 && year%100!=0)
     printf("是闰年\n");
 else if(year%400==0)
     printf("是闰年\n");
 
 return 0;
}
//代码2 
int main()
{
 int year = 0;
 scanf("%d", &year);
 if((year%4==0 && year%100!=0) || (year%400==0))
     printf("是闰年\n");
 
 return 0;
} 

上述代码1的解释:先定义了一个整型变量year,用于接收键盘输入的年份。然后进入if语句,如果可以被4并且不可以被100整除的数字,就打印闰年。进入第二个if语句,如果可以被400整除就打印闰年。
上述代码2的解释:2和1的区别就是2把1的两个if语句用逻辑或操作符替换掉了,具体效果是一样的。

5.短路

C语言逻辑运算符还有⼀个特点,它总是先对左侧的表达式求值,再对右边的表达式求值,这个顺序是固定的。如果左边的表达式满足逻辑运算符的条件,就不再对右边的表达式求值。这种情况称为"短路"。

如前面的代码:if(month >= 3 && month<= 5) 表达式中&&的左操作数是 month >= 3 ,右操作数是 month<=5 ,当左操作数 month >= 3 的 结果是0的时候,即使不判断 month ,整个表达式的结果也是0(不是春季)。所以,对于&&操作符来说,左边操作数的结果是0的时候,右边操作数就不再执行。

对于 || 操作符是怎么样呢?我们结合前⾯的代码: if(month == 12 || month==1 || month == 2) 如果month==12,则不用再判断month是否等于1或者2,整个表达式的结果也是1(是冬季)。 所以, || 操作符的左操作数的结果不为0时,就无需执行右操作数。

像这种仅仅根据左操作数的结果就能知道整个表达式的结果,不再对右操作数进行计算的运算称为短路求值。

阅读下面代码,写出最后的结果:

cpp 复制代码
#include <stdio.h>
int main()
{
 int i = 0,a= 0,b= 2,c = 3,d= 4;
 i = a++ && ++b && d++;
 printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
 return 0;
}

上述代码的解释:上述代码考察了逻辑运算符短路的问题。a++为先用后加的自增运算,所以a++为0,逻辑且后面的运算将不会执行。故最后的答案为:a:1 b:2 c:3 d:4

五.switch语句

1.switch语句的介绍

除了 if 语句外,C语言还提供了 switch 语句来实现分支结构。switch 语句是一种特殊形式的if...else 结构,用于判断条件有多个结果的情况。它把多重 的 else if 改成更易用、可读性更好的形式。下面给出switch语句的语法形式:

cpp 复制代码
switch(表达式0)        //需要注意的是:switch后面的表达式0必须是整形表达式

case结果1:            //case后面的数字必须是整型常量表达式

表达式1

break;

case结果2

表达式2

break;

.......

default:

表达式n

上述语法形式中,表达式0计算的结果对应不同的case,对应的case执行下面的表达式。如果没有对应的值就执行default语句后的表达式n。

2.if语句和switch语句的对比

题目描述:输入任意一个整数值,计算除3之后的余数

代码实践:

cpp 复制代码
#include <stdio.h>
int main()
{
 int n = 0;
 scanf("%d", &n);
 if(n%3 == 0)
     printf("整除,余数为0\n");
 else if(n%3 == 1)
     printf("余数是1\n");
 else
     printf("余数是2\n");
 return 0;
}
cpp 复制代码
#include <stdio.h>
int main()
{
 int n = 0;
 scanf("%d", &n);
 switch(n%3)
 {
 case 0:                            //case和后面的整型常量表达式之间必须有空格
     printf("整除,余数为0\n"); 
     break;                         //每个case语句结束必须有break,这样才能跳出整个switch语句
 case 1:
     printf("余数是1\n"); 
     break;
 case 2:
     printf("余数是2\n"); 
     break;
 }
 return 0;
}

3.switch语句中的break语句

前面的代码,我们将去掉break语句,来查看代码运行的结果:

cpp 复制代码
#include <stdio.h>
int main()
{
 int n = 0;
 scanf("%d", &n);
 switch(n%3)
 {
 case 0:
     printf("整除,余数为0\n"); 
 case 1:
     printf("余数是1\n"); 
 case 2:
     printf("余数是2\n"); 
 }
 return 0;
}

可以看出上述代码去掉break语句后,本应该只打印:"余数是1"即可,但是代码结果也打印出了:"余数是2" 。

原因是 switch 语句也是分支效果的,只有在 switch 语句中使用 break 才能在跳出 switch 语 句,如果某⼀个 case 语句的后边没有 break 语句,代码会继续往下执行,有可能执行其他 case 语句中的代码,直到遇到 break 语句或者 switch 语句结束。就比如上面的代码就执行了 case 2 中的语句。 所以在 switch 语句中 break 语句是非常重要的,能实现真正的分支效果。当然,break 也不是每个 case 语句都得有,这就得根据实际情况来看了。下面举一个不需要break语句的例子:

题目1描述:输入一个1~7的数字,打印对应的星期几例如: 输入:1输出:星期一;输入:2 输出:星期二;输入:3 输出:星期三 ......

代码实践:

cpp 复制代码
#include <stdio.h>
int main()
{
 int day = 0;
 scanf("%d", &day);
 switch(day)
 {
 case 1:
     printf("星期⼀\n");
     break;
 case 2:
     printf("星期⼆\n");
     break;
 case 3:
     printf("星期三\n");
     break; 
 case 4:
     printf("星期四\n");
     break; 
 case 5:
     printf("星期五\n");
     break;
 case 6:
     printf("星期六\n");
     break;
 case 7:
     printf("星期天\n"); 
     break;
 }
 return 0;
}

题目2描述:输入1~5,输出的是"工作日" 输入6~7,输出"休息日"

代码实践:

cpp 复制代码
#include <stdio.h>
int main()
{
 int day = 0;
 scanf("%d", &day);
 switch(day)
 {
 case 1:
 case 2:
 case 3:
 case 4:
 case 5:
     printf("⼯作⽇\n");
     break;
 case 6:
 case 7:
     printf("休息⽇\n");
     break;
 }
 return 0;
}

上述两个代码演示可以看出:switch语句中不一定非得有break语句,在日常生活中,我们可以根据实际需求来决定break语句是否存在?

4.switch语句中的default

在使用 switch 语句的时候,我们经常可能遇到一种情况,比如 switch 后的表达式中的值无法匹配代码中的 case 语句的时候,这时候要不就不做处理,要不就得在 switch 语句中加入default语句。

就比如前面做的打印星期的练习,如果 day 的输入不是1~7的值,如果我们要提示:输入错误。

cpp 复制代码
#include <stdio.h>
int main()
{
int day = 0;
 scanf("%d", &day);
 
 switch(day)
 {
 case 1:
 case 2:
 case 3:
 case 4:
 case 5:
     printf("⼯作⽇\n");
     break;
 case 6:
 case 7:
     printf("休息⽇\n");
     break;
 default:
     printf("输⼊错误\n");
     break;
 }
 return 0;
}

5.switch语句中case和default的顺序问题

在 switch 语句中 case 语句和 default 语句有要求顺序吗?default 只能放在最后吗?

其实,在 switch 语句中 case 语句和 default 语句是没有顺序要求的,只要你的顺序是满足实际需求的就可以。不过我们通常是把 default 语句放在最后处理的。

六.while循环

C语言中提供了三种循环语句,分别是while语句、for语句、do while语句,下面我们将一一讲解,先从while循环开始:

1.while语句的语法形式

while(表达式)

语句; //左边语法形式的意思是当表达式为真时,执行语句;执行完之后继续判断表达式是否为真,若为假则跳出循环;若为真则继续执行语句,以此类推...

cpp 复制代码
#include <stdio.h>
int main()
{
 while(1)
     printf("hehe\n"); //while后边的条件满⾜,死循环的打印hehe 
 return 0;
}

上述代码的解释:因为1恒为真,所以一直不间断的打印:"hehe"。

2.while语句的执行流程

上述为while语句执行的流程图,可以看出:while循环先是判断表达式的真假,若为真,则执行语句的程序;若为假,则跳出循环。

3.while循环的代码实践

(1)练习一

题目描述:在屏幕上打印1~10的值

代码实践:

cpp 复制代码
#include <stdio.h>
int main()
{
 int i = 1;
 while(i<=10)
 {
     printf("%d ", i);
     i = i+1;
 }
 return 0;
}

上述代码的解释:先定义一个整型变量i,当i小于等于10就进入while循环,每次循环i自增1。当i自增到11时,循环终止。于是上述代码就打印出了1-10的数字。

(2)练习二

题目描述:输入⼀个正的整数,逆序打印这个整数的每⼀位

例如: 输入:1234,输出:4321

输入: 521,输出:125

代码实践:

cpp 复制代码
#include <stdio.h>
int main()
{
 int n = 0;
 scanf("%d", &n);
 while(n)
 {
     printf("%d ", n%10);        //一个数对10求余数是该数的个位上的数字
     n /= 10;                    //每次将该数自除以10,可以少去该数的最低位
 }
 return 0;
}

上述代码的解释:定义一个整型变量,用于接收键盘输入的值。如果输入的值为非0情况下,就进入while循环,打印n%10这个数,每次打印完之后n自除以10。以此类推就打印出了数字的逆序。

七.for循环

1.for语句的语法形式

for(语句1;语句2;语句3)

语句4; //语句1是循环变量的初始化,语句2是循环结束条件的判断,语句3是循环变量的调整。

2.for语句的执行流程

上述为for循环语句执行的流程图:先进行语句1:循环变量的初始化;然后进行语句2:循环进行的判断语句,判断是否满足进入循环的条件;下一步执行语句4;执行结束后下一步执行语句3:循环变量的调整。调整结束后,执行语句2进行循环条件的判断,如果满足条件就执行语句2。以此类推.....

所以可以得出for循环执行的顺序是:语句1->语句2->语句4->语句3->语句2->语句4->语句3->语句2->语句4->语句3......

3.for循环的代码实践

(1)练习一

题目描述:在屏幕上打印1-10的数字

代码实践:

cpp 复制代码
#include <stdio.h>
int main()
{
 int i = 0;
 for(i=1; i<=10; i++)
 {
     printf("%d ", i);
 }
 
 return 0;
}

上述代码的解释:先定义一个循环变量i,然后当i小于等于10,进入for循环内,然后执行循环语句打印i的值,打印完成后i自增1。然后判断i是否小于等于10,若为真,则进入循环;若为假,则跳出循环。以此类推就可以在屏幕上打印出1-10的数字了。

(2) 练习二

题目描述:计算1~100之间3的倍数的数字之和

代码实践:

cpp 复制代码
#include <stdio.h>
int main()
{
 int i = 0;
 int sum = 0;
 for(i=1; i<=100; i++)
 {
     if(i % 3 == 0)
     sum += i;
 }
 printf("%d\n", sum);
 return 0;
}

上述代码的解释:先定义了循环变量i和整型变量sum,分别用于进入循环和累计求和。然后利用循环遍历1-100所有的数字,然后用if语句判断是否是3的倍数,如果是就累加到sum上,最后得到的sum就是结果。但是代码不够简便,我们可以直接遍历3的倍数,直接进行累加,这样就可以省去判断的代码。

代码优化:

cpp 复制代码
#include <stdio.h>
int main()
{
 int i = 0;
 int sum = 0;
 for(i=3; i<=100; i+=3)
 {
     sum += i;
 }
 printf("%d\n", sum);
 return 0;
}

4.while循环和for循环的区别

比较:for 和 while 在实现循环的过程中都有初始化、判断、调整这三个部分,但是 for 循环的三个部分非常集中,便于代码的维护,而如果代码较多的时候,while 循环的三个部分就比较分散,所以从形式上 for 循环要更优一些。

八.do while循环

1.do while语句的语法形式

在三种循环中,do while循环是用的最少的一个循环,它的语法形式如下:

do

语句;

while(表达式); //左边语法形式的意思是先执行一次语句,然后判断表达式是否为真,若为真则继续执行语句;如果为假,就终止循环。

2.do while语句的执行流程

上述do while语句的执行流程可以得出:do while语句不论条件是否满足循环条件,必执行一次循环语句,执行完之后,才对循环条件进行判断,条件为真则继续执行;反之,终止循环。 所以在 do while 语句中循环体是至少执行一次的,这是 do while 循环比较特殊的地方。

3.do while循环的代码实践

(1)练习一

题目描述:在屏幕上打印1-10的数字

代码实践:

cpp 复制代码
#include <stdio.h>
int main()
{
 int i = 1;
 do
 {
     printf("%d ", i);
     i = i + 1;
 }while(i<=10);
 
 return 0;
}

上述代码的解释:先定义一个循环变量i,然后执行循环语句:打印i的值,打印完成之后,i自增1,下来进入循环条件的判断,判断为真,则继续执行循环语句;判断为假,则循环终止。以此类推就可以在屏幕上打印出1-10的数字了。

(2)练习二

题目描述:输入一个正整数,计算这个整数是几位数?

例如: 输入:1234 ;输出:4

输入:12 ; 输出:2

代码实践:

cpp 复制代码
#include <stdio.h>
int main()
{
 int n = 0;
 scanf("%d", &n);
 int cnt = 0;
 do
     {
         cnt++;
         n = n / 10;
     }
     while (n);
 printf("%d\n", cnt);
 return 0;
 }

上述代码的解释:先定义一个整型变量n表示键盘输入的数字。再定义一个变量用于表示该数的位数。下来进入do while 循环先执行循环语句,将cnt变量自增1。然后对n自除以10,从而去掉n的最低位。以此类推当n变成0时,循环终止,得到的cnt就是键盘输入的数字位数。

九.break和continue语句

在循环执行的过程中,如果某些状况发生的时候,需要提前终止循环,这是非常常见的现象。C语言中提供了 break 和 continue 两个关键字,就是应用到循环中的。

• break 的作用是用于永久的终止循环,只要 break 被执行,直接就会跳出循环,继续往后执 行。

• continue 的作用是跳过本次循环中continue 后边的代码,在for 循环和 while 循环中有所差异的。

1.while循环中的break和continue语句

(1)break语句

cpp 复制代码
#include <stdio.h>
int main()
{
 int i = 1;
 while(i<=10)
 {
     if(i == 5)
     break;//当i等于5后,就执⾏break,循环就终⽌了 
     printf("%d ", i);
     i = i+1;
 }
 return 0;
}

上述代码的解释:打印了1,2,3,4后,当i等于5的时候,循环在 break 的地方终止,不再打印,不再循环。所以 break 的作用就是永久的终止循环,只要 break 被执行, break 外的第⼀层循环就终止了。 那以后我们在循环中,想在某种条件下终止循环,则可以使用break 来完成我们想要的效果。

(2)continue语句

cpp 复制代码
#include <stdio.h>
int main()
{
 int i = 1;
 while(i<=10)
 {
     if(i == 5)
     continue;
             //当i等于5后,就执⾏continue,直接跳过continue的代码,去循环的判断的地⽅ 
             //因为这⾥跳过了i = i+1,所以i⼀直为5,程序陷⼊和死循环 
     printf("%d ", i);
     i = i+1;
 }
 return 0;
}

上述代码的执行结果为1 2 3 4,然后程序就陷入了死循环,光标一直在闪烁,但是没有任何实质性的操作

上述代码的解释:continue 可以帮助我们跳过某一次循环 continue 后边的代码,直接到循环的判断部分,进行下一次循环的判断,如果循环的调整是在 continue 后边的话,可能会造成死循环。

2.for循环中的break和continue语句

(1)break语句

cpp 复制代码
#include <stdio.h>
int main()
{
 int i = 1;
 for(i=1; i<=10; i++)
 {
     if(i == 5)
     break;
     printf("%d ", i);
 }
 return 0;
}

上述代码的解释: for 循环中的 break 也是用于终止循环的,不管循环还需要循环多少次,只要执行到了 break语句 ,循环就彻底终止。

(2)continue语句

cpp 复制代码
#include <stdio.h>
int main()
{
 int i = 1;
 for(i=1; i<=10; i++)
 {
     if(i == 5)
     continue;//这⾥continue跳过了后边的打印,来到了i++的调整部分 
     printf("%d ", i);
 }
 return 0;
}

上述代码的解释:在 for 循环中 continue 的作用是跳过本次循环中 continue 后的代码,直接去到循环的调整部分。未来当某个条件发生的时候,本次循环无需再执行后续某些操作的时候,就可以使用 continue 语句来实现。

(3) 两种循环continue的区别

上述图片可以看出来:while循环的continue直接跳到循环条件的判断表达式位置;而for循环的continue将循环跳到循环变量调整的表达式位置。

3.do while循环中的break和continue语句

do while循环中的break和continue语句和while循环的一模一样 ,下面给出两个代码:

cpp 复制代码
#include <stdio.h>
int main()
{
 int i = 1;
 do
     {
         if(i == 5)
         break;
         printf("%d ", i);
         i = i + 1;
     }while(i<=10);
return 0;
}

上述代码的解释:当i等于5时,不打印5,跳出整个循环。

cpp 复制代码
#include <stdio.h>
int main()
{
 int i = 1;
 do
 {
     if(i == 5)
     continue;
     printf("%d ", i);
     i = i + 1;
 }while(i<=10);
return 0;
}

上述代码的解释:当i等于5时,跳出本次循环到循环条件的判断表达式位置处。因此也跳过了循环变量的自增,导致上述代码的执行结果为1 2 3 4,然后程序就陷入了死循环,光标一直在闪烁,但是没有任何实质性的操作。

这里需要注意的是:将循环变量自增代码写在continue可以规避上述情况。

十.循环的嵌套

题目描述:找出100~200之间的素数,并打印在屏幕上。

代码实践:

cpp 复制代码
#include <stdio.h>
int main()
{
 int i = 0;
                                 //循环产⽣100~200的数字 
 for(i=100; i<=200; i++)
 {
                                 //判断i是否为素数 
                                 //循环产⽣2~i-1之间的数字 
     int j = 0;
     int flag = 1;               //假设i是素数 
     for(j=2; j<i; j++)
     {
         if(i % j == 0)
         {
             flag = 0;
             break;
         }
     }
 if(flag == 1)
     printf("%d ", i);
 }
 return 0;
 }

上述代码的解释:素数是只能被1和它本身整除的数相当于质数。先定义一个循环变量i,然后遍历100-200之间的数定为i,得到100-200之间的数字之后,然后遍历从2到该数之间的所有数定为j,当数字i能被j中的一个数整除时,就说明:该数不是素数,跳出此次循环。进行下一个数i的判断,以此类推......

十一.go to语句

C语言提供了一种非常特别的语法,就是 goto 语句和跳转标号,goto 语句可以实现在同一个函数内跳转到设置好的标号处。

代码实践:

cpp 复制代码
#include <stdio.h>
int main()
{
 printf("hehe\n");
 goto next;
 printf("haha\n");
 
next:
 printf("跳过了haha的打印\n"); 
 return 0;
}

上述代码的解释:先打印hehe然后执行go to语句,跳到next的位置打印:"跳过了haha的打印"

goto 语句如果使用的不当,就会导致在函数内部随意乱跳转,打乱程序的执行流程,所以我们的建议是能不用尽量不去使用;但是 goto 语句也不是⼀无是处,在多层循环的代码中,如果想快速跳出使用 goto 就非常的方便。

cpp 复制代码
for(...)
{
     for(...)
     {
         for(...)
         {
             if(disaster)
             goto error;
         }
      }
 }
error:
.........

本来 for 循环想提前退出得使用break ,但是一个 break 只能跳出一层 for 循环,如果3层循环嵌套就得使用3个 break 才能跳出循环,所以在这种情况下我们使用 goto 语句就会更加的快捷。