第八周!第八周意味着什么?学期已经过去一半了!!
但想着这个学期,全是网课,非常难受(悲。希望早点恢复正常
来看看这周的C语言作业吧
目录
上机实验
4-8 判断闰年
本题要求编写程序,输出21世纪中截止某个年份以来的所有闰年年份。注意:闰年的判别条件是该年年份能被4整除但不能被100整除、或者能被400整除。
输入格式:
输入在一行中给出21世纪的某个截止年份。
输出格式:
逐行输出满足条件的所有闰年年份,即每个年份占一行。输入若非21世纪的年份则输出"Invalid year!"。若不存在任何闰年,则输出“None”。
输入样例1:
2048
输出样例1:
2008
2012
2016
2020
2024
2028
2032
2036
2040
2044
2048
输入样例2:
2000
输出样例2:
Invalid year!
我们好像在之前写过判断闰年的题目(第六周3-20),直接把那个 if 拿过来用吧!
那么这道题就是,从2001开始循环判断,是闰年就输出,不是就不管它。
代码如下:
#include <stdio.h>
int main()
{
int year;
scanf("%d", &year);
if (year <= 2000 || year > 3000)
printf("Invalid year!\n");
else if (year < 2004)
printf("None");
else
{
for (int i = 2001; i <= year; i++)
{
if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)
printf("%d\n", i);
}
}
return 0;
}
4-9 最大公约数和最小公倍数
本题要求编写程序,求两个给定正整数的最大公约数和最小公倍数。
输入格式:
输入在一行中给出两个正整数M和N(≤1000)。
输出格式:
在一行中顺序输出M和N的最大公约数和最小公倍数,两数字间以1空格分隔。
输入样例:
511 292
输出样例:
73 2044
首先我们得意识到,这一题需要用循环,并且最大公约数一定是比最小的数小。所以在求最大公约数的时候,我们可以从 2 开始判断,是否为两数的公约数,若是则跳出。
而最小公倍数一定是最小数的整数倍,所以不用从自加的方法穷举,直接从1倍的最小数开始就可以了。
理论存在,魔法…咳咳,代码开始
代码如下:
#include <stdio.h>
int main()
{
int numA, numB, z;
int convention, commonMultiple;
scanf("%d%d", &numA, &numB);
if (numA > numB)
{
z = numB;
numB = numA;
numA = z;
}
for (int i = 2; i <= numA; i++)
{
if((numA % i) == 0 && (numB % i) == 0)
convention = i;
}
for (int i = 1;;i++)
{
if((i * numA) % numB == 0)
{
commonMultiple = i * numA;
break;
}
}
printf("%d %d", convention, commonMultiple);
return 0;
}
4-10 求整数的位数及各位数字之和
本题要求编写程序,对于给定的正整数N,求它的位数及其各位数字之和。
输入格式:
输入在一行中给出一个不超过10的9次方的正整数N。
输出格式:
在一行中输出N的位数及其各位数字之和,中间用一个空格隔开。
输入样例:
321
输出样例:
3 6
这一题和我们之前写过的某道题很像,只是之前我们写过的是求三位数(固定),现在我们是求不确定的位数(小于9位)。因此只需要关注如何判断位数就行。
#include <stdio.h>
#include <math.h>
int main()
{
int num, order, sum = 0;
scanf("%d", &num);
for (int i = 0;; i++)
{
if (num / (int)pow(10, i) == 0)
{
order = i;
break;
}
else
{
sum += (num / (int)pow(10, i)) % 10;
}
}
printf("%d %d", order, sum);
return 0;
}
4-11 分队列
本题要求编写程序,班级第一次列队,通常老师会让同学按身高排成一列,然后1、2报数,喊到1的同学向前一步,就这样,队伍就变成两列了。假设现在一个班级有n个同学,并且他们已经按身高排成了一列,同学按身高从1到n编号,你能告诉我最后哪些编号的同学站在了第一列么?
输入格式:
输入一个正整数n,表示班级的人数。
输出格式:
按顺序输出所有在第一列的同学对应的编号,每两个编号之间用一个空格隔开。
输入样例:
11
输出样例:
1 3 5 7 9 11
第一眼看这个题目以为是排序,想不到是判断奇偶。这一题的程序比前几题更加简单,直接看代码吧
#include <stdio.h>
int main()
{
int num;
scanf("%d", &num);
for (int i = 1; i <= num; i++)
{
if(i % 2)
printf("%d ", i);
}
return 0;
}
4-12 找出最小值
本题要求编写程序,找出给定一系列整数中的最小值。
输入格式:
输入在一行中首先给出一个正整数n,之后是n个整数,其间以空格分隔。
输出格式:
在一行中按照“min = 最小值”的格式输出n个整数中的最小值。
输入样例:
4 -2 -123 100 0
输出样例:
min = -123
输出最小数啊…没学数组有点麻烦。
首先我们回想一下,上一周我们写的针对不确定长度输入的代码。我们将每次的数值取入,每次都与目前的最小值判断,若小于就替换,一直便利整个队列就可以了。
代码如下:
#include <stdio.h>
int main()
{
int num, min;
for (int i = 0; scanf("%d", &num) != EOF; i++)
{
if(i == 0)
min = num;
else if (min > num)
min = num;
if(i > 10)
break;
}
printf("min = %d", min);
return 0;
}
这段代码不知道为什么,在我的电脑上运行会有问题,但我使用了菜鸟教程的C在线工具,编译是通过的,没有问题。很奇怪,希望读者能自己试试,有什么问题还请在评论区留言或者私信,感谢!
4-13 小于m的最大的10个素数
本题要求编写程序,给定一个整数m(50<m<20000),找出小于m的最大的10个素数。
输入格式:
输入在一行中给出一个正整数m(50<m<20000)。
输出格式:
在一行中按递减顺序输出10个满足条件的素数,每个素数输出占6列。没有其它任何附加格式和字符。
输入样例:
229
输出样例:
227 223 211 199 197 193 191 181 179 173
这一题如果用嵌套循环则需要占用非常多的系统资源,如果用素数表则相对简单。
不过由于我们这节所学的是循环而不是数组,所以还是用嵌套循环的办法吧。
首先我们得思考,如何判断这个数为素数?从素数定义看,是除了1和自身之外没有能整除的数。所以假设有一个数n,我们可以从2开始,循环到n-1为止,有满足模等于0的就break出来。
那如何只输出十个呢?很简单,从高往低输出,每次输出都计数,达到次数之后break就可以了!
代码如下:
#include <stdio.h>
int main()
{
int num, count = 0;
scanf("%d", &num);
for (--num; count < 10; num--)
{
for (int i = num - 1; i > 1; i--)
{
if(!(num % i))
{
break;
}
if(i == 2)
{
printf("%d\t", num);
count++;
}
}
}
return 0;
}
4-14 计算阶乘和
本题要求编写程序,对于给定的正整数n,需要你计算 sum=1!+2!+3!+...+n!。
输入格式:
输入在一行中给出一个不超过10的正整数n。
输出格式:
在一行中输出sum的值。
输入样例:
3
输出样例:
9
嘶…真要我们用嵌套循环?
(这时候咱就得找找有没有现成的阶乘的函数了(不用找了,没有
咳咳,言归正传,阶乘的实现也是非常简单的,难度并没有上一题高
直接看代码吧:
#include <stdio.h>
int main()
{
int num, allSum = 0, oneSum = 1;
scanf("%d", &num);
for (; num > 0; num--)
{
for (int i = num; i > 0; i--)
{
oneSum *= i;
}
allSum += oneSum;
oneSum = 1;
}
printf("%d", allSum);
return 0;
}
结语
非常抱歉这周的拖了这么久,绝对不是因为懒(狡辩)。
这周的第13 14两题,我觉得可以说道说道。
13题我用了 if(i == 2) 来判断这次循环是否正常结束,从而判断这次的值是否为素数,这并不美观优雅。
同样的,第14题的oneSum = 1复位这个值的操作也并不是很好。
那有没有什么办法可以解决这一问题呢?在不同的位置退出,得到的值不一样;在退出重新进来之后,自动复位所需要的值……
有啊,这个能用函数来实现!比如阶乘那一段,中间那个循环是干啥,好像一眼看不出来,但是如果用函数,写成
allsum += digitalFactorial(num);
的话,看起来就会简洁很多,并且可读性也增强了。
基于以上原因,今后可能会看到我在代码中用一些自己写的函数。当然,定义也会贴出。
那么,下周见!