大家好,很高兴又能和各位见面了。咱们今天的内就是写代码,通过不同的题目进行代码编写来提高我们的编写能力以及对知识点的理解。下面开始咱们今天的题目。
我们先解决在switch语句知识点中遗留的一个问题;
1.请问最后输出的m和n分别是多少?
int main()
{
int n = 1;
int m = 2;
switch (n)
{
case 1:
m++;
case 2:
n++;
case 3:
switch (n)
{
case 1:
n++;
case 2:
m++;
n++;
break;
}
case 4:
m++;
break;
default:
break;
}
printf("m = %d,n = %d\n", m, n);
return 0;
}
这一题并不复杂,但是在做这一题之前我们先要明白switch语句的执行流程:
这个流程图的意思是,在switch语句中,switch充当的像是一个筛选条件,而case相当于是一个入口,我们要先通过switch的判定来选择从哪个case入口进入语句;
如果我们从case1进入,则程序会从case1里的执行语句开始执行,也就是流程图中的执行语句1一直执行到遇到break;
如果我从case2进入,则case1的执行语句被跳过,程序直接从case2里的执行语句开始执行,也就是流程图中的执行语句2一直执行到遇到break;
如果我们从case3进入,则case1,case2里的执行语句被跳过,直接从case3里的执行语句开始执行直到遇到break,在流程图中case3的执行语句就是break。
最后再跳出switch语句后开始执行语句外的执行语句,一直到结束。这就是switch语句的执行流程。
下面我们顺着这个逻辑返回到题目中再来看这个代码,代码里总共有3个break,一个是在嵌套的switch语句里,一个是在case4的执行语句里,还有一个是在default执行语句里。也就意味着,第一个break结束的是嵌套的switch语句,只有第二个和第三个break才是结束的主体的switch语句。接下来我们看看对象语句分别是n=1,m=2,而n是主体和嵌套switch语句的判断对象,接下来我们就可以关注程序应该从哪个入口开始进入语句,对象语句是n=1,所以我们这题的入口是从主体语句的case1开始执行,执行语句的顺序依次是:
m++(m=3) -> n++(n=2) -> 嵌套switch判断 -> case2 -> m++(m=4),n++(n=3),break -> 跳出嵌套switch语句,继续执行case4 -> m++(m=5),break -> 跳出主体switch语句 -> 打印m,n -> 结束
从这个执行顺序中我们得到了最终答案m=5,n=3,接下来我们通过计算机来验证我们的答案:
不知道大家对这题还有没有疑问,欢迎留言提问,我会及时解答哦!接下来我们看下一题:
2.将任意三个数按从大到小的顺序排列出来:
这一题我们第一次在初识C语言10中有编写过一种解题思路,今天我们要使用另一种解题思路来编写代码:
int main()
{
int a, b, c, d;
scanf("%d%d%d", &a, &b, &c);
while ((a > b && b > c) != 1)
{
if (a < b)
{
d = a;
a = b;
b = d;
}
else if (b < c)
{
d = b;
b = c;
c = d;
}
else if (a < c)
{
d = a;
a = c;
c = d;
}
}
printf("%d>%d>%d\n", a, b, c);
return 0;
}
这一次我们通过换位的思路,将最大的数换位到第一个位置,将最小的数换位到第三个位置,这种编写方式,相比于我们第一次用if多分支从句把所有的情况都列举出来,这种通过while循环来完成换位的思路会更有效率一点,大家如果有新的编写思路也可以在评论区分享出来。接下来我们来看第三题:
3.打印(0-100)之间3的倍数
这一题相对来说比较简单,要完成这一题,我们需要解决两个问题:
1.寻找3的倍数,也就是我们需要判断这个数与3的余数是否为零,为零那就说明是3的倍数,这里取余数我们用到的操作符是%——取模操作符,取模也就是取余数;
2.要生成0-100这些数,然后每个数都要去跟3进行取模,能解决这个问题的就是循环语句;
顺着这个思路,我们开始编写代码,这里循环语句我采用的是for语句,当然你们也可以采用其它两种语句:
int main()
{
int a = 0;
for (a = 0; a < 101; a++)
{
if (a % 3 == 0)
{
printf("%d ", a);
}
}
return 0;
}
不知道各位有没有新的编写思路呢?可以在评论区分享出来。接下来我们来看第三题:
4.编写代码求两个数的最大公约数
这一题我们先要解决几个问题:
1.什么是最大公约数?
最大公因数,也称最大公约数、最大公因子,指两个或多个整数共有约数中最大的一个。a,b的最大公约数记为(a,b),同样的,a,b,c的最大公约数记为(a,b,c),多个整数的最大公约数也有同样的记号。如果数a能被数b整除,a就叫做b的倍数,b就叫做a的约数。约数和倍数都表示一个整数与另一个整数的关系,不能单独存在。几个整数中公有的约数,叫做这几个数的公约数;其中最大的一个,叫做这几个数的最大公约数。
2.如何求最大公约数?
求最大公约数有多种方法,常见的有质因数分解法、短除法、辗转相除法、更相减损法。
质因数分解法:把每个数分别分解质因数,再把各数中的全部公有质因数提取出来连乘,所得的积就是这几个数的最大公约数。例如:求24和60的最大公约数,先分解质因数,得24=2×2×2×3,60=2×2×3×5,24与60的全部公有的质因数是2、2、3,它们的积是2×2×3=12,所以,(24,60)=12。
短除法:短除法求最大公约数,先用这几个数的公约数连续去除,一直除到所有的商互质为止,然后把所有的除数连乘起来,所得的积就是这几个数的最大公约数。
辗转相除法:辗转相除法是求两个自然数的最大公约数的一种方法,也叫欧几里德算法。
第一步:任意给定两数;
第二步:用两数中较大的数除以较小的数,取余数1;
第三步:因为除数肯定大于余数,所以取除数和余数作为新的给定两数,重复步骤二,直到余数为零,此时的除数就是最大公约数。
更相减损法:也叫更相减损术,是出自《九章算术》的一种求最大公约数的算法,它原本是为约分而设计的,但它适用于任何需要求最大公约数的场合。
第一步:任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步。
第二步:以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。则第一步中约掉的若干个2与第二步中等数的乘积就是所求的最大公约数。
其中所说的“等数”,就是最大公约数。求“等数”的办法是“更相减损”法。所以更相减损法也叫等值算法。
解决完了这两个问题,那我们通过辗转相除法和更相减损法两种方法分别来编写代码:
//最大公约数1——辗转相除法
int main()
{
int a, b, c;
scanf("%d%d", &a, &b);
if (a < b)//a、b先进行换位,保证较大的数赋值给a
{
int d = a;
a = b;
b = d;
}
while (a % b != 0)//判断取模是否为0,不为0,说明b不是a的最大公约数,继而开始辗转相除;
{
c = a % b;//通过变量完成换位,先将取模结果赋值给c
a = b;//将除数b赋值给a;
b = c;//将取模值赋值给b,随后继续进入循环判断;
}
printf("最大公约数:%d\n", b);
return 0;
}
//最大公约数2——更相减损法
int main()
{
int a, b, c, d = 0;
scanf("%d%d", &a, &b);
while (a != b)
{
if (a < b)
{
c = a;
a = b;
b = c;
}
d = a - b;
a = b;
b = d;
}
printf("最大公约数为:%d\n", a);
return 0;
}
这两个代码供大家参考,如果各位有更好的方法来编写的话,可以在评论区分享出来哦!下面我们继续看下一题:
5.打印闰年(1000-2000)
这一题做之前,我们先了解一下闰年以及闰年的判定方式:
1.什么是闰年?
凡公历中有闰日(2月29日)的年份,阴阳历中有闰月的年份。
2.如何判定闰年?
1、非整百年份:能被4整除的是闰年;
2、整百年份:能被400整除的是闰年;
3、对于数值很大的年份:如果这一年不仅能被3200整除,还能被172800整除,则为闰年。如果这一年只能被3200整除,不能被172800整除那么这一年不是闰年。
在了解完这些内容后,我们开始顺着判定思路进行编写:
//打印闰年(1000-2000)
int main()
{
int a = 0;
for (a = 1000; a < 2001; a++)
{
if (((a % 4 == 0) && (a % 100 != 0)) || (a % 400 == 0) || ((a % 3200 == 0) && (a % 172800 == 0)))
//(a % 4 == 0) && (a % 100 != 0)——能被4整除但不能被100整除;
// (a % 400 == 0)——能被400整除;
// (a % 3200 == 0) && (a % 172800 == 0)——能被3200整除也能被172800整除
{
printf("闰年:%d\n", a);
}
}
return 0;
}
这里要注意在使用操作符逻辑与&&和逻辑或||时,操作符的两侧操作对象是一个整体,如果是表达式,则表达式外需要加上括号。接下里我们来看今天的最后一题:
6.打印素数(100-200)——试除法1
不管是答什么题,它肯定都是需要有解题思路的,这个思路怎么来呢?我们肯定是现需要了解了相关知识,才能对症下药。下面我们来分析一下这道题:
1.什么是素数?
质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数(规定1既不是质数也不是合数)。
2.素数的判定方法?
试除法:任意一个数i如果在2~(i-1)的范围内都不能被整除,那说明i为素数。
通过这个方法,我们可以开始尝试着编写代码了:
//打印素数(100-200)——试除法1
int main()
{
int a = 0, b = 0;
for (a = 100; a < 201; a++)//生成100~200范围内的数
{
for ( b = 2; b < a; b++)//生成2~(a-1)范围内的数
{
if (a % b == 0)//b如果能被a整除,那说明a有除1和它本身外的其它的约数,那说明a不是素数;
break;//a不是素数则跳出当前的循环;
}
if (a == b)//如果跳出循环时,a与b相等,那说明在2~(a-1)的范围内,无法找到能被整除的数,那说明a为素数;
{
printf("素数:%d\n", a);
}
}
return 0;
}
下面我们思考一个问题,偶数可能是素数吗?
答案是不可能,因为只要是偶数就能被2整除,也就是说偶数除了1和它本身外,还有至少一个2能被它整除,既然这样,我们在生成100~200范围内的数时是不是就可以直接把偶数给过滤掉了呢?
下面对上述的代码进行优化:
//打印素数(100-200)——试除法2
int main()
{
int a = 0, b = 0;
for (a = 101; a < 201; a += 2)//生成101~200范围内的奇数
{
for (b = 2; b < a; b++)//生成2~(a-1)范围内的数
{
if (a % b == 0)//b如果能被a整除,那说明a有除1和它本身外的其它的约数,那说明a不是素数;
break;//a不是素数则跳出当前的循环;
}
if (b == a)//如果跳出循环时,a与b相等,那说明在2~(a-1)的范围内,无法找到能被整除的数,那说明a为素数;
{
printf("素数:%d\n", a);
}
}
return 0;
}
接下来我们再来思考一个问题,如果一个数不是素数,那就说明这个数可以写成除i=1*i外的另一个等式i=x*y,此时x和y两个数要么一个大一个小,要么就相等,假设x<=y,如果我们在2~(i-1)这个范围内能找到x的话是不是就说明了i是存在除1和它本身以外的其它约数,那这个x具体是在什么范围内呢?根据x<=y这个条件我们可以两边同时乘以x得到x*x=x^2<=y*x=i,此时式子两边同时开平方可以得到sqrt(x^2)=x<=sqrt(y*x)=sqrt(i),这样我们就可以进一步确定x的范围是从2~sqrt(i)的,那我们可以继续优化上面的代码:
//打印素数(100-200)——试除法3
int main()
{
int a = 0, b = 0;
for (a = 101; a < 201; a += 2)//生成101~200范围内的奇数
{
for (b = 2; b <= sqrt(a); b++)//生成2~aqrt(a)范围内的数
{
if (a % b == 0)//b如果能被a整除,那说明a有除1和它本身外的其它的约数,那说明a不是素数;
break;//a不是素数则跳出当前的循环;
}
if (b > sqrt(a) )//如果跳出循环时,b>sqrt(a),那说明在2~aqrt(a)的范围内,无法找到能被整除的数,那说明a为素数;
{
printf("素数:%d\n", a);
}
}
return 0;
}
注:sqrt——开平方的数学库函数,如果我们需要使用这个函数的话就需要引用头文件<math.h>。
这一题咱们就做完了,当然打印素数肯定还有更好的方法,朋友们如果你们有更好的方法可以分享在评论区,供大家参考一下。
到这里我们就把今天的题目全部解决了,因为代码编写的题目除了理解以外,还需要自己上手操作,所以今天我没有附上各道题目的运行结果,朋友们可以自己亲自动手操作一遍,方面更好的去理解这些题目的解题思路以及提升自己的动手操作能力。
我们今天的内容就全部结束了,希望这篇内容能够帮助大家提升理解能力和动手操作能力,接下来随着学习的深入,我会继续分享我在学习中的感受,谢谢大家的翻阅,咱们下一篇见。