当前位置:网站首页>分支与循环(1)
分支与循环(1)
2022-07-28 09:12:00 【菜菜求捞】
分支与循环(1)
前言
在之前学习了初识C语言,只是对知识有一个初步的学习,但是很多细节还不够了解,所以从今天开始进行细致的学习。
c语言是结构化的程序设计语言
结构化指的是什么呢?
C语言中有三种结构,顺序结构,选择结构,循环结构。
顺序结构,从头走到尾(默认)
选择结构,生活中有很多选择,有人选择就业,有人选择考研
循环结构,重复做某一件事情就是循环
如果不是这三种结构,也是这三种结构的组合。
生活中的任意一件事情都可以拆分成三种结构。
选择结构在C语言中提供了if语句 switch语句
循环结构在C语言中提供了while循环 for循环 do while 循环。
分支语句与循环语句
分支语句对应的选择结构(if switch)
循环语句对应的循环结构(while for do…while)
1. 什么是语句
语句可以分为五类:
1表达式语句
2函数调用语句
3控制语句
4复合语句
5空语句
int main()
{
2+3; //表达式语句
Add(2,3); //函数调用语句
; //空语句
return 0;
}
本章后面介绍的是控制语句。
控制语句用于控制程序的执行流程,以实现程序的各种结构方式(C语言支持三种结构:顺序结构、选择结构、循环结构),它们由特定的语句定义符组成,C语言有九种控制语句。
可分成以下三类:
\1. 条件判断语句也叫分支语句:if语句、switch语句;
\2. 循环执行语句:do while语句、while语句、for语句;
\3. 转向语句:break语句、goto语句、continue语句、return语句。
像转向语句中的break语句、continue语句是在循环语句当中使用
return语句是放在函数当中使用的。
2. 分支语句(选择结构)
如果你好好学可以拿一个好offer
如果不好好学,回家卖红薯。
选择中可以有多个选择,可以有两个选择,也可以有多个选择。
2.1 if语句
if语句的语法结构
语法结构:
//单分支
if(表达式) //if后的表达式如果为真,执行语句。
语句; //C语言中0为假,非0为真,包括小数,负数,等非0数字。
//双分支
if(表达式) //表达式为真执行语句1,否则执行语句2
语句1;
else
语句2;
//多分支
if(表达式1) //表达式1为真,执行语句1
语句1;
else if(表达式2) //表达式1为假,表达式2为真,执行语句2
语句2;
else //如果表达式1,表达式2为假,执行语句3
语句3;
补充:
if else 语句默认控制一条语句,若想控制多条语句,可以使用大括号{}
课堂演示代码:
单分支:
#include <stdio.h>
int main()
{
int age = 20;
if (age<18)
printf("未成年\n");
return 0;
}
双分支:
#include <stdio.h>
int main()
{
int age = 20;
if (age<18)
{
printf("未成年\n");
printf("不能喝酒\n");
}
else
{
printf("成年\n");
printf("可以适量饮酒\n");
}
return 0;
}
多分支:
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if(age<18)
{
printf("少年\n");
}
else if(age>=18 && age<30)
{
printf("青年\n");
}
else if(age>=30 && age<50)
{
printf("中年\n");
}
else if(age>=50 && age<80)
{
printf("老年\n");
}
else
{
printf("老寿星\n");
}
}
这里的一堆{}就是一个代码块
2.1.1 悬空else
当你写了这个代码:
#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;
}
//--------------------------
//输出结果为
//不输出
else是与if的匹配原则为就近原则。
改正:
//适当的使用{}可以使代码的逻辑更加清楚。
//代码风格很重要
#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; }
else的匹配:else是和它离的最近的if匹配的。
2.1.2 if书写形式的对比
//代码1
if (condition)
{
return x;
}
return y;
//代码2
if(condition)
{
return x;
}
else
{
return y;
}
//代码3
int num = 1;
if(num == 5)
{
printf("hehe\n");
}
//代码4
int num = 1;
if(5 == num)
{
printf("hehe\n");
}
代码2和代码4更好,逻辑更加清晰,不容易出错。
2.1.3 练习
1判断一个数是否为奇数
2输出1-100之间的奇数
1
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d",&num);
if (num % 2 == 1)
{
printf("奇数\n");
}
else
{
printf("偶数\n");
}
return 0;
}
表达式不能被赋值,所以不需要 1 == num % 2
2方法一
#include <stdio.h>
int main()
{
int i = 0;
for (i=1; i<=100; i++)
{
if (i % 2 == 1)
{
printf("%d ",i);
}
}
return 0;
}
2方法二
#include <stdio.h>
int main()
{
int i = 1;
while (i<=100)
{
printf("%d ",i);
i += 2;
}
}
2.2 switch语句
switch语句也是一种分支语句。
常常用于多分支的情况。
比如:
输入1,输出星期一
输入2,输出星期二
输入3,输出星期三
输入4,输出星期四
输入5,输出星期五
输入6,输出星期六
输入7,输出星期日
那我没写成 if...else if ...else if 的形式太复杂,那我们就得有不一样的语法形式。
2.2.1在switch语句中的break
在switch语句中,我们没办法直接实现分支,搭配break使用才能实现真正的分支。
#include <stdio.h>
int main()
{
int day = 0;
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;
}
switch case 工作原理
case决定入口
break是出口
switch后面的表达式必须是整型表达式
case 后面的表达式必须是整型常量表达式
错误示范
int n = 0;
case n: //错误的,会报错
//即使是const修饰的常变量,本质也属于变量
有时候我们的需求变了:
1输入1-5,输出的是“工作日”;
2输入6-7,输出“休息日”
#include <stdio.h>
//switch代码演示
int main()
{
int day = 0;
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; }
编程好习惯
在最后一个 case 语句的后面加上一条 break语句。
之所以这么写是可以避免出现在以前的最后一个 case 语句后面忘了添加 break语句。
2.2.2 default子句
当switch表达式的值
当 switch 表达式的值并不匹配所有 case 标签的值时,这个 default 子句后面的语句就会执行。所以,每个switch语句中只能出现一条default子句。但是它可以出现在语句列表的任何位置,而且语句流会像执行一个case标签一样执行default子句。
2.2.3 练习
#include <stdio.h>
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\n", m, n);
return 0;
}
//------------------------------
//打印结果为
//m = 5, n = 3
switch支持嵌套,在嵌套里面的break只会跳出嵌套中的switch,不会跳过整个大的switch。
3. 循环语句
- while
- for
- do while
3.1 while循环
int main()
{
while (1)
printf("haha\n");
return 0;
}
while语法结构
while (表达式)
循环语句;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tNjZmHrE-1658845274898)(C:\Users\85989\AppData\Roaming\Typora\typora-user-images\image-20220724085614035.png)]
进行判断expr是否为真(!=0),为真执行stmt,再进行判断,反复执行,当有一天expr为假,退出循环。
在屏幕上打印1—10
int main()
{
int i = 1;
while (i <= 10)
{
printf("%d",i);
i++;
}
}
3.1.1 while语句中的break和continue
int main()
{
int i = 1;
while (i <= 10)
{
if(i==5)
break;
printf("%d ",i);
i++;
}
}
//--------------------
//打印结果为
//1 2 3 4
break总结:
break在while循环中的作用:
其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环
所以:while中的break是用于永久终止循环的。
break换成continue
int main()
{
int i = 1;
while (i <= 10)
{
if(i==5)
continue;
printf("%d ",i);
i++;
}
}
//--------------------
//打印结果为
//1 2 3 4 无限循环
continue会跳过本次循环continue后边的代码,直接去判断部分进行判断。由于i未发生变化,所以会陷入死循环中。
打印1-10除了5
int main()
{
int i = 0;
while (i <= 10)
{
i++;
if(i==5)
continue;
printf("%d ",i);
}
}
//--------------------
//打印结果为
//1 2 3 4 6 7 8 9 10
continue总结:
continue在while循环中的作用就是:
continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,而是直接跳转到while语句的判断部分。进行下一次循环的入口判断。
再看几个代码:
int main()
{
int ch = getchar();//获取字符,因为字符对应的ASCII码值是整数,所以放int可以。并且eof本质是-1,无法存储在char类型里面。
putchar(ch);
}
//输入一个字符,打印一个字符
//A
//A
int getchar (void);
如果成功,返回值就是读取到的字符,如果失败会返回EOF
EOF(end of file是文件结束标志)的本质是-1
int putchar (int character);
int main()
{
int ch = 0;
while((ch=getchar)!=EOF)
{
putchar(ch);
}
return 0;
}
可以实现多次输入和输出。
想要停止按ctrl+z
输入了一个A后回车,getchar读取了两次,第一次读取到A,A!=EOF,所以输出A,缓存区里面还有一个回车字符,!=EOF,所以输出一个回车
int main()
{
char password[20]={0};
printf("请输入密码:>");
scanf("%s",password); //数组名就是地址,所以不需要&
printf("请确认密码(Y/N):");
int ch = getchar();
if(ch=='Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
}
//---------------------------
//测试结果为:
//请输入密码:>asd
//请确认密码(Y/N):确认失败
确认失败原因:
scanf需要读取数据,在scanf和键盘之间有一个区域叫输入缓冲区,
scanf读取数据,先去输入缓冲区查看,有数据就读取,如果没有就等待
键盘中敲击的数据想要进入输入缓冲区需要回车\n
这个时候缓冲区内不仅有敲击的数据还有\n。
scanf从缓冲区拿走的数据仅仅是敲击的数据,\n还在输入缓冲区
这个时候缓冲区有东西,getchar直接读取,不需要等待,于是\n放在了ch中进行后续if的判断。
处理办法:
int main()
{
char password[20]={0};
printf("请输入密码:>");
scanf("%s",password); //数组名就是地址,所以不需要&
getchar(); //清理缓冲区的\n,只能清理掉一个字符
printf("请确认密码(Y/N):");
int ch = getchar();
if(ch=='Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
}
//------------------------------
//请输入密码:>adsfas123
//请确认密码(Y/N):Y
//确认成功
缺点
请输入密码:>asd asda
请确认密码(Y/N):确认失败
scanf在读取信息的时候,遇到空格不再读取,读取到asd,所以缓冲区还剩下空格asda\n,getchar会读取空格
修正
int main()
{
char password[20]={0};
printf("请输入密码:>");
scanf("%s",password); //数组名就是地址,所以不需要&
//清空缓存区,将\n以及之前的字符全部清空
int tmp = 0;
while((tmp = getchar())!='\n')
{
}
printf("请确认密码(Y/N):");
int ch = getchar();
if(ch=='Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
}
while(getchar()!='\n')
{
}
//也可以直接进行读取,不用进行存储在tmp
补充
((ch=getchar)!=EOF)中里面的括号不能省略,省略后先判断getchar()!=EOF为真,ch赋值为1,循环始终为真
getchar的返回值为int 不能定义为char类型。
练习
#include <stdio.h>
int main()
{
int ch = '\0';
while ((ch = getchar()) != EOF)
{
if (ch < '0'|| ch > '9')
continue;
putchar(ch);
}
return 0;
}
这个代码的作用是:只打印数字字符,跳过其他字符的、
3.2 for循环
for循环的形式是更优于while
int main()
{
int i =1; //初始化
while (i<10) //判断
{
i++; //调整
}
}
随着代码的逐渐增多,初始化,判断,调整三部分逐渐远离,容易出错。
3.2.1 for 语法
for(表达式1;表达式2;表达式3)
循环语句;
表达式1
表达式1为初始化部分,用于初始化循环变量的。
表达式2
表达式2为条件判断部分,用于判断循环时候终止。
表达式3
表达式3为调整部分,用于循环条件的调整。
用for循环实现打印1—10
int main()
{
int i = 0;
for(i=1;i<=10;i++)
{
printf("%d ",i);
}
return 0;
}
i=1为1 i<=10为2 代码块内部为3 i++为4
1执行一次后,2进行判断判断为真执行3,4进行调整,再次进行判断,是否为真,进行234步的循环
for循环的执行流程图
先进行表达式1,对表达式2进行判断,如果为真,执行循环体,再进行表达式3,表达式2再次判断进行循环,如果某次表达式2结果为假,则退出判断。
3.2.2 break和continue在for循环中的使用
在for循环中也可以出现break和continue,他们的意义和在while循环中是一样的。
但是还是有些continue上的差异:
break
#include <stdio.h>
int main()
{
int i = 0;
for(i=1;i<=10;i++)
{
if(i==5)
break;
printf("%d ",i);
}
return 0;
}
//----------------
//打印结果为
//1 2 3 4
continue
#include <stdio.h>
int main()
{
int i = 0;
for(i=1;i<=10;i++)
{
if(i==5)
continue;
printf("%d ",i);
}
return 0;
}
//----------------
//打印结果为
//1 2 3 4 6 7 8 9 10
i==5时跳过代码块的中的内容,进入调整部分,进行下一次循环。
在while循环中如果调整部分在continue后面的话可能会导致死循环。
但是for循环会进入调整部分,再进行判断。
3.2.3 for语句的循环控制变量
建议:
1.不可在for 循环体内修改循环变量,防止 for 循环失去控制。
2.建议for语句的循环控制变量的取值采用“前闭后开区间”写法。
1
int main()
{
int i = 0;
for(i=1;i<=10;i++)
{
i = 5;
printf("%d ",i);
}
return 0;
}
//-------------------
//循环打印5,所以不建议在循环体内修改循环变量。
2有时候建议采用前闭后开的方式
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int i = 0;
for(i=0;i<10;i++)
{
printf("%d ",arr[i]);
}
return 0;
}
3.2.4 一些for循环的变种
for循环语句中三个表达式可以省略,但是分号不可以省略
#include <stdio.h>
int main()
{
//代码1
for(;;)
{
printf("hehe\n");
}
//for循环中的初始化部分,判断部分,调整部分是可以省略的,但是不建议初学时省略,容易导致问题。
//但是省略但判断部分,则意味着判断恒为真
//代码2
int i = 0;
int j = 0;
//这里打印多少个hehe?
for(i=0; i<10; i++)
{
for(j=0; j<10; j++)
{
printf("hehe\n");
}
}
//代码3
int i = 0;
int j = 0;
//如果省略掉初始化部分,这里打印多少个hehe?
for(; i<10; i++)
{
for(; j<10; j++)
{
printf("hehe\n");
}
}
//代码4-使用多余一个变量控制循环
int x, y;
for (x = 0, y = 0; x<2 && y<5; ++x, y++)
{
printf("hehe\n");
}
return 0; }
//代码2
int main()
{
//代码2
int i = 0;
int j = 0;
//这里打印多少个hehe?
for(i=0; i<10; i++)
{
for(j=0; j<10; j++)
{
printf("hehe\n");
}
}
}
//打印100个hehe
//代码3
int main()
{
//代码3
int i = 0;
int j = 0;
//如果省略掉初始化这里打印多少个hehe?
for(; i<10; i++)
{
for(; j<10; j++)
{
printf("hehe\n");
}
}
}
//打印10个hehe
//当i=0 j=10的时候由于j没有初始化,不再进行内部循环
//代码4-使用多余一个变量控制循环,循环变量可以是多个,不止一个。
int main()
{
int x, y;
for (x = 0, y = 0; x<2 && y<5; ++x, y++)
{
printf("hehe\n");
}
return 0;
}
//-----------------
//打印结果为
//hehe
//hehe
3.2.5 笔试题
//请问循环要循环多少次?
#include <stdio.h>
int main()
{
int i = 0;
int k = 0;
for(i =0,k=0; k=0; i++,k++)
k++;
return 0;
}
//循环了0次,因为在判断部分k被赋值为0,为假。
边栏推荐
- Regular expressions are hexadecimal digits?
- Window源码解析(一):与DecorView的那些事
- C# 窗体应用使用对象绑定 DataGridView 数据绑定
- Source code analysis of view event distribution mechanism
- Introduction to SD card (based on spec3.0)
- View事件分发机制源码解析
- ShardingSphere之分库分表概念介绍(二)
- With frequent data leakage and deletion events, how should enterprises build a security defense line?
- MQTT. JS introductory tutorial: learning notes
- 就这么一个简单的校验,80%的程序员却做不到,更不理解!
猜你喜欢

【广西大学】考研初试复试资料分享

My vivado practice - single cycle CPU instruction analysis
![376. Swing sequence [greedy, dynamic planning -----]](/img/c3/46cdd8c9320c529171cbf963c768a7.png)
376. Swing sequence [greedy, dynamic planning -----]

ShardingSphere之分库分表概念介绍(二)

Oracle creates users with query permission only

Personal blog applet

ECCV 2022 | can be promoted without fine adjustment! Registration based anomaly detection framework for small samples

IDC script file running

就这么一个简单的校验,80%的程序员却做不到,更不理解!

Introduction to shardingsphere (I)
随机推荐
ASP.NET Core 6框架揭秘实例演示[29]:搭建文件服务器
The maximum recommended number of rows for MySQL is 2000W. Is it reliable?
21天学习挑战赛-《Autosar从入门到精通-实战篇》
2022 examination question bank and simulation examination of crane driver (limited to bridge crane)
网络工程——软科中国大学专业排名
Introduction to shardingsphere (I)
FPGA development learning open source website summary
Arouter source code analysis (III)
What is cross domain? How to solve the cross domain problem?
MQTT.js 入门教程:学习笔记
Hexadecimal representation of negative numbers
Changes in the relationship between data and application in IT industry
Pytorch deep learning practice lesson 9 multi classification problems (handwritten numeral MNIST)
Go language slice vs array panic runtime error index out of range problem solving
[high number] high number plane solid geometry
Analysis of the internal principle of ArrayList
mq的学习
Window源码解析(一):与DecorView的那些事
[multithreading] non atomic agreement of long and double
MySQL 8.0.30 GA