【C语言】 if switch 语句与 while for 语句

发布时间:2026/9/14 17:22:54
【C语言】 if switch 语句与 while for 语句 目录选择语句if else 语句悬空 else 问题关系运算符逻辑运算符逻辑运算符与 逻辑运算符或||逻辑运算符取反短路问题switch 语句循环语句for 循环while 循环do while 循环break 与continue 中断语句for与while 和do while的区别循环嵌套goto 语句随机数生成rand 伪随机数srandtime设置随机数的范围前言C语⾔是结构化的程序设计语⾔这⾥的结构指的是顺序结构、选择结构、循环结构C语⾔是能够实 现这三种结构的其实我们如果仔细分析我们⽇常所⻅的事情都可以拆分为这三种结构或者这三种结构的组合。选择语句if else 语句if else 的介绍if 语句的语法形式如下if(表达式){ 语句 }在C语⾔中0为假⾮0表⽰真也就是表达式的结果如果是0则语句不执⾏表达式的结果如果不 是0则语句执⾏。表达是如果成立,执行语句如果不成立就不执行。但他有一个兄弟叫else语句不执行 他来执行。if else语句的语法形式如下if(表达式) { 语句; } else { 语句; }如果if语句中的表达式如果不成成立就由else来执行后面的语句。if else 的嵌套使用形式如下if(表达式) { 语句; } else if(表达式) { 语句; } else { 语句; }如果if语句中的表达式如果不成成立就由else来执行后面的语句。但因为else 后的语句有个if那么如果if语句中的表达式如果不成成立就由else来执行后面的。理论上可以一直执行下去。悬空 else 问题代码展示int main(){ int a0; int b2; if(a!0) if(b2) printf(hello world); else printf(hehe); return 0; }问 代码会打印出什么答案什么也打印出来在C语言中else 只会认离自己最近的if 为一对我把这种称为就近原则所以代码中的else 与ifb2 为一对。代码执行后第一个if 条件一开始就为假就直接代码执行结束了。我们在打印代码的时候的要有一个良好的习惯为了避免出现这种的代码错误。关系运算符C 语⾔⽤于⽐较的表达式称为 “关系表达式”relational expression⾥⾯使⽤的运算符就称为“关系运算符”relational operator主要有下⾯6个。 , , , , ,! (大于小于等于大于等于小于等于不等于)代码展示ab; ba; ab; ab; ab; a!b;一些注意点一定是,,一定是等于号在前等于 一定是两“”不然容易变成赋值操作逻辑运算符逻辑运算符与 形式如下(表达式)(表达式)逻辑与运算符当左右两边的代码条件为真非0时则整个表达式为真当然逻辑与运算符也是可以多个运用()()()(); (()())();逻辑运算符或|||| 形式如下形式如下(表达式)||(表达式);逻辑或||运算符当左右两边的代码条件其中一个为真非0时则整个表达式为真。当然逻辑或运算符也是可以多个运用。逻辑运算符取反形式如下(表达式)逻辑取反运算符当条件为真非0时则整个表达式为假0条件为假表达式为真。短路问题()()()(); ()||()||()||();在C语言中计算机为了进一步的加快程序的运行速度不一定会判断全部的表达式就像你在有限的时间内做选择题里遇到了已经很明显的错误或者正确的选选项了会继续观看其他选择吗在计算机中像一下代码的代码会从左往右的读取int main(){ int a0; a a a--; printf(%d,a); a9; a-- !a a; printf(%d,a); a1; a--a--a--; printf(%d,a); return 0; }打印代码18-1a0a a a--;会先读取第一个a因为a0 所以直接结束但a 还得执行 第一个代码直接打印 1a9;a-- !a a;因为a9所以为真, a 取反为假所以结束a--打印 8a1a--a--a--;第一次a--返回1a变为0逻辑与继续。第二次a--返回0a变为-1逻辑与短路第三次a--不执行。所以打印出-1所以计算机会先读在经行判断真就继续读假就停止执行。而|| 就与 相反条件为真 就直接退出。int main(){ int a0; a || a || a--; printf(%d,a); a9; !a || a || a; printf(%d,a); a1; a--||a--||a--; printf(%d,a); return 0; }打印结果2100第一段a || a || a--;初始a0第一个a先使用a的值0再自增到 1。0为假继续执行右侧表达式。第二个a先使用a的值1再自增到 2。1为真短路求值终止执行a--不执行。结果a最终为2printf输出2。第二段!a || a || a;初始a9!a9为真!a为假继续执行右侧表达式。第一个a先使用a的值9再自增到 10。9为真短路求值终止执行后续a不执行。结果a最终为10printf输出10。第三段a-- || a-- || a--;初始a1第一个a--先使用a的值1再自减到 0。1为真短路求值终止执行后续操作均不执行。结果a最终为0printf输出0。switch 语句除了if语句外C语⾔还提供了switch语句来实现分⽀结构。switch语句是⼀种特殊形式的if...else结构⽤于判断条件有多个结果的情况。它把多重的else if改成更易⽤、可读性更好的形式。switch (expression)//注意一定要整数 { case value1: statement//case 也是要整数 case value2: statement ... default: statement }value 和expression 都要整数default 分支如果没有找到case 的数值就会执行。其实就类似的else 。if 语句和switch 语句的对比#include stdio.h int main() { int n 0; scanf(%d, n); if(n % 3 0) printf(整除余数为0\n); else if(n % 3 1) printf(余数是1\n); else printf(余数是2\n); return 0; }#include stdio.h int main() { int n 0; scanf(%d, n); switch(n % 3) { case 0: printf(整除余数为0\n); break; case 1: printf(余数是1\n); break; case 2: printf(余数是2\n); break; } return 0; }switch 与break#include stdio.h int main() { int n 0; scanf(%d, n); switch(n % 3) { case 0: printf(整除余数为0\n); case 1: printf(余数是1\n); case 2: printf(余数是2\n); } return 0; }当输入3的时候就会直接打印出整除余数为0余数是1余数是2当case 0 执行后面的代码就会引起执行后面的代码所以需要一个语句break 来中断指令的执行。default其实就是switch 版的else 当所有的case 都没办法符合条件时就会执行该default 后的条件语句。include stdio.h int main() { int day 0; scanf(%d, day); switch(day) { case 1 case 2: case 3: case 4: case 5: printf(⼯作⽇\n); break; case 6: case 7: printf(休息⽇\n); break; default: printf(输⼊错误\n); break; } return 0; }循环语句for 循环for 代码展示for( int i0;i10;i) { //代码 }for表达式1表达式2表达式3第一个表达式:是用来初始化的第二个表达式通常用来判断循环是否还需要进行运行如果结果是否为0决定循环是否继续。第三个表达式调整循环变量然后再去 表达式2的地⽅执⾏判断for 语句的代码更偏向于格式化的循环输出想要输出多少就会都少次。代码展示for(int i0;i10;i) { printf(%d ,i); }输出结果0 1 2 3 4 5 6 7 8 9写法的注意细节int i0 for(i0;i10;i){ printf(%d,i); } printf(%d,i);for(int i0;i10;i){ printf(%d,i); } printf(%d,i);//error第二种写法最后printf 是识别不到 i 的。i 是for 循环里的临时变量出循环后 i 就被销毁。while 循环while 代码展示while(表达式) { 代码; }如果表达式为真就执行循环如果表达式为假就结束循环。其实while 循环有点像if 的循环模式但是与if 不同他没有对应的else 当条件为假就结束循环。代码展示int i10; while(i){ printf(%d ,i); i--; }输出结果10 9 8 7 6 5 4 3 2 1注意如果条件是恒成立就会导致一直循环例如while(1)等这种就需要一个break 来跳出循环。do while 循环do while 的代码展示do{ //代码 }while(表达式);do while 与while 的循环其实差不多但是 do while 会先执行一次代码然后再判断是否执行第二次代码他相当于把判断这个操作放到了第二次循环这就是他们本质上的区别但要注意的是do{}while();后面是有一个 分号的不然会报错。代码展示int i0; do{ printf(%d ,i); i; }while(i)输出结果0 1 2 3 4 5……死循环当然也不准确会循环到2^31-1然后变成-2^31,-2^311,直到0为止但也算是死循环了break 与continue 中断语句代码展示break; continue;刚刚在switch 分支和for 循环有提到过break那么break其实就是跳出循环continue也是跳出循环但有所不同准确的说continue是跳出当前循环的一个小循环但是循环如果条件成立那么循环还是会进行进行而break是跳出当前整个循环相当于就是永久结束循环无论条件是否成立。我们也可以把continue 理解为小跳和break 理解为大跳。代码展示for(int i0;i100;i) { if(i60 || (i10i20)) continue; if(i50) break; printf(%d\n,i); }打印结果1-921-49其中i60 确实没有起到作用因为循环到50 循环已经结束了。其他的whiledo while遇到break 和continue 是相同的。for与while 和do while的区别格式化输出方便上int i0; for(i0;i10;i) { printf(%d ,i); } printf(\n); i0; while(i10) { printf(%d ,i); i; }在两个输出都是一样的情况下for 的代码格式上其实比while 的代码格式更加的规范do while就更不用说。在格式化输出的时候其实更加推荐for 循环当然这句化并不绝对不同的运用场景就会后不同的代码。for 与while 用continue时注意事项int i0; for(i0;i10;i) { if(i5) continue; printf(%d ,i); } printf(\n);i0; while(i10) { if(i5) continue; printf(%d ,i); i; }for 输出结果为 0 1 2 3 4 6 7 8 9while 输出结果为 0 1 2 3 4 卡死死循环原因就是for 在循环到5时 会跳过i 的代码依然执行但是while循环执行到5时会跳出代码但是i的代码不会执行所有一直在5循环里一直执行小跳continen 的代码。解决方式i0; while(i10) { i; if(i5) continue; printf(%d ,i); }这样就却确实的解决i 的代码没有执行的问题虽然输出结果是 1 2 3 4 6 7 8 9 10。循环嵌套冒泡排序int main() { int arr[10] { 0 }; int* p arr; int i 0; while (i!10) { scanf(%d, p[i]);//输入数值 i; } int falg 0; for (i 0; i 10; i) { for (int j 0; j 10 - i ; j) { if (arr[j] arr[j 1]) //决定升序还是降序关键 { int p arr[j]; arr[j] arr[j 1];//交换操作 arr[j 1] p; falg 1; } } if(!falg)//判断是否已经符合降序或者升序的关键 { break; } } for (i 0; i 10; i) //打印输出 { printf(%d , arr[i]); } return 0; }代码介绍输入数据按从大到小的序flag 变量来检查输入的代码是否已经符合条件符合条件直接退出循环 其中 if (arr[j] arr[j 1]) 来决定是升序还是降序的根本。找出100~200之间的素数#include stdio.h int main() { int i 0; //循环产⽣100~200的数字 for(i 100; i 200; i) { //判断i是否为素数 //循环产⽣2~i-1之间的数字 int j 0; int flag 1;//假设i是素数 for(j 2; j i; j) { if(i % j 0) { flag 0; break; } } if(flag 1) printf(%d , i); } return 0; }goto 语句goto 代码展示标记: goto 标记:goto 的效果 就如图上面 我们在代码设置了一个标记那么当代码执行到goto 标记时就会跳转到我们标记的位置继续往下执行代码就形成了一个简易的死循环但是这种循环break 和continue 是没办法去干预的goto 不能说算是循环他的任务就是跳转到对应的标记的位置他也可以这样。goto 标记: //代码; 标记:就行也可以跳转到下面来省略了中间的代码所以goto 循环要跳出循环也只有 goto 或者用 if 等等来限定goto 的使用条件。当然怎么逆天的功能也是有限定的只能限定在当前函数内。在平时写代码其实也并不建议使用goto 使用 标记 太多会导致整个代码运行起来很混乱使用两三个左右会就还好。代码展示#define _CRT_SECURE_NO_WARNINGS #include stdlib.h #include stdio.h typedef struct node { int count; struct node* next; }NODE, * LQNODE; /*初始化函数*/ void crea_linkqueue(LQNODE* front_2, LQNODE* rear_2) { *front_2 (NODE*)malloc(sizeof(NODE)); if (*front_2 NULL) { perror(malloc); return 1; } (*front_2)-next NULL; *rear_2 *front_2; } /*入队函数*/ void push_queue(LQNODE* rear, int y) { NODE* p; p (NODE*)malloc(sizeof(NODE)); if (p NULL) { perror(malloc); return 1; } p-count y; p-next NULL; (*rear)-next p; *rear p; } /*输出函数*/ void print_my(LQNODE* front) { NODE* p; p (*front)-next; if (p ! NULL) { printf(输出的队列为:); while (p ! NULL) { printf(%5d, p-count); p p-next; } printf(\n); } else { printf(这个队列为空队列!!!!!\n); } } /*出栈函数*/ int pop_queue(LQNODE* front, LQNODE* rear, int* x) { NODE* p; if (*front ! *rear) { p (*front)-next; (*front)-next p-next; if (p-next NULL) *rear *front; *x p-count; free(p); p NULL; return 0; } else { printf(这个队列为空队列!!!!!\n); return 1; } } /*求队头元素*/ int get_front(LQNODE* front, LQNODE* rear,int* x) { if (front NULL|| (*front)(*rear)) { return 0; } else { *x (*front)-next-count; return 1; } } /*菜单*/ void menu() { printf(-----------------------------------------------------\n); printf(| |\n); printf(| 1——初始化操作 |\n); printf(| 2——入队操作 |\n); printf(| 3——出栈操作 |\n); printf(| 4——求队头元素 |\n); printf(| 5——显示所有元素 |\n); printf(| 0——退出系统 |\n); printf(| |\n); printf(-----------------------------------------------------\n); } int main() { int i, x, y, I;//循环i 赋值显示x 传参y 循环最大上限I int input,input3;//switch 选项input 功能3的返回值判断是否为空队列input3 LQNODE front, rear;//头指针front 尾指针rear crea_linkqueue(front, rear);//初始化 statr://开始标准 menu();//菜单 printf(请输入相对应的系统操:); statr2://错误输入开始标志 scanf(%d, input);//输入操作数 printf(\n); switch (input) { case 1: //初始化操作 crea_linkqueue(front, rear); goto statr; case 2: //入队操作 printf(请输入想要入队的数值个数:); scanf(%d, I); printf(\n请%d个数值的大小:,I); for (i 0; i I; i)//循环输入 { scanf(%d, y); push_queue(rear, y); } print_my(front);//输出打印 goto statr; case 3: //出队操作 if (front rear)//判断是否为空指针 { printf(该队列为空队列\n); goto statr; } printf(请输入想要出队的数量:); scanf(%d, I); printf(\n); for (i 0; i I; i)//循环出列 { input3pop_queue(front, rear, x);//出队如果出队超出上限就直接返回值为1如果成功出列就返回值为0 if (input3) { printf(该队列已经没有可以出列的元素了已经式空队列。\n); goto statr; } else { printf(已经出列:%d\n, x); } } goto statr; case 4: /*求队头数值*/ if (get_front(front, rear, x)) { printf(队列的头元素为:%d\n, x); } else { printf(队列为空队列!!!\n); } goto statr; case 5: /*输出打印*/ print_my(front); goto statr; case 0: goto off; default: printf(错误输入请重新输入数字:);//错误操作 goto statr2; } off : return 0; }一些注意点因为代码中已经使用了goto 所有switch 中的对应case需要要break 可以省略当然也有例外的写法就是把所有的goto statr 改成break 在off 标记前加入 go to statr 代码展示#include stdio.h int main() { printf(hehe\n); goto next; printf(haha\n); next: printf(跳过了haha的打印\n); return 0; }随机数生成rand 伪随机数代码展示int rand(void);为什么说rand 是伪随机数呢因为rand()第一次确定的数值在第二次输出后依然与第一次相同所以被成为伪随机数。当然要使用rand 函数要用对应的头文件 stdlib.h代码展示#include stdio.h #include stdlib.h int main() { printf(%d\n, rand()); printf(%d\n, rand()); printf(%d\n, rand()); printf(%d\n, rand()); printf(%d\n, rand()); return 0; }为什么说第一次打印出来与第二次打印出来的是相同的呢那么我们就要去了解rand函数如果再深⼊了解⼀下我们就不难发现其实 rand 函数⽣成的随机数是伪随机的伪随机数不是真正 的随机数是通过某种算法⽣成的随机数。真正的随机数的是⽆法预测下⼀个值是多少的。⽽ rand 函 数是对⼀个叫“种⼦”的基准值进⾏运算⽣成的随机数。之所以前⾯每次运⾏程序产⽣的随机数序列是⼀样的那是因为rand函数⽣成随机数的默认种⼦是1。 如果要⽣成不同的随机数就要让种⼦是变化的。srandC语⾔中⼜提供了⼀个函数叫srand⽤来初始化随机数的⽣成器的srand的原型如下void srand (unsigned int seed);而这个函数就用来改变种子的关键函数。程序中在调⽤ rand 函数之前先调⽤ srand 函数通过 srand 函数的参数seed来设置rand函数⽣成随 机数的时候的种⼦只要种⼦在变化每次⽣成的随机数序列也就变化起来了。那也就是说给srand的种⼦是如果是随机的rand就能⽣成随机数在⽣成随机数的时候⼜需要⼀个随 机数这就⽭盾了。time在程序中我们⼀般是使⽤程序运⾏的时间作为种⼦的因为时间时刻在发⽣变化的。在C语⾔中有⼀个函数叫time就可以获得这个时间time函数原型如下time_t time (time_t* timer);总之time 是会随着时间改变的数值了解time 函数会返回当前的⽇历时间其实返回的是1970年1⽉1⽇0时0分0秒到现在程序运⾏时间之间的差值单位是秒。返回的类型是time_t类型的time_t 类型本质上其实就是32位或者64位的整型类型。time函数的参数 timer 如果是⾮NULL的指针的话函数也会将这个返回的差值放在timer指向的内存中带回去。如果 timer 是 NULL就只返回这个时间的差值。time函数返回的这个时间差也被叫做时间戳。time函数的时候需要包含头⽂件time.h代码展示#include stdio.h #include stdlib.h #include time.h int main() { //使⽤time函数的返回值设置种⼦ //因为srand的参数是unsigned int类型我们将time函数的返回值强制类型转换 srand((unsigned int)time(NULL)); printf(%d\n, rand()); printf(%d\n, rand()); printf(%d\n, rand()); printf(%d\n, rand()); printf(%d\n, rand()); return 0; }所以这样才能正确的输出随机值。设置随机数的范围其实这个实现起来其实并不困难我们在之前已经学过的内容了其实就是最不起眼的 % 取余。rand()%n;随机值的范围就在 0到n-1arand()%n;随机值的范围就在 a到an-1感谢阅读悠仁さん