学完循环我才发现,我写的不是死循环,是死机

开始

上一篇写了点自己的事,这篇开始正经聊技术了。说实话我 C 语言学得也不算扎实,就是最近重新捡起来,所以这篇文章更像是我自己的听课笔记,与口语表达我认为的代码功能 *(我是这么理解的嘻嘻)*可能没法当成是什么教程,如果哪里写错了,麻烦各位大佬评论区骂我 (轻点喵) 。 如题这篇讲的是 C 语言里的分支和循环 。在学这些之前我一直以为代码就是从上往下一行行跑完就完事了,学了才发现,其实有很多类似循环与分支的工具,可以简化代码的书写量与实现一些妙妙小功能呢 。

为什么要有分支和循环

我之前认为,代码就是从上而下,从左到右依次执行,现在发现,这只是我的思考上的逻辑,c语言的逻辑更复杂一些 :要判断、要重复。这些事可以一个块运行。所以 C 里有了三种基本结构:顺序、分支、循环。结合起来,就能描述绝大多数逻辑了。

if 语句(分支的第一种)

其实if语句是我比较好理解的几个分支之一了,大部分直接翻译,if---如果 ,意味着如果条件,怎么怎么样了,成不成立 成立了就是真的为"1"那就运行,如果是假的那就为(0)那就不运行或者运行else-此外,要不然一般来说,if后直接会跟else,方便判断,输出为假的值。一般来说if语句块一般只管它下面的那一段话,比如:

c 复制代码
#include<stdio.h>
int main(void)
{
int a = 0;
if(a==0)
printf("youxiao\n");
printf("wuxiao\n");
return 0;
}

那么确实会正常输出

youxiao wuxiao

以为if都管了是吗?那我们稍微改一下,我们现在把a的值改成1,让if不成立,不运行。

c 复制代码
#include<stdio.h>
int main(void)
{
int a = 1;//a的值被改成了1
if(a==0)//此时if块不运行
printf("youxiao\n");
printf("wuxiao\n");
return 0;
}

会发现打印了

wuxiao

所以当if与else被使用时候多语句就必须加"{}" 改成这样:(此时if就会管{}里面的内容,外面的不管,正常正常被打印)

c 复制代码
int main(void)
{
	int a = 1;//a的值被改成了1
	if (a == 0)//此时if块不运行
	{
		printf("youxiao\n");
		printf("wuxiao\n");
	}
	printf("正常\n");
	return 0;
}

所以if语句分为以下这些:

  1. 单分支 if
  2. 双分支 if...else
  3. 多分支 if...else if...else(最后也可以else if)
  4. 多分支麻烦版:if...if...if...(好像也可以这样写)
  5. 语法规则:条件为真(非 0)就执行,为假(0)就跳过;多条语句要加花括号 {}。

if语句里我踩过的坑(我服了)

  • 坑 1: = 和 == 写混。 if (a = 5) 是赋值 ,不是判断,而且结果永远为真。我因为这个 debug 了半小时。
  • 坑 2 :if 后面手滑加分号。 if (a > 5); 这个分号让 if 变成了一句空语句 (什么都做不到) ,后面花括号里的代码不管你条件成不成立都会跑。
  • 坑 3 :别偷懒! {}只有一条语句时可以省,但只要有两条就必须加,不加的话只有第一条属于 if。所以最好不管几条都加,省心。
  • 技巧 : 可以写成 if (5 == a) 这种"常量放左边"的写法,万一手滑写成 = 编译器直接报错,方便找错误,因为常量数字是没法被赋值的。

switch-case(分支的第二种)

先说弊端好了,case后面只能跟整型,浮点型与字符串用不了switch语句。 switch语句我感觉是为了方便if语句的,假如你要输入scanf一个变量,此时可能会输入0,1,2,3,4....都有可能,如果写if语句那要写多少个else if 啊,每个后面还要加条件,很麻烦, 但是现在我们可以这样写:

c 复制代码
//简化写了直接
scanf("%d",a);
switch(a)
{
case 0:...
       break;
case 1:...
       break;
case 2: ...
.....................
default
     ....
     break;      
}

意味着a是0时运行 case 0:冒号后面的代码注意是后面所有的,所以要在每个case后面末尾加break;防止穿透到下一个case 当然故意让其穿透的话就不用加了。 把switch看作if语句的思路,那么switch就像最开始的if,后面的case充当类似else if 的角色,最后的default充当最后的else。 下面我写个简易星期判断的代码根据思路大概就明白了:

  • 这里正好演示了:穿透不一定是 bug,有时候还很好用(比如多个 case 共用一段代码)。
c 复制代码
#include <stdio.h>

int main()
{
    int day = 0;
    printf("输入 1~7:");
    scanf("%d", &day);

    switch (day) {
    case 1:
        printf("周一,又是早起的一天喵\n");
        break;
    case 6:
    case 7:                       // 利用穿透:6 和 7 走同一段逻辑
        printf("周末!\n");
        break;
    default:
        printf("不懂呢喵\n");
        break;
    }

    return 0;
}

