上一篇 <一起学习C语言:C语言基本语法(四)> 中,我们了解了位运算符的语法和不同的应用场景中的选择。本篇文章中,我们分析switch语句,并通过几个示例分析break、#define和三目运算符的应用场景。
章节预览:
5. switch语句
5.1 break用法
5.2 switch语句分析
5.3 #define用法
5.4 switch语句用法
6. 三目运算符
6.1 三目运算符保护形式
7. 本章总结
8. 练习题
目录预览
章节内容:
5. switch语句
C语言中,if和switch都属于分支结构,其中if分支条件可以是表达式,也可以是常量表达式。而switch入口条件可以是表达式,也可以是常量表达式,而分支条件只能是常量表达式。
比如:if (a == 1) 语句一 形式一
else if (a == ‘2’) 形式二
语句二
else
语句三
使用switch可以写为:
int a = 1,或a = ‘2’,或a = 0(或a不等于1且a不等于2)
switch (a 或 常量值) {
case 1: 语句一 形式一
case ‘2’: 形式二
语句二
default:
语句三
}
【例4.25】 使用伪随机函数rand()得到3以内的值,然后加上“表达式n”的n值并输出结果。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
int N = 0;
srand((unsigned)time(NULL));
N = rand() % 3;
switch(N) {
case 1: (“N=%d,n=%d. \n”, N, N + 1); //语句形式一
case 2: //语句形式二
printf(“N=%d,n=%d. \n”, N, N + 2);
default: printf(“N=%d,n=%d. \n”, N, N + 3); //语句形式一
}
return 0;
}
程序分析:
1. 根据time()函数获取到当前时间,并通过srand()函数重新“播种”伪随机数种子。
2. 通过rand()函数生成随机数,然后通过取模运算符“%”获取到0-3的整数(3会被整除,余0)。
3. 由多个switch语句组成的分支结构,它首先从“case 1:”开始判断,如果N不相等1,则继续向下执行一直到“case 2:”,如果都不相等,则进入default:分支下的语句执行。
程序结果:
【例4.25】 如果N == 1,输出case 1、case 2和default对应的语句块“N=1,n=2.”、“N=1,n=3.”和“N=1,n=4.”,参考图4-19。
如果N == 2,输出case 2和default对应的语句块 “N=2,n=4.”和“N=2,n=5.” ,参考图4-20。
如果N == 0,输出default对应的语句块 “N=0,n=3.” ,参考图4-21。
结果分析:
【例4.25】 只有N == 0输出的结果是我们想要的,而N1,N2时,都输出了它们之后的分支结果。
接来下,我们来了解在实际编程中,如何避免这种情况的发生。
5.1 break用法
上述示例中,switch结构的某个分支内的语句执行完成时,应跳出switch语句块,并执行switch之后的语句。
【例4.25】 中,switch语句可以改为:
switch(N) {
case 1: (“N=%d,n=%d. \n”, N, N + 1); break; //语句形式一
case 2: //语句形式二
printf(“N=%d,n=%d. \n”, N, N + 2);
break;
default: printf(“N=%d,n=%d. \n”, N, N + 3); //语句形式一
}
即分支语句后增加break(12)语句(13)。再次执行程序会发现,输出结果与我们的设计思路符合。
(12):break属于关键字,它用来跳出switch结构或循环结构使用。
(13):在C程序中,分号(;)是一条语句的结束符,即“break;”是一条跳转语句。
5.2 switch语句分析
switch的分支结果范围只能是逻辑值、整数值或字符值,比如:布尔false、整数2或字符’3’。现在我们来分析switch语法:
switch (N) {
case !true: printf(“false.”); break;
case 1 == 1: printf(“1 == 1.”); break;
case 2:
{
printf(“2.”);
break;
}
case ‘3’:
{
printf("‘3’.");
}
break;
case 1 << 4:
printf(“1 << 4.”); break;
default:
printf(“default.”);
}
示例分析:
第一个case表达式为!true,它的结果为逻辑值“假”,即false或数字0。
第二个case表达式为1 == 1,它的结果为逻辑值“真”,即true或数字1。
第三个case是一个数字值2。
第四个case是一个字符值’3’,转换成数字为51(14)。
第五个case表达式为1 << 4,即数字16。
第六个是default(15),它属于默认分支,一般在写case分支最后位置。
(14):字符值一般选择ascll码表128以内的十进制数字,它的值由一个整数表示。比如字符’3’对应ascll码表中的十进制数字51。字符值转换到整数值也比较简单,即’3’ – ‘0’ = 3,其中字符’0’-‘9’是数字段,我们只需要拿字符值减去它对应的数字段首个值即可得到。类似的情况还有’a’、’A’,它们的数字段长度为26,即表示’a’-’z’和’A’-’Z’。
(15):default的用法类似于if语句中的else,即所有case都不进入的情况下,进入default。default语句后可以不加break,我们只需把它写在所有case的后面即可。
上述示例中,无论我们是否使用语句块,都应在执行语句最后写上break语句。使用语句块的情况下,break可以写在语句块内,也可以写在语句块外。
5.3 #define用法
实际编码时,如果不确定某个常量值是否修改,或者为这个常量值定义一个标识符,可以通过 #define来实现这部分功能。比如case 1,我们为数字1起个名字,可以写成#define TAG 1,完整代码如下:
#include <stdio.h>
#include <stdlib.h>
#define SNOW 1
int main() {
int N = 1;
switch (N) {
case TAG:
printf(“1.”);
break;
default:
printf(“default.”);
}
return 0;
}
#define定义标识符的一般形式为:
#define 标识符 常量
“#define XXXX XXXX”是在程序编译之前要处理的内容,称为编译预处理命令。
#define一般称为宏定义,标识符是定义中的宏名称,简称宏。宏在程序中不占内存,它只是一个临时变量,预编译后这个符号就不存在了。宏所表示的常量可以是数字、字符、字符串、表达式。
#define语句可以写在“#include XXXX”下面,也可以写在函数中。但大部分情况下,都建议写在“#include XXXX”下面。
5.4 switch语句用法
switch语句中的case分支应写常量值,这样即可以减少编译时的开销,又可以表达出具体数字。比如“case 1 << 4”和 “case 16”,其中“case 16”不通过运算就能表达出具体数字。
【例4.26】 为了帮助学生更接近实际编程,学校决定购买100套“四通道信号数据采集卡”。每套采集卡工作时,只能开启一个数据通道,通道号占用一个字节,并按照1、10、100、1000二进制数字分别表示通道一至通道四的开启情况。现在,我们根据二进制数字计算出开启通道号。
根据这个例子,我们首先计算出二进制数字对应的十进制数字,然后通过宏定义写出每个通道的宏:
二进制数字1、10、100、1000,分别对应十进制表达式1 << 0、1 << 1、1 << 2、1 << 3,即十进制数字1、2、4、8。
#define CHANNEL1 1
#define CHANNEL2 2
#define CHANNEL3 4
#define CHANNEL4 8
char N = CHANNEL1;
switch (N)
{
case CHANNEL1:
printf(“通道一.”);
break;
case CHANNEL2:
printf(“通道二.”);
break;
case CHANNEL3:
printf(“通道三.”);
break;
case CHANNEL4:
printf(“通道四.”);
break;
default:
printf(“未开启通道.”);
}
示例分析:
1. 程序中使用宏,可以较清晰表达出代码的含义。
2. 当某个具有实际意义的常量值被大量使用时,使用宏也可以做到避免出错的情况。比如:数字1,它在示例中表示开启通道一,代码中多处使用它时,修改较为困难。如果用宏表示,只需修改宏所对应的常量值。
6. 三目运算符
C语言中,有一种运算符即可以通过判断条件输出语句,也可以结合赋值运算符为变量赋值,它称为三目运算符。三目运算符由三个表达式或表达式结果组成,又称为三元运算符。
三目运算符的形式:
表达式1 ? 表达式2 : 表达式3;
三目运算符的用法:
true ? printf(“表达式成立.”) : printf(“表达式不成立.”);
【例4.27】 判断int类型变量a和b的值,并输出比较结果。
int a = 1, b = 2;
a > b ? printf(“a大于b.”) : printf(“a小于b.”);
示例结果:
a小于b.
示例分析:
程序首先执行“a > b ?”,如果为“真”,执行printf(“a大于b.”),否则执行printf(“a小于b.”)。
【例4.28】 判断int类型变量a和b的值,并把最大值赋给c。
int a = 1, b = 2, c;
a > b ? c = a : c = b;
或
c = a > b ? a : b;
示例结果:
c等于2.
示例分析:
程序首先执行“a > b ?”,如果为“真”,a赋值给c,否则b赋值给c。
三目运算符的用途不仅仅如此,在后面的示例中将接触更多写法。
6.1 三目运算符保护形式
当三目运算符与别的运算符一起使用时,也存在优先级的关系,接下来我们了解如何避免因运算符优先级的原因导致结果出错。
【例4.29】“非”运算符和三目运算符一起运算。
int a = 1, b = 1, c;
c = !a == b ? 3 : 2;
示例结果:
c等于2.
示例分析:
1. 程序如果先执行“a == b”,得到"!3",结果为“假”,即0。
2. 程序如果先执行“!a”,得到“0 == 1”,结果为2。
从输出结果来看,程序执行顺序符合“2.”,即先执行“!a”,破坏了三目运算符的运算数据。
接下来,增加小括号保护三目运算符:
int a = 1, b = 2, c;
c = !(a == b ? 3 : 2);
示例结果:
c等于0.
示例分析:
这次把三目运算符放入小括号内,得到的结果符合我们的设计逻辑。
实际使用时,如果我们不能确定三目运算符内是否存在优先级问题,可以写成以下形式:
((表达式1) ? (表达式2) : (表达式3));
7. 本章总结
本章节,我们了解了C语言基本语法和不同的运算符的使用方式,日常编程中,我们需要做到正确选择分支结构、正确使用运算符,这样可以避免结构体积庞大、数据运算错误等问题。本章节内容相对简单一些,但也需要多次学习才能完全理解。
8. 练习题
- if语句分为几种形式?
- 逻辑运算符和关系运算符分别适合哪些场景?
- 计算出int类型数字“-1234567 >> 9”的结果,并通过数据保护方式做到清除高位保留低位的效果。
- if语句和switch语句有哪些不同之处?如何保证switch执行得到正确结果?
- 宏定义是什么?结合宏定义编写出合理的switch结构。
- 三目运算符适合用在哪些场景?当a = 1,b = 2,c =3时,计算出!a < b ? a > c ? a : c : b;的结果,然后使用小括号按照“表达式1 ? 表达式2 : 表达式3”执行顺序,编写新的语句。
目录预览
<一起学习C语言:C语言发展历程以及定制学习计划>
<一起学习C语言:初步进入编程世界(一)>
<一起学习C语言:初步进入编程世界(二)>
<一起学习C语言:初步进入编程世界(三)>
<一起学习C语言:C语言数据类型(一)>
<一起学习C语言:C语言数据类型(二)>
<一起学习C语言:C语言数据类型(三)>
<一起学习C语言:C语言基本语法(一)>
<一起学习C语言:C语言基本语法(二)>
<一起学习C语言:C语言基本语法(三)>
<一起学习C语言:C语言基本语法(四)>