C++研发笔记14——C语言程序设计初阶学习笔记12

本篇笔记我们继续来学习第三部分《分支语句和循环语句》,在上一篇中我们详细学习了什么是语句以及分支语句------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循环进行了详细的讲解。在下一篇笔记中,我们将继续第三部分的学习。

相关推荐
橘子真甜~4 分钟前
Linux操作系统3-文件与IO操作1(从C语言IO操作到系统调用)
linux·运维·服务器·c语言·io·文件操作·文件fd
优雅的落幕14 分钟前
多线程---线程安全(synchronized)
java·开发语言·jvm
小黄编程快乐屋16 分钟前
前端小练习——大雪纷飞(JS没有上限!!!)
开发语言·前端·javascript
程序猿阿伟18 分钟前
《平衡之策:C++应对人工智能不平衡训练数据的数据增强方法》
前端·javascript·c++
爱上语文20 分钟前
请求响应:常见参数接收及封装(数组集合参数及日期参数)
java·开发语言·spring boot·后端
清风徐来辽31 分钟前
Kotlin学习:1.7.语言基础之空安全
开发语言·kotlin
CQU_JIAKE32 分钟前
926[study]Docker,DHCP
java·开发语言
程序猿进阶37 分钟前
Tomcat 都有哪些核心组件
java·开发语言·后端·面试·性能优化·tomcat·firefox
猫猫的小茶馆39 分钟前
【Linux系统】Linux内核框架(详细版本)
linux·运维·服务器·开发语言·嵌入式软件
CodeGrindstone42 分钟前
Muduo网络库剖析 --- 架构设计
网络·c++·网络协议·tcp/ip