目录
分支语句(选择结构)
if语句
switch语句
循环语句
while循环
do…while循环
for循环
循环语句的练习
转向语句
goto语句
break语句
continue语句
return语句
什么是控制语句?
控制语句用于控制程序的执行流程,以实现程序的各种结构方式,他们由特定的语句定义符组成,C语言有九种控制语句。
可以分为以下三类:
- 条件判断语句/分支语句:if语句、switch语句
- 循环执行语句:do while语句、while语句、for语句
- 转向语句:break语句、goto语句、continue语句、return语句
C语言中真假的表示
- 0表示假
- 非0表示真。
—— 那!0应该返回哪个数?
—— 返回1
if语句的结构语法
//第一种
if(表达式)
{
语句;
}
//第二种
if(表达式)
{
语句;
}
else
{
语句;
}
//第三种
if(表达式)
{
语句;
}
else if(表达式)
{
语句;
}
else
{
语句;
}
对于if语句来说,只要有一个分支执行,整个if语句全部结束。
所有控制语句都是可以嵌套使用,但是嵌套要合理。嵌套时一定要注意缩进。
IF语句的分支只有一条语句时,大括号可以省略不写。(不推荐这种方式,但是别人这样写要可以看懂)
if(表达式)
语句;
if(表达式)
语句;
else
语句;
悬空else:如果没有加{},else与离自己最近的那个if配对
//这段程序什么都不打印。因为else与离自己最近的那个if配对,因为a!=1,所以程序直接结束
#include
int main()
{
int a = 0;
int b = 0;
if(a == 1)
if(b == 2)
printf("hahaha");
else
printf("hehehehe");
//实际会被解析为
if(a == 1)
if(b == 2)
printf("hahaha");
else
printf("hehehehe");
return 0;
}
改正
#include
int main()
{
int a = 0;
int b = 0;
if(a == 1)
{
if(b == 2)
{
printf("hahaha");
}
}
else
{
printf("hehehehe");
}
return 0;
}
练习
/*
* 假设系统给定;一个考生的成绩,成绩可能带有小数点,学生成绩范围在[0-100]
* 根据学生的成绩判断该学生的成绩等级
* [90-100]A 、 [80-90) B 、 [70-80) C 、 [60-70) D 、 [0-60) E
*/
#include
int main()
{
double score = 61;
if(score>100 || score<0)
{
printf("该考生成绩不合法,请确认后重新输入");
}
else if(score >= 90)
{
printf("该考生成绩等级为:A");
}
else if(score >= 80)
{
printf("该考生成绩等级为:B");
}
else if(score >= 70)
{
printf("该考生成绩等级为:C");
}
else if(score >= 60)
{
printf("该考生成绩等级为:D");
}
else
{
printf("该考生挂科!");
}
return 0;
}
switch语句的语法结构
switch语句也属于选择结构,也是分支语句
/*
switch语句可以看作是一种基于计算的跳转,根据整型表达式的值,跳转到相匹配到case处。
在匹配了case,执行了其中的语句之后,如果没有break; 就会顺序执行下面的case中的语句。
直到遇到break; ,或switch结束。
*/
/*
switch()中的表达式,要是整形的,如n或n+1
case 后面跟的是常量或常量表达式,如1或1+3
*/
switch(整型表达式){
case 常量/常量表达式:
语句;
case 常量/常量表达式:
语句;
case 常量/常量表达式:
语句;
....
default 常量/常量表达式:
语句;
}
switch语句执行原理
switch()中的数据,与case后面的数据 ,按照自上而下的顺序,依次匹配。匹配成功的分支执行。
switch分支中,default字句可以放在任意位置,不是必须在case字句之后。
匹配成功的分支执行
分支中如果有break;语句,则这个分支执行后整个switch语句终止。
分支中如果没有break;语句,则会直接进入下一个分支执行。直到遇到break; ,或switch语句结束。
这种现象被称为“case穿透”现象
所有分支都没有匹配成功,当有default: 语句时,会执行default分支中的语句
case合并
#include
int main()
{
int day = 0;
scanf("%d",&day);
switch (day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("工作日");
break;
case 6:
case 7:
printf("休息日");
break;
}
return 0;
}
练习
#include
int main()
{
int n = 1;
int m = 2;
switch (n)
{
case 1:
m++;
case 2:
n++;
case 3:
switch (n) //switch嵌套使用
{
case 1:
n++;
case 2:
m++;
n++;
break;
}
case 4:
m++;
break;
default:
break;
}
printf("m=%d , n=%d",m,n);//m=5 , n=3
return 0;
}
2
/*
需求:
假设系统给定;一个考生的成绩,成绩可能带有小数点,学生成绩范围在[0-100]
根据学生的成绩判断该学生的成绩等级,成绩可能带有小数
[90-100]A
[80-90) B
[70-80) C
[60-70) D
[0-60) E
以上的逻辑判断采用switch语句完成,不考虑[0,100]以外的
*/
#include
int main()
{
float grade = 0;
scanf("%f",&grade);
switch ((int)grade/10) {
case 9:
case 10:
printf("该考生成绩等级为:A");
break;
case 8:
printf("该考生成绩等级为:B");
break;
case 7:
printf("该考生成绩等级为:C");
break;
case 6:
printf("该考生成绩等级为:D");
break;
default:
printf("该考生成绩等级为:E");
break;
}
return 0 ;
}
while循环结构
while(布尔表达式){
循环体;
}
执行原理
先判断表达式的结果:
*非0
-执行循环体
*判断表达式的结果:
*非0
-执行循环体
*判断表达式结果
*非0
—执行循环体
*判断表达式结果:
·······
*0
—循环结束
*0
-循环结束
*0
-循环结束
getchar()方法的使用
/*
* int getchar(void)函数 —— 作用:输入一个字符。通常用于接收空格/换行符
* 返回值:该函数以无符号char强制类型转换为int的形式返回读取的字符,如果达到文件末尾或发生错误,则会返回(-1)EOF
* 返回字符对应的ASCII码
*
* int putchar(int char) —— 作用:输出一个字符。char是要输出的参数。
* 返回值:该函数以无符号char强制转换为int的形式返回写入的字符,如果发生错误则会返回(-1)EOF
* 参照ASCII表,将char对应的字符返回。
*
*注意:
* - 当程序调用getchar()时,等待用户按键,用户输入的字符被存放在键盘缓冲器中,直到用户按回车为止(这个回车字符也存放在缓冲区中)。
* 用户键入回车之后,getchar才开始从stdin流中每次读入一个字符。
* - getchar()函数不仅可以从输入设备获取一个可显示的字符,而且可以获得屏幕上无法显示的字符,如:回车换行/空格等
* - getchar()函数的返回值是:用户输入的字符的ASCII码,若文件结尾则返回-1(EOF),且将用户输入的字符回显到屏幕
* - 如果用户在按回车之前输入了不止一个字符,其他字符也会保留在键盘缓冲区中,等待后续getchar()调用读取
* 也就是说:后续的getchar调用不会等待用户按键,而是直接读取缓冲区中的字符,直到缓冲区中的字符读取完之后,才等待用户按键
*
*主要用法:
* - 清空回车符,这种情况一般发生在寻魂中涉及到输入的情况。
* - 某些编译平台(IDE)在运行程序时,并没有在程序程序运行后给别人看结果的时间。这时在程序最后加上getchar(),就可以造成程序的暂停。
* - 使用getchar();时,输入完字符,要按回车才能读取进去
* 使用getch();时,在键盘上按一个字符马上就被读取进去,不用按回车,因此可以作为“按任意键继续”的执行语句。
*/
/*
* - getch()函数
* getch与getchar基本功能相同,差别是:getch直接从键盘获取键值,不等待用户按回车,只要用户按一个键,getch就立刻返回
* getch返回值是用户输入的字符的ASCII码,出错返回-1。
* - 输入的字符不会会现在屏幕上。getch函数常用于程序调试中。在调试时,在关键位置显示有关的结果以待查看。
* 然后用getch函数暂停函数运行,当按任意键后程序继续运行。
* - getch()是非缓冲输入函数,就是不能用getch()来接收缓冲区已存在的字符。
*
* - getche()函数
* 这个函数与前两上类似,功能也相近,都是输入一个字符,返回值同样是输入字符的ASCII码。
* 但不同的是,此函数在输入后立即从控制台取字符,不以回车为结束(带回显)。
*
*/
#include
int main()
{
int ch = 0;
/*
* - 虽然getchar()是用于输入一个字符。
* 但如果用户在按回车之前输入了不止一个字符,其他字符也会保留在键盘缓冲区中,等待后续getchar()调用读取。
* 也就是说:后续的getchar调用不会等待用户按键,而是直接读取缓冲区中的字符,直到缓冲区中的字符读取完之后,才等待用户按键
*
* 程序运行后,等待键盘输入。输入一串字符后,循环读取这串字符,按顺序输出。
* 如输入abc并回车,实际输入:abc\n
* 则会输出 97——a---- 98——b---- 99——c---- 10——
----
* 这里10——后面换行才输出了----,就说明了:\n也被存储到了缓冲区中,其对应的ASCII码是:10。
*
*/
while ((ch=getchar()) != EOF)
{
//getchar()函数的返回值是其字符对应的ASCII码
printf("%d——",ch);
//putchar()函数的返回值是其传入变量对应的字符。
putchar(ch);
printf("----\t");
}
}
统计从键盘输入的一行字符的个数
//统计从键盘输入的一行字符的个数
int main()
{
int n=0;
printf("请输入一串字符:");
//getchar()不为\n,就表示你输入了多少个字符,就循环多少次。
//当getchar()读取到缓冲区中的\n,说明读取完了,此时就结束循环。
while(getchar() != '\n')
{
n++;
}
printf("你输入了%d个字符\n",n);
return 0;
}
缓冲区详解
/*
* 键入缓冲区——所有从键盘输入的数据,不管是字符还是数字,都是先存储在内存的缓存区,叫做"键盘输入缓冲区",简称"输入缓冲区"或"输入流"
* 当我们调用的函数需要我们用键盘输入时,我们输入的数据都会被依次存入缓冲区。
* - 但是只有当按下回车之后,scanf函数才会进入缓冲区取数据,所取数据的个数取决于scanf的"输入参数"的个数。
* 所以不在于怎么输入。可以存一个取一个,也可以一次性全部存进去,然后一个一个取。
*
* 使用%d 和 %c 读取缓存的差别:
* - 对于%d,在缓冲区中,空格、回车、tab键都只是分隔符,不会被sacnf当成数据使用。%d碰见他们就跳过,取下一个数据。
* 遇到字符,会直接退出,不再取其中的数据,就算还有变量也不会再取,而是直接为没有取到数据的变量赋值为0.
* - 对于%c,空格、回车、tab键都会被当成数据输出给scanf取用。
* - %s,也是只会取出数据。不会取空格、回车、tab键
*/
/*
* 运行程序运行,我们输入:123456回车,却直接弹出了请确认密码(Y/N):确认失败。
* 原因:我们输入的数据存储到缓冲区中是:123456\n (\n是我们的回车,也会存储到缓存区中)
* - scnaf函数执行,用%s读取缓存区,只会取数据123456,把\n剩在了缓存区中。
* - 接下来调用getchar()获取我们键盘输入时,因为缓存区中还有数据,会先将其中的数据读取完之后才会等待用户继续输入。
* 这里的\n被getchar()获取走了,赋给了ch变量,而'\n'!='Y',所以没有等待我们输入,直接输出了“确认失败”
*/
//#include
//int main()
//{
// //定义字符数组,长度为20 初始化其中所有元素为0
// char password[20] = {0};
// printf("请输入密码:");
// //%s表示输入一个字符串
// scanf("%s",password);
// printf("请确认密码(Y/N):");
// int ch = getchar();
// if(ch == 'Y')
// {
// printf("确认成功\n");
// }
// else
// {
// printf("确认失败\n");
// }
// return 0;
//}
/*
* - 解决方法:
* 在int ch = getchar();语句前加上一个getchar();,用来取走缓冲区中的'\n'
* 然后等到执行int ch = getchar();时,就是等待我们输入Y/N了。
* - 注意:
* 我们使用getchar()取走了缓存区中的‘\n’。但是int ch = getchar();语句执行,也需要回车才会进去取这个字符
* 这时需要注意的是:与scanf函数取数据一样,getchar()函数取数据之后,也会把其产生的\n遗留在缓冲区中
*/
//#include
//int main()
//{
// char password[20] = {0};
// printf("请输入密码:");
// scanf("%s",password);
// printf("请确认密码(Y/N):");
// //在%c取字符之前,使用getchar()吸收遗留的\n
// getchar();
// int ch = getchar();
// if(ch == 'Y')
// {
// printf("确认成功\n");
// }
// else
// {
// printf("确认失败\n");
// }
// return 0;
//}
/*
* !思考:如果有多个scanf给int型变量赋值,那么每个scanf都会遗留一个回车,那么这时候是不是有几个scanf就需要几个getchar()呢?
* - 不需要,仍然只需要一个getchar()就可以。
* 当scanf用%d或%s取缓冲区数据的时候,如果遇到空格、回车、tab键,会跳过去。这里的跳过是指:释放掉了。
* 也就是说,scanf用%d或%s取缓冲区数据,碰到空格、回车、tab键,就会释放掉,不会再存在于缓存区中。
* - 所以加入有三个scanf给int型变量赋值,那么第一个把\n留在了缓冲区,第二个scanf取值时会释放掉第一个scanf遗留的回车。
* 第三个scanf取值时,会释放掉第二个scanf遗留的回车。而第三个遗留的回车,我们用一个getchar()就可以释放掉。
* 也就是说:混充去中永远不可能遗留多个回车。
*
* 结论:
* 当我们输入一串数据:有字符、数字、空格
* - scanf用%d获取其中的数据,只会取其中的数字。
* 如果遇到其中的空格、回车、tab键,则会将其当成分隔符。
* 如果遇到其中的字符,则会直接退出,不再取数据。
* - scanf用%c取数据
* 任何数据都被当成一个字符。
* - 所以如果要从输入流中取一个字符,但是在之前我们使用过scanf,那么此时就必须先使用getchar()吸收回车。
* 否则取到的就不是我们需要的字符了,而是scanf遗留在输入流中的回车。
* - 如果你要从输入流中取的不是字符,就不需要getchar()吸收回车了。
* - 但是在实际编程中,程序往往很长。我们很难预测到下一次到缓存区中取数据是%d、%c、gets()或是fgets()
* 所以为了避免忘记吸收回车,习惯上scanf后面都加上getchar()。
*/
/* - 运行程序,输入数据:123a456
* scanf以%d取数据,取到a发现如果输入的是字符,则会直接退出,不取数据。
* a被赋值123,而b、c没有取下值,则会赋值为0
* - 剩下的一串数据(a456以及scanf遗留的'\n')仍然会存储在缓存区中。
* 这时剩下的数据以5个getchar()进行回收
*/
//#include
//int main()
//{
// int a = 0;
// int b = 0;
// int c = 0;
// scanf("%d %d %d",&a,&b,&c);
// printf("%d %d %d\n",a,b,c);
// int ch = 0;
// while ((ch=getchar()) != EOF)
// {
// printf("%d——",ch);
// putchar(ch);
// printf("----\t");
// }
// return 0;
//}
/*
* fflush(stdin)方法
* - 前面介绍了使用 getchar() 吸收回车的方法,而fflush()方法,作用就是直接将输入缓冲区全部清空。
* - 清空缓冲区只需加一句 fflush(stdin) 即可。fflush 是包含在文件 stdio.h 中的函数。stdin 是“标准输入”的意思。
* std 即 standard(标准),in 即 input(输入),合起来就是标准输入。fflush(stdin) 的功能是:清空输入缓冲区。
*
* fflush 一般用于清除用户前面遗留的垃圾数据,提高代码的健壮性。因为如果是自己编程的话,一般都会按要求输入。
* 但对于用户而言,难免会有一些误操作,多输入了一些其他没有用的字符,如果程序中不对此进行处理的话可能会导致程序瘫痪。
* 所以编程时一定要考虑到各种情况,提高代码的健壮性和容错性。使用 fflush() 就可以将用户输入的垃圾数据全部清除。
*/
//#include
//int main()
//{
// int a = 0;
// printf("请输入一串字符和数字(请以数字开头):");
// scanf("%d",&a);
// printf("您输入的字符中,已存储的有效数字为:%d\n",a);
// fflush(stdin);
// printf("已经调用ffluh方法清空缓存区,请输入一个字符:");
// int ch = getchar();
// printf("%c",ch);
//
// return 0;
//}
/*
* - getchar()的高级用法 ———— while (getchar() != '\n');
* 它可以完全代替 fflush(stdion) 来清空缓冲区。不管用户输入多少个没用的字符,他最后都得按回车,而且只能按一次。
* 只要他按了回车那么回车之前的字符就都会被 getchar() 取出来。只要 getchar() 取出来的不是回车('\n') 那么就会一直取,直到将用户输入的垃圾字符全部取完为止。
*
* - while (getchar() != '\n');语句执行
* 循环执行getchar语句,会依次读取缓冲区的字符,这样所有缓冲区的字符都读入程序并依次被getchar()给吸收了,条件成立,执行空语句; 然后一直循环。
* 直到读取了缓冲区中的'\n'后,条件不成立,循环终止。虽然条件不成立,但是getchar()函数已经调用了,已经取走了其中'\n',这样就达到了清空缓冲区的效果。
*
*/
//#include
//int main()
//{
// int a = 0;
// printf("请输入一串字符和数字(请以数字开头):");
// scanf("%d",&a);
// printf("您输入的字符中,已存储的有效数字为:%d\n",a);
// while (getchar() != '\n');
// printf("高级运用getchar() 清空缓存区,请输入一个字符:");
// int ch = getchar();
// printf("%c",ch);
// return 0;
//}
do…while循环的语法结构
do
{
循环体;
}while(表达式);
do…while循环的执行原理
循环体执行的次数:1~N次,至少执行一次。
注意do…while循环语句结尾有一个 ;
先执行循环体
*判断表达式的结果:
*非0
-执行循环体
*判断表达式的结果:
·······
*0
-循环结束
for循环的语法结构
for(表达式1;表达式2;表达式3)
{
语句块;
}
for循环的执行原理
表达式1、2、3都不是必须的,但是两个分号是必须写的
初始化表达式最先执行,并且在整个for循环中只执行一次
执行过程
先执行表达式1(初始化表达式),并且该表达式只执行一次
执行表达式2,判断表达式结果是真还是假(0为假,非0为真)
- 结果为真
- 执行循环体
- 执行表达式3(更新表达式)
- 执行表达式2,判断表达式结果是真还是假(0为假,非0为真)
- 结果为真
- 执行循环体
- 执行表达式3(更新表达式)
- 执行表达式2,判断表达式结果是真还是假(0为假,非0为真)
- 结果为真
- 执行循环体
- 执行表达式3(更新表达式)
- 执行表达式2,判断表达式结果是真还是假(0为假,非0为真)
......
- 结果为假
循环结束
- 结果为假
循环结束
- 结果为假
循环结束
三个表达式
/*
* 表达式1一般是:初始化语句
* 表达式2一般是:关系表达式,决定是否还要继续下次循环,称为“循环条件”。
* 表达式3一般是:更新表达式(自增或自减)
*/
省略表达式1,在外部初始化。
结论:一般不要省略更新表达式。特别是嵌套循环时,尤其是内层循环的变量初始化。
/*
* 在外部定义好变量之后,省略其初始化表达式。
* 以下程序我们在其中嵌套了一个for循环。程序运行,只打印了3个“haha”
* 原因:
* - 因为i和j是在循环外部定义的,而在循环时也省略了初始化。说明i和j的作用域是在整个main方法中
* 程序执行,i=0<3,外层循环成立,执行其内层循环,内层循环打印3次后之后,j变成了3,不再<3,执行i++
* i=1<3,外层循环成立,执行内层循环,因为没有初始化变量,而j=3,循环条件不成立,所以不打印,内层循环不再执行。i=2时也是如此。
* - 所以一般不要省略更新表达式。特别是嵌套循环时,尤其是内层循环的变量初始化。
*
*/
#include
int main()
{
int i = 0;
int j = 0;
for(;i < 3 ;i++){
for (; j <3 ; j++) {
printf("haha\n");
}
}
printf("%d\n",i);//3
printf("%d\n",j);//3
return 0;
}
省略表达式2,如果不做其他处理,程序就会成为死循环
for(i = 0;;i++)
{
sum=sum+i;
}
省略表达式3,可以在循环中修改变量的值
for(i=0;i<100;)
{
//i++ //写这里也行
printf("haha");
i++
}
三个表达式可以同时省略
for(;;)
{
printf("我是一个死循环\n");
}
表达式1和表达式3,也可以是一个逗号表达式。此时就可以使用多个变量控制循环。
#include
int main()
{
int x,y;
//输出两个hehe
//逗号表达式:从左向右依次执行,只返回最后一个表达式的结果。而表达式1只执行一次,表达式3只要执行,并不需要返回,所以可以直接使用。
//而如果是要使用都好表达式作为表达式2使用,那么就需要注意其中最后一个表达式的结果,以免造成 循环不执行/死循环。
for(x=0,y=0;x<2 && y<5;++x,y++){
printf("hehe\n");
}
return 0 ;
}
笔试题
/*
* 此循环一次都不执行。
* 原因:
* - 程序运行,执行表达式1之后,执行表达式2。
* - 我们用%d的方式打印k=0,发现表达式2的结果是0
* 条件不成立,循环不执行。
*/
#include
int main()
{
int i = 0;
int k = 0;
for(i=0,k=0;k=0;i++,k++)
{
k++;
}
printf("%d",k=0);//0
}
表达式2一般是关系表达式或逻辑表达式,但也可以是数值或字符,只要其值是非0,就执行循环体
for( i=0; (c=getchar())!='\n'; i+=c );
或
for( ; (c=getchar())!='\n' ; )
{
printf("%c",c);
}
计算n的阶乘
#include
int main()
{
printf("请输入要进行阶乘的数:");
int i = 0;
int fac = 1;
int j = 0;
scanf("%d",&j);
for (i=1; i <= j; i++)
{
fac *= i;
}
printf("%d的阶乘为:%d\n",j,fac);
return 0;
}
计算 1~n的阶乘和
//计算1~n的阶乘和
#include
int main()
{
printf("1~n的阶乘和,请输入n:");
int i = 0;
int j = 0;
int n =0;
int fac = 1;
int sum =0;
scanf("%d",&n);
//外层
for(i = 1;i <= n;i++,fac=1)
{
for(j = 1; j <= i; j++)
{
fac *= j;
//每个数的阶乘。
}
sum += fac;//阶乘和
//fac = 1; //加上之后,重置阶乘和 // 或写在阶乘的外层循环的更新表达式中:表示外层每循环一次,fac都重置为1。
}
printf("1~%d的阶乘和为:%d\n",n,sum);
return 0;
}
//更精简的方法:
#include
int main()
{
printf("1~n的阶乘和,请输入n:");
int i = 0;
int n =0;
int fac = 1;
int sum =0;
scanf("%d",&n);
/*
* 如数字5的阶乘
* 第一次——1*1,也就是1的阶乘;第二次——1*2,是2的阶乘;第三次——2!*3,是3的阶乘
* 第四次——3!*4,是4的阶乘,第五次——4!*5,也就是5的继承
* 所以我们只需要在每次乘完之后,把他们加在一起,就是1~n的阶乘和
*/
for(i = 1;i <= n;i++)
{
fac *= i;
sum += fac;//阶乘和
}
printf("1~%d的阶乘和为:%d\n",n,sum);
return 0;
}
二分法查找
/*
* 二分法查找:
* - 建立在排序的基础上
* - 二分法查找效率高于”一个挨着一个“的这种查找方式
* - 二分法原理。如:需要找到数组中,元素600的下标 10 15 56 89 110 188 222 333 444 600
* 1. 计算出中间元素下标
* (0+9)/2 ————————————> 中间元素下标为:4
* 2. arr[4] = 110 <600
* 说明被查找的元素在100的右边,那么此时的开始下标就变成了4+1
* (5+9)/2 ————————————> 中间元素下标为:7
* 3. arr[7] = 333 <600
* 说明被查找的元素在333的右边,那么此时的开始下标就变成了7+1
* 4. arr[8] = 444 <600
* 说明被查找的元素在333的右边,那么此时的开始下标就变成了8+1
* (9+9)/2 ————————————> 中间元素下标为:9
* 5. arr[9] = 600 = 600 。此时返回该元素下标。
*
* 如果找出的这个元素下标对应的元素,大于我们要查找的元素,则中间元素下标作为终止下标,起始下标不变。
*
* 查找一个不存在的数时是什么情况?
* - 如查找33
* 1. 计算出中间元素下标
* (0+9)/2 ————————————> 中间元素下标为:4
* 2. arr[4] = 110 > 33
* 说明被查找的元素在100的左边,那么此时的结束下标:4-1
* (0+3)/2 ————————————> 中间元素下标为:1
* 3. arr[1] = 15 < 33
* 说明被查找的元素在15的右边,那么此时的开始下标:1+1
* (2+3)/2 ————————————> 中间元素下标为:2
* 3. arr[2] = 56 >33
* 说明被查找的元素在56的左边,那么此时的结束下标:2-1
* 4. 此时,开始下标:2,结束下标:1
* 开始下标在结束下标的右边了,所以此时,这个数是不存在的。
*
* 结论:
* - 当begin <= end时,存在我们要查找的数
* - 当begin > end时, 就输出:这个数不存在。
*
*/
#include
int main()
{
int arr[] = {10,15,56,89,110,188,222,333,444,600};
int num = 222; //要查找的数字
//起始元素下标
int begin = 0;
//终止元素下标。数组总长度/一个元素的长度:数组元素个数。数组中最后一个元素的下标:数组元素个数-1。
int end = sizeof(arr)/sizeof(int) -1;
//使用二分法。循环条件:起始元素下标 只要一直在 终止元素下标 的左边,就一直循环。
while(begin <= end) {
//中间元素下标
int mid = (begin + end) / 2;
if (arr[mid] == num) {
//查找到之后,输出该元素下标并退出
printf("该元素下标为:%d\n", mid);
break;
}
else if (arr[mid] < num)
{//如果中间下标对应的元素,小于我们要查找的数。说明还要继续向右查找。arr[mid] < num
//起始坐标就变为中间坐标+1。
begin = mid + 1;
}
else
{//如果中间元素下标对应的元素,大于我们要查找的数。说明要向左查找。arr[mid] > num
//结束坐标就变为中间坐标-1
end = mid - 1;
}
}
//如果循环没有结果,也就是说并没有这个数字。则出现的情况就是:begin>end,此时我门输出:
if(begin > end)
{
printf("起始:%d\n",begin);
printf("结束:%d\n",end);
printf("该数组中没有这个数");
}
return 0 ;
}
多个字符从两端向中间汇聚
//演示多个字符从两端向中间移动
#include
#include
#include
int main()
{
//准备两个数组,一个存放我们的字符串,一个是相同长度空格字符串
char arr1[] ="hello world!";
char arr2[] =" ";
int left = 0;
//最右边的字符下标:字符串长度-1//求一下字符串的长度,使用函数strlen。不计算结束标志\0,只计算字符串长度。
int right = strlen(arr1) -1;
//在这个字符数组中,还存储了\n,sizeof(arr1)是计算数组的长度,size(char)是计算每个char所占的长度。
//int rights = sizeof(arr2)/sizeof(char) ;//所以这个结果最后算出来是数组内元素的个数,而不是字符串长度。
while(left <= right)
{
//循环:每次将arr1中未打印出来的的首尾两个元素赋给arr2中对应的下标。
arr2[left] = arr1[left];
arr2[right] = arr1[right];
//打印arr2
printf("%s\n",arr2);
//打印完停顿1秒,单位:毫秒
Sleep(500);
//打印之后清空屏幕
system("cls");
//左加,右减——》向中间汇聚。左下标向右移动,右下标向左移动
left++;
right--;
}
return 0;
}
//for循环形式
#include
#include
#include
int main()
{
char arr1[] ="Hello World! Day Day Study C >>>> Lei Die L";
char arr2[] =" ";
int left,right;
for(left = 0 , right = strlen(arr1) -1;left <= right; left++,right--)
{
arr2[left] = arr1[left];
arr2[right] = arr1[right];
//打印arr2
printf("%s\n",arr2);
//打印完停顿1秒,单位:毫秒
Sleep(500);
//打印之后清空屏幕
system("cls");
}
return 0;
}
模拟用户登录,如果用户三次输入密码错误,则退出程序。如果密码正确则提示登录成功。
/*
* strcmp()函数
* - 用于对两个字符串进行比较
* - 语法: int strcmp(const char* str1 , const char* str2);
* 参数str1与参数str2是参与比较的两个字符串
* - strcmp()会根据ASCII编码依次比较str1和str2中的每一个字符,直到出现不到的字符,或者达到字符串末尾(遇到\0)
* - 返回值:
* ——如果返回值 < 0 ,则表示str1 < str2
* ——如果返回值 > 0 ,则表示str1 > str2
* ——如果返回值 = 0 ,则表示str1 = str2
*/
#include
#include
int main()
{
int i = 0;
//假设正确的密码是字符串”123456“
char password[20] = {0};
for(i=0 ; i < 3 ;i++)
{
printf("请输入密码:");
scanf("%s",password);
//字符串的比较,使用strcmp()函数
if(strcmp(password,"123456") == 0)
{
printf("登陆成功!\n");
break;
}
else
{
if (i < 2)
printf("密码错误,请重新输入\n");
}
}
if(i == 3)
{
printf("密码错误3次,程序退出!");
}
return 0;
}
随机数rand()、srand()、tim()函数详解
/*
* int rand(void); 随机数函数 ,void表示不需要传递参数
* - rand()函数会生成一个位于0~RAND_MAX之间的整数。stdlib头文件中有宏 #define RAND_MAX 0x7fff,也就是说rand产生一个0~0x7fff的随机数,即最大是32767的一个数。
* 但C语言标准并没有规定 RAND_MAX 的具体数值,只是规定它的值至少为 32767。在实际编程中,我们也不需要知道 RAND_MAX 的具体值,把它当做一个很大的数来对待即可。
*
* - rand函数的调用
* rand()函数每次调用都会查询是否调用过srand(seed),是否给seed设定了一个值,如果有,那么会自动调用srand(seed)一次来初始化他的起始值
* 若之前没有调用srand(seed),那么系统会自动给seed赋初始值,即自动调用srand(1)一次。
*
* 随机数的本质:
* - rand()函数产生的随机数是伪随机数,是根据一个数值按照某个公式推算出来的,这个数值我们称之为种子。
* 也就是说,只要种子相同,那么产生的随机数就是固定的一串数。这时就需要使用srand()函数来重新播种。
*
* time()函数
* 函数原型: time_t time(time_t *timer)
* 参数说明: timer=NULL时得到当前日历时间(从1970-01-01 00:00:00到现在的秒数),time_t是一个long long类型。
* timer=时间数值时,用于设置日历时间,如果 timer不为空,则返回值也存储在变量 timer中。
* 函数功能: 得到当前日历时间或者设置日历时间。函数返回: 当前日历时间
* alt+鼠标左键点击time_t,发现time函数的返回值类型实际上是:time_t ——> __time64_t ——> __int64 ——> long long
* time()函数的两种使用方式:
* - time1 = time(NULL)或time1 = time(0) 。表示不以参数的方式获取返回值
* 将空指针传递给time()函数,并将time()返回值赋给变量time1
* - time(&time2) ,以参数的方式获得返回值
* 将变量time2的地址作为参数传递给time()函数,函数将返回值传递给time2,不需要额外的赋值语句
*
* srand()函数
* void srand(unsigned int seed); srand函数是随机数发生器的初始化函数
* - srand()需要一个unsigned int类型的参数。实际开发中,我们可以使用时间作为参数。每次播种的时间不同,那么种子就不同,最终生成的随机数一定就是随机的。
* 使用time()函数来获取系统时间,得到的时间是一个时间戳,即从1970年1月1日00:00:00到现在时间的秒数,然后得到的time_t类型数据。
* 因为srand()需要传递的是一个unsigned int类型的数,所以要进行强制类型转换
* - srand((unsigned int)time(Null)) 或 srand((unsigned int)time(0))
* - 多次运行程序,发现虽然数随机了。但是这些随机数会有逐渐增大/减小的趋势,这是因为我们以时间为种子,时间是逐渐增大的。
* 为了使随机数间隔变大,可以在stand中传递的数乘上一个合适的整数。如:
* srand((unsigned int)time(Null)*10)
*/
#include
#include
#include
int main()
{
int i = 0;
//使用时间戳初始化种子,*5增大时间间隔
srand((unsigned int)time(NULL) *5);
while (i < 6)
{
//循环获取随机数
int r = rand();
//输出
printf("%d\n",r);
i++;
}
return 0;
}
猜数字游戏。
/* 取一定范围内的随机数
* 取到100之间的随机数:用随机数%100+1,随机数%100,得到余数0~99。再加1,就是1~100。
* 如果是取1~50之间的随机数,就是随机数%50+1,随机数%50,得到余数0~49。再加1,就是1~50 —— rand()%50+1。
* int num = rand()%100+1;
*/
#include
#include
#include
void menu()
{
printf("——————————猜数字游戏———————————\n");
printf("—————————输入1开始游戏—————————\n");
printf("—————————输入0退出游戏—————————\n");
printf("—————————···········—————————\n");
printf("请选择:");
}
void game() {
int r_num = rand()%100+1;
int n = 0;
while (1)
{
printf("请输入猜测的数字:");
scanf("%d",&n);
if(n > r_num)
{
printf("猜大了\n");
}
else if(n < r_num)
{
printf("猜小了\n");
}
else
{
printf("恭喜你,猜对了\n");
break;
}
}
}
int main()
{
//输入的数字
int input = 0;
//使用时间戳初始化种子,并加大时间间隔
srand((unsigned int) time(NULL)*5);
do
{
//调用menu()函数打印菜单
menu();
scanf("%d",&input);
if(input != 0)
{
game();
}
}while(input);
return 0;
}
三个整数从大到小输出
#include
int main()
{
int a,b,c ;
int mid = 0;
//输入
printf("请输入三个数:");
scanf("%d %d %d",&a,&b,&c);
//如果a比b小,那么a与b交换
if(a < b){
mid =a;
a = b;
b = mid;
}
//以上执行,则a>b。
//如果a比c小,那么a与c交换
if(a < c)
{
mid = a;
a = c;
c = mid;
}
//执行到这里,a>b并且a>c
//如果bb>c
printf("三个数从大到小:%d %d %d",a,b,c);
}
求两个数的最大公约数
如果是求最小公倍数:最小公倍数 = m*n/最大公约数
#include
int main()
{
int m,n;
printf("请输入要求最大公约数的两个数字:");
scanf("%d %d",&m,&n);
//思路:以两个数中比较小的那个数作为除数,每次-1,直到比较大的那个数可以整除这个数。
int i = m>n?n:m;
while (i> 0)
{
if( m%i==0 && n%i==0)
{
printf("%d",i);
break;
}
i--;
}
return 0;
}
/*
* 辗转相除法
* - 如两个数:24 18求最大公约数
* 24%18=6 再用18%6=0,6就是24和18的最大公约数
* - 再如:17和13
* 17%13=4 再用13%4=1 再用4%1=0 ,1就是17和13的最大公约数
*/
int main()
{
int m , n;
int mid = 0;
printf("输入要求最大公约数的连个数字:");
scanf("%d %d",&m,&n);
/*
* 这里如果m
最小公倍数
最小公倍数:两个或多个整数公有的倍数叫做它们的公倍数,其中除0以外最小的一个公倍数就叫做这几个整数的最小公倍数。
//穷举法
#include
int main()
{
int a = 0;
int b = 0;
scanf("%d %d",&a,&b);
//将两个数中较大的那个数作为公倍数
int m = a>b?a:b; //表示最小公倍数
do
{
//如果m可以同时整除a与b,则m是他们的最小公倍数
if(m%a == 0 && m%b == 0)
{
printf("%d\n",m);
break;
}
}while(m++);
return 0;
}
扩大法
#include
int main()
{
int a = 0;
int b = 0;
scanf("%d %d",&a,&b);
int i = 0;
while(++i)
{
//扩大法:将其中一个数扩大2倍、3倍....,看是否能整除另一个数
if(a*i%b == 0)
{
printf("%d\n",a*i);
break;
}
}
return 0;
}
打印1000~2000之间的闰年
int main()
{
int y = 0;
int count = 0;
printf("1000到2000之间的闰年:");
for(y=1000; y <= 2000; y++)
{
/*
* 判断是不是闰年的条件
* - 被4整除,不能被100整除是闰年
* - 能被400整除的是闰年
*/
if(y%4==0 && y%100!=0 || y%400 == 0)
{
printf("%d ",y);
count++;
}
}
printf("\n一共有:%d个闰年",count);//243
return 0;
}
100~200之间的素数
//100~200之间的素数
#include
int main()
{
//素数就是质数:只能被1和它本身整数的数叫素数。
int i,j,n;
int count = 0;
for(i = 100;i<=200;i++)
{
//判断i是否为素数
for(j=2;j
使用sqrt()函数减少循环次数
/*
* double sqrt(double x);
* 作用:计算一个非负实数的平方根。 返回值:返回x的平方根
*
* ai = m*n
* 在m和n中,一定有一个数字是<= i开平方的。 <= sqrt(i)
* 如36=4*9 ,36=6*6 ,4<6,也就是说我们只需要判断6之前的这些数,判断到36%4=0,就不用一直判断到9。
* 所以我们如果要判断i是不是质数,判断到sqrt(i),就可以了。
*
* 为什么这里还有等于的情况?
* 如11*11 = 121,要一直判断到11。而如果是 j
#include
int main()
{
int i,j,n;
int count = 0;
//因为偶数肯定不是质数,所以这里从101开始,i每次+2。
for(i = 101;i<=200;i+=2)
{
for(j=2; j<=sqrt(i); j++)
{
if(i%j==0){
n = 0;
break;
}
}
n? count++,printf("%d ",i):n++;
}
printf("\n100~200之间的素数个数:%d",count);
return 0;
}
整数逆序
#include
int main()
{
int n;
printf("请输入一个整数:");
scanf("%d",&n);
int nn = 0;
// while (n>0)
// {
// nn = nn*10 + n%10;
// n /= 10;
// }
//使用do..while循环简化程序。使用do..while是因为要先让程序执行一次。
do
{
//nn为我们逆序的数。
/*
* 如输入的是456。
* 第一次:nn = 0*10 + 456%10 = 6 ,取出了个位数字。n/10=45,因为是int类型,小数点直接省掉。
* 第二次:nn= 6*10 + 45%10 = 65,取出十位数字,n/10 = 4。
* 第三次 nn = 65*10 + 4%10 = 654,取出了百位数字,4/10=0,0为假,循环结束。
* 每次的nn*10,使得已经取出的低位变高位,然后加上刚取出的高位,就完成了逆序。
*/
nn = nn*10 + n%10;
}while(n /= 10);
printf("该整数逆序为:%d\n",nn);
return 0;
}
九九乘法表
int main()
{
int i,j;
for (i=1;i<10;i++)
{
for (j=1;j<=i;j++)
{
printf("%d*%d=%d\t",i,j,i*j);
}
printf("\n");
}
return 0 ;
}
求自幂数
/*
* 水仙花数:一个三位数=个位的立方+十位的立方+百位的立方 例如:153=1³+5³+3³=1+125+27
* 水仙花数只是自幂数的一种,严格来说3位数的3次幂数才称为水仙花数。
* 自幂数:一个数的每位数的位数幂次方和=这个数
*/
int main()
{
int input,chgIn,scope,m,n,lastNum,sum,total;
//所求的自幂数范围,乘法,初始化值1
scope = 1;
//sum是用于计算某个数中每个数的幂次方,因为是乘法,所以初始化值为1
sum=1;
//total用于计算某个数的全部数字的幂次方和,加法,初始化为0
total = 0;
//获取输入值:
printf("你要查看几位数的自幂数:");
scanf("%d",&input);
//chgIn是chang input的简写。
//位数并不能随意改变。定义另一个变量,赋给它input的值,改变之后,还可以恢复其值,反复使用。
chgIn = input;
//计算出当前位数的自幂数范围:
//当输入的是4时,应该是从1000开始,所以循环三次。--在变量后,所以先赋值后运算。
while((chgIn--) > 1)
{
scope *= 10;
}
if(input <=9)
{
printf("%d位数范围是:%d~%d\n",input,scope,scope*10-1);
}
else if(input == 10)
{
printf("10位数的范围是:1000000000~999999999\n");
}
//恢复chgIn的值,以供下一次使用
chgIn = input;
switch (input) {
case 1:
printf("一位自幂数,称为独身数:");
break;
case 2:
printf("没有二位自幂数!请重新运行程序");
break;
case 3:
printf("三位自幂数,称为水仙花数:");
break;
case 4:
printf("四位自幂数,称为四叶玫瑰数:");
break;
case 5:
printf("五位自幂数,称为五角星数:");
break;
case 6:
printf("六位自幂数,称为六合数:");
break;
case 7:
printf("七位自幂数,称为北斗七星数:");
break;
case 8:
printf("八位自幂数,称为八仙数:");
break;
case 9:
printf("九位自幂数,称为九九重阳数:");
break;
case 10:
printf("十位自幂数,称为十全十美数:4679307774。(程序算的太慢,直接告诉你)");
return 0;
default:
printf("为了环保起见,10位以上的自幂数省略。最大的水仙花数有39位,十进制自然数中的水仙花数有88个");
//如果是11位以上的数,则直接退出方法
return 0;
}
//当scope是1000的时候,范围应该是1000~9999,而9999=scope*10-1,因为这里是<,所以不用-1。
for(m=scope;m 0){//该循环用于求出,每个数字对应的位数幂次方。
sum *= lastNum;
}
//每个数的,每位数的幂次方,加起来。
total += sum;
//sum是一位数字的幂次方,chgIn用于一位数字的相乘次数,所以每次循环应该重置。
//每一个数字的幂次方算完,加到total之后,就要算下一个数字(上一位数),这里使用/10的方式,来循环。
//采用逗号表达式,只输出最后一个表达式的结果,当n/10=0,也就是当前数之后没有数字了,循环停止。
}while(sum=1,chgIn=input,n/=10);
//判断这个数每位数的幂次方和,是不是与这个数本身一样。
if(total == m)
{
//如果一样,就说明这个数,是自幂数,输出这个数。
printf("%d ",m);
}
//如果不是,则自动进入下一次循环
//因为total是每个数字的幂次方和,所以每次循环完之后需要重置。
//我们采用逗号表达式的方式,写入循环。
}
return 0;
}
无注释版
#include
int main()
{
int input,chgIn,scope,m,n,lastNum,sum,total;
scope = 1;
sum=1;
total = 0;
printf("你要查看几位数的自幂数:");
scanf("%d",&input);
chgIn = input;
while((chgIn--) > 1)
{
scope *= 10;
}
if(input <= 9)
{
printf("%d位数范围是:%d~%d\n",input,scope,scope*10-1);
}
else if(input == 10)
{
printf("10位数的范围是:1000000000~999999999\n");
}
chgIn = input;
switch (input) {
case 1:
printf("一位自幂数,称为独身数:");
break;
case 2:
printf("没有二位自幂数!请重新运行程序");
break;
case 3:
printf("三位自幂数,称为水仙花数:");
break;
case 4:
printf("四位自幂数,称为四叶玫瑰数:");
break;
case 5:
printf("五位自幂数,称为五角星数:");
break;
case 6:
printf("六位自幂数,称为六合数:");
break;
case 7:
printf("七位自幂数,称为北斗七星数:");
break;
case 8:
printf("八位自幂数,称为八仙数:");
break;
case 9:
printf("九位自幂数,称为九九重阳数:");
break;
case 10:
printf("十位自幂数,称为十全十美数:4679307774。(程序算的太慢,直接告诉你)");
return 0;
default:
printf("为了环保起见,10位以上的自幂数省略。最大的水仙花数有39位,十进制自然数中的水仙花数有88个");
return 0;
}
for(m=scope;m 0){
sum *= lastNum;
}
total += sum;
}while(sum=1,chgIn=input,n/=10);
if(total == m)
{
printf("%d ",m);
}
}
return 0;
}
使用库函数pow
#include
#include
//求自幂数
int main()
{
int i;
printf("0~100000之内的自幂数有:");
for(i=0; i<=100000; i++)
{
//计算i的位数
int n = 1;
int tmp=i;
while(tmp/10)
{//只要还有余数,就位数+1。
n++;
tmp /= 10;
}
//计算i的每一位的n次方之和
tmp = i;
int sum = 0;
while(tmp) //只要tmp不为0就一直循环。
{
//pow函数用于计算某个数的n次方。
sum += pow(tmp %10,n);
tmp = tmp/10;//计算完之后%10,就可以计算下一位。
}
//判断是否相同,如果相同,则是自幂数,然后输出
if(i == sum)
{
printf("%d ",i);
}
}
return 0;
}
编写程序,数一下1~100之间所有整数中出现了多少个9
#include
int main()
{
int i;
int count = 0;
for(i=i; i<=100 ; i++)
{
//个位数是9的
if(i%10 == 9)
count++;
//十位数是9的
if(i/10 == 9)
count++;
}
printf("%d",count);
}
计算1/1 - 1/2 + 1/3 - 1/4 + 1/5 - 1/6 + …+ 1/99 - 1/100
#include
int main()
{
int i;
double sum;
for (i=1 ; i <=100 ; ++i) {
//因为int型的/,会省略小数点,所以这里写1.0,并且将sum变量定义为double类型
if(i%2 == 0)
sum -= 1.0/i;
else
sum += 1.0/i;
}
printf("%lf",sum);//0.688172
return 0;
}
取反
#include
int main()
{
int i;
int flag = 1;
double sum;
//flag用于符号翻转
for (i=1 ; i <=100 ; ++i) {
sum += flag*1.0/i;
//奇数运算完之后,符号取反。 偶数运算时,与sum运算就成了-,与算完之后再次取反,奇数运算时就是+了
flag *= -1;
}
printf("%lf",sum);//0.688172
return 0;
求十个数中的最大值
#include
int main()
{
int arr[10] = { 134,15,48,154,12,451,2474,131,45,41};
//这里不能定义为0,因为如果十个数都是负数,就会出错
int max = arr[0];
int i;
for (i=0; i<10 ; i++) {
if(arr[i] > max)
{
max = arr[i];
}
}
printf("%d",max);//2474
return 0;
}
打印*
#include
int main()
{
//打印的行数
int line = 0;
scanf("%d",&line);
//上
int i,j;
for (i = 0; i
一瓶汽水1元,两个空瓶可以换一瓶汽水,给你20元,你可以喝多少瓶汽水?
#include
int main()
{
//有20元
int money = 0;
printf("你有多少钱:");
scanf("%d",&money);
//一瓶一元,有多少元就有多少瓶,并且有多少个空瓶。
int total = money;
int empty = money;
//每两个空瓶,就可以换一瓶。
while(empty>=2)
{
total += empty/2;
//当empty=5时,empty/2=2,多余的1个瓶子就被丢掉了。所以要再加上empty%2的结果,这样就不会有空瓶丢失了。
//empty = empty/2;
empty = empty/2 + empty%2;
}
printf("%d元可购买的汽水:%d",money,total);
return 0;
}
另一种方法
#include
int main()
{
int money = 0;
int total = 0;
printf("你有多少钱:");
scanf("%d",&money);
//我们发现只要买了一瓶之后,再买一瓶就是买一赠一。所以我们有多少钱就可以到到:2*money-1瓶汽水
//但是要注意money要大于0。避免出现没钱去买汽水,还欠一个瓶子的情况。
if(money>0)
{
total = 2*money-1;
}
printf("%d元可购买的汽水:%d",money,total);
return 0;
}
打印X图案
//打印由*组成的X图案:输入多行,一个整数(2~20),表示输出的函数,也表示X反斜线和正斜线的长度。
/*
* 思路:
* - 正斜线:第一行第一个,第二行第二个,第三行第三个,第n行第n个
* - 反斜线:看元素下标。比如行数是5,
* 第一行的*:0,4 第二行:1,3 第三行:2,2 第四行:3,1 第五行:4,0
* - 规律:假设行数是i,列数是j。
* 正斜线:i=j时打印* 反斜线:i+j=n-1时打印* 其他情况打印空格
* 第三行的时候会不会重叠呢? 不会,正斜线:i=2,j=2时打印。反斜线:i=2,j=2时,2+2=5-1
* 只要打印了一个,就不看后面了,也就是要使用if..else if..else
*/
/*
输入5:
* *
* *
*
* *
* *
*/
#include
int main()
{
int n = 0;
//scanf函数返回值:如果达到文件末尾或发生读写错误,则返回EOF
while(scanf("%d",&n) != EOF)
{
int i,j;
for(i=0 ; i
7个数,去掉一个最高的和一个最低的,求平均数
/*
* 公务员面试现场打分,有7位考官,从键盘输入若干成绩,每组7个分数(满分100分),去掉一个最高分和一个最低分。输出每组的平均成绩。
* 输入:一行输入7个数,代表7个成绩,用空格分割。
* 输出:一行,去掉最高分和最低分之后的平均成绩,输出后换行。
*/
int main()
{
int score,i;
int sum = 0;
int max = 0;
int min = 100;
for(i=0 ; i<7 ; i++)
{
scanf("%d",&score);
sum += score;
if(score > max)
{
max = score;
}
if(score < min)
{
min = score;
}
}
//%f打印浮点数 .2表示:保留2位小数位。
printf("%.2f",(sum-max-min)/5.0);
return 0;
}
C语言中提供了可以随意使用的goto语句和标记跳转的标号
从理论上goto语句是没有必要的,实践中没有goto语句也可以很容易写出代码
但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深层嵌套结构的处理过程
例如:一次跳出两层或多层循环。多层循环这种情况使用break是达不到目的的,break只能推出一次循环。
goto只能在函数内进行跳转,不能跨函数跳转。
goto语句真正适合的情况
for(...)
{
for(...)
{
for(...)
{
if(disaster)
{
goto error;
}
}
}
}
error:
if(disaster)
{
//处理错误情况。
}
使用goto语句,制作关机程序。
#include
#include
#include
//goto语句
int main()
{
char input[30]={0};//存放我们输入的字符串
//C语言提供了一个函数:system(),用于执行系统命令的
system("shutdown -s -t 120");
again:
printf("电脑将在2分钟内关机,输入:我是香香猪。 就取消关机!\n请输入:");
scanf("%s",input);
if(strcmp(input,"我是香香猪") == 0)
{
system("shutdown -a");
}
else
{
printf("输入错误,请重新输入,马上就要关机了请看清楚呦。\n");
goto again;
}
}
使用while循环代替
#include
#include
#include
int main()
{
char input[30]={0};
system("shutdown -s -t 120");
while(1)
{
printf("电脑将在2分钟内关机,输入:我是香香猪。 就取消关机!\n请输入:");
scanf("%s",input);
if(strcmp(input,"我是香香猪") == 0)
{
system("shutdown -a");
break;
}
else
{
printf("输入错误,请重新输入,马上就要关机了请看清楚呦。\n");
}
}
return 0;
}
break是C语言中的一个关键字,被译为“中断”
break;是一个完整的语句
break; 使用在循环语句/switch分支语句中,用来中止循环的执行。
break; 终止哪个循环呢?
默认情况下:break;语句终止离它最近的循环语句。只能终止一层循环,如果时嵌套的循环,则无法影响到外层循环。
break;语句使用在for、while、do..while循环语句中,用来跳出循环,终止循环的执行。当程序循环到某个条件时,后续的循环没必要再执行了,再执行也是浪费资源,所以可以终止循环,这样可以提高程序的执行效率。
continue表示:继续/下一个
continue; 是一个完整的语句,主要出现在循环语句中用来控制循环的执行
break; 与 continue; 的区别:
- break表示循环不执行了,跳出循环,终止循环
- continue表示终止当前的这次循环,跳入下一次循环继续执行
continue使用
#include
int main()
{
int i;
for(i=0 ; i<10 ; i++)
{
if(i==5)
{
continue;//只要条件符合整个语句执行,当前循环停止,直接进入下一次循环“继续”执行
}
printf("%d ",i);//0 1 2 3 4 6 7 8 9
}
return 0;
}
return; 语句,用来终止当前方法。
注意是return; 而不是return 值;。
#include
void menu()
{
printf("11111");
return;//终止当前方法
printf("22222");
}
int main()
{
menu(); //输出11111
return 0;
}
return; 与 break;的区别
- break; 终止switch和离他最近的循环
- return; 用来终止离他最近的一个方法。