【C语言必学知识点一】分支与循环——习题演练八

导言

大家好,很高兴又和大家见面啦!!!今天我们继续介绍分支与循环的相关习题。在上一篇结语中我们已经提前分享了今天的习题给各位练习,也不知道大家都练习的怎么样了。有练习过的朋友可以看一下这篇内容,看看博主的解题思路与你们的有没有不同,没有练习过的朋友可以跟随这我的思路一起来思考并解决今天的习题。下面我们来看看今天的题目:

分数求和(1/1-1/2+1/3-1/4+1/5……+1/99-1/100)
求最大值(求10个整数中的最大值)
乘法口诀表(在屏幕上输出九九乘法表)

话不多说,我们来开始今天的习题吧!

分数求和(1/1-1/2+1/3-1/4+1/5……+1/99-1/100)

大家看到这一题有没有找到一股熟悉的感觉?没错和前面涉及到1-100的习题大同小异。前面我们做的都是累加型的,今天我们遇到的确实加减交错的。而且之前我们做的是整数加法,今天我们遇到的是分数加法。
那这种分数加法我们又应该如何求解呢?下面让我们一起来探讨一下吧!

题目解析

仔细观察我们可以发现题目可以改写成分母为奇数的分数总和减去分母为偶数的分数总和,这也就意味我们可以从奇数和偶数这个角度入手,这样是不是和从1-100中找出奇数这一题就很相似了;
接下来我们尝试着通过代码实现这一题的解答;

代码实现

现在我们按照找出奇数和偶数的思路来解答这一题,那我们就需要在代码中实现以下几个功能:

功能一:生成分母
功能二:区分奇偶
功能三:分数求和
功能四:总和求差
功能五:结果打印

下面我们来一步一步实现这些功能:

功能一——生成分母

这个功能的实现实质上就是生成1-100之间的数,我们还是使用循环语句来实现:

	int i = 0;
	//功能一——生成分母
	for (i = 1; i <= 100; i++)

在有了分母后我们就可以进行奇偶的区分了;

功能二——区分奇偶

奇偶的区分有两种方式:

方法一——与2取模求余数来区分奇偶
方法二——累加来区分奇偶

这里我给大家都一一展示一下是如何应该如何实现这两种区分方式;

方法一——与2取模

我们知道偶数都是2的倍数,所以与2取模时,能被整除的为偶数,不能整除的为奇数,按照这个思路我们来编写代码:

	int i = 0;
	//功能一——生成分母
	for (i = 1; i <= 100; i++)
	{
		//功能二——区分奇偶(取模法)
		if (0 == i % 2)
		else
	}

通过判断语句来判断余数的值,就能很好的区分了,下面我们来看看第二种方式;

方法二——累加

我们知道奇数和偶数是交错排序的,也就是说奇数与奇数差值为2,偶数与偶数的差值也为2。根据这一点我们可以通过两次循环来进行奇偶的区分,代码如下:

	int i = 0;
	//功能二——区分奇偶(累加法)
	for (i = 1; i <= 100; i += 2)
	for (i = 2; i <= 100; i += 2)

这两种实现方式都是可以的,今天我们介绍的是通过法一来实现,大家下去后可以尝试着通过法二来实现;

功能三——分数求和

求和的话总和我们就需要将其存储起来,所以这里需要定义一个新的求和变量,现在我们思考一下这个总和的数据类型应该是什么呢?
在C语言中,变量的数据类型分为整型、字符型、浮点型、布尔型;
(具体的内容我们后续会重点讲解,今天简单介绍一下)

整型也就是整数;
字符型就是键盘上能打出来的字符;
浮点型就是小数;
布尔型是专门用来判断真假的类型;

