目录
1.6.3do while循环中的break和continue
前言
C语⾔是结构化的程序设计语⾔,这⾥的结构指的是顺序结构、选择结构、循环结构,C语⾔是能够实 现这三种结构的,其实我们如果仔细分析,我们⽇常所⻅的事情都可以拆分为这三种结构或者这三种 结构的组合。 我们可以使⽤ if 、 switch 实现分⽀结构,使⽤ for 、 while 、 do while 实现循环结构。
1.分支和循环语句
1.1 if else语句
if语句的形式如下:
表达式成⽴(为真),则语句执⾏,表达式不成⽴(为假),则语句不执⾏。
判断奇数和偶数:
代码如下:
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if(num % 2 == 1)
printf("%d 是奇数\n", num);
return 0;
}
例⼦:输⼊⼀个整数,判断是否为奇数,如果是奇数打印是奇数,否则打印数偶数。
#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;
}
注:悬空else问题
如果有多个 if 和 else ,可以记住这样⼀条规则, else 总是跟最接近的 if 匹配。 我们⾸先从下⾯代码开始。
1.2 switch语句
除了 if 语句外,C语⾔还提供了 switch 语句来实现分⽀结构。
switch 语句是⼀种特if...else 结构,⽤于判断条件有多个结果的情况。它把多重 的 else if 改成更易⽤、可读性更好的形式。
格式:
上⾯代码中,根据表达式 expression 不同的值,执⾏相应的 case 分⽀。如果找不到对应的值, 就执⾏ default 分⽀。
注1:
• switch 后的 expression 必须是整型表达式
• case 后的值,必须是整形常量表达式
注2:
1. case 和后边的数字之间必须有空格
2. 每⼀个 case 语句中的代码执⾏完成后,需要加上 break ,才能跳出这个switch语句。
switch语句的default
在使⽤ switch 语句的时候,我们经常可能遇到⼀种情况,⽐如 switch 后的表达式中的值⽆法匹 配代码中的 case 语句的时候,这时候要不就不做处理,要不就得在 switch 语句中加⼊
default ⼦句。
注3:
在 switch 语句中 case ⼦句和 default ⼦句有要求顺序吗? default 只能放在最后吗? 其实,在 switch 语句中 case 语句和 default 语句是没有顺序要求的,只要你的顺序是满⾜实 际需求的就可以。 不过我们通常是把 default ⼦句放在最后处理的。
1.3 while循环
执行流程:
⾸先上来就是执⾏判断表达式,表达式的值为0,循环直接结束;表达式的值不为0,则执⾏循环语 句,语句执⾏完后再继续判断,是否进⾏下⼀次判断。
练习:
题⽬解析
1. 要想得到n的最低位,可以使⽤n%10的运算,得到的余数就是最低位,如:1234%10得到4
2. 要想去掉n的最低位,找出倒数第⼆位,则使⽤ n=n/10 操作就可以去掉最低位的,如: n=1234/10得到123,123相较于1234就去掉了最低位,123%10就得到倒数第⼆位3。
3. 循环1和2两个步骤,在n变成0之前,就能到所有的位。
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
while(n)
{
printf("%d ", n%10);
n /= 10;
}
return 0;
}
1.4 for循环
语法形式:
表达式1⽤于循环变量的初始化
表达式2⽤于循环结束条件的判断(可以不写)
表达式3⽤于循环变量的调整
流程图:
⾸先执⾏ 表达式1 初始化循环变量,接下来就是执⾏ 表达式2 的判断部分, 表达式2 的结果如果 ==0,则循环结束; 表达式2 的结果如果!=0则执⾏循环语句,循环语句执⾏完后,再去执⾏表 达式3 ,调整循环变量,然后再去 表达式2 的地⽅执⾏判断, 表达式2 的结果是否为0,决定循环是否继续。
整个循环的过程中,表达式1初始化部分只被执⾏1次,剩下的就是表达式2、循环语句、表达式3在循环。
练习:
#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;
}
//⼩⼩的优化
//如果能直接产⽣3的倍数的数字就省去了多余的循环和判断
#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;
}
1.5 do-while循环
语法形式:
while 和 for 这两种循环都是先判断,条件如果满⾜就进⼊循环,执⾏循环语句,如果不满⾜就跳 出循环; ⽽ do while 循环则是先直接进⼊循环体,执⾏循环语句,然后再执⾏ while 后的判断表达式,表达式为真,就会进⾏下⼀次,表达式为假,则不再继续循环。
执行流程:
练习:
#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;
}
1.6 break和continue语句
在循环执⾏的过程中,如果某些状况发⽣的时候,需要提前终⽌循环,这是⾮常常⻅的现象。C语⾔中 提供了 break 和 continue 两个关键字,就是应该到循环中的。
• break 的作⽤是⽤于永久的终⽌循环,只要 break 被执⾏,直接就会跳出循环,继续往后执⾏。
• continue 的作⽤是跳过本次循环 continue 后边的代码,在 for 循环和 while 循环中有所差异的。
1.6.1while循环中的break和continue
break:
#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;
}
continue:
#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.6.2for循环中的break和continue
break:
#include <stdio.h>
int main()
{
int i = 1;
for(i=1; i<=10; i++)
{
if(i == 5)
break;
printf("%d ", i);
}
return 0;
}
continue:
#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;
}
1.6.3do while循环中的break和continue
do.while 语句中的 break 和 continue 的作⽤和 while 循环中⼏乎⼀模⼀样,⼤家下来可以 ⾃⾏测试并体会。
1.7 goto语句
C语⾔提供了⼀种⾮常特别的语法,就是 goto 语句和跳转标号, goto 语句可以实现在同⼀个函数 内跳转到设置好的标号处
#include <stdio.h>
int main()
{
printf("hehe\n");
goto next:
printf("haha\n");
next:
printf("跳过了haha的打印\n");
return 0;
}
2.操作符
2.1关系操作符
C语⾔⽤于⽐较的表达式,称为“关系表达式”(relational expression),⾥⾯使⽤的运算符就称 为“关系运算符”(relational operator),主要有下⾯6个。
• > ⼤于运算符
比特就业课主页:https://m.cctalk.com/inst/s9yewhfr 比特就业课-专注IT大学生就业的精品课程
• < ⼩于运算符
• >= ⼤于等于运算符
• ⼩于等于运算符
• == 相等运算符
• != 不相等运算符
2.2条件操作符
条件操作符也叫三⽬操作符,需要接受三个操作数的,形式如下:
条件操作符的计算逻辑是:如果 exp1 为真, exp2 计算,计算的结果是整个表达式的结果;如果
exp1 为假, exp3 计算,计算的结果是整个表达式的结果。
2.3逻辑操作符:&&,||,!
逻辑运算符提供逻辑判断功能,⽤于构建更复杂的表达式,主要有下⾯三个运算符。
• ! :逻辑取反运算符(改变单个表达式的真假)。
• && :与运算符,就是并且的意思(两侧的表达式都为真,则为真,否则为假)。
• || :或运算符,就是或者的意思(两侧⾄少有⼀个表达式为真,则为真,否则为假)。
!:
&&:
||:
练习:
#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;
}
注:短路思想
C语⾔逻辑运算符还有⼀个特点,它总是先对左侧的表达式求值,再对右边的表达式求值,这个顺序是保证的。
如果左边的表达式满⾜逻辑运算符的条件,就不再对右边的表达式求值。这种情况称为“短路”。 如前⾯的代码:
表达式中&&的左操作数是 month >= 3 ,右操作数是 month ,当左操作数 month >= 3 的 结果是0的时候,即使不判断 month ,整个表达式的结果也是0(不是春季)。
所以,对于&&操作符来说,左边操作数的结果是0的时候,右边操作数就不再执⾏。
3.根据循环和分支写⼀个猜数字游戏
要求:
1. 电脑⾃动⽣成1~100的随机数
2. 玩家猜数字,猜数字的过程中,根据猜测数据的⼤⼩给出⼤了或⼩了的反馈,直到猜对,游戏结束
3.1随机数⽣成
C语⾔提供了⼀个函数叫rand,这函数是可以⽣成随机数的,函数原型如下所⽰:
rand函数会返回⼀个伪随机数,这个随机数的范围是在0~RAND_MAX之间,这个RAND_MAX的⼤⼩是 依赖编译器上实现的,但是⼤部分编译器上是32767。
rand函数的使⽤需要包含⼀个头⽂件是:stdlib.h
举例:
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
return 0;
}
但是我们可以看到虽然⼀次运⾏中产⽣的5个数字是相对随机的,但是下⼀次运⾏程序⽣成的结果和上⼀次 ⼀模⼀样,这就说明有点问题。
如果再深⼊了解⼀下,我们就不难发现,其实rand函数⽣成的随机数是伪随机的,伪随机数不是真正 的随机数,是通过某种算法⽣成的随机数。真正的随机数的是⽆法预测下⼀个值是多少的。⽽rand函 数是对⼀个叫“种⼦”的基准值进⾏运算⽣成的随机数。 之所以前⾯每次运⾏程序产⽣的随机数序列是⼀样的,那是因为rand函数⽣成随机数的默认种⼦是1。 如果要⽣成不同的随机数,就要让种⼦是变化的。
办法:C语⾔中⼜提供了⼀个函数叫srand,⽤来初始化随机数的⽣成器的,srand的原型如下:
程序中在调⽤rand函数之前先调⽤srand函数,通过srand函数的参数seed来设置rand函数⽣成随 机数的时候的种⼦,只要种⼦在变化,每次⽣成的随机数序列也就变化起来了。
那也就是说给srand的种⼦是如果是随机的,rand就能⽣成随机数;在⽣成随机数的时候⼜需要⼀个随机数,这就⽭盾了。
所以我们需要一个变化的种子:
这个种子就是时间;在程序中我们⼀般是使⽤程序运⾏的时间作为种⼦的,因为时间时刻在发⽣变化的。 在C语⾔中有⼀个函数叫time,就可以获得这个时间,time函数原型如下:
time函数会返回当前的⽇历时间,其实返回的是1970年1⽉1⽇0时0分0秒到现在程序运⾏时间之间的 差值,单位是秒。返回的类型是time_t类型的,time_t类型本质上其实就是32位或者64位的整型类型。
time函数的参数timer如果是⾮NULL的指针的话,函数也会将这个返回的差值放在timer指向的内存 中带回去。
如果timer是NULL,就只返回这个时间的差值。time函数返回的这个时间差也被叫做:时间戳。
time函数的时候需要包含头⽂件:time.h
如果只是让time函数返回时间戳,我们就可以这样写:
所以我们可以这样写:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
//使⽤time函数的返回值设置种⼦
//因为srand的参数是unsigned int类型,我们将time函数的返回值强制类型转换
srand((unsigned int)time(NULL));
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
return 0;
}
注:关于如何设置随机数的范围
如果我们要⽣成0~99之间的随机数,⽅法如下:
如果要⽣成1~100之间的随机数,⽅法如下:
如果要⽣成100~200的随机数,⽅法如下:
所以如果要⽣成a~b的随机数,⽅法如下:
3.2 猜数字游戏实现
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void game()
{
int r = rand()%100+1;
int guess= 0;
while(1)
{
printf("请猜数字>:");
scanf("%d", &guess);
if(guess < r)
{
printf("猜⼩了\n");
}
else if(guess > r)
{
printf("猜⼤了\n");
}
else
{
printf("恭喜你,猜对了\n");
break;
}
}
}
void menu()
{
printf("***********************\n");
printf("****** 1. play ******\n");
printf("****** 0. exit ******\n");
printf("***********************\n");
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch(input)
{
case 1:
game();
break;
case 0:
printf("游戏结束\n");
break;
default:
printf("选择错误,重新选择\n");
break;
}
}while(input);
return 0;
}
还可以加上猜数字的次数限制,如果5次猜不出来,就算失败.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void game()
{
int r = rand() % 100 + 1;
int guess = 0;
int count = 5;
while (count)
{
printf("\n你还有%d次机会\n", count);
printf("请猜数字>:");
scanf("%d", &guess);
if (guess < r)
{
printf("猜⼩了\n");
}
else if (guess > r)
{
printf("猜⼤了\n");
}
else
{
printf("恭喜你,猜对了\n");
break;
}
count--;
}
if (count == 0)
{
printf("你失败了,正确值是:%d\n", r);
}
}
void menu()
{
printf("***********************\n");
printf("****** 1. play ******\n");
printf("****** 0. exit ******\n");
printf("***********************\n");
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("游戏结束\n");
break;
default:
printf("选择错误,重新选择\n");
break;
}
} while (input);
return 0;
}