一、i++和++i的区别
都相当于 i=i+1 ,但是在一些有其他运算或判断的情况下:
i++:在表达式中,先返回原来的i值,表达式结束后再执行i=i+1
++i:先执行i=i+1,再返回自增后的新值
就比如下面这段代码:
int i = 0;
if (i++ == 1) {
printf("先比较后加:此时i = %d", i);
} else {
printf("执行了else,此时 i= %d", i);
}
运行之后的结果为:
执行了else,此时 i= 1
相当于 i++ == 1为false,因为i++是先返回原来的 i 值,表达式结束后再执行i=i+1,就是先判断i==1,再执行i=i+1,所以执行了else,并且i=1(注:一个=为赋值,两个=才是判断相等,初学者很容易把判断也写成一个=)
i++的示例看完了,接下来看一个++i的示例:
int i = 0;
if (++i == 1) {
printf("先加后比较:此时i = %d", i);
} else {
printf("此时i = %d", i);
}
运行之后的结果为:
先加后比较:此时i = 1
如果理解了i++,那这个可以说毫无难度,先执行i=i+1,再判断i==1,i初始为0,此时等于1,所以执行if
二、if-else if 和 if-if-if 的区别
比如编写已下程序:
输入一个成绩,按照如下标准输出成绩等级:
如果成绩在 0(含)到 59(含)之间,输出“不合格”;
如果成绩在 60 到 69(含)之间,输出“合格”;
如果成绩在 70 到 79(含)之间,输出“良好”;
如果成绩在 80 到 100(含)之间,输出“优秀”;
提示:输入成绩为整数,范围应在 0 到 100 之间。
你可能会这样写:
int sc;
scanf("%d", &sc);
if (sc >= 0 && sc < 60) {
printf("不合格");
}
if (sc >= 60 && sc < 70) {
printf("合格");
}
if (sc >= 70 && sc < 80) {
printf("良好");
}
if (sc >= 80 && sc <= 100) {
printf("优秀");
}
用多个独立的 if 语句,每一个都会被执行判断——即使你的分数只符合某一个区间,其余的条件也会挨个判断一遍。如果只是简单的小程序,比如判断一次分数等级,影响不大。但在一些复杂项目或大量数据运算时,多余的判断会消耗性能,特别是每次有很多条件分支、或者每个分支内逻辑很复杂时,性能和资源消耗就会明显增加。
这正是 if-else if 优势所在——一旦某个条件成立,其后面的分支就不会继续判断了,可以及时“短路”跳过后续判断,提升效率:
int sc;
scanf("%d", &sc);
if (sc >= 0 && sc < 60) {
printf("不合格");
} else if (sc < 70) {
printf("合格");
} else if (sc < 80) {
printf("良好");
} else if (sc <= 100) {
printf("优秀");
}
比如输入 50,只执行 “不合格” 的判断,后面 3 个 if 都跳过;输入 65,只执行 “合格”的判断,其他都跳过。
虽然在这个小程序上,判断方式和效率差别不明显,也没太大性能影响,但在更复杂或大型的项目中,分支判断方式就很重要了
三、switch-case语句
基本框架
switch (变量) {
case 值1:
// 当变量等于值1时执行这里的语句
break;
case 值2:
// 当变量等于值2时执行这里的语句
break;
...
default:
// 都不匹配时执行这里的语句
}
switch:选择判断哪个分支执行case:每个分支的具体值,匹配时执行后面的语句break:跳出 switch 结构,避免“穿透”到下一个分支- 一定要加 break!否则会出现“穿透效应”:执行完一个 case 后会继续执行下面的 case,直到遇到 break 或结构结束。
default:前面所有 case 都不匹配时执行- 注:
default可以省略,但建议写上,方便处理异常或未知情况
示例:
int a;
scanf("%d", &a);
switch (a) {
case 1:
printf("a=1");
break;
case 2:
printf("a=2");
break;
case 3:
printf("a=3");
break;
case 4:
printf("a=4");
break;
default:
printf("a=%d",a);
}
此时输入1,很明显输出case 1后的语句,即输出:
a=1
输入6呢?明显不能和任何一个case匹配,所以输出default后的语句:
a=6
为什么一定要加break?
不加的话:执行完一个 case 后会继续执行下面的 case,直到遇到 break 或结构结束,例如:
int a;
scanf("%d", &a);
switch (a) {
case 1:
printf("a=1");
case 2:
printf("a=2");
case 3:
printf("a=3");
break;
case 4:
printf("a=4");
break;
default:
printf("a=%d",a);
}
输入 2 的话,输出:
a=2a=3
这就是“穿透效应“,输入2,匹配了case 2,执行后面的语句,但是没有break,所以穿透,直接执行下一个case,即case 3后的语句,执行完之后,遇到break,结束;如果一直没有break,就会直接运行到结构结束,包括default后的语句,可以自己敲代码验证
四、循环结构(粗略讲解)
之后会有更详细的讲解
while:
while (条件表达式) {
// 循环体
}
示例:
int i = 0;
while (i < 5) {
printf("%d\n", i);
i++; // 记得更新循环变量,否则可能死循环
}
输出:
0
1
2
3
4
先判断条件表达式是否成立。
如果条件为真,执行循环体。
循环体执行完毕,重新判断条件。
当条件为假(为0),跳出循环。
do-while:
do {
// 循环体
} while (条件表达式);
-
do:先执行一次大括号里的循环体 -
while (条件):然后判断条件表达式是否为真。如果为真就继续循环,为假就结束 -
先执行一次循环体,再判断条件。这意味着,无论条件是否成立,循环体都至少会执行一次
-
最后的分号
;不要忘记。
示例:
int i = 10;
do {
printf("%d\n", i);
i++;
} while (i < 5);
输出:
10
即使条件i<5不成立,也会先执行一次循环体
for:
for (初始化; 条件判断; 更新变量) {
// 循环体
}
- 初始化:循环开始前设置变量的初值。
- 条件判断:每次循环前判断,满足则执行循环体。
- 更新变量:每次循环结束后执行,通常用来修改循环变量的值。
示例:
for (int i = 0; i < 5; i++) {
printf("%d\n", i);
}
输出:
0
1
2
3
4
如果使用while则是这样写(等价于上面 for):
int i = 0;
while (i < 5) {
printf("%d\n", i);
i++;
}
对比:
| for循环 | while循环 | |
|---|---|---|
| 结构 | 三部分(初始化、条件、更新)写在一起 | 结构更灵活,三部分可分开写 |
| 循环次数 | 常用于循环次数已知的情况 | 适用于循环次数未知、按条件结束的情况 |
| 变量作用域 | for内部声明变量只在循环体内有效 | 在循环外声明变量,可在循环结束后继续使用 |
| 可读性 | 一行能看出循环所有控制部分,清晰简洁 | 分散在多行,适合复杂逻辑 |
| 变种 | 可以没有任何表达式(例如 for(;; ))无限循环 | while(true) 也可以无限循环 |
总结:
for循环适合计数、遍历等场合,结构简洁,控制变量集中管理;while循环适合循环次数不确定、仅需判断条件即可的场合,书写更灵活;
595

被折叠的 条评论
为什么被折叠?