我们现在做的是分数求和,分数也就是小数的一种表现形式,所以我们这里需要定义的应该是浮点型的求和变量;
但是有一点需要注意,我们要考虑变量的生命周期。
我们知道局部变量的作用域是作用在对应的代码块内,生命周期是进入代码块生成,离开代码块销毁
这里我们求的总和要考虑到后续要根据这两个总和进行加减,所以总和的生命周期应该是进入主函数的代码块生成,离开主函数的代码块销毁,根据这一点我们继续编写代码:

	int i = 0;
	//奇数求和变量
	double sum1 = 0;
	// 偶数求和变量
	double sum2 = 0;
	//功能一——生成分母
	for (i = 1; i <= 100; i++)
	{
		//功能二——区分奇偶(取模法)
		if (0 == i % 2)
		{
			//功能三——偶数求和
			sum2 += 1.0 / i;
		}
		else
		{
			//功能三——奇数求和
			sum1 += 1.0 / i;
		}
	}

可以看到代码中我使用的是1.0/i,这是因为我们定义的i为整型,如果要将分数变为浮点型,那使用/时就需要左右操作数至少有一个是浮点型,此时的除法才是小数除法,如果都为整型,那除法则是整数除法;
整数除法就是结果为整数值,自动忽略小数部分;
小数除法就是结果为小数值,包含整数部分与小数部分;
(这个知识点,在操作符的章节,我们会重点讲解,目前了解即可)
在完成奇数与偶数的求和之后,我们就可以对两者之和求差值了;

功能四——总和求差

这个功能的实现有多种方法,这里我们主要介绍两种做法,一种是直接在功能五中进行一种是通过定义变量存储差值进行;
在功能五中进行的情况我们在介绍功能五时来介绍,现在我们要介绍的是第二种通过定义变量存储差值;
和前面的求和一样在求两数之差时,我们也是需要通过变量来存储这个值,由前面可知,不管是奇数总和还是偶数总和,都是浮点型的值,所以这里的变量我们也需要一个浮点型的值来存储;
又因为我们在求差值时是完成了全部的求和后进行的,也就是说,此时的操作是主函数的执行语句,所以我们只需要在主函数再定义一个浮点型的变量就可以实现这个功能,代码如下:

	int i = 0;
	//奇数求和变量
	double sum1 = 0;
	//偶数求和变量
	double sum2 = 0;
	//奇偶求差变量
	double res = 0;
	//功能一——生成分母
	for (i = 1; i <= 100; i++)
	{
		//功能二——区分奇偶(取模法)
		if (0 == i % 2)
		{
			//功能三——偶数求和
			sum2 += 1.0 / i;
		}
		else
		{
			//功能三——奇数求和
			sum1 += 1.0 / i;
		}
	}
	//功能四——总和求差
	res = sum1 - sum2;

到这里,题目的计算我们基本上就完成了,现在之差最后一步了;

功能五——结果打印

这里打印结果我们肯定还是借用的printf函数,但是具体如何打印呢?这就是我们这里需要介绍的内容;
在前面的题目中,我们基本上都是以打印整型来展示最终结果的,但是在这一题中我们的结果是一个浮点型,所以如果再以整型打印肯定是不合适的,这时我们肯定期望打印出来的值是一个浮点型的值,这应该如何实现呢?
C语言在这种情况下给我们提供了几种打印形式——%f——以单精度浮点型打印%lf——以双精度浮点型打印;
从它们的自身介绍来看,我们也能知道,%f是打印float类型的数值,%lf是打印double类型的数值
在这一题的编码过程中,我们定义的是double,所以此时的打印肯定使用%lf更加合适,完整代码如下:

//分数求和
int main()
{
	int i = 0;
	//奇数求和变量
	double sum1 = 0;
	//偶数求和变量
	double sum2 = 0;
	//奇偶求差变量
	double res = 0;
	//功能一——生成分母
	for (i = 1; i <= 100; i++)
	{
		//功能二——区分奇偶(取模法)
		if (0 == i % 2)
		{
			//功能三——偶数求和
			sum2 += 1.0 / i;
		}
		else
		{
			//功能三——奇数求和
			sum1 += 1.0 / i;
		}
	}
	//功能四——总和求差
	res = sum1 - sum2;
	//功能五——结果打印
	printf("%.2lf\n", res);
	return 0;
}

