本篇笔记我们继续来学习第三部分《分支语句和循环语句》,在上一篇中我们详细学习了什么是语句以及分支语句------if语句,接下来本部分的内容还包括:分支语句------switch语句、循环语句------while循环、循环语句------for循环、循环语句------do while循环、折半查找算法、猜数字游戏、goto语句。
第三部分 分支语句和循环语句
三、分支语句------switch语句
1、switch语句概述
switch语句也是一种分支语句。 常常用于多分支的情况。
比如当我们想输入一个输出,输出对应的星期时:
输入1,输出星期一
输入2,输出星期二
输入3,输出星期三
输入4,输出星期四
输入5,输出星期五
输入6,输出星期六
输入7,输出星期七
写成 if...else if ...else if 的形式太复杂,那我们就得有不一样的语法形式。这时便使用到了switch 语句。
2、switch语句的语法结构
cpp
switch(整型表达式)
{
语句项;
}
而语句项是什么呢?------ 是一些case语句
cpp
case 整形常量表达式:
语句;
但是值得我们注意的是,switch语句没有办法直接实现分支,case语句只是决定了程序的入口,这时候需要搭配break才能实现真正的分支,当编译器遇到break时,才能主动将代码停止运行。
比如为了实现上面示例中的代码功能,实现代码如下:
cpp
#include <stdio.h>
int main(){
int day = 0;
printf("请输入一个整数:");
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("选择错误\n");
break;
}
return 0;
}
3、default子句
上面这段代码用到了default子句,这是用来解决如果表达的值与所有的case标签的值都不匹配的情况,此时结构中所有的语句都被跳过。但程序并不会终止,也不会报错,因为这种情况在C语言编译器中并不认为是个错误。
但是,如果你并不想忽略不匹配所有标签的表达式的值时就需要增加一条default子句,当 switch表达式的值并不匹配所有case标签的值时,这个default子句后面的语句就会执行。
所以,每个switch语句中只能出现一条default子句。但是它可以出现在语句列表的任何位置。
我们再来看一个例子可以更加深刻的理解switch语句的使用:
cpp
// 当我们希望输入数字1-5时,输出"weekday"
// 输入数字6-7时,输出"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;
default:
printf("输入错误\n");
break;
}
return 0;
}
4、switch语句编程习惯
(1)break语句的实际效果是把语句列表划分为不同的部分。所以我们应该明确什么时候break语句是必要的。
(2)在最后一个case语句的后面加上一个break语句。
(3)在每一个switch语句中都放入一条default子句,甚至可以在后面再加一个break。
5、switch语句的练习
(1)写出下面这段代码的运行结果
cpp
#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
四、循环语句------while循环
1、while循环的语法结构
我们已经学习并掌握了if语句:
cpp
if(表达式)
语句;
当条件满足的情况下,if语句后的语句执行,否则不执行。但是这个语句只会执行一次。但是我们发现生活中很多的实际的例子是:同一件事情我们需要完成很多次。此时C语言中便给我们引入了循环语句,while语句便是其中的一种,可以实现循环。
while语句的语法结构与if语句非常相似:
cpp
while (表达式)
循环语句;
while语句执行的流程:
比如我们实现一个简单的问题来观察while循环的语法结构:
cpp
//在屏幕上打印1-10的数字。
#include<stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
printf("%d ", i);
i += 1;
}
return 0;
}
2、while语句中的break语句和continue 语句
(1)break介绍
在循环中只要遇到break语句,就停止后期的所有的循环,直接终止循环。所以while循环中的 break语句是用于永久终止循环的。也就是当我们希望提前终止跳出循环的时候,可以使用到break语句。
下面我们来看这段代码,通过其输出结果体会break语句在while循环中的作用:
cpp
#include<stdio.h>
int main(){
int i = 1;
while (i <= 10){
printf("%d ", i);
if (5 == i)
break;
i += 1;
}
return 0;
}
(2)continue 介绍
continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,而是直接跳转到while语句的判断部分。进行下一次循环的入口判断。
continue 语句的运行结果会因为代码顺序导致结果并不相同,我们观察下面三个代码:
cpp
// 代码一
#include<stdio.h>
int main(){
int i = 1;
while (i <= 10){
printf("%d ", i);
if (5 == i)
continue;
i += 1;
}
return 0;
}
这个代码当i = 5进入时,会打印一次 5 ,但是由于continue语句,导致 i += 1; 永远不会执行,所以这段代码的运行结果会是在输出1 2 3 4 后不断地重复打印 5 。是一个死循环。
cpp
// 代码二
#include<stdio.h>
int main(){
int i = 1;
while (i <= 10){
if (5 == i)
continue;
printf("%d ", i);
i += 1;
}
return 0;
}
这个代码当i = 5进入时,由于continue语句,导致 5并不会被打印,同时 i += 1; 也永远不会执行,所以i = 5将会不断进入循环判断,所以这段代码也是一个死循环,但是运行结果为1 2 3 4。(这里打印完 4 之后便不断进行判断循环操作,没有输出,但是代码也并没有停止运行)
cpp
// 代码三
#include<stdio.h>
int main(){
int i = 1;
while (i <= 10){
printf("%d ", i);
i += 1;
if (5 == i)
continue;
}
return 0;
}
这个代码由于continue语句并没有其他内容,当 i = 5 进入时没有跳过任何内容,所以continue语句对这个代码的运行结果并没有影响,结果依旧为 1 2 3 4 5 6 7 8 9 10。
3、while循环的拓展
(1)getchar以及putchar
cpp
#include<stdio.h>
int main() {
char ch1 = 0;
char ch2 = 0;
scanf("%c", &ch1); // 这是我们常见的使用%c去输入一个字符
printf("%c\n", ch1); // 这是我们常见的使用printf函数打印一个字符
// 下面我们使用 getchar 和 putchar 去输入输出一个字符
ch2 = getchar();
putchar(ch2);
// getchar 和 putchar 实现了与 scanf 和 printf一样的效果
// 但是 getchar 和 putchar 仅仅适用于字符变量的打印
return 0;
}
1)getchar()
· 函数原型:int getchar(void);
· 功能:从标准输入(通常是键盘)读取下一个可用的字符。
· 返回值:返回读取的字符,如果读取失败,则返回EOF。
2)putchar()
· 函数原型:int putchar(int c);
· 功能:向标准输出(通常是屏幕)写入一个字符。
· 参数:c 是要输出的字符。
· 返回值:成功时返回写入的字符,如果发生错误则返回EOF。
cpp
#include <stdio.h>
int main()
{
int ch = 0;
while ((ch = getchar()) != EOF)
putchar(ch);
return 0;
}
当你运行这个程序时,它会等待你从键盘输入字符。可以输入任何字符,包括字母、数字、标点符号等,程序会立即将你输入的字符显示在屏幕上。如果按下Ctrl+D(在Unix/Linux/Mac系统)或Ctrl+Z然后回车(在Windows系统),这会发送EOF信号给程序,程序接收到EOF后会结束循环,然后退出。
上述的代码以及效果是在实际应用中有一定应用场景的,比如说当我们想提取一段文字中的所有数字的时候:
cpp
#include <stdio.h>
int main(){
int ch = 0;
while ((ch = getchar()) != EOF)
{
if (ch < '0' || ch > '9')
continue;
putchar(ch);
}
return 0;
}
程序通过比较ch的ASCII值来判断它是否为数字字符。在ASCII编码中,'0'到'9'的值是连续的,因此可以通过简单的比较来确定一个字符是否为数字。并使用if语句和continue关键字来控制循环的流程。如果当前字符不是数字,则跳过输出步骤,直接读取下一个字符。这样就实现了程序会忽略所有非数字字符,只将数字字符输出到屏幕上。
(2)getchar() 和 scanf() 的比较
getchar() 用于读取单个字符,不进行任何格式化处理,直接返回输入流中的下一个字符。getchar() 每次调用时会从输入缓冲区中读取一个字符,如果缓冲区中没有字符,它会等待用户输入。getchar() 提供了更细粒度的控制,因为它每次只处理一个字符。
scanf() 用于读取格式化输入,可以根据指定的格式字符串读取一个或多个输入项,并将其赋值给相应的变量。scanf() 会根据格式字符串读取输入,直到遇到格式字符串中指定的分隔符或缓冲区结束。scanf() 会跳过空白字符(空格、制表符、换行符等),直到找到匹配格式字符串的输入。提供了更高层次的控制,因为它可以一次读取多个输入项,并根据格式字符串进行处理。
当我们掌握了getchar()就可以去实现一些较为复杂的逻辑了:
cpp
#include<stdio.h>
int main()
{
int ch = 0;
char password[20] = { 0 };
printf("请输入你的密码:>> ");
scanf("%19s", &password);// 防止缓冲区溢出,使用%19s来限制输入的长度
//清理缓冲区
while (getchar() != '\n');
printf("请确认密码(Y):>> ");
ch = getchar();
if (ch == 'Y')
printf("确认成功\n");
else
printf("确认失败\n");
return 0;
}
这段代码实现了让用户输入一个密码,并在之后确认是否继续使用该密码。其中的while循环的目的是清理输入缓冲区。scanf()函数在读取输入时,如果输入的字符串后面还有额外的字符(例如用户输入了密码后直接按了回车),这些额外的字符会被留在输入缓冲区中。while循环使用getchar()函数读取并丢弃这些额外的字符,直到遇到换行符\n为止。
以上便是本篇笔记的全部内容,我们继续了第三部分的学习,介绍了分支语句------if语句以及循环语句------while循环进行了详细的讲解。在下一篇笔记中,我们将继续第三部分的学习。