抽丝剥茧C语言(中阶)分支与循环练习

练习编程

  • 导语
  • 判断一个数是否为奇数
  • 输出1-100之间的奇数
  • 盲盒!
  • 一道笔试题
  • 计算 n的阶乘。
  • 计算 1!+2!+3!+……+10!
  • 在一个有序数组中查找具体的某个数字n。
  • 编写代码,演示多个字符从两端移动,向中间汇聚。
  • 编写代码实现,模拟用户登录情景,并且只能登录三次。
  • 猜数字游戏
  • 本篇完

导语

这一篇主要讲解一下关于分支与循环的一些练习,好记性不如烂笔头,虽然我们不用笔,但是我们需要自己动手写代码,你记性再好都不如自己动手写一下代码,多写代码你才能成为大牛!

判断一个数是否为奇数

这道题我们的思路是什么?
首先先让代码灵活起来,肯定不能是你去创建一个变量然后去反复修改,这时候当然要利用好我们的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之间的奇数

上一道题,已经知道如何判断奇数了,这道题也很简单,首先思路是生成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;
}

这段代码输出是:
抽丝剥茧C语言(中阶)分支与循环练习_第1张图片
代码没问题。
我们学习了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次。

计算 n的阶乘。

数学里的阶乘是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的阶乘了。

计算 1!+2!+3!+……+10!

上一道题算的是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 的阶乘了。

在一个有序数组中查找具体的某个数字n。

我们这里要求在一个有序的数组里找一个数字,利用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循环。
这个代码看起来有些抽象,我画个图给大家看看!
抽丝剥茧C语言(中阶)分支与循环练习_第2张图片
这里,红色是数组的下标,然后紫色的是最左边的下标,褐色的是最右边的下标,蓝色的变量left和变量right相加和的一半的下标变量mid,这个变量也是用于锁定你要查找数的量,如果mid等于你要找的数的下标,说明找到了。
我们要找的是7这个数字,下标是6,第一次mid为4,它对应的是数组里面的5,5小于7所以我们查找的范围就变成了下标5到下标9之间,因为i虽然mid等于4,可是我们排查mid下标对应的数小于要查找的数,所以说mid对应下标的数一定不是要查找的范围,所以需要加一。
抽丝剥茧C语言(中阶)分支与循环练习_第3张图片
然后就变成了这个样子。这次我们找到了下标为7的元素,发现大于要查找的元素,所以范围缩小到了:
抽丝剥茧C语言(中阶)分支与循环练习_第4张图片
这里要强调一下,因为分为浮点数和整数,储存方式也不一样,下标是整形,两个数的和除以2的结果会把小数点后面的几位给丢掉,也就是(5+6)/2=5。
这次是小了,继续再找:
抽丝剥茧C语言(中阶)分支与循环练习_第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;
}

代码的运行(视频不太好使,只能传图片了)
抽丝剥茧C语言(中阶)分支与循环练习_第6张图片

这段代码主要是进行数组元素的改变,因为要将一点一点向中间汇聚,所以就从两端开始一元素一个元素的改变。

编写代码实现,模拟用户登录情景,并且只能登录三次。

要求:只允许输入三次密码,如果密码正确则提示登录成,如果三次均输入错误,则退出程序。
当然我们经常用的登陆更加高级,这个只是模拟实现而已。
原理也就是通过循环制造三次条件,然后用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;
}

输出结果三种分别是:
抽丝剥茧C语言(中阶)分支与循环练习_第7张图片
这就完成了我们的上一个逻辑,我们最好是写完一个逻辑的代码就运行一次试一试,因为你很可能就会写出来BUG,如果现在不测试一下你的这一段代码,那么你就会越写越多。
我们要完成一个也是最复杂的逻辑,生成随机数
我来介绍一些函数:
rand
这个是用于生成随机数的函数,将返回值储存进变量ret中,但是值是固定的,虽然每个数都很随机,范围是0~32767。但是我们运行发现
抽丝剥茧C语言(中阶)分支与循环练习_第8张图片
每一次开始游戏,我们需要猜的值都是固定一样的,所以仅仅这一个函数是不够用的。
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);

但是我们又发现一个问题:
抽丝剥茧C语言(中阶)分支与循环练习_第9张图片
我们每一次的随机值都很接近对吗,原因是我们设置随机数起点一直在重复,如果按快了都可能数值重复,起点的数是根据时间戳,过了几秒就重新定制起点,肯定数值差不多。
这里我们放在不循环的地方,选择一开始设置起点就好,一次就行,不用重复设置:

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;
}

这样就结果正常了:
抽丝剥茧C语言(中阶)分支与循环练习_第10张图片
因为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语言(中阶)分支与循环练习_第11张图片

没啥问题。

本篇完

我的参考代码不一定是非常好的,但是绝对没什么大问题!家人们放心看就好了,主要是一起学习怎么分析任务,任务目的是什么,先想想用正常思维怎么解决这个任务,然后再用C语言的语法和特点来去完成思维代码。
分支与循环的练习题到此完结,相信大家对分支与循环有了一个更加深刻的理解,和学会如何应用。那么请路过的关注一波,顺便点点赞,如果哪里有错误请大佬指点,谢谢!

你可能感兴趣的:(C,笔记,c语言)