我们这里使用.2的意思是保留两位小数,有也可以,没有的话计算机会默认打印6位,下面我们来看一下打印结果:
分数求和
现在这一题就被很好的完成了,而且结果也按照两位小数进行打印了。
前面我们还介绍了一种方式通过在功能五中完成求和,也就是我们不需要额外定义变量,直接将奇数偶数的差值通过printf函数直接打印出来,代码如下:

printf("%.2lf\n", sum1 - sum2);

像这样编写代码也是可以的,这里结果我就不演示了,感兴趣的朋友可以自己尝试一下;

思维拓展

对于这一题,我们除了区分奇偶外,还有没有其它的方式来求解呢?这就是我们现在要分享的内容;
从题目的表达式中,我们可以看到,如果符号全部都是正号的话,就会变的很简单了,但是并不是这样,它的符号是一正一负交替存在的,也就是说前一个数是正号,后一个数必然是负号。
这个样子是不是跟循环有点类似了,在每一次循环中进行一次符号替换,如下表所示:

循环次数符号正负
1+
2-
3+
4-
…………
99+
100-

接下来我们根据这个思路来进行代码编写;

代码实现

如果只是改变符号正负的话,那我们可以不需要再区分奇偶,直接生成所有分母,通过改变分数求和时的符号就可以完成这一题了,也就是说,我们需要完成以下几个功能:

功能一——生成分母
功能二——分数求和
功能三——打印结果

有了前面的思路,这里我就不继续对每一个功能进行展开介绍了,接下来我们要重点介绍的是如何在求和时改变累加值的符号;
根据题目表达式,我们很明确的一点就是第一个数为正数,第二个数为负数我肯定做不到在生成分母时就改变了正负,那我能不能换一种思路,我们来看一下,将表达式改写成下面这种形式:
1×1/1+(-1)×1/2+1×1/3+(-1)×1/4+……+1×1/99+(-1)×1/100
从表达式中我们可以看到,我们通过一个1和-1来进行符号的转变,我们暂且把它叫做正负标志好了,通过这个正负标志,我们是不是就能实现累加项的正负交替了。接下来我们就可以编写代码了:

//分数求和
int main()
{
	int i = 0;
	int j = 1;//正负标志
	double sum = 0;
	//功能一——生成分母
	for (i = 1; i <= 100; i++)
	{
		//功能二——分数求和
		sum += j * 1.0 / i;
		//每次求和完改变标志正负
		j *= -1;
	}
	//功能三——结果打印
	printf("%.2lf\n", sum);
	return 0;
}

下面我们来看看运行结果,进一步验证代码:
分数求和2
从结果中可以看到,咱们的代码编写也是没问题的,而且这种解题思路使代码的编写效率大大提高了。
对于这一题的解题,我就分享到这里,如果各位还有其它的解题思路,欢迎在评论区分享;

求最大值(求10个整数中的最大值)

这一题是不是感觉和比较三个数的大小很相似,前面我们只比较了三个数,现在我们要比较十个数,只不过这题我们不需要将这些数排序,只要找到最大值就行了,借助比较三个数的大小的解题思维,我们这里还是可以尝试着用交换的方式来解决,具体怎么操作呢?下面我们就来对题目进行解析;

题目解析

在比较三个数的大小并排序时,我们有提过我们可以默认三个数是以a>b>c的方式排序的,让后再依次进行比较并将大数换位到前面,小数换位到后面。
在这一题中,我们同样可以默认一个变量max的值为最大值,然后我让max跟这十个整数依次进行比较,但是此时我们不是进行换位,而是将比max大的值赋值给max,经过与说有的数比较完,我们是不是就可以找到最大值了呢?
接下来我们顺着这个思路开始进行编码;

代码实现

