系列文章目录
C语言学习入门第一节——初识C语言
C语言学习入门第二节———分支语句和循环语句
分支语句和循环语句
分支语句
if
switch
循环语句
while
for
do while
goto语句
文章目录
一、语句的定义及分类
C语句可分为以下五类:
- 表达式语句
- 函数调用语句
- 控制语句
控制语句用于控制程序的执行流程,以实现程序的各种结构方式,它们由特定的语句定义符组成,C语言由九种控制语句。
可分为以下三类:
1.条件判断语句也叫分支语句:if语句、switch语句;
2.循环执行语句:do while语句、while语句、for语句;
3.转向语句:break语句、goto语句、continue语句、return语句。
- 复合语句(一个大括号括起来的几条语句)
- 空语句(只有一个 ; 就是空语句)
//表达式
#include <stdio.h>
int main()
{ //一个大括号括起来的几条语句就是复合语句
3 + 5; //这里的 3 + 5 就是表达式语句
printf("hehe"); //这里的 printf() 就是函数调用语句
; //只有一个 ; 就是空语句
return 0;
}
二、分支语句(选择结构)
1.if语句:
语法结构:
单分支:
if (表达式)
{
语句;}
双分支:
if (表达式)
{
语句1;}
else
{
语句2; }
多分支:
if (表达式)
{
语句1;
}else if (表达式2)
{
语句2;
}else
{
语句3;
}
单分支:
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
//单分支
if (age < 18)
{
printf("未成年");
//如果符合 表达式 ,则打印相应内容
//如果不符合 表达式 , 什么都不打印
}
return 0;
}
双分支:
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age < 18)
{
printf("未成年");
}
else
{
//如果不符合 表达式 ,则执行else里的语句
printf("已成年");
}
return 0;
}
多分支:
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age < 18)
{//<18 青少年
printf("青少年\n");
}
else if (age >= 18 && age <=30)
{//18~30 青年
printf("青年\n");
}
else if (age >= 31 && age <= 50)
{//31~50 中年
printf("中年\n");
}
else if (age >= 51 && age <= 80)
{//51~800 中老年
printf("中老年\n");
}
else if (age >= 81 && age <= 100)
{//81~100 老年
printf("老年\n");
}
else
{//100+ 寿星
printf("寿星\n");
}
return 0;
}
容易出错的地方:( * * * )
1.写语句部分时,最好都加上{},即使用复合语句,不然不管if是否成立,第一条语句后面的语句都会执行。
#include <stdio.h>
int main()
{
int age = 0;
scanf( "%age", &age );
if ( age > 18 )
printf("已毕业");
printf("上大学");
return 0;
}
2.不加{}的话,else会和最近的if匹配,有时会判断不清else是属于哪个if语句的(else的匹配: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");//else是和它离的最近的if匹配的,所以结果什么也不打印
return 0;
}
3.不同风格的写法会带来歧义
//补充3
#include <stdio.h>
int test1()
{
//int n = 20;
int n = 2;
if ( n > 5 )
return 1;
return 2;
printf("hehe\n");
}
int test2()
{
//int n = 20;
int n = 2;
if (n > 5)
{
return 1;
}
else
{
return 2;
}
}
int main()
{
int m = test1();
printf("%d\n", m);
//test1与test2结果一致但test2更容易理解
int n = test2();
printf("%d\n", n);
return 0;
}
3.if语句中的判断不要写成赋值。
#include <stdio.h>
int main()
{
int n = 0;
/*if (n == 5)
printf("hehe\n");*/
if (n = 5)
printf("hehe\n");//无论n是否等于5,都会打印hehe
return 0;
}
//解决少打一个=的方法,将常量放到左边
#include <stdio.h>
int main()
{
int n = 5;
if (5 == n)
//if (5 = n)会报错
printf("hehe\n");
return 0;
}
2.switch语句:
witch语句也是一种分支语句,常常用于多分支的情况。
语法结构:
语法结构: switch (整型表达式)
{
case 整型常量表达式: // case相当于入口
语句;
break; // break相当于出口
case1 整型常量表达式: // case相当于入口
语句;
break; // break相当于出口
case2 整型常量表达式: // case相当于入口
语句;
break; // break相当于出口 } ```
//switch语句
#include <stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
switch (day) // 得输入整型表达式
{
case 1: // case后写整形常量表达式
printf("星期一\n"); //语句
break; // 如果进入对应的case语句的话,退出switch语句,
// 否则之后的case语句也会被执行
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;
}
//星期一 ~ 星期五打印"weekday",星期六 ~ 星期日打印”weekend“
#include <stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("weekday\n");
break;
case 6:
case 7:
printf("weekend\n");
break;
}
return 0;
}
编程好习惯: 在最后一个 case 语句的后面加上一条 break语句。 (之所以这么写是可以避免出现在以前的最后一个 case 语句后面忘了添加 break语句)。
default不用非得放在switch的最后,switch也允许嵌套使用,break只会跳出一层switch
三、循环语句 (循环结构)
1.while循环语句:
while - 语法结构:
while (表达式)
{
…
循环语句;
}
(循环语句执行完后,再判定表达式,若成立,再进入while循环)
#include <stdio.h>
int main()
{
int n = 0;
//使用while循环打印 0~10
while ( n <= 10 )
{
printf("%d ", n);
n++;
}
return 0;
}
while语句中的break:
break在while循环中的作用: 其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。
所以:while中的break是用于永久终止循环的
//while循环
#include <stdio.h>
int main()
{
int n = 0;
//使用break终止while循环
while (n <= 10)
{
if (n == 5)
{
break;//当n = 5时跳出循环,结束打印
}
printf("%d ", n);
n++;
}
return 0;
}
while语句中的continue:
continue在while循环中的作用就是: continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,
而是直接跳转到while语句的判断部分。进行下一次循环的入口判断
//while循环
#include <stdio.h>
int main()
{
int n = 1;
//使用continue跳过循环中continue后面的语句
while (n <= 10)
{
if (n == 5)
{
continue;//当n = 5时,因为遇到continue跳过continue后面的语句
//不再打印和++所以n永远为5,程序进入死循环
}
printf("%d ", n);
n++;
}
return 0;
}
getchar()函数 和 putchar()函数:
#include <stdio.h>
int main()
{
int ch = getchar();// getchar()函数:接收一个字符
// 如果接收失败的话,会返回EOF(即-1),
// 所以,该函数的返回类型是 int,
// 接收该函数返回值的变量也应该是int
// 因为字符本质是ASCii码,所以也可以接收字符
printf("%c\n", ch);
putchar(ch); // 跟getchar对应的还有putchar
// putchar()函数:打印字符,只能打印字符
return 0;
}
利用while和getchar()函数来实现多组输入:
#include <stdio.h>
int main()
{
int ch = 0;
// EOF - end of file - 文件结束标志
// #define EOF (-1)
// 在函数读取失败的时候返回了 EOF
// 之前介绍过利用 scanf函数 来实现多组输入
// scanf 函数读取成功,返回的是读取到的数据的个数
// 读取失败返回 EOF
// getchar 读取成功返回字符的ASCII码值
// 读取失败返回EOF
// 回车也会读取,先读输入的字符,在读回车
// ctrl + Z - 会让 scanf 或者 getchar 返回 EOF
while ( (ch = getchar()) != EOF )
{
putchar( ch );
}
return 0;
}
利用while和getchar清空缓冲区:
#include <stdio.h>
int main()
{
//123456
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s", password); // 数组本身就是地址,所以这里不用加&(取地址符)重点!!
printf("请确认密码(Y/N):");
char input = 0;
//getchar(); // 把键盘输入的 \n(回车) 取走 ,如果不清除缓冲区就会直接打印确认失败。
//清理掉缓冲区中剩余的数据
while (getchar() != '\n')//循环直到取走\n(回车)为止
{
;
}
scanf("%c", &input); // 因为input是变量,所以要加&(取地址符)
if ('Y' == input)
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}
2.for循环语句
for循环语句格式:
for (表达式1; 表达式2; 表达式3)
{
循环语句;
}
表达式1:初始化部分,用于初始化循环变量的。
表达式2:条件判断部分,用于判断循环是否终止。
表达式3:调整部分,用于循环条件的调整。
#include <stdio.h>
int main()
{
int i = 0;
//表达式1的变量最好在for循环外部声明
//在表达式1中声明可能会出问题,C++可以这么用(C99)
for ( i = 0; i <= 10; i++)
// 表达式1 表达式2 表达式3
{
printf("%d ", i);
//表达式4(循环语句)
//程序执行顺序1->2->4->3,然后2->4->3循环
}
return 0;
}
for语句中的break:
#include <stdio.h>
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
if (i == 5)
{
break;//当i = 5时,break跳出循环。整个for循环结束
}
printf("%d ", i);
}
return 0;
}
for语句中的continue:
#include <stdio.h>
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
if (i == 5)
{
continue;//当i = 5时,continue跳过continue后面的代码,所以5跳过不打印
}
printf("%d ", i);//结果为1 2 3 4 6 7 8 9 10
}
return 0;
}
for循环语句的循环控制变量:
建议:
- 不可在for 循环体内修改循环变量,防止 for 循环失去控制。
- 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。
(1).不要在for循环体内修改循环变量,防止for循环失去控制:
#include <stdio.h>
int main()
{
int i = 0;
for (i = 0; i <= 10; i++)
{
i = 4;//i永远为4,死循环打印4
if (i == 5)
{
continue;
}
printf("%d ", i);
}
return 0;
}
(2).建议for语句的循环控制变量的取值采用“前闭后开区间”写法:
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//下标: 0 1 2 3 4 5 6 7 8 9
int i = 0; //[0 , 10)
for ( i = 0; i < 10 ; i++)
// 这里 i = 0 是 闭区间,i < 10 是 开区间,即“前闭后开区间”写法,[0 , 10).
// 可以清楚地看到 循环次数是 10次
{
printf("%d ", arr[i]);
}
return 0;
}
一些for循环的变种:
1.for循环中的初始化部分(表达式1),判断部分(表达式2),调整部分(表达式3)是可以省略的,但是不建议初学时省略,容易导致问题.
2.省略掉初始化部分。
3.使用多于一个变量控制循环:
(1).省略for循环中的初始化部分(表达式1),判断部分(表达式2),调整部分(表达式3):
#include <stdio.h>
int main()
{
//初始化和调整部分的省略就是啥都不做
//判断部分省略了,意味着判断是恒为真的
//建议不要随便省略
for (;;)
{
printf("hehe\n");//死循环打印hehe
}
return 0;
}
(2).省略掉初始化部分:
#include <stdio.h>
int main()
{
int i = 0;
int j = 0;
for ( ; i < 4; i++)//两个循环初始都省略
{
for ( ; j < 4; j++)//循环四次后,j 此时等于4,j < 4 不成立,跳出循环
{
printf("hehe\n");
}
}
return 0;
}
(3).使用多于一个变量控制循环:
#include <stdio.h>
int main()
{
int x, y;
for ( x = 0, y = 0 ; x<2 && y<5 ; ++x, y++ )
{
printf("hehe\n");
}
return 0;
}
3…do while循环语句
do while循环语句的语法:
do
{
循环语句;
}while (表达式);
注:无论是否满足条件,先执行一次循环语句,循环语句至少被执行一次是do while的特点
//使用do while语句打印1~10
#include <stdio.h>
int main()
{
int i = 1;
do
{
printf("%d ", i);
i++;
} while ( i <= 10 );
return 0;
}
四、go to语句
C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。 从理论上
goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。
但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。 例如:一次跳出两层或多层循环。
多层循环这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环.
某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程
goto语句真正适合的场景如下:
for(...)
{
for(...)
{
for(...)
{
if(disaster)
{
goto error;
}
}
}
}
....
error:
if (disaster)
{
//处理错误情况
}
1.goto语句和标记跳转的标号
C语言中提供了可以随意滥用的goto语句和标记跳转的标号
#include <stdio.h>
int main()
{
again://(顶格写)
printf("hehe\n");
goto again; //跳转到again的地方去
//随意跳转的goto语句
//标记跳转的标号:again
//死循环打印hehe
return 0;
}
2.使用goto语句完成关机小程序:( * * * )
//关机程序
//1. 程序运行起来后,1分钟内电脑关机
//2. 如果输入:1 就取消关机(可修改)
#include <stdio.h>
#include <string.h>
#include <stdlib.h> // 类似java的import进入需要用的类
int main()
{
char input[20] = { 0 }; // 接收“1”
//程序倒计时关机
system("shutdown -s -t 60"); // 用system函数调用系统的倒计时关机命令
again:
printf("请注意,你的电脑在1分钟内关机,如果输入:1 就取消关机\n");
scanf("%s", input); // 数组名本来就是地址,不用加&
if (strcmp(input, "1") == 0) // strcmp这里需要<string.h>头文件
{
system("shutdown -a"); // 调用系统的取消关机命令
// system这里需要<stdlib.h>头文件
}
else
{
goto again;
}
return 0;
}
从理论上goto语句是没有必要的,实践中没有goto语句也可以很容易地写出该代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h> // 类似java的import进入需要用的类
int main()
{
char input[20] = { 0 }; // 接收“1”
//程序倒计时关机
system("shutdown -s -t 60"); // 用system函数调用系统的倒计时关机命令
while (1) // 条件非0,一直为真,死循环
{
printf("请注意,你的电脑在1分钟内关机,如果输入:1 就取消关机\n");
scanf("%s", input); // 数组名本来就是地址,不用加&
if (strcmp(input, "1") == 0) // strcmp这里需要<string.h>头文件
{
system("shutdown -a"); // 调用系统的取消关机命令
// system这里需要<stdlib.h>头文件
break;
}
}
return 0;
}