分支和循环
引言
在 C语言 中,0 表示假,非0 表示真。 了解这一点很重要,因为很多变量出现在分支和循环的判断框中。常见的有 if 和 while.
#include <stdio.h>
int main() {
int a = -3;
if (a)
{
printf("aaa\n");
}
else
{
printf("bbb\n");
}
return 0;
}
输出结果:
一、if 语句
1. 场景1
程序清单:if - else
#include <stdio.h>
int main() {
int a = -3;
if (a) {
printf("aaa\n");
}else{
printf("bbb\n");
}
return 0;
}
// 输出结果:aaa
2. 场景2
程序清单:if - else if… - else
#include <stdio.h>
int main() {
int a = 99;
if (a >= 0 && a <= 9)
{
printf("个\n");
}
else if(a >= 10 && a <= 99)
{
printf("十\n");
}
else if(a >= 100 && a <= 999)
{
printf("百\n");
}
else
{
printf("其他\n");
}
return 0;
}
// 输出结果:十
3. 场景3
程序清单:if - return
#include <stdio.h>
int test() {
int a = 0;
if (a)
{
return 1;
}
return -1;
}
int main() {
int ret = test();
printf("%d\n", ret);
}
// 输出结果:-1
4. 场景4
#include <stdio.h>
int main()
{
int a = 0;
int b = 2;
if (a == 1)
if (b == 2)
printf("hehe\n");
else
printf("haha\n");
return 0;
}
// 输出结果:无结果
上面的程序显然是代码编写的问题,才导致的歧义。实际上,在我们日常写代码的时候,一个 if 就对应着一个 else. 但在大学考试的时候,可能就会碰到这种无聊的题目,那么我们就应该明白:else 是和它离的最近的 if 匹配的。
二、switch 语句
程序清单:
#include <stdio.h>
int main() {
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
printf("星期一\n");
case 2:
printf("星期二\n");
case 3:
printf("星期三\n");
case 4:
printf("星期四\n");
case 5:
printf("星期五\n");
case 6:
printf("星期六\n");
case 7:
printf("星期七\n");
default:
printf("输入错误!\n");
}
return 0;
}
输出结果:
程序清单:
#include <stdio.h>
int main() {
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
printf("星期一\n");
break;
case 2:
printf("星期二\n");
break;
case 3:
printf("星期三\n");
break;
case 4:
printf("星期四\n");
break;
case 5:
printf("星期五\n");
break;
case 6:
printf("星期六\n");
break;
case 7:
printf("星期七\n");
break;
default:
printf("输入错误!\n");
break;
}
return 0;
}
总结语法:
switch(整型表达式)
{
case 整型常量表达式:
{
语句;
}
case 整型常量表达式:
{
语句;
}
case 整型常量表达式:
{
语句;
}
...
}
注意事项:
① switch 括号内、case 后 必须是整型类型的数据,否则就会报错。
② default 表示不匹配所有的 case 标签,通常放在 switch 语句最后。default 可根据场景自己设定,可不加。
③ case 决定 switch 语句的入口,break 决定 switch 语句的出口。
三、while 语句
1. 场景1
while 循环搭配 break 关键字 ( break 用于跳过整个循环 )
#include <stdio.h>
int main() {
int n = 0;
while (n < 10) {
n++;
if (n == 5) {
break;
}
printf("%d ", n);
}
return 0;
}
// 输出结果:1 2 3 4
2. 场景2
while 循环搭配 continue 关键字 ( continue 用于跳过本次循环 )
#include <stdio.h>
int main() {
int n = 0;
while (n < 10) {
n++;
if (n == 5) {
continue;
}
printf("%d ", n);
}
return 0;
}
// 输出结果:1 2 3 4 6 7 8 9 10
3. 场景3
getchar 为单个输入 ( getchar 返回类型是 int,每次读取一个字符,如果未读到字符,就返回 EOF,即 -1. )
putchar 为单个输出
#include <stdio.h>
int main() {
int ch = 0;
while ( (ch = getchar()) != EOF ) {
putchar(ch);
}
return 0;
}
测试结果:( Ctrl + Z 停止循环输入 )
scanf 循环输入 ( 返回值是 int,如果读到一个字段数据,就返回1;读到两个字段数据,就返回2;如果未读到字符,就返回 EOF,即 -1. )
#include <stdio.h>
int main() {
int ch = 0;
while (scanf("%d", &ch) != EOF) {
printf("%d\n", ch);
}
return 0;
}
测试结果同上,不展示。
4. while 循环清空缓冲区数据
程序清单1:
#include <stdio.h>
int main()
{
char password[20] = { 0 };
printf("请输入密码:");
scanf("%s", password);
printf("请确认密码:");
int ch = getchar();
if ('y' == ch) {
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}
程序清单2:
#include <stdio.h>
int main()
{
char password[20] = { 0 };
printf("请输入密码:");
scanf("%s", password);
int tmp = 0;
while ( (tmp = getchar()) != '\n') {
;
}
printf("请确认密码:");
int ch = getchar();
if ('y' == ch) {
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}
输出结果:
对比两个程序我们发现,第一个程序没有提示我们 " 确认密码 ",就直接输出了确认失败,这显然是因为 getchar 函数直接将我们的回车也读进去了。因为我们每次使用 scanf 函数的时候 ,最后都要点击键盘上的回车键,才能使 scanf 真正的输入。那么这是为什么呢?
其实,在程序和键盘之间,还有一个东西:缓冲区。 scanf 每次都是从缓冲区读取数据的,并且 getchar 也是如此。所以只要 getchar 在 scanf 读取后,再次从缓冲区读数据,就可能会读到缓冲区的 " 残留数据 \n 字符 "。
解决方案:所以后来,我们在第二个程序中加上了如下代码,即可以让 getchar 把缓冲区的所有字符读取完之后,程序就可以读取到真正由键盘键入的数据了。
int tmp = 0;
while ( (tmp = getchar()) != '\n') {
;
}
四、for 循环
for 循环和 while 循环大同小异,这里就一笔带过了。
#include <stdio.h>
int main() {
for (int i = 1; i <= 10; i++) {
if (i == 5) {
break;
}
printf("%d ", i);
}
return 0;
}
// 输出结果:1 2 3 4
注意事项:
① 在下面的 for 循环中," int i = 1 " 称为【初始化】,只会执行一次;" i<=10 " 称为【判断】;" i++ " 称为【调整】。
② 本质上,for 循环就是上面所说的三个核心要素,然而它们都可以省略,但最好不要这么做,因为当 for 循环嵌套使用的时候,就会容易出错。
for (int i = 1; i <= 10; i++) {
}
五、do…while 循环
do…while 循环的应用场景较少,它的循环至少执行一次。
#include <stdio.h>
int main() {
int i = 1;
do {
if (i == 5) {
break;
}
printf("%d ", i);
i++;
} while (i <= 10);
return 0;
}
// 输出结果:1 2 3 4
二分查找
/*
二分查找
*/
int find(int arr[], int size, int k) {
int left = 0;
int right = size - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (k == arr[mid]) {
return mid;
}
else if (k > arr[mid]) {
left = mid + 1;
}
else {
right = mid - 1;
}
}
return -1;
}
int main() {
int arr[] = { 0,5,7,8,13,21,24,55,77,85,93,94,95,97 };
int size = sizeof(arr) / sizeof(arr[0]); // 计算数组长度
int k = 85;
int ret = find(arr, size, k);
if (ret == -1) {
printf("参数出错\n");
}else {
printf("数组下标:%d\n", ret);
}
}
// 输出结果:【数组下标:9】
注意事项:
① 二分查找只能针对于有序数组 (升序 / 倒序)
② 关于求平均值,也可以采取下面的方式。
int mid = left + (right - left) / 2;