在编写代码前,我们首先要解决一个问题,这十个数从哪里来?
现在有几种方式——给定10个数、输入10个数以及随机生成10个数,在这里我们要介绍的是第一种,给定10个数。
在确定了这十个数后,我们应该将这十个数存放在哪里呢?
此时有朋友就说了,那肯定是变量啊,我只要定义10个变量不就可以将它们以此存放了吗?
没错,变量确实是个不错的选择,但是如果下次我们要比较20个数、30个数、100个数……是不是也就意味着我们要定义相对应的变量来存放这些值呢?有没有什么更好的方法呢?
有朋友马上就想到了,之前不是提到过数组吗?我们直接定义一个整型类型的数组存放不就行了吗?没错,这就是我们在这题中要介绍的方法,通过数组存放。
在前面提到数组时,我们有说过,我们可以通过下标来访问数组元素,也就是说不管今后我要比较多少个数,只要这些数在数组中,我就能通过下标来访问这些数并进行比较。
下面我们就可以开始进行代码编写了:

//比较10个数的大小
int main()
{
	//定义数组存放10个整数
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//定义最大值变量
	int max = 0;
	//定义下标变量
	int i = 0;
	//通过下标依次访问数组元素
	for (i = 0; i < 10; i++)
	{
		//两数进行比较
		if (arr[i] > max)
		{
			//将较大值赋值给max
			max = arr[i];
		}
	}
	//循环结束,打印最大值
	printf("max=%d\n", max);
	return 0;
}

这样我们就完成了代码的编写,但是这样写就可以了吗?下面我们换一个数组
int arr2[10] = { -1,-2,-3,-4,-5,-6,-7,-8,-9,-10 };
如果此时用max=0来与数组中的元素进行比较,还能找到最大值吗?显然是找不到的,因为0以及不是这10个数的其中一个数了,题目的要求是需要我们找到这十个数中的最大值,所以我们可以对代码进行一下优化:

	//定义最大值变量
	int max = arr[0];

我们将数组中的首元素的值赋值给max,此时就能保证不管数组中的元素值如何改变,都是这十个数在进行比较大小,完整代码如下:

//比较10个数的大小
int main()
{
	//定义数组存放10个整数
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//定义最大值变量
	int max = arr[0];
	//定义下标变量
	int i = 0;
	//通过下标依次访问数组元素
	for (i = 0; i < 10; i++)
	{
		//两数进行比较
		if (arr[i] > max)
		{
			//将较大值赋值给max
			max = arr[i];
		}
	}
	//循环结束,打印最大值
	printf("max=%d\n", max);
	return 0;
}

下面我们来看一下运行结果如何:
比较10个数的大小
可以看到现在就能很好的完成比较数组arr中的十个数的大小了;
接下来我们继续来看下一题;

乘法口诀表(在屏幕上输出九九乘法表)

乘法口诀表这个内容说难吧,其实也不难,说简单吧其实也不简单,下面我们来看看具体怎么实现吧。

题目解析

乘法口诀表大家都很熟悉了,无非就是1~9这个九个数字每一个都与其它数字相乘得到一个乘积,最后按照顺序排雷起来,第一排有1列,第九排有9列,那我是不是可以通过行列的方式来将其打印出来呢?下面我们来进行编码来实现;

代码实现

从上面的分析可知,行与列是一一对应的,每一行的列数与函数相等,下面我们就来根据这个特性来进行代码的编写,实现的方式通过循环来生成每行每列的数字:

//九九乘法表
int main()
{
	//定义行变量
	int i = 0;
	//定义列变量
	int j = 0;
	//生成行数
	for (i = 1; i <= 9; i++)
	{
		//生成列数
		for (j = 1; j <= i; j++)
		{
			//打印每列的内容
			printf("%d*%d=%-2d  ", i, j, i * j);
		}
		//打印完一排,就进行换行
		printf("\n");
	}
	return 0;
}