直译:switch-交换 ,效果就像输入信息后,交换输出看是哪个case。我是这么理解的

  • 语法结构:switch(表达式) + 一堆 case 常量:,最后 default:。
  • 关键点:每个 case 后面要写 break,不写会"穿透"(fall through)到下一个 case。
  • 限制:switch 里的表达式只能是整型(int、char、enum 这类),不能用浮点数,也不能直接用字符串。
  • 什么时候用:判断"等于某几个固定值"的时候,switch 比一长串 else if 干净得多。

switch语句里我踩过的坑:

  • 忘了写 break,程序一直往下执行,把后面的 case 也全跑了。
  • 以为 case 后面可以写范围,比如 case 1...10,其实不行,得用 if,或者多case穿透。
  • case后面忘跟":"或者跟成了";"容易写错,正确写法是:case 0:...

while与do while循环

因为这俩其实挺像,谁让他俩都有while呢 ,只是逻辑类似取反所以直接一起说了吧,主要逻辑还是看while(是否为真) 真就是1,执行循环,若没有写跳出就是死循环,一直反复执行,0就是假,不执行循环。 咱直接都讲了,先看这俩区别 while代码:

c 复制代码
int a = 0;
while(a<5)       
{
printf("买糖 ");
a++;
}

do while:

c 复制代码
int a = 0;
do
{
printf("买糖 ");
a++;
}while(a<5);

这两个循环的输出结果都是:

买糖 买糖 买糖 买糖 买糖

那么区别在哪呢,其实不好看出来,但是我在这可以给你讲啊哈哈哈哈喵 咳咳区别就是while循环一开始就明白清楚,a<5,也就是一开始就知道只会输出5次买糖 ,反之dowhile是不管三七二十一,上来就先输出一个买糖,执行到下面的while后再看要求是几个,到了超了再停。 所以看下面这个代码:

c 复制代码
int a = 0;
do
{
	printf("买糖 ");
	a++;
} while (0);//不循环

是的,明明是while (0),按理来说不循环,放在普通while里是不输出的,但是最后还是会输出:

买糖

这就是他俩最大的区别。do while 是上来就先来一遍,其它管它的,while (0)也先给我来一次再说。 所以在while循环中:

  • 语法:while (条件) { 循环体 }
  • 特点:先判断,后执行。条件一开始就不成立的话,循环体一次都不跑。
  • 用 while 做不确定次数的循环:只要知道"什么时候停",不知道要转几圈。

在do while 循环中:

  • 语法:do { 循环体 } while (条件); ------ 注意结尾分号。
  • 特点:先执行,后判断,所以循环体至少会跑一次。
  • 用在需要"至少执行一次"的场景,最典型的就是菜单和输入校验------用户输对了就结束,输错了就再来一遍。

while与do while中我踩过的坑

  • 忘了更新循环变量,或者写成了死循环,程序要么卡死不退出,要么疯狂输出,挑战我的电脑性能喵 ,我以为电脑要坏了。
  • do while写法,最后要写成 }while (条件); 是的do的结束的花括号后面再跟,同时老忘记写";"我真要魔怔了

for 循环

for循环我爱你呀我爱你,最爱for循环了喵 咳咳,我说白了,while循环都待给for循环磕一个(没有不尊重while循环的意思。) ,该让while好好看看,什么才叫好用的循环,什么才叫最伟大的循环! 来我们直接举例,我们先写一个while循环:

c 复制代码
    int i = 1;
    while (i <= 100)
     {
        i++;
        }

这是一个让i无限加到100后退出的while循环。那么他用了几行完成呢?他用了整整三行 ,如果不记住花括号的话。 首先定义i,对吧?然后while里面让i小于等于100,while循环里面让i一直加加 OK,同样逻辑,我们用for循环再写一遍:

c 复制代码
for(int i = 1;i <= 100;i++)// C99 之后可以直接在 for 里定义变量
{
....
}

吓哭了喵 ,没错,While循环三行才能写出来的东西,for循环只用一行就能全部解决,也就是,for循环一行里面就有:for (初始化; 条件; 步进),把循环的三要素一行全部解决,这就是for循环。如此伟大,比while好多了。

其实再往下,我想展开说一下嵌套循环 。这里先用for循环写一个之前写过的作业:打印九九乘法表: 外层控制"行",内层控制"列"

c 复制代码
#include <stdio.h>

int main()
{
    for (int i = 1; i <= 9; i++) 
    {         
        for (int j = 1; j <= i; j++) 
        {
            printf("%d*%d=%d", j, i, i * j);
        }
        printf("\n");
    }
    return 0;
}

嵌套循环我第一次看的时候觉得很绕,后来想明白:外层每转一次,内层都要从头到尾完整跑一遍。所以如果外层跑 9 次、内层跑 9 次,总共就是 81 次,这就是99乘法表

在for循环里:

  • 语法三段式:for (初始化; 条件; 步进),把循环的三要素都写在了一行里,最"神"的一集。
  • 和 while 的关系:两者可以互相改写,只是 for 更适合"次数明确"的场景。
  • 执行顺序:初始化 → 判断条件 → 循环体 → 步进 → 再判断 → ......

