wtf,为啥连个最好办的 c 语言语法都要我这种口口声声讲得神乎其神,搞得像是天书一样。 实际上这就是个好办的 if 嵌套难题,大量小白写的代码一旦写错,程序直接崩,就连直接回毛病提示。
比如你要判断一个整数是不是奇数,按常规逻辑,你写个 if-else 结构,看数字除以 2 余数是不是零。
不过这里有个坑,0 是偶数但 0/2=0,这时候判断逻辑得有点小心思,比如用 % 运算来算余数,要么干脆硬编码判断,不然写起来好办绕晕。
举个例子,假设你要判断 5 是不是素数,不是用循环试除 2 到 sqrt(n),而是直接写个 switch 来跳转流程。 先别急着看代码,你得明白 switch 的本质是条件分支,但它只能处理离散值,比如整数要么字符串,不能像 if-else 那样处理浮点数要么函数调用这种复杂逻辑。
要是你把 1000 和 1001 这种连续的大整数扔进去,程序可能会崩溃要么乱跑,出于 switch 对不同类型的数据都有隐含的隐式转换,就连还会报错。
比如你想打印一个字符串,直接写 switch(s) { case "a": ...; },这时候 switch 会尝试把字符串转换成 int,默认是 0,然后按整型去匹配 case 标签,要是类型彻底对不上,编译器就会直接告诉你“switch 表达式类型和数据类型不匹配”,这时候多试几次,你就会发现代码报错,不得不改回 if-else 了。 那要是是用来处理数字分支呢?比如你要写个累加器,从 1 加到 100。用 switch 写的话,得写 102 个 if-else 分支,否则一个都写不出来,并且维护起来简直是噩梦。 switch 的优势就是“少”,只需写几个 key-value 对。
比如用 switch(i) { case 1: printf("ONE"); case 2: printf("TWO"); ... },这样既撇脱又干净利落。
不过这里有个细节要注意,switch 里的值务必是常表达式,不能是循环变量要么函数回值,别看 C 语言有时候比较“宽容”,但在严格的定义下,switch 里的值要是常量表达式,否则就是 Syntax Error。
比如你在循环里写 switch(i) 而 i 是循环变量,编译器肯定无法编译,出于编译器不知道当前循环的 i 到底是多少,没法做匹配。
这时候你得在循环外把 i 的值存到一个变量里,比如 int temp = i; switch(temp) { ... },这样就把动态值转成了静态值,switch 才能跑通。 再深入一点说说 switch 的启动方式。switch 语句的语法结构实际上挺好办的,关键字是 switch,然后跟一个表达式,接着是个左括号,里面是若干个 case 标签,最终是冒号,然后是具体的实现代码,最终是右括号。
这里有个挺好办让人迷糊的点:case 标签之间不能直接连着,中间务必有空格,不能写成 case 2: printf("two"); case 3: printf("three");,务必写成 case 2: ...; case 3: ...;,不然编译器会当成一个 case label 解析,害得逻辑错乱。就像你写代码写错了,直接写 case 2 case 3 这种,编译器会把你当成一个 case label,然后它的值是多少呢?要是是 int,编译器就会去查整数类型有哪些值,然后逐个匹配,结局可能就彻底不对了。 不过 switch 还有个挺实用的用法,就是处理字符串要么枚举值。
比如你要判断一个字符是个大写字母还是小写字母,要么判断一个字符串是不是 "hello"。
这时候用 switch 就特别顺手,不用写 case 'a': case 'b': ... 这种冗长的 if-else 链。
比如写个函数,输入一个字符串,输出是不是 "hello"。用 switch(s) { case "hello": ...; default: ...; },一下子就把逻辑理清楚了。
这里有个小陷阱,switch 里的字符串字面量务必是合法的标识符,比如 "hello" 和 "Hello" 是能够的,但 "HELLO" 也是能够的,出于字符串字面量本质上是字面量类型。
不过要注意,switch 对字符串的匹配是区分大小写的,case "hello" 只能匹配大小写一样的字符串,case "Hello" 就找不到,这实际上是 switch 的一个特性,有时候正是你需求的,有时候又搞反了。 再说说 switch 的默认值。大量人写 switch 的时候,会忘记加 default 分支,要么写成了 case 0: ...,别看有些编译器准 case 0,但在严格的 C 语言规则里,case 标签的值务必是整型,不能是 0 要么空,否则就是编译毛病。并且,就算你加了 default,也要确保 switch 的表达式类型和 case 标签类型匹配。
比如你要判断一个数字,用 switch(i) { case 1: ...; case 2: ...; default: ...; },这里 i 务必是 int 类型,要是 i 是 char 类型,编译器会把 char 转成 int,默认值是 0,这时候 case 0 就跳到了 default 分支,但实际你可能想处理的是 1 和 2 的情况,故此务必把类型对齐,否则逻辑全乱套。 还有种情况,就是处理数组要么集合。
比如你要遍历一个整型数组,检查有没有最大值。
这时候能够用 switch 做索引判断,但这在 C 语言里是个大坑,出于 switch 的表达式类型是固定的,你不能在 case 里写索引运算。
比如写 switch(c) { case 0: ...; case 1: ...; },这只能处理数字,不能处理数组下标。
要是你想要做下标比较,得用 if-else 要么指针运算,这时候 switch 就发挥不出来了。
故此在使用 switch 之前,要么在调试过程中,最好把数据类型预先规划好,别让它跟着数组下标跑,要不就你确定这就是你想要的行为模式。 另外,switch 语句在循环内部使用挺常见,比如判断某个变量是否在某范围内。
比如在循环里判断 i 是否在 1 到 10 之间。
这时候要是写成 switch(i) { case 1: ...; case 10: ...; default: ...; },只要 i 的值是固定的或已经确定的常量表达式,switch 就能正常工作。
要是 i 是循环变量,那就在循环前把它存下来,要么在 switch 之前做一次转换,确保它是常值类型。 实际上 switch 的核心就一句话:把条件分支硬编码成 case 语句。它比 if-else 更紧凑,但代价就是灵活性差。
要是你每次都要写 case 1, case 2, case 3 这种,那就别用了。但要是你确实是处理常量、枚举要么字符串,switch 绝对是最好的选择。
比如做密码强度判断,要么做菜单选择,switch 能帮你省下几十行代码。 最终总结一下,写 switch 语句时,起初确认数据类型是否匹配,其次确保表达式是常量表达式,然后注意 case 标签间务必有空格,还得记得加 default 分支(要不就你确定不会用),最终确保不混用数组下标。一旦这些细节都抓对,switch 就成了一行代码就能搞定的分支逻辑,既高效又简洁,再也不用揪心写复杂逻辑时的脑子直冒火。