下面我们看一下打印效果:
九九乘法表
可以看到我们很好的实现了乘法表的打印;
经过前面的习题讲解,我相信大家已经能够理解每一行代码的含义了,不理解也没关系,可以通过每行代码上面的注释来进一步理解;

思维拓展

像前面这样通过循环实现生成数字打印确实很简单,那还有没有其它的方式呢?这就是我现在要重点介绍的通过数组来打印九九乘法表;
我们通过观察九九乘法表就能发现,它是通过两个数相乘并按规律进行排列的一个阶梯式的表格,每一行的最后一次运算都是两个乘数相等,也就是说但两个乘数相等时,我们还要进行换行的操作;
我们现在希望实现的是九九乘法表的最终效果如下:
九九乘法表2
那下面我们又应该如何通过数组来实现呢?

代码实现

要通过数组实现,我们要弄清以下几个问题:

数组的元素类型是什么?
数组的大小是什么?
数组的元素有哪些?

数组的元素类型是什么?

因为我们需要的是1~9这些整数进行乘法,所以数组元素的类型肯定是整型数组;

数组的元素类型是什么?

既然是1~9这些数字相乘,那数组大小肯定不能小于9;

数组的元素类型是什么?

数组内的元素除了1~9就不需要有其它元素了;

解决了这些问题,我们现在就可以定义数组了,这里需要注意,因为是有两个乘数,所以这里我们需要定义两个大小不小于9的整型数组,并将1~9赋值给这个数组,代码如下:

	//定义两个整型数组
	int a[10] = { 1,2,3,4,5,6,7,8,9 };
	int b[10] = { 1,2,3,4,5,6,7,8,9 };

数组定义好后接下来我们就可以使用循环通过下标来调用数组元素了;

	//定义下标变量
	int i = 0, j = 0;
	//通过下标调用数组元素
	for (i; i < 9; i++)
	{
		for (j = 0; j < 9; j++)
	}

通过观察最终效果图我们可以发现,每一行的打印第二个乘数是不变的,第一个乘数是从1一直递增到与第二个乘数相等时,进行换行,并且第二个乘数+1。
根据这个发现,按照嵌套循环的执行逻辑来看,第二个乘数相当于是最外面的这一层循环,第二个乘数相当于是嵌套的循环,第一个乘数的大小是不超过第二个乘数,而第二个乘数的大小是从1一直增加到9;
也就是说第一层循环的判断为i<9,而第二层循环的判断为j<=i;
如果我将数组a放在第一个乘数的位置,那它的下标就为j,我通过a[j]来调用数组a的元素;
我将数组b放在第二个循环的位置那它的下标就为i,我通过b[i]来调用数组b的元素;
当满足a[j]==b[i]时,我们需要打印一个换行符;
因此我们可以继续编写代码:

//九九乘法表
int main()
{
	//定义两个整型数组
	int a[10] = { 1,2,3,4,5,6,7,8,9 };
	int b[10] = { 1,2,3,4,5,6,7,8,9 };
	//定义下标变量
	int i = 0, j = 0;
	//通过下标调用数组元素
	for (i; i < 9; i++)
	{
		for (j = 0; j <= i; j++)
		{
			printf("%d*%d=%-2d  ", a[j], b[i], a[j] * b[i]);
			if (a[i] == b[j])
			{
				printf("\n");
			}
		}
	}
	return 0;
}

下面我们来看一下运行效果:
九九乘法表3
可以看到此时我们很好的完成了九九乘法表的打印。
今天的习题也就全部介绍完了,如果这些习题各位有其它的解题思路,也可以在评论区分享出来;

结语

经过这段时间的练习巩固,我相信大家对分支与循环的相关知识点已经没什么问题了,那分支与循环这个篇章我们也要告一段落了。接下来我们将进入新篇章的学习,各位期待一下吧!
希望这段时间的练习能够真正帮助大家去理解分支与循环的相关知识点,最后感谢大家的翻阅,咱们下一篇再见!

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值