上一篇中提到:
流程控制 1.顺序结构 2.选择结构 3.循环结构
第三部分
3.循环结构
▶定义
某些代码会被重复执行
循环之for
①for (重点讲)
▶格式
for(1; 2; 3)
语句A
顺序: 1 2 A 3
执行3表示循环一次结束
是否执行下次循环看2是否成立,若不成立,跳出循环
首先明确一点:
笔记<2>中说过 if 控制一个语句,for也是如此
所以下图中⑤不受for的控制
下图中的for只需看前两行
▶循环实现顺序(重要)
▷执行①,②条件成立,进入循环,执行④,再执行③,③执行完标志着一次循环结束
▷是否执行下一次的循环要看②是否成立,若成立,则执行循环,执行④,再执行③,③执行完标志着一次循环结束
自己跟着图顺一遍,再看图下面具体的执行步骤,记忆的会更牢固(一定要思考)
依照上图,若设sum初始值为0
代码中顺序为:
i=1 1<=4 √ sum=1+0→1 i=1+1→2
i=2 3<=4 √ sum=2+1→3 i=2+1→3
i=3 3<=4 √ sum=3+3→6 i=3+1→4
i=4 4<=4 √ sum=6+4→10 i=4+1→5
i=5 5<=4 X 不成立 循环结束 sum为10
▶for循环的最简单的用法
例:求1-10的奇数和
#include <stdio.h>
int main()
{
int i;
for(i=0;i<4;++i)
printf("喵喵喵喵\n");
return 0;
}
回顾笔记<2>中“如何看懂一个程序”的三个步骤: 流程→每个语句的功能→试数
尝试计算下列代码中i和sum的值
#include <stdio.h>
int main()
{
int i;
int sum=0;
for(i=1;i<10;i+=2) //假设将中间i<10改成i<10000 则计算1-10000的奇数和
{ //{ }内只有一句,删掉并不影响程序的执行,但未了直观,加上最好
sum=sum+i; //本行换成 printf("今天我很高兴!\n"); 可以发现,共循环了五次
}
printf("i=%d\n",i);
printf("sum=%d\n",sum);
return 0;
}
/*----输出结果-----------
i=11
sum=25
-------------------------*/
▶for和if的嵌套使用
例一:范围问题
下列代码循环了几次?
#include <stdio.h>
int main()
{
int i;
for(i=0;i<4;++i)
printf("喵喵喵喵\n");
return 0;
}
/*----输出结果-----------
喵喵喵喵
喵喵喵喵
喵喵喵喵
喵喵喵喵
-------------------------*/
答:共4次
因此,将for中语句进行修改
.将i<4的条件修改为i<10000,则循环了10000次
.将i=0;i<4; 的条件改为i=5;i<8; 则循环了3次
.将i=0;i<4; 的条件改为i=5;i<90; 则循环了85次
▷代码添加一行输出,结果为?
#include <stdio.h>
int main()
{
int i;
for(i=0;i<4;++i)
printf("喵喵喵喵\n");
printf("哈哈哈哈\n");
return 0;
}
/*----输出结果-----------
喵喵喵喵
喵喵喵喵
喵喵喵喵
哈哈哈哈
-------------------------*/
▷代码for的语句添加{ },结果为?
#include <stdio.h>
int main()
{
int i;
for(i=0;i<4;++i)
{
printf("喵喵喵喵\n");
printf("哈哈哈哈\n");
}
return 0;
}
//一定注意是交替输出
/*----输出结果-----------
喵喵喵喵
哈哈哈哈
喵喵喵喵
哈哈哈哈
喵喵喵喵
哈哈哈哈
喵喵喵喵
哈哈哈哈
-------------------------*/
例二:求1-100的和
#include <stdio.h>
int main()
{
int i;
int sum=0;
for(i=1;i<=100;++i) //若为1+2+..+10最终结果为55
sum=sum+i;
printf("sum=%d\n",sum);
return 0;
}
/*----输出结果-----------
sum=5050
-------------------------*/
例三:求1-100所有能被3整除的数字之和
#include <stdio.h>
int main()
{
int i;
int sum=0;
for(i=3;i<=100;++i) //若想检验代码是否正确,可将i<=100改为i<=12尝试运行。
{
if(i%3==0)//如果i能被3整除
sum+=i;
}
printf("sum=%d\n",sum);
return 0;
}
/*----输出结果-----------
sum=1683
-------------------------*/
若将代码printf的位置进行调整,结果为?
#include <stdio.h>
int main()
{
int i;
int sum=0;
for(i=3;i<=10;++i) //为更好讲解换成1-10的范围
{
if(i%3==0)//如果i能被3整除
sum=sum+i;
printf("sum=%d\n",sum);
}
return 0;
}
/*----输出结果-----------
sum=3
sum=3
sum=3
sum=9
sum=9
sum=9
sum=18
sum=18
-------------------------*/
流程(最关键):
▷执行①,②条件成立,进入循环,执行④,④成立则执行⑤,⑤后执行⑥,⑥后执行③,③执行完标志着一次循环结束
但是,若进入循环后,④不成立,则执行⑥,⑥后执行③,③执行完标志着一次循环结束。
▷是否执行下一次的循环要看②是否成立,若成立,则执行循环,执行④,再判断④是否成立,来确认下一步的执行
因此:
若所有条件都成立,循环一次的顺序为:①②④⑤⑥③
若 if 的条件不成立,循环一次的顺序为:①②④⑥③
i为3时,i<=10 √ i%3==0 √ sum=0+3=3 ++i后i为4 输出3
i为4时,i<=10 √ i%3==0 X sum不执行 ++i后i为5 输出3(以前的值)
i为5时,i<=10 √ i%3==0 X sum不执行 ++i后i为6 输出3(以前的值)
i为6时,i<=10 √ i%3==0 √ sum=6+3=9 ++i后i为7 输出9
i为7时,i<=10 √ i%3==0 X sum不执行 ++i后i为8 输出9(以前的值)
i为8时,i<=10 √ i%3==0 X sum不执行 ++i后i为9 输出9(以前的值)
i为9时,i<=10 √ i%3==0 √ sum=9+9=18 ++i后i为10 输出18
i为10时,i<=10 √ i%3==0 X sum不执行 ++i后i为11 输出18(以前的值)
i为11时,i<=10 X 条件不成立,循环结束
学for循环的思路,思维方式很重要
先执行什么后执行什么一定要捋清楚
掌握如何看懂程序(动笔写)
作业:4个程序
求1-100之间的奇数之和
求1-100中间的奇数的个数
求1-100中间的奇数的平均值
求1-100之间的奇数之和与偶数之和
▶强制类型转换和对初学者很重要要求和程序讲解
作业答案:
求1-100之间的奇数之和
#include <stdio.h>
int main()
{
int i;
int sum =0;
for(i=1;i<101;++i)
{
if(i%2==1)
sum+=i; //sum=sum+i
}
printf("sum=%d\n",sum);
return 0;
}
/*----输出结果-----------
sum=2500
-------------------------*/
求1-100中间的奇数的个数
#include <stdio.h>
int main()
{
int i;
int cnt=0;//个数一般用cnt表示 (count)
for(i=1;i<101;++i)
{
if(i%2==1)
++cnt;
}
printf("cnt=%d\n",cnt);
return 0;
}
/*----输出结果-----------
cnt=50
-------------------------*/
补充:将“求1-100之间的奇数之和”、“求1-100中间的奇数的个数”两个问题用一段代码表示出来:
#include<stdio.h>
int main()
{
int i;
int sum=0;
int cnt=0;
for(i=1;i<101;++i)
{
if(i%2==1)
{ //一定要加{ },若不加,当if不成立,仍会执行++cnt,结果会cnt为100,导致出错
sum+=i;
++cnt;
}
}
printf("sum=%d\n",sum);
printf("cnt=%d\n",cnt);
return 0;
}
/*----输出结果-----------
sum=2500
cnt=50
-------------------------*/
求1-100中间的奇数的平均值
#include <stdio.h>
int main()
{
int i;
int sum=0;
int cnt=0;
float avg;//average的缩写
for(i=1;i<101;++i) //条件中的i<101也可替换为i<=100
{
if(i%2==1)
{
sum+=i;
++cnt;
}
}
avg=1.0*sum/cnt; //1.0是默认的double类型
printf("sum=%d\n",sum);
printf("cnt=%d\n",cnt);
printf("avg=%f\n",avg);
return 0;
}
/*----输出结果-----------
sum=2500
cnt=50
avg=50.000000
-------------------------*/
求1-100之间的奇数之和与偶数之和
#include <stdio.h>
int main()
{
int i;
int sum1=0; //奇数和
int sum2=0; //偶数和
for(i=1;i<101;++i)
{
if(i%2==1)
{
sum1 += i;
}
else
{
sum2 += i;
}
}
printf("奇数和=%d\n",sum1);
printf("偶数和=%d\n",sum2);
return 0;
}
/*----输出结果-----------
奇数和=2500
偶数和=2550
-------------------------*/
练习:1+1/2+1/3+...+1/100
#include <stdio.h>
int main()
{
int i;
float sum=0; //浮点型
for(i=1;i<=100;++i)
{
sum=sum + 1.0/i; //也可写为sum=sum + 1/(float)i;,但前面那个最简单
//sum=sum + (float)(1/i)这样写是不对的
}
printf("sum=%f\n",sum); //float型必须用%f输出
return 0;
}
先看懂程序→模仿程序
一开始学的时候写不出来很正常,看懂背会,模仿多了就会了
想看懂程序,要培养“三步看程序”的方法,前两步都会,还是看不懂就要关注第三步:试数
试数详细步骤举例
试数时注意:
- 不要问为什么,就把自己当做计算机,一步一步去执行
- 不要把某一步省略了
- 写的时候写整齐
1-> i=1 1<=100 成立
sum=0+1/1.0=1 ++i i=2
2-> i=2 2<=100 成立
sum=1+1/2.0 ++i i=3
3-> i=3 3<=100 成立
sum=1+1/2.0+1/3.0 ++i i=4
......依此类推,一般写5步就够了
▶浮点数的存储所带来的问题
#include <stdio.h>
int main()
{
float i;
float sum=0;
for(i=1.0;i<=100;++i)
{
sum=sum + 1/i;
}
printf("sum=%f\n",sum);
return 0;
}
输出结果跟上面的结果一致,所以不正确,循环中更新的变量(float i)不能定义为浮点型
float 和 double 都不能保证可以精确的存储一个小数
例如x=6.234,可能存为x=6.23339
举例一:有一个浮点型变量x,如何判断x的值是否为零
if(0 == x)
是零
else
不是零
上述做法错误,因为它的是一个近似值
举例二:为什么循环中更新的变量不能定义成浮点型?
浮点型为非准确存储
自增时,i<=100,i和100进行比较,若为1/i,最终结果可能为100.00001,导致这一步就不会被执行进去
(如果这句话看不懂,可去看老师本节课的讲解)
if(|x-0.000001|<0.000001)
是
else
不是
▶多层for循环嵌套使用时的执行顺序问题(重难点)
形式一:
a行 for(1; 2; 3)
b行 for(4; 5; 6)
c行 A;
d行 B;
上面这四行,整体来看是两个语句
bc行是一个语句,bc行是a行中的语句,所以abc看做是一个语句,d行是第二个语句。
1→ 2 ,2成立则执行bc部分(4→ 5 → A→ 6),bc只有在5不成立的情况下才会返回到a。
执行顺序
语句全部成立:1 → 2→ 4 → 5→ A→ 6 → 5→ A→ 6 ..
5不成立执行3 → 2→ 4→ 5→ A→ 6....
6之后绝对不可能到B,退出循环(2不成立时)才会到B
一定一定一定一定要理解!
形式二:
for(1; 2; 3)
for(4; 5; 6)
{
A;
B;
}
整体是一个语句
形式三:
for(1; 2; 3)
A;
for(4; 5; 6)
B;
整体是两个语句
形式四:
for(1; 2; 3)
{
A;
B;
for(4; 5; 6)
C;
}
整体是一个语句
形式五:
for(7; 8; 9)
for(1; 2; 3)
{
A;
B;
for(4; 5; 6)
C;
}
整体是一个语句
▶进制
▷什么叫n进制
逢n进一
n进制的范围中没有n
二进制 逢二进一 范围为0 1 没有2
十进制 逢十进一 范围为0-9 没有10
▷把r进制转换为十进制
二进制转换为十进制,从右向左依次标位2的n次方,上下相乘然后相加
八进制转换为十进制,从右向左依次标位8的n次方,上下相乘然后相加
▷把十进制转换为r进制
十进制转二进制:除二取余 商为0后,余数从下往上写
十进制转八进制:除八取余 商为0后,余数从下往上写
▷不同进制所代表的数值之间的关系
十进制的3981转换为十六进制是 F8D ,二者所代表的本质都是同一个数字。
▶运算符补充
自增自减
自增
前自增 ++i
后自增 i++
前自增和后自增的异同:
相同: 最终都使i的值加1例子
#include <stdio.h>
int main()
{
int i;
int j;
int k;
int m;
i=j=3; //等价与i=3,j=3
k=i++;
m=++j;
printf("i=%d,j=%d,k=%d,m=%d",i,j,k,m);
return 0;
}
/*----输出结果-----------
i=4,j=4,k=3,m=4
-------------------------*/
不同:
前自增整体表达式的值是i加1之后的值
后自增整体表达式的值是i加1之前的值
为什么会出现自增:
代码更精炼
自增的速度更快
学习自增要明白的几个问题:
1.我们编程时应该尽量屏蔽掉前自增和后自增的差别
2.自增表达式最好不要作为一个更大的表达式的一部分来使用
或者说
i++和++i单独成一个语句,不要把它作为一个完整复合语句的一部分来使用
例一:int n =i++ + ++i + i + i++
//这样写不但是不规范的代码,而且是不可移植的代码(换一个机器,结果可能就不一样)
例二:printf("%d %d %d",i++,++i,i);
//理由同上,是一种不好的写代码习惯,其他人也看不懂
自减同上
三目运算符
格式:
形如: A ? B : C
等价于: if(A)
B;
else
C;
例子
#include <stdio.h>
int main()
{
int i;
i=(3>2 ? 5 : 1);//若改为0>2 结果为1
printf("%d\n",i) ;
return 0;
}
/*----输出结果-----------
5
-------------------------*/
逗号表达式
格式
A ,B ,C ,D
功能: 从左到右执行
例一
#include <stdio.h>
int main()
{
int i;
i=(3, 2, 5, 6);
printf("%d\n",i) ;
return 0;
}
/*----输出结果-----------
6
-------------------------*/
例二
#include <stdio.h>
int main()
{
int i;
int j=2;
i=(j++, ++j, j+2, j-3); //j+2不等于j=j+2
printf("%d\n",i) ;
return 0;
}
/*----输出结果-----------
1
-------------------------*/
复习多个for循环嵌套使用时执行顺序
格式一:
for(1; 2; 3)
A;
B;
1永远只执行一次
1之后执行2,2成立执行A,A之后执行3,3执行后标记着一次循环结束
是否再次循环需在此执行2,看条件是否成立,若成立,继续上面步骤
若2不成立,退出循环,执行B.
格式二:
for(1; 2; 3)
for(4; 5; 6)
A;
B;
整体分为两个语句
前三行为第一个,第四行为第二个语句
顺序:
l后执行2
2成立,进入循环,整个循环结束后执行3,3后执行2,2成立再次进入循环
若2不成立,跳出循环,执行B
第二行for循环内,先执行4,4后执行5
5成立,执行A,A后执行6,6后判断5,只要5成立,一直执行A和6
5不成立,跳出循环,执行3
多个for循环嵌套使用举例
用已学的知识去编写程序
例一:
#include <stdio.h>
int main()
{
int i,j;
for(i=0;i<3;++i) //循环3次
for(j=2;j<5;++j)//循环3次,共9次
printf("哈哈!\n"); //本行之前为第一个语句
printf("喵喵!\n"); //第二个语句
return 0;
}
/*----输出结果-----------
哈哈!
哈哈!
哈哈!
哈哈!
哈哈!
哈哈!
哈哈!
哈哈!
哈哈!
喵喵!
-------------------------*/
例二:
#include <stdio.h>
int main()
{
int i,j;
for(i=0;i<3;++i) //循环3次
printf("嘿嘿!\n");
for(j=2;j<5;++j)//循环3次
printf("哈哈!\n");
printf("喵喵!\n");
return 0;
}
/*----输出结果-----------
嘿嘿!
嘿嘿!
嘿嘿!
哈哈!
哈哈!
哈哈!
喵喵!
-------------------------*/
例三:
#include <stdio.h>
int main()
{
int i,j;
for(i=0;i<3;++i)
{
printf("1\n");
for(j=2;j<5;++j)
{
printf("2\n");
printf("3\n");
}
printf("4\n");
}
return 0; //结果 12323234 重复三次
}
/*----输出结果-----------
1
2
3
2
3
2
3
4
1
2
3
2
3
2
3
4
1
2
3
2
3
2
3
4
-------------------------*/
代码有些绕,多看几遍
for循环到此结束
循环之while
②while
执行顺序
while(表达式)
语句;
表达式成立,执行语句,执行后判断表达式是否成立
因此,只要表达式成立一直执行,不成立则跳出
与if和for一样,while默认控制一个语句
与for的相互比较
求1+2+3+..+100 用for来实现
#include <stdio.h>
int main()
{
int sum;
int i;
sum=0;
for (i=1;i<101;++i)
{
sum=sum+i;
}
printf("sum=%d\n",sum);
return 0;
}
/*----输出结果-----------
sum=5050
-------------------------*/
求1+2+3+..+100 用while来实现
#include <stdio.h>
int main()
{
int sum;
int i;
i=1;
while(i<101)
{
sum=sum+i; //这两行顺序不可互换
++i;
}
printf("sum=%d\n",sum);
return 0;
}
/*----输出结果-----------
sum=5050
-------------------------*/
因此,for和while可以相互转换,但for逻辑性更强,更不易出错,推荐多使用for
for(1;2;3)
A;
等价于
1
while(2)
{ //一定要加这个大括号,不加while无法控制3
A;
3;
}
举例
从键盘输入一个数字,如果该数字是回文数,则返回yes,否则返回no
回文数:正着写和倒着写都一样
例:121 12321 都是回文数
- 求回文数
#include <stdio.h>
int main()
{
int val;//存放带判断的数字
int m;
int sum =0;
printf("请输入您需要判断的数字:");
scanf("%d",&val);
m=val;
while(m) //m只要非零即为真
{
sum=sum*10+m%10;
m/=10; //被除数和除数如果两个都是整数,则没有小数
}
if(sum == val)
printf("Yes!\n");
else
printf("No!\n");
return 0;
}
/*----输出结果-----------
请输入您需要判断的数字:1234
No!
-------------------------*/
试数:把自己当做计算机一步步去试,试的时候写整齐,写详细
1> m=1234 成立
sum=0*10+1234%10=4
m=m/10=1234/10=123
2> m=123 成立
sum=4*10+123%10=43
m=m/10=123/10=12
3> m=12 成立
sum==43*10+12%10=432
m=m/10=12/10=1
4> m=1 成立
sum=432*10+1%10=4321
m=m/10=1/10=0
5> m=0 不成立
最终sum=4321
1234=4321 X 故输出No
- 斐波那契数列
/*
斐波那契数列
1 2 3 5 8 13 21 34
*/
#include <stdio.h>
int main()
{
int n; //保存用户的值
int f1, f2, f3; //最终输出的值用f3表示
int i;
f1 = 1;
f2 = 2;
printf("请输入您需要求的项的序列:"); //第n项的值为多少
scanf("%d",&n);
if(1 == n)
{
f3 = 1;
}
else if(2 == n)
{
f3 = 2;
}
else
{
for (i=3; i<=n; ++i)
{
f3 = f1 + f2;
f1 = f2;
f2 = f3;
}
}
printf("%d\n",f3);
return 0;
}
/*----输出结果-----------
请输入您需要求的项的序列:6
13
-------------------------*/
试数:
假设输入n为6
1>i=3 3<=6 成立
f3=1+2=3
f1=f2=2
f2=f3=3
++i i=4
2>i=4 4<=6 成立
f3=2+3=5
f1=f2=3
f2=f3=5
++i i=5
3>i=5 5<=6 成立
f3=3+5=8
f1=f2=5
f2=f3=8
++i i=6
4>i=6 6<=6 成立
f3=5+8=13
f1=f2=8
f2=f3=13
++i i=7
5>i=7 7<=6 不成立
故循环了4次,当n为6时,f3的值为13
试数可横着写可竖着写
i i<=6 f1 f2 f3 ++i
3 √ 1 2 3 4
4 √ 2 3 5 5
5 √ 3 5 8 6
6 √ 5 8 13 7
7 X
while和for使用场合
没法说,用多了自然而然就知道了(老师的原话,用的多了就好了,不用纠结)
循环之do..while
③do..while
场合:
主要用于人机交互
格式:
do
{
...
}while(表达式);
注意:
do..while和while不可相互转换
while和for有可能一次也不执行,若表达式为假,退出循环
do..while一定会执行一次,先执行语句,再判断
一元二次方程
无do..while循环
仅执行一次
#include <stdio.h>
#include <math.h>
int main()
{
double a,b,c;
double delta;
double x1,x2;
printf("请输入一元二次方程的三个系数:\n");
printf("a = ");
scanf("%lf",&a);
printf("b = ");
scanf("%lf",&b);
printf("c = ");
scanf("%lf",&c);
delta=b*b-4*a*c;
if(delta >0)
{
x1=(-b+sqrt(delta))/(2*a);
x2=(-b-sqrt(delta))/(2*a);
printf("有两个解,x1=%lf,x2=%lf\n",x1,x2);
}
else if(0 == delta)
{
x1=x2=(-b)/(2*a);
printf("有唯一解,x1=x2=%lf\n",x1,x2);
}
else
{
printf("无实数解!\n");
}
return 0;
}
/*----输出结果-----------
请输入一元二次方程的三个系数:
a = 1
b = 5
c = 6
有两个解,x1=-2.000000,x2=-3.000000
-------------------------*/
有do..while循环
#include <stdio.h>
#include <math.h>
int main()
{
double a,b,c;
double delta;
double x1,x2;
char ch;
do
{
printf("请输入一元二次方程的三个系数:\n");
printf("a = ");
scanf("%lf",&a);
printf("b = ");
scanf("%lf",&b);
printf("c = ");
scanf("%lf",&c);
delta=b*b-4*a*c;
if(delta >0)
{
x1=(-b+sqrt(delta))/(2*a);
x2=(-b-sqrt(delta))/(2*a);
printf("有两个解,x1=%lf,x2=%lf\n",x1,x2);
}
else if(0 == delta)
{
x1=x2=(-b)/(2*a);
printf("有唯一解,x1=x2=%lf\n",x1,x2);
}
else
{
printf("无实数解!\n");
}
printf("您想继续吗(Y/N):");
scanf(" %c",&ch); //%c前必须得加一个空格,原因略
}while('y'==ch || 'Y'==ch); //只要不是y就终止
return 0;
}
/*----输出结果-----------
请输入一元二次方程的三个系数:
a = 1
b = 5
c = 6
有两个解,x1=-2.000000,x2=-3.000000
您想继续吗(Y/N):y
请输入一元二次方程的三个系数:
a = 1
b = 3
c = 4
无实数解!
您想继续吗(Y/N):n
-------------------------*/
switch的用法简介
把电梯程看懂就可以了
#include <stdio.h>
int main()
{
int val;
printf("请输入您要进入的楼层:");
scanf("%d",&val);
switch(val)
{
case 1: //注意使用的是冒号
printf("1层开!\n");
break;
case 2:
printf("2层开!\n");
break;
case 3:
printf("3层开!\n");
break;
default: //默认
printf("没有盖到这一层!\n");
break;
}
return 0;
}
/*----输出结果-----------
请输入您要进入的楼层:5
没有盖到这一层!
-------------------------*/
若将上述代码中的break注释掉,变成如下格式,结果为?
#include <stdio.h>
int main()
{
int val;
printf("请输入您要进入的楼层:");
scanf("%d",&val);
switch(val)
{
case 1: //注意使用的是冒号
printf("1层开!\n");
//break;
case 2:
printf("2层开!\n");
break;
case 3:
printf("3层开!\n");
break;
default: //默认
printf("没有盖到这一层!\n");
break;
}
return 0;
}
/*----输出结果-----------
请输入您要进入的楼层:1
1层开!
2层开!
-------------------------*/
case1,case2,case3,default是程序的入口
val是输入的值
若val是1,从case1入口进入后,依次顺序执行,不再第二次找入口
若val是2,从case2入口进入后,依次顺序执行,不再第二次找入口
若val是3,从case3入口进入后,依次顺序执行,不再第二次找入口
因此,break起到终止switch的作用。
若将上述代码中的break重新注释掉,变成如下格式,结果为?
#include <stdio.h>
int main()
{
int val;
printf("请输入您要进入的楼层:");
scanf("%d",&val);
switch(val)
{
case 1: //注意使用的是冒号
printf("1层开!\n");
break;
case 2:
printf("2层开!\n");
//break;
case 3:
printf("3层开!\n");
//break;
default: //默认
printf("没有盖到这一层!\n");
break;
}
return 0;
}
/*----输出结果-----------
请输入您要进入的楼层:3
3层开!
没有盖到这一层
-------------------------*/
若将所有break注释掉,并输入1,会依次输出
#include <stdio.h>
int main()
{
int val;
printf("请输入您要进入的楼层:");
scanf("%d",&val);
switch(val)
{
case 1: //注意使用的是冒号
printf("1层开!\n");
//break;
case 2:
printf("2层开!\n");
//break;
case 3:
printf("3层开!\n");
//break;
default: //默认
printf("没有盖到这一层!\n");
//break;
}
return 0;
}
/*----输出结果-----------
请输入您要进入的楼层:1
1层开!
2层开!
3层开!
没有盖到这一层!
-------------------------*/
switch琐碎非重点知识介绍
switch(表达式)
{
case 常量表达式1:
语句1;
case 常量表达式2:
语句2;
default: //一般写的时候,default在case3后面
语句3;
case 常量表达式3:
语句4;
}
第一:所有case后面的常量表达式为便于描述,姑且称之为标签,
这些标签都只能是四种
1.枚举常量(有些书称之为枚举元素)
2.数值常量
3.字符常量
4.常变量
5.宏名的中的一种
注意普通变量,枚举变量是不能作为标签使用的。
第二:switch后面括号例“表达式”允许是任何类型。
但vc++只允许为int或char类型
第三:执行完一个case语句后,流程控制就转移到下一个case子句中继续执行。
“case”常量表达式只是起语句标号的作用,并不是在该处进行条件判断。
在执行switch语句时,根据switch()中表达式的值找到与之匹配的case子句,
就从此case子句开始执行下去,不再进行判断。
switch(i)
{
case 1:
语句1;
case 2:
语句2;
default:
语句3;
case 3:
语句4;
}
当i==1时,从case1处开始往下,一个不落的执行
当i==2时,从case2处开始往下,一个不落的执行
当i==3时,只执行case3一句
当i==4时,从 default处开始往下,一个不落的执行
当i==0时,执行情况同i==4。
第四:switch是选择,不是循环,如果在switch中出现了break语句,
该语句的功能知识退出switch语句,转去执行它下面的语句,
在switch中出现continue是错误的,除非switch本身就属于for或while循环的一部分。
break的用法(重点)
break如果用于循环是用来终止循环
break如果用于switch,则是用于终止switch
break不能直接用于if,除非if属于循环内部的一个子句
break与if的错误例子
#include <stdio.h>
int main()
{
switch(2)
{
case 2:
printf("哈哈!\n");
break;
}
if (3>2)
break;//错误
return 0;
}
break与if的正确例子
#include <stdio.h>
int main()
{
int i;
switch(2)
{
case 2:
printf("哈哈!\n");
break; //ok,break可以用于switch
}
for(i=0; i<3; ++i)
{
if (3>2)
break; //break虽然是if内部的语句,但终止的却是外部的for循环
printf("嘿嘿!\n"); //永远不会输出
}
return 0;
}
break用于多层for循环时,只能终止距离它最近的循环
#include <stdio.h>
int main()
{
int i,j;
for(i=0;i<3;++i)
{
for(j=1;j<4;++j)
break; //只能终止距离它最近的循环
printf("喵喵喵!\n");
}
return 0;
}
/*----输出结果-----------
喵喵喵!
喵喵喵!
喵喵喵!
-------------------------*/
break用于多层switch嵌套时,只能终止距离它最近的switc
continue的用法
用于跳过本次循环余下的语句,转去判断是否需要执行下次循环
例一:
for(1;2;3)
{
A;
B;
continue; //如果执行该语句,则执行完该语句后,会执行语句3,C和D都会被跳过去(不会被执行)
C;
D;
}
//若将for循环转换为while循环,3一定要放在continue上面
例二:
while(表达式)
{
A;
B;
continue; //如果执行该语句,则执行完该语句后,会执行表达式,C和D都会被跳过去(不会被执行)
C;
D;
}
之前写过的代码:scanf时对用户非法输入的处理
//不用关注结果,只看while和continue的作用
#include <stdio.h>
int main()
{
int i;
char ch;
scanf("%d",&i);
printf("i=%d\n",i);
//......
while((ch=getchar())!='\n') //getchar()从键盘上输入的字符 \n是回车
continue; //继续
int j;
scanf("%d",&j);
printf("j=%d\n",j);
return 0;
}
/*-----------------------
若未写while和continue,用户输入非法后,结果会出错
因此while语句,会将用户输入的垃圾信息清楚掉
-------------------------*/
C语言为什么无法做出像样的东西
和各门课程之间的关系
c中有很多东西是其他语言中学不到的,例如函数,指针(c++中的指针源自c语言)
学c有助于后续课程的学习,
面向过程的c,到后期学习面向对象的JAVA SE
其他语言的函数与c的函数不一样,学c之后视野更加开阔
c语言短小精悍,学起来更易上手
前面枯燥,难以理解,但基础打牢,后面的内容越容易接受
流量控制总复习
不熟悉的再去回顾一下
顺序:自上而下的执行
----------------------------
选择:if和、witch
if的范围问题 语句是否成立取决于条件是否成立
if..else:只会执行其中的一个语句
空语句的问题——分号的位置
if..else..最后面的else结尾,不要用else if(语法没错,但逻辑有漏洞)
最后的else不要有表达式
switch 看懂电梯程序
与break的关系
----------------------------
循环:for、while、do..while
for循环的执行流程问题
for(1;2;3)1永远只执行一次
1/2的结果0
while与for的转换,二者的比较,最常用的for
do..while,先执行内部,再判断是否成立,一定会执行一次
do..while与while不能相互转换
----------------------------
break作用
在循环中用于终止循环,多层循环时终止距离最近的循环
在switch中用于终止距离最近switch
在循环内部的if中,用于终止距离最近的那个循环,不是用来终止if的
----------------------------
continue作用
for(1;2;3) 中一旦执行continue,余下的语句都不执行,直接执行3
while中一旦执行continue,余下的语句都不执行,直接执行表达式
流量控制总测试
数据结构中的一些例子,不管代码含义,只看流程
注:下面的代码都不全
例一:折半查找
//折半查找
//if..else 的嵌套
if(low == high) //条件成立,执行下一个if
{
if(p[mid] == val) //条件成立,语句终止(后面讲return的时候讲)
{
return mid;
}
else
{
return -1;
}
}
else
{
if(p[mid]<val)
{
Find(p,mia+1,high,val);
}
else if(p[mid]>val)
{
Find(p,low,mid-1,val);
}
else if(p[mid] == val)
{
return mid;
}
}
例二:冒泡排序
i=1;
while(flag)
for(j=0;j<n-i;++j)
{
if(a[j]>a[j+1]) //若不成立,执行++j
{
temp=a[j];
a[j]=a[j+1];
continue; //会跳去执行++j
a[j+1]=temp;
flag=1;
break; //1,跳出for循环,到第二个break位置
}
}
break; //2,跳出while循环
++i;
}
}
例三:快速排序
while(low<high) //语句成立,执行下一个while
{
while(high>low && a[high] >=value) //语句成立,执行high--,不成立执行if语句
high--; //执行完再次判断while是否成立 本行语句执行后不执行if
if(high!=low) //成立执行内部的三行语句,不成立执行下面的while
{
t=a[low];
a[low]=a[high];
a[high]=t;
}
while(low<high && a[low]<=value)//语句成立,执行low++,不成立执行下面的if语句
low++;
if(low!=high) //成立执行内部的三行语句,不成立返回最上面的while
{
t=a[low];
a[low]=a[high];
a[high]=t;
}
}
例四:do..while与continue
int i=0,s=0;
do
{
if(i%2) //成立,执行内部两行语句 第一次循环是i%2=0,所以直接跳到第二个i++位置
{
i++; //1
continue; //之后执行while(i<5)
}
i++;//2
s+=i;
}while(i<5);
printf("%d\n",s); //s最终值为9
return 0;
}
/*
执行过程
i s
0 0
1 1
2
3 4
4
5 9
*/
例五:for与break和continue
int a=1,b;
for(b=1;b<=10;b++)
{
if(a>=8)
break; //跳到最下面的printf
if(1 == a%2)
{
a+=5;
continue;//跳到for里面的b++
}
a-=3;
}
printf("b=%d\n",b);