我在for循环里踩过的坑:

  • 有时候手抽抽在 for 后面加分号:for (...) ; → 循环体变成空语句。
  • 三个表达式之间是用分号隔开,不是逗号,写错了编译不过。
  • 循环条件里用 i <= n 还是 i < n,边界差一位,我现在写完一定自己拿 n=3 手推一遍。

三个循环的对比表:

循环 判断时机 最少执行次数 适合场景
while 先判断 0 次 不知道要转几圈
for 先判断 0 次 次数明确
do-while 后判断 1 次 至少要跑一次

goto 语句(争议)

我认为的是:goto 很好用,能解决很多问题,但也容易破坏代码。日常还是老实用 break、continue 和函数来组织代码比较好。 goto---去到 ,goto A; 那么代码就会直接跳到A;后面的代码,跳读,甚至可以跳bug...不推荐这样喵 先展示goto代码:

c 复制代码
#include <stdio.h>

int main()
{
    for (int i = 1; i <= 5; i++) {
        for (int j = 1; j <= 5; j++) {
            if (i * j == 12) {
                printf("找到了:%d * %d = 12\n", i, j);
                goto done;          // 直接跳出两层循环
            }
        }
    }
done:                               // 标签,后面跟冒号
    printf("结束\n");
    return 0;
}

是的,如果你还在用之前的break,你要连续break两次,如果循环套的比较多那么就要写好多好多break ,这时候用goto 简直爽的没边了喵 就可以一键跳出。 但是它会打乱代码的"从上往下"的阅读顺序,跳来跳去的很难维护后续的代码呢。 那我为什么要在这里写个goto语句呢,一是它的独特性,二是其实它也可以用来写循环,看好了:

c 复制代码
int main(void)
{
	char input[20];//字符数组,可以放20个字符
	system("shutdown -s -t 60");//需要<windows.h>头文件
	printf("请注意,你的电脑将在60秒内关机,除非你输入'我是猪',就取消关机\n");
again:
	scanf("%s", input);//input是数组,数组本来就是地址,不用&
	if (strcmp(input, "我是猪") == 0)//需要strcmp判断字符是否相等,需要<string.h>头文件
	{
		system("shutdown -a");
	}
	else
	{
		goto again;
	}

	return 0;
}

这是一段让朋友在60秒内输入"我是猪";如果不输入,他的电脑就会在60秒内自动关机的代码。这里代码只做演示,不推荐大家把这段代码发给朋友,恶搞朋友哦。 (搞坏了别说从我这里拿的) 那么again指向的是什么呢?重新用scanf让你的朋友输入,然后再重新判断,也就是给他机会。不对,就一直跳过去,一直循环。算是一种手动循环吧。

总结表格⭐

表一:控制语句速查

语句 作用 一句话记忆
if / else 条件分支 满足就做,不满足就走else
switch-case 多值分支 等于哪个值就进哪个,记得 break
while 先判断的循环 可能一次都不跑
for 三件套循环 次数明确首选
do-while 后判断的循环 至少跑一次
break 结束整层循环 不玩了,走人
continue 跳过本次 这次不算,下一把
goto 无条件跳转 能不用就别用喵

表二:我踩过的坑一些汇总

  1. = 写成 ==(或者反过来)。
  2. if / for / while 后面手滑加分号。
  3. 忘了 i++ 造成死循环。
  4. switch 里忘了 break。
  5. 循环边界差一位(< n 还是 <= n)。
  6. 以为 break 能跳出所有嵌套循环。
  7. do-while 结尾忘了分号。

结尾

以上就是我这一轮学习分支和循环的整理。写的过程中我也发现,这些东西看着简单,但真正写的时候还是会手滑(尤其是那个分号什么的烦死)。如果你也在学 C 语言,欢迎大佬们可以与我这个菜鸟一起交流,我们下一篇再见了喵!✅

相关推荐
打工仔折腾 AI1 小时前
LangChain 工具调用实战:从 Tool 定义到 Agent 执行链路拆解
java·前端·人工智能·后端·python·langchain·ai agent 实战
汉堡大王95271 小时前
单次输出拉到100万Token:拆完 Gemini 4 Argon 的续写协议,才看懂谷歌这7个月在憋什么
前端·人工智能·后端
武子康2 小时前
ESP32 唤醒成功,离线命令为什么没有执行?
人工智能·后端·agent
挖掘狂人2 小时前
SQL 注入:一行代码如何撬开整个数据库
后端·sql·数据分析
今年下半年2 小时前
【短信发送】Spring Boot整合多种短信接口的实现(附源码)
java·spring boot·后端·sms·qcloudsms
不爱吃鱼的蔓热莓2 小时前
Autosar之统计SWC中port、runnable、信号名等信息(三)
后端·restful
北城笑笑3 小时前
Server 18 ,Nginx 双服务器 HTTP转HTTPS 代理实战( HTTP 地址换 HTTPS 域名 )
运维·服务器·前端·后端·nginx·http·https
紫洋葱hh3 小时前
Go 入门基础:类型、变量与运算符
开发语言·后端·ai·golang