这一篇主要讲解一下关于分支与循环的一些练习,好记性不如烂笔头,虽然我们不用笔,但是我们需要自己动手写代码,你记性再好都不如自己动手写一下代码,多写代码你才能成为大牛!
这道题我们的思路是什么?
首先先让代码灵活起来,肯定不能是你去创建一个变量然后去反复修改,这时候当然要利用好我们的scanf这个函数,我们输入任何值都可以判断了。
然后就是我们如果去分辨是否为奇数,这就需要用到我们的分支语句了。
参考代码如下:
#include
int main()
{
int a = 0;
scanf("%d", &a);//你要输入任意值的地方
if (a % 2 == 1)//这里为判断,代码核心的地方,奇数除2余数为1,偶数能整除2
{
printf("YES");//这里是结果1
}
else
{
printf("NO");//这里是结果2.如果第一个结果不成立就会执行这个代码
}
return 0;
}
各位老铁可以复制到自己的编译器测试一下,我试过了,没问题。
上一道题,已经知道如何判断奇数了,这道题也很简单,首先思路是生成1到100的数字,然后每一个数字进行判断,是就打印,不是就不打印。
参考代码如下:
#include
int main()
{
int i = 0;
for (i = 1; i <= 100; i++)//生成1到100数字
{
if (i % 2 == 1)//判断是否为奇数
{
printf("%d ", i);//打印奇数
}
}
return 0;
}
这段代码输出是:
代码没问题。
我们学习了for循环,那么就要巧妙利用for循环,我们不可能定义100个变量然后赋值1到100,所以就用循环去生成。
虽然我们的变量 i 初始化为0,不符合我们从1开始,但是for循环可以赋值 i ,也就是说,i 被赋值等于1,先判断 i 是否<=100,成立就进入循环,然后到i++的部分进行调整,也就等于i+1,这时变量i 就变成了2。
如上循环,等i=101时就会跳出循环,所以就生成了1到100之间的数。
判断我们只需要一个if就可以了,因为只是让我们打印奇数,不是让你判断是不是奇数,所以没用else。
给家人们康一个好康的~
#include
int main()
{
int n = 1;
int m = 2;
switch (n)
{
case 1:
m++;
case 2:
n++;
case 3:
switch (n)
{//switch允许嵌套使用
case 1:
n++;
case 2:
m++;
n++;
break;
}
case 4:
m++;
break;
default:
break;
}
printf("m = %d, n = %d\n", m, n);
return 0;
}
猜一猜结果是神魔~
我们来慢慢看,代码是从上往下运行的,我们知道这里有两个变量,n=1,m=2,进入switch语句之后,判断条件是n等于1,为真,进入之后进入对应的case 1的这个语句,然后从上往下运行,直到case 3然后判断第二个switch语句,因为经过上面的计算,n=2,m=3,所以进入第二个switch语句中的case 2,,计算完之后break跳出第二个switch语句,到第一个switch语句的case 4进行计算,计算完之后跳出第一个switch语句。
输出结果为:
m=5 n=3
没错,这是一道去公司应聘,笔试部分的真题。让我们一起看一看
请问循环要循环多少次?
#include
int main()
{
int i = 0;
int k = 0;
for(i =0,k=0; k=0; i++,k++)
k++;
return 0;
}
这里家人们的答案应该五花八门,但是注意,我们看这个for循环的判断条件部分,它是把k赋值成了0,也就是说判断条件部分等于放了一个0进去,这说明条件为假,他和 == 不一样, == 是判断两端是否相等,就算是k == 0也没问题,因为条件是k == 0,这个条件成立就会进入循环,而这道题是赋值,别看少了一个等号,可是缺天差地别!
经过上面的分析我们就知道正确答案了,循环0次。
数学里的阶乘是1*2*3*…*n。
C语言里我们又应该如何实现呢?
我们首先分析一下,无论你算谁的阶乘,开头都是1*多少多少,然后在观察一下其他规律,2的阶乘是1*2,3的阶乘是1*2*3,4的阶乘是1*2*3*4。
我们可不可以用这个思路,算3的阶乘时,就要用2的阶乘 * 和3的本身,4的阶乘就要用3的阶乘和 *4 的本身。
我们可以利用C语言变量可以存储的特性把你要算n阶乘前面n-1的阶乘存储进去。例如:
#include
int main()
{
int n;
int i = 0;
int ret = 1;
scanf("%d", &n);//这里是我们要计算某个数的阶乘
for (i = 1; i <= n; i++)//i变成了1,是因为都要从1开始乘起,循环次数是根据你想算n的阶乘中的n为界限
{
ret = ret * i;//ret是储存n-1的阶乘
}
printf("%d", ret);//打印的就是n的阶乘
return 0;
}
我们输入4,结果是24。
我们声明了一个变量n,然后利用scanf函数改变n的值。这里n为3,第一次进入for循环,ret=1*1,然后再次进入for循环,上次因为i算的是1的阶乘,所以ret等于1,这次要算2的阶乘,也就等于1的阶乘乘以2等于2,ret就等于2,第三次进入循环,用ret也就是2的阶乘乘以3算出来3的阶乘,最后一次循环算出来4的阶乘了。
上一道题算的是n 的阶乘,我们也明白了阶乘用改如何计算啊,如何存储到变量里面,这道题就利用上面的原理,然后把这写常量的阶乘给加起来,然后储存到一个变量里。
首先我们不可能将1到10用变量一一生成出来。
#include
int main()
{
int i = 0;//储存1到10的变量
int j = 0;//储存要求n的阶乘变量
int ret = 1;//依然是储存n的阶乘
int sum = 0;//储存1到10的阶乘相加的变量
for (i = 1; i <= 10; i++)
{
ret = 1;//重新给变量ret赋值为1
for (j = 1; j <= i; j++)
{
ret = ret * j;//1到j阶乘的数
}
sum = sum + ret;//1到i阶乘的和
}
printf("%d", ret);//打印的是1到10的阶乘的和
return 0;
}
我们这里的结果是
3628800
这里需要注意的是什么?ret在每一次第一层for循环进入的时候重新给ret赋值为1,这是为什么?因为ret在第二层循环算的是1到变量 j 的阶乘,但是,出来之后,ret并不是1,也就是说再次进入时候,ret是上次 j 的阶乘,我们从新进入第二层for循环的时候ret不是1,也就是说算的已经不是 j 的阶乘了。
我们这里要求在一个有序的数组里找一个数字,利用C语言的方法最普遍的方法就是从后往前直找或者是从后往前找,那么,如果有100个数呢,1000个数呢,10000个数呢,你需要找多久呢?
在现实生活中,比如我买了一双鞋,你好奇问我多少钱,我说不超过300元。你还是好奇,你想知道到底多少,我就让你猜,你会怎么猜?
当然是每次从猜中间数。
我们怎么利用C语言来实现这个算法呢?
首先我们创建一个数组,在里面找一个数怎么表达?当然是数组的下标,然后通过下标实现这种算法,叫做折半查找法。
例如:
#include
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,10};//创建数组
int left = 0;//数组最左边的下标
int right = sizeof(arr)/sizeof(arr[0])-1;//数组最右边的下标,减一前面算的是数组的大小,原理是数组的长度除以数组里面第一个元素的长度
int key = 7;//要查找的数
int mid = 0;//两个数组下标和的平均数,也是二分查找的核心
while(left<=right)//判断条件是因为左下标和右下标如果跑到了相反的方向,就说明数组中没有这个数
{
mid = (left+right)/2;//这是查找的中间数
if(arr[mid]>key)//重新定义要查找的范围
{
right = mid-1;
}
else if(arr[mid] < key)//重新定义要查找的范围
{
left = mid+1;
}
else
break;//这个地方代表是找到了
}
if(left <= right)
printf("找到了,下标是%d\n", mid);//打印要查找数的下标
else
printf("找不到\n");
}
因为查找是一个重复动作,所以利用while循环。
这个代码看起来有些抽象,我画个图给大家看看!
这里,红色是数组的下标,然后紫色的是最左边的下标,褐色的是最右边的下标,蓝色的变量left和变量right相加和的一半的下标变量mid,这个变量也是用于锁定你要查找数的量,如果mid等于你要找的数的下标,说明找到了。
我们要找的是7这个数字,下标是6,第一次mid为4,它对应的是数组里面的5,5小于7所以我们查找的范围就变成了下标5到下标9之间,因为i虽然mid等于4,可是我们排查mid下标对应的数小于要查找的数,所以说mid对应下标的数一定不是要查找的范围,所以需要加一。
然后就变成了这个样子。这次我们找到了下标为7的元素,发现大于要查找的元素,所以范围缩小到了:
这里要强调一下,因为分为浮点数和整数,储存方式也不一样,下标是整形,两个数的和除以2的结果会把小数点后面的几位给丢掉,也就是(5+6)/2=5。
这次是小了,继续再找:
这次终于找到了,下标为6。
打印结果是:
找到了,下标是6
这次大家也可以明白为什么是这样一个查找范围,如果left到了right的右边,数组里面没有我们要查找的数。
这就是二分查找法C语言的实现。
#include
#include
int main()
{
char arr1[] = "Welcome to League of Legends!";//要一点一点改变的内容
char arr2[] = "#############################";//被改变的数组
int left = 0;//最左边下标
int right = strlen(arr1) - 1;//最右边下标
printf("%s\n", arr2);
//while循环实现
while (left <= right)
{
Sleep(1000);//这个函数是等1000毫秒=1秒之后进行下面代码的运行
arr2[left] = arr1[left];//这里实现arr1数组内容的转换
arr2[right] = arr1[right];
left++;
right--;
printf("%s\n", arr2);
}
return 0;
}
这段代码主要是进行数组元素的改变,因为要将一点一点向中间汇聚,所以就从两端开始一元素一个元素的改变。
要求:只允许输入三次密码,如果密码正确则提示登录成,如果三次均输入错误,则退出程序。
当然我们经常用的登陆更加高级,这个只是模拟实现而已。
原理也就是通过循环制造三次条件,然后用if语句判断对错:
int main()
{
char psw[10] = "" ;//这是储存你要输入字符串的空间。最多可以输入9个字节的字符串,因为还最后还有一个 \0 放在末尾
int i = 0;
int j = 0;
for (i = 0; i < 3 ; ++i)//代表三次机会
{
printf( "please input:");
scanf("%s", psw);//输入密码
if (strcmp(psw, "password" ) == 0)//判断是否正确
break;
}
if (i == 3)
printf("exit\n");//代表三次机会都输入错误
else
printf( "log in\n");//代表输入成功
}
strcmp是个什么函数呢?是判断字符串是否相同,相同返回0,所以需要判断是否等于0。这里是判断是否等于0,并不是赋值给strcmp为0,大家不要搞混了。至于为什么不把两个字符串直接用 == 比较,这里后面会讲。
大家应该熟悉了我们上面的折半查找法,我们可以利用这个算法来玩个游戏。
我们来猜1到100数字的如何?
首先,我们要做一个游戏菜单,把它放在自定义函数里面,代码如下:
void menu()//函数名为menu,因为只需要调用一下这个函数打印游戏菜单,所以返回类型是void,不需要返回任何值,因为在menu函数就已经完成所有需要的内容了。
{
printf("**********************\n");
printf("*****1.猜数字游戏*****\n");
printf("*****0.游戏结束 *****\n");
printf("**********************\n");
}
游戏菜单出来了,那么,我们要做到玩完一次还想继续玩,那么应该怎么办?玩完某一次之后想退出怎么办?
我们可以利用学习过的语句来进行这个逻辑,我的方法只是其一。
#include
void menu()//游戏菜单
{
printf("**********************\n");
printf("*****1.猜数字游戏*****\n");
printf("*****0.游戏结束 *****\n");
printf("**********************\n");
}
void game()//游戏要实现的内容,暂时没写
{
}
int main()
{
int a = 0;
while (1)//循环无数次
{
menu();//调用游戏菜单
scanf("%d", &a);
if (a == 0)
{
printf("退出游戏");
break;
}
else if (a == 1)
{
printf("游戏开始\n");
game();//调用game函数
}
else
{
printf("输入无效,请重新输入\n");
}
}
return 0;
}
输出结果三种分别是:
这就完成了我们的上一个逻辑,我们最好是写完一个逻辑的代码就运行一次试一试,因为你很可能就会写出来BUG,如果现在不测试一下你的这一段代码,那么你就会越写越多。
我们要完成一个也是最复杂的逻辑,生成随机数。
我来介绍一些函数:
rand。
这个是用于生成随机数的函数,将返回值储存进变量ret中,但是值是固定的,虽然每个数都很随机,范围是0~32767。但是我们运行发现
每一次开始游戏,我们需要猜的值都是固定一样的,所以仅仅这一个函数是不够用的。
srand
这个函数是设置随机数起点的,这个函数需要你传进去不同的值生成随机数。
假如说我们先这么写:
srand(10);
int ret =rand();
printf(“%d”,ret);
输出:71
srand(100);
int ret =rand();
printf(“%d”,ret);
输出:365
也就是说我们在srand(随机整形数字)就可以生成一个随机数,但这是固定的,也就是说我们这里需要能变化的数字,我们电脑里面什么是可以变化的呢?答案:时间。
time
我们有一个东西叫做时间戳.
这里是时间戳转换的工具,有兴趣可以研究一下时间戳转换工具.
时间戳这个东西就像我们在某个时间段给盖章一样,每一串数字都代表着一个时间。
在C语言我们就有这个东西,他的格式是这样的
time(传进去一个指针)返回的值是unsigned int类型
也就是说我们可以这么写:
srand((unsigned int)time(NULL));
int ret = rand();
printf(“%d\n”, ret);
但是我们又发现一个问题:
我们每一次的随机值都很接近对吗,原因是我们设置随机数起点一直在重复,如果按快了都可能数值重复,起点的数是根据时间戳,过了几秒就重新定制起点,肯定数值差不多。
这里我们放在不循环的地方,选择一开始设置起点就好,一次就行,不用重复设置:
void game()
{
int ret = rand();
printf("%d\n", ret);//打印猜测的数检测是否有问题
}
int main()
{
int a = 0;
srand((unsigned int)time(NULL));//我们把随机数的起点设置到了这里
while (1)
{
menu();
scanf("%d", &a);
if (a == 0)
{
printf("退出游戏");
break;
}
else if (a == 1)
{
printf("游戏开始\n");
game();
}
else
{
printf("输入无效,请重新输入\n");
}
}
return 0;
}
这样就结果正常了:
因为time函数太过于复杂,这里就不进行具体了解了。
最后一步,我们只需要进行玩家猜测的逻辑部分就写好了。
#include
#include //时间戳的头文件
#include //随机数的头文件
void menu()
{
printf("**********************\n");
printf("*****1.猜数字游戏*****\n");
printf("*****0.游戏结束 *****\n");
printf("**********************\n");
}
void game()
{
int b;
int ret = rand()%100+1;//因为我们要猜测的是1到100之间的数,任何数模100都是0到99,加一就是1到100
while (1)//猜数字不可能只是一次,所以循环
{
printf("请输入你要猜测的数值:\n");
scanf("%d", &b);
if (b < ret)
{
printf("猜小了\n");
}
else if (b > ret)
{
printf("猜大了\n");
}
else
{
printf("猜对了\n");
break;
}
}
}
int main()
{
int a = 0;
srand((unsigned int)time(NULL));
while (1)
{
menu();
scanf("%d", &a);
if (a == 0)
{
printf("退出游戏");
break;
}
else if (a == 1)
{
printf("游戏开始\n");
game();
}
else
{
printf("输入无效,请重新输入\n");
}
}
return 0;
}
没啥问题。
我的参考代码不一定是非常好的,但是绝对没什么大问题!家人们放心看就好了,主要是一起学习怎么分析任务,任务目的是什么,先想想用正常思维怎么解决这个任务,然后再用C语言的语法和特点来去完成思维代码。
分支与循环的练习题到此完结,相信大家对分支与循环有了一个更加深刻的理解,和学会如何应用。那么请路过的关注一波,顺便点点赞,如果哪里有错误请大佬指点,谢谢!