作者前言
哦哈哟,大家们!!不知不觉已经来到第四篇了,在不断的学习中我发现我的c语言功底还是十分的不牢固啊,看到一些之前的题目都全忘记了┭┮﹏┭┮。太难了。。。不过在不断地复习中我也渐渐地放平心态得心应手,慢慢地给大家写到了这里。
今天我们就来学习c语言里面的分支语句
分支语句:
- if
- switch
循环语句:
- while
- for
- do while
分支语句
分支语句就是有着不同的选择
if else:
// 单分支
if (条件):
{
语句;
}
else:
{
语句;
}
// 多分支
if (条件)
{
语句;
}
else if (条件)
{
语句;
}
else:
{
语句;
}
当我们的条件表达式的结果是0,那么这条分支就走不下去失败了,如果我们的结果不是0(非0),那么结果是真,可以继续运行。
int main()
{
int age = 60;
if (age < 18)
{
printf("青少年");
}
else if (age >= 18 && age < 30)
{
printf("年轻人");
}
else if (age >= 30 && age < 60)
{
printf("中年人");
}
else
{
printf("老年人");
}
return 0;
}
当我们想写一个范围的时候我们不能写 18<= age < 30。 我们要写成 age>=18&&age<30。
int main()
{
int a = 0;
int b = 2;
if (a == 1)
if (b == 2)
printf("hehe\n");
else
printf("haha\n");
return 0;
}
对于在这个题大部分人会下意识认为,答案是haha,因为if里面的语句为假,所以下面的语句不运行,运行else里的语句。但实际上c语言跟python不一样,不是按照缩进来分配代码的,最下面的else 实际上是和最近的一个if连接。
当你在visual studio打代码的时候,你会发现IDE会自动将第二个if和最后一个else拼在一起。
int main()
{
int a = 0;
int b = 2;
if (a == 1)
if (b == 2)
printf("hehe\n");
else
printf("haha\n");
return 0;
所以结果是什么都不打印。
所以我们可以用{}来方便我们正确的看代码的运行。
int test()
{
if (1)
return 0;
return 1;
}
int main()
{
test();
return 0;
}
我们看这个例子,主函数运行test函数,然后if(1)运行return0后,就不会再运行了,我们的所有函数都只能return一个值。所以当return0的时候就不再运行了。
int main()
{
int num = 3;
if (num = 5)
{
printf("hehe\n");
}
return 0;
}
这里也是非常容易错的地方,会有人认为,3不等于5,所以最后什么都不运行,但你仔细看,if里的分支条件是num赋值3,实际上条件为真,打印hehe。
好!我们现在来写几个练习:
1.判断一个数是否为奇数
2.输出1-1000之间的奇数
int main()
{
int a = 0;
scanf("%d", &a);
if (a % 2)
{
printf("结果为奇数");
}
else
{
printf("结果为偶数");
}
return 0;
}
int main()
{
int i = 0;
for (i = 0; i <= 1000; i++)
{
if (i % 2)
{
printf("%d\n", i);
}
}
return 0;
}
switch:
当我们想要输入像
输入1,输出星期一
输入2,输出星期二
输入3,输出星期三
输入4,输出星期四
输入5,输出星期五
输入6,输出星期六
输入7,输出星期日
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;
}
return 0;
}
我们用case +不同的数字来形成多个类似的分支,但是加入我们原代码里没有break,那么当我们输入1,他会从case 1进入,然后打印星期一,但是他没有跳出循环的标志,那么他就会继续运行,到case 2输出星期二,直到最后。
case + 整型常量
当我们设定1-5是工作日,6-7是休息日我们就会发现其实不是每个case都一定要加break
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");
}
return 0;
}
当我们输入1 或者 6 的时候 就会输出 工作日 和 休息日。
但是对于我们最后一个break,我们会认为没有必要,但是如果我们未来需要填入新的分支就会方便和易读。
但是我们故意打1-7之外的东西怎么办呢?
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");
default:
printf("输入错误\n");
break;
}
return 0;
}
我们的default 语句就会在所有前面的语句都没实现的时候输出。我们的default的语句可以放在switch语句内部的任意地方。
循环结构
while:
while(条件)
{
循环语句;
}
当我们的条件一直满足就会导致出现死循环。
int main()
{
while (1)
{
printf("hehe\n");
}
return 0;
}
所以我们就需要一些语句来防止这个死循环的发生:
int main()
{
int i = 0;
while (i < 10)
{
printf("hehe\n");
i++;
}
return 0;
}
i++, 不断自增来使得i的大小大于等于10。突破循环。
如果我们加入if和break的组合会发生什么。
int main()
{
int i = 0;
while (i < 10)
{
if (i == 5)
break;
printf("hehe\n");
i++;
}
return 0;
}
当我们的if语句成立的时候,break的效果是直接把一整个循环给跳出去了直接从if语句里调到return 0。
int main()
{
int i = 0;
while (i < 10)
{
if (i == 5)
continue;
printf("hehe\n");
i++;
}
return 0;
}
虽然也是打印出5个hehe,但是你会看到光标一直在跳动,代表的意思是程序一直在运行。我们的continue是跳过本次循环。
int main()
{
int ch = 0;
while ((ch = getchar()) != EOF)//从键盘中一个一个读取信息然后获取
putchar(ch);
return 0;
}
我们会看到两个新的函数:getchar 和 putchar
getchar的定义:
Get character from stdin
Returns the next character from the standard input (stdin).
putchar的定义:
Write character to stdout
Writes a character to the standard output (stdout).
【C语言】C语言学习整理-putchar,printf,getchar,scanf定义及区别_getchar()与scanf()的区别,putchar()和printf()的区别?-CSDN博客
这一片博客讲的非常的详细,可以看一看。
当我们输入abc的时候,实际上我们的缓存区里存放着abc\n,应为你的结束必须是回车才能运行。
我们想要退出的时候只要输入ctrl+z就行,但是我看弹幕有说别的键位,可能是版本不同。
int main()
{
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s", password);
//这里没有&是因为,数组名本身就是地址。
int ch = getchar();
if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}
这里假如我们输入了1234,我们会发现结果会直接“确认失败”。
我们可以这么理解,当我们把114514输入的时候,我们按下了回车。这个时候我们的printf从缓冲区里面拿去了114514,但是没有拿走\n(换行),所以我们的getchar就直接从缓冲区里把\n拿走当做变量ch的值。所以直接错误。
那我们就可以在printf后,用getchar将\n拿走,清空我们的缓冲区。
int main()
{
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s", password);
//这里没有&是因为,数组名本身就是地址。
getchar();
int ch = getchar();
if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}
或者
int main()
{
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s", password);
//这里没有&是因为,数组名本身就是地址。
// 清理缓冲区里面的内容
int tmp = 0;
while ((tmp = getchar()) != '\n')
{
;
}
int ch = getchar();
if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}
我们可以用while循环来一直取走缓冲区里的数据,直到‘\n’。
for循环
for(表达式1;表达式2;表达式3)
循环语句;
表达式1:初始化
表达式2:条件语句
表达式3:调整部分
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
printf("%d", i);
}
return 0;
}
i = 1就是提前设定i的初始值为1;
i<=1就是我们循环的条件;
i++ 自增,就是我们跳出循环的方式。
for循环中的一些建议:
1. 不可在for循环中修改循环变量,防止for循环失去控制
2. 建议for语句的循环控制变量的取值采用‘前闭后开区间’写法。
后开的数字可以代表着这个循环的次数,可读性更好。
for循环也有一些变种:
int main()
{
for(;;)
{
printf("hehe\n");
}
return 0;
}
判断部分的省略,使得整个循环一直真,陷入了死循环。
int main()
{
int i = 0;
int j = 0;
for(; i < 3 ; i ++)
{
for(; j < 3; j++)
{
printf("hehe\n");
}
}
return 0;
}
这里我们的两个for循环都省略了初始化,所以当我们第一个for的第一个循环里j已经变成了3,所以2,3次循环的时候,第二个for循环就不再进行了。所以结果为3。
#include <stdio.h>
int main()
{
int i = 0;
int k = 0;
for (i = 0, k = 0; k = 0; i++, k++)
{
k++;
}
return 0;
}
这里仔细看for循环的条件,是k = 0, 所以这个循环一直是假。 0次循环
do...while()语句
do
循环语句;
while(条件);
与while的不同点在于,while是先判断后进行,do...while是先进行后判断。
int main()
{
int i = 0;
do
{
printf("%d\n", i);
i++;
} while (i < 10);
return 0;
}
加上break和continue会怎么样呢?
int main()
{
int i = 0;
do
{
if (i == 5)
{
break;
}
printf("%d\n", i);
i++;
} while (i < 10);
return 0;
}
int main()
{
int i = 0;
do
{
if (i == 5)
{
continue;
}
printf("%d\n", i);
i++;
} while (i < 10);
return 0;
}
接下来我们来个练习。
1.求n的阶乘
2.求1! + 2! + 3!+.....+ n!
int main()
{
int n = 0;
scanf("%d", &n);
int i = 0;
int a = 1;
int b = 0;
for (i = 1; i < n + 1; i++)
{
a *= i;// 求第n的阶乘
b += a;// 求1!+ 2!+ 3!+.....+ n!
}
printf("%d\n", a);
printf("%d\n", b);
return 0;
}
我们来个难一点的:
3.在一个有序的数组中查找具体的某个数字n。
int main()
{
int a = 8; // 我们设定的想要找到的数字
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // 我们的数组
int n = sizeof(arr) / sizeof(arr[0]); // 求出我们数组的大小
int Left = arr[0]; // 最左端的元素
int Right = arr[n - 1]; // 最右端的元素
int Mid = (n - 1) / 2; // 中间的元素
while (Left <= Right) // 二分法。
{
int Middle = arr[Mid];
if (a < Middle)// 我们要找的数小于中间值
{
Right = arr[Mid - 1]; // 右端的最大值改变为中间元素的左边一个
Mid = (Mid - 1 + 0) / 2; // 中间元素的下标改变
}
else if (a > Middle)// 我们要找的数大于中间值
{
Left = arr[Mid + 1]; // 我们左端的最小值改变为中间元素的右边一个
Mid = (Mid + n) / 2; // 中间元素的下标改变
}
else
{
a = Middle;
printf("成功找到");
break;
}
}
if (Left > Right)
{
printf("找不到了");
}
return 0;
}
4.编写代码,演示多个字符从两端移动,向中间汇聚。
int main()
{
char arr1[] = "welcome to osu";
char arr2[] = "##############";
int left = 0;
int right = strlen(arr2) - 1;
while (left <= right)
{
arr2[left] = arr1[left];
arr2[right] = arr1[right];
Sleep (1000);
system("cls");//清空屏幕
left++;
right--;
printf("%s\n", arr2);
}
return 0;
}
Sleep,system函数需要头文件<windows.h>,sleep就是相当于停止运行多少毫秒然后继续运行,有一种卡顿的没,system("cls")函数就是将终端内的内容清空。使得最后呈现的样子像是一行内两端逐渐出字。
5.编写代码实现,模拟用户登录的情景,并且只能登录三次。
int main()
{
int i = 0;
char password[20] = { 0 };
for (i = 0; i < 3; i++)
{
printf("请输入你的六位密码\n");
scanf("%s", password);
if (strcmp(password, "123456") == 0)
{
printf("登录成功\n");
break;
}
else
{
printf("密码输入错误\n");
}
}
return 0;
}
这篇博客里看一下,这里的代码就是比较我们输入的密码和预设的密码“123456”之间是否相同,相同的时候就会输出0。
这个我在之前就发了一篇博客,你可以直接点击标题进入那篇博客的链接。
我们将代码分为菜单,奖励,游戏和主函数四个部分:
菜单:
void menu()
{
printf("********* guess game ********\n");
Sleep(100);
printf("*****************************\n");
Sleep(100);
printf("********* 1. play *********\n");
Sleep(100);
printf("********* 0. exit *********\n");
Sleep(100);
printf("*****************************\n");
Sleep(100);
}// 打印出我们的菜单界面
这里我们设置了menu函数,
menu();// 打印菜单
我们在主函数内部用这个就可以打印出我们菜单。
奖励:
void prize()
{
printf("\n");
printf(" ************ \n");
printf(" ****************** \n");
printf(" *********** ************ \n");
printf("********* *********\n");
printf(" *********** ************ \n");
printf(" ****************** \n");
printf(" ************ \n");
printf("\n");
}// 成功猜对数字获得奖励
我们自己随便花了个硬币的样子,当我们成功猜成功,我们就会显示一个硬币。
到我们最难的地方,游戏逻辑部分:
游戏
void game()
{
//猜数字游戏的实现
// 1. 生成随机数
// rand函数返回从0到rand_max(32767)范围内的一个伪随机整数。
// 主函数处使用srand函数对伪随机数生成器生成种子。
int ret = rand() % 100 + 1;//范围就是100
//printf("%d\n", ret);
// 2. 猜数字
int guess = 0;
int i = 0;
int a = 0;
int b = 0;
while (1)
{
//printf("猜数字");
scanf("%d", &guess);
if (guess < ret)
{
printf("猜小了\n");
i++;
a++;
printf("第%d次guess\n", i);
}
else if (guess > ret)
{
printf("猜大了\n");
i++;
b++;
printf("第%d次guess\n", i);
}
else
{
printf("恭喜你,猜对了\n");
i++;
printf("第%d次guess\n", i);
prize();
printf(" 获得第%d个硬币 \n", c_gol);
break;
}
}
printf("猜小%d次 猜大%d次 总共%d次\n", a, b, i);
}
主函数:
int main()
{
srand((unsigned int)time(NULL));//srand函数接受的是unsigned int类型,
//time(null)/time(0)返回的就是现在的时间戳
int input = 0;
do
{
c_gol++;
menu();// 打印菜单
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("猜数字\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
srand是通过你输入的数字来生成种子,种子就有点想我的世界里的种子,所有的随机数都会按照不同的种子产生,所以我们不需要时时刻刻有着不同的种子来达到随机的可能。这时候我们可以用时间,我们的时间一直会改变,那么种子也会随时改变,达到随机。
srand((unsigned int)time(NULL));//srand函数接受的是unsigned int类型,
时间我们就用time函数。因为我们的srand接受unsigned int类型,我们就强制类型转换。点击time你就能看到相关的函数意思。我们的游戏部分里我们用if语句来达到猜大猜小,主函数里我们用do..while加上switch分支来达到我们能够一直玩的目的。
第四期结束啦,我们结束了分支循环语句的旅程!!(*^▽^*)
感谢这些大大!!!