1. 分支和循环
C语言是一门结构化的程序设计语言
- 顺序结构
- 选择结构
- 循环结构
1.1 什么是语句?
C语言中由一个分号 ; 隔开的就是一条语句。
2. if语句 - 分支语句(选择结构)
语法结构:
if (表达式)
语句;
if (表达式)
语句1;
else
语句2;
多分支
if (表达式1)
语句1;
else if (表达式2)
语句2;
else
语句3;
2.1 代码1
#include <stdio.h>
int main()
{
int age = 0;
scanf_s("%d", &age);
if (age < 18)
{
printf("未成年\n");
}
}
2.2 代码2
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age < 18)
{
printf("未成年\n");
}
else
{
printf("成年\n");
}
}
2.3 代码3
#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");
}
}
注:
- 如果表达式的结果为真,则语句执行。
- 在C语言中如何表示真假?
- 0表示假,非0表示真。
- 要执行多条语句,要用一对 { } 括起来,{ }就是一个代码块。
- if…else语句控制多条语句时要用{ }的代码块
- 在C语言中如何表示真假?
2.4 悬空else
2.4.1 错误代码
/** 悬空else
*
* 错误代码
* 代码什么也没有显示,代码没错,只是else是属于第二个if语句的,
* 因为第一个if语句判断为假,所以没有执行第二条if语句,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;
}
2.4.2 改正
/** 悬空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;
}
2.4.3 运算符不正确
#include <stdio.h>
int main()
{
int num = 4;
if (5 == num)
{
printf("hehe\n");
}
//if (num = 5)
//{
// //= 赋值 == 判断相等
// printf("hehe\n");//运算符不正确 : 在 Boolean 上下文中执行了常量赋值。应考虑改用“ == ”
//}
return 0;
}
3. 循环语句
c语言循环语句
while循环
do..while循环
for循环
循环语句三要素:
1.循环变量的初始化;
2.循环条件;
3.循环变量的更新语句
4.switch语句
在switch语句中的 break
switch语句是一种分支语句。常常用于多分支的情况。
在switch语句中,我们没法直接实现分支,搭配break使用才能实现真正的分支。
4.1 语法形式
switch (整型表达式)
{
语句项;
}
语句项:
case 整型常量表达式
语句;
4.2 例子:
// 输入1,输出星期一
// 输入2,输出星期二
// 输入3,输出星期三
// 输入4,输出星期四
// 输入5,输出星期五
// 输入6,输出星期六
// 输入7,输出星期七
//switch (整型表达式)
//{
// 语句项;
//}
//
//语句项:
//case 整型常量表达式
// 语句;
#include <stdio.h>
int main()
{
int day = 3;
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;
default :
printf("输入错误");
break;
}
return 0;
}
4.2.1 default子句
如果表达的值与所有的case标签的值都不匹配怎么办?
-
其实也没什么,结构就是所有的语句都被跳过而已。
-
程序并不会终止,也不会报错,因为这种情况在C中并不认为适合错误。
但是,如果你并不想忽略不匹配所有标签的表达式的值时该怎么办呢?
- 你可以在语句列表中增加一条default子句
default: 可以写在任何一个case标签可以出现的位置。
- 当 switch表达式的值并不匹配所有case标签的值时,这个default子句后面的语句就会执行。
所以,每个switch语句中只能出现一条default子句。
- 但是它可以出现在语句列表的任何位置,而且语句流会像贯穿一个case标签一样贯穿default子句。
编程习惯:
- 在每个switch语句中都放一条default子句是个好习惯,甚至可以在后边再加一个break 。(之所以这么写是可以避免出现在以前的最后一个 case 语句后面忘了添加 break语句)。
4.2.2 练习
//练习
#include <stdio.h>
int main()
{
int n = 1,m = 2;//开始:n =1,m =2
switch (n)//因为 n=1 所以执行case 1
{
case 1:
m++;
case 2:
n++;
/*
因为case 1没有加break,执行完case 1继续执行case 2
所以m++ ==> 3 n++ ==>2
*/
case 3://因为case 2也没有加break,继续执行
switch (n)
{//switch允许嵌套使用
case 1:
n++;
case 2:
m++;
n++;
break;
}
/*
继续执行switch语句
因为n = 2,所以执行case 2语句项m++ ==> 4 n++==>3
break退出
又因为case 3没有加break,继续执行case 4
*/
case 4://执行case 4m++==> 5 遇到 break 退出
m++;
break;
default:
break;
}
printf("m = %d, n = %d\n", m, n);//打印m= 5, n = 3
return 0;
}
代码步骤图解
5. while语句
5.1 while 语法结构
while (表达式)
循环语句;
当条件满足的情况下,if语句后的语句执行,否则不执行。但是这个语句只会执行一次。
而且生活中很多的实际的例子是∶同一件事情我们需要完成很多次。
C语言中引入了 : while语句,可以实现循环。
5.2 Eg:在屏幕上打印1-10的数字
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
printf("%d ", i);
i = i + 1;
}
return 0;
}
5.3 while语句中的break和continue
5.3.1 break介绍
/* while语句中的break
*
* 总结:
* break在while循环中的作用:
* 其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。
* 所以:while中的break是用于永久终止循环的。
*/
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (i == 5)//当i为5的时候终止循环
break;
printf("%d ", i);//1 2 3 4
i = i + 1;
}
return 0;
}
5.3.2 continue介绍
/*while语句中的continue
*
* 总结:
* continue在while循环中的作用就是:
* continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,
* 而是直接跳转到while语句的判断部分。
* 进行下一次循环的入口判断。
*/
continue死循环了
//#include <stdio.h>
//
//int main()
//{
// int i = 1;
// while (i < 10)
// {
// if (i == 5)
// continue;
// printf("%d ", i);
// i = i + 1;
// }
// return 0;
//}
//改正
#include <stdio.h>
int main()
{
int i = 0;
while (i < 10)
{
i = i + 1;
if (i == 5)//判断为5成立,跳出该次循环
continue;
printf("%d ", i);
}
return 0;
}
6. while 练习题
//介绍getchar()
//getchar()函数的功能是一个一个地读取你所输入的字符
#include <stdio.h>
int main()
{
int ch = getchar();
putchar(ch);//接受一个字符并打印输出
printf("%c\n", ch);//将ch的字符打印输出
return 0;
}
6.1 下面代码什么意思?
6.1.1 代码1
#include <stdio.h>
int main()
{
int ch = 0;
//ctrl + z ==> EOF
//EOF - end of file -> -1
while ((ch = getchar()) != EOF)
{
putchar(ch);
}
//输入EOF还是不行,ctrl+z才可以停止循环,因为OF被放在缓冲区
/*
getchar输入字符,每次读取一个字符其他放入缓冲区
OF放入缓冲区,留下E,E被putchar接收
putchar接收到E <-- EOF --> OF放入缓冲区
*/
return 0;
}
//-----------------------出现问题-----------------------------------
//输入EOF还是不行,ctrl+z才可以停止循环,因为OF被放在缓冲区
//查看系统的EOF其实是 -1
//-----------------------出现问题-----------------------------------
输入EOF还是不行,ctrl+z才可以停止循环,因为OF被放在缓冲区
查看系统的EOF其实是 -1
6.1.2 getchar()的使用
//确认密码
#include <stdio.h>
int main()
{
int ret = 0, ch = 0;
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s", password);//输入密码,并存放在passsword数组中
printf("请确认(Y/N):>");
ret = getchar();//输入一个Y/N字符
if (ret == 'Y')//判断是否输入的事“Y”
{
printf("确认成功\n");//如果输入“Y”字符则输出确认成功
}
else
{
printf("放弃确认\n");//否则输出确认成功
}
return 0;
}
//-----------------------出现问题-----------------------------------
//出现错误:运行程序,输入密码,确定后,没有下一步操作就直接放弃确认
/* - 分析步骤
步骤1:经过输入函数,输入密码:1234
步骤2:输入的密码放入缓冲区
步骤3:因为输入1234的时候还有一个“\n”结束符,1234放入数组,但是“\n”还放在输入缓冲区,所以getchar()接受的是“\n”
步骤4:getchar接收的“\n”赋值给ret
步骤5:if语句判断ret的内容不为“Y",所以执行elsei语句操作
*/
//程序没有下一步操作就直接放弃确认
//-----------------------出现问题-----------------------------------
解决方法:缓冲区还有一个“\n”,可以再用getchar()读取一下“\n”
但是若输入的时候有空格,空格也是会停止输入数组
空格后面若很多字符,可以设置一个while循环把字符读取掉
//修改代码--确认密码
#include <stdio.h>
int main()
{
int ret = 0, ch = 0;
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s", password);//输入密码,并存放在passsword数组中
//修改
//缓冲区还有一个“\n”,可以再用getchar()读取一下“\n”
//但是若输入的时候有空格,空格也是会停止输入数组
//空格后面若很多字符,可以设置一个while循环读取字符掉
while ((ch = getchar()) != '\n')
{
;//空语句,因为此处不需要有操作
}
printf("请确认(Y/N):>");
ret = getchar();//输入一个Y/N字符
if (ret == 'Y')//判断是否输入的事“Y”
{
printf("确认成功\n");//如果输入“Y”字符则输出确认成功
}
else
{
printf("放弃确认\n");//否则输出确认成功
}
return 0;
}
6.1.3 代码2
#include <stdio.h>
int main()
{
int ch = 0;
while ((ch = getchar()) != EOF)//遇到EOF停止循环
{
if (ch < '0' || ch > '9')//遇到不是数字的字符就跳出这次循环,回到while判断语句,继续循环
continue;
putchar(ch);//遇到数字字符就打印输出
}
return 0;
}
7. for循环
7.1 语法
7.1.1 用for循环打印1-10
//for循环
// for (表达式1;表达式2;表达式3)
// 循环语句;
//表达式1 表达式1为初始化部分,用于初始化循环变量的。
//表达式2 表达式2为条件判断部分,用于判断循环时候终止。
//表达式3 表达式3为调整部分,用于循环条件的调整。
#include <stdio.h>
int main()
{
int i = 0;
//for(i=1/*初始化*/; i<=10/*判断部分*/; i++/*调整部分*/)
for (i = 1; i <= 10; i++)
{
printf("%d ", i);
}
return 0;
}
7.2 for循环和while循环对比
//for循环
//可以发现在while循环中依然存在循环的三个必须条件,
//但是由于风格的问题使得三个部分很可能偏离较远,
//这样查找修改就不够集中和方便。
#include <stdio.h>
int main()
{
int i = 0;
int j = 0;//while初始化
//初始化 判断 调整
for (i = 1; i <= 10; i++)
{
printf("for:%d\n", i);
}
while (j < 10)//判断
{
printf("while:%d\n", j);
j++;//调整
}
return 0;
}
//相同方法用while循环
#include <stdio.h>
int main()
{
int i = 0;
int j = 0;//while初始化
//初始化 判断 调整
for (i = 1; i <= 10; i++)
{
if (i == 5)
continue;
printf("for:%d\n", i);
}
//因为循环到i=5的时候,if语句判断成立跳过循环,执行下一次循环
//while (j < 10)//判断
//{
// if (j == 5)
// continue;
// printf("while:%d\n", j);
// j++;//调整
//}
//因为j=5的时候判断跳过循环执行下一次循环,但是没有进行调整操作,还是等于5,继续就死循环
return 0;
}
7.3 for语句的循环控制变量
7.3.1 建议1
//for语句的循环控制变量
//一些建议:
//1. 不可在for 循环体内修改循环变量,防止 for 循环失去控制。
//2. 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。
//1. 不可在for 循环体内修改循环变量,防止 for 循环失去控制。
//举例 - 错误代码 - 会出现死循环
//#include <stdio.h>
//
//int main()
//{
// int i = 0;
// for (i = 0; i < 10; i++)
// {
// if (i = 5)
// printf("haha\n");
// printf("hehe\n");
// }
//
// return 0;
//}
7.3.2 建议2
//for语句的循环控制变量
//一些建议:
//1. 不可在for 循环体内修改循环变量,防止 for 循环失去控制。
//2. 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。
//2. 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。
//举例
#include <stdio.h>
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;
}
7.4 一些for循环的变种
7.4.1 变种1
第一个例子
//一些for循环的变种
//变种1
/*
1.for循环的初始化、调整、判断都可以省略
但是∶
for循环的额判断部分如果被省略,那判断条件就是:恒为正
2.如果不是非常熟练,建议不要随便省略
*/
//以下代码出现死循环
//#include <stdio.h>
//
//int main()
//{
// for (;;)
// {
// printf("hehe\n");
// }
//
// return 0;
//}
第二个例子
#include <stdio.h>
int main()
{
int i = 0;
int j = 0;
//代码只打印10次 hehe ,因为j = 10(停止循环)回到第一个循环,
//第一个循环进行判断成立,继续执行第二个循环
//因为j在上一次循环已经等于10,并且第二个循环没有对j进行初始化
//所以判断j = 10 不小于 10,判断不成立,循环不执行
for (; i < 10; i++)
{
for (; j < 10; j++)
{
printf("hehe\n");//0 1 2 3 3 4 5 6 7 8 9 j = 10(停止循环)
}
}
return 0;
}
7.4.2 变种2
//变种2
#include <stdio.h>
int main()
{
int x, y;
//第一次判断:x = 0,y = 0, x < 2 && y < 5判断成立,执行循环
//第二次判断:x = 1,y = 1, x < 2 && y < 5判断成立,执行循环
//第三次判断:x = 2,y = 2, x < 2 && y < 5判断不成立,不执行循环
//因为&&:短路与,表示如果两个条件都成立则执行之后的逻辑
//所以因为x=2,x<2的条件不成立,循环不执行
for (x = 0, y = 0; x < 2 && y < 5; ++x, y++)
{
printf("hehe\n");
}
return 0;
}
7.5 面试题
请问下面代码循环要循环多少次?
//请问循环要循环多少次?
//循环0次,因为for循环的判断处事0赋值给k
//k恒为0,0为假,则循环条件不成立,循环0次
#include <stdio.h>
int main()
{
int i = 0;
int k = 0;
for (i = 0, k = 0; k = 0; i++, k++)
k++;
return 0;
}
8. do…while语句
8.1 do语句的语法
//do..while循环
// do语句的语法︰
// do
// 循环语句;
// while (表达式);
#include <stdio.h>
int main()
{
int i =1;
do
{
printf("%d ", i);
i++;
} while (i <= 10);
return 0;
}
8.2 do…while的break和continue
8.2.1 break
//break
#include <stdio.h>
int main()
{
int i = 0;
do
{
if (i == 5)
break;
printf("%d ", i);//打印0 1 2 3 4
i++;
} while (i <= 10);
return 0;
}
8.2.2 continue
//do..while循环的continue
//#include <stdio.h>
//
死循环
//int main()
//{
// int i = 0;
// do
// {
// if (i == 5)
// continue;
// printf("%d ", i);
// i++;
// } while (i <= 10);
//
// return 0;
//}