No.1-No.5 C语言500例
| No.1 有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?
题目分析:
首先我们可以从题中分析出以下两个关键信息:
– 1,数字个数是限定的,只有:1,2,3,4,共4位数
– 2,目标是从四个数中抽取三位数字,且该三位数字只能出现一次
如果本题只是求总的满足条件的数字个数,则其本质上是只是一个排列组合的数学问题,但是题目要求我们将其所有可能结果进行输出,因此,我们更需要关注的是:如何达到排除重复数字的目的
对于一个数组,我们应该知道的一个特性是:数组的下标是唯一的,通过下标能访问到的数组内的元素也是唯一的,当然其值可能不唯一,但这点其实就是我们解决本题的关键所在。
如何做到通过数组下标达到本题所要求的:组成的三位数中不存在重复的数字 呢?我们都知道,如果要遍历一个数组,最直接的方法就是循环,而本题要求的从四位数字中选择三位数字,可以通过三个嵌套循环来实现,具体来说,我们可以使用最直观的 for循环 来实现。
具体思路就是:通过三个嵌套的for循环来实现不漏地选择三个数字,再通过for循环中设置的循环变量来不重地选择数字,具体实现方式如下:
for (int i=0; i<4; i++){
for(int j=0; j<4; j++){
for(int k=0; k<4; k++){
if (i!=j && j!=k && i!=k){
num = arr[i]*100 + arr[j]*10 + arr[k]; // 组成体中要求的三位数
printf("%d", num); // 打印这个数
cnt ++; // 计数器自增
}
}
}
}
以上就是本题的核心部分了,那么本题的完整代码如下:
#include<stdio.h>
int main(){
int arr[] = {1,2,3,4}; // 已知的数组
int num = 0; // 用于临时存储满足条件的三位数
int cnt = 0; // 用于统计满足条件的三位数的个数
for (int i=0; i<4; i++){
for(int j=0; j<4; j++){
for(int k=0; k<4; k++){
if (i!=j && j!=k && i!=k){
num = arr[i]*100 + arr[j]*10 + arr[k]; // 组成体中要求的三位数
printf("%d\n", num); // 打印这个数
cnt ++; // 计数器自增
}
}
}
}
printf("cnt: %d", cnt);
}
本地运行结果:
| No.2 企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%;20万到40万之间时,高于20万元的部分,可提成5%;40万到60万之间时高于40万元的部分,可提成3%;60万到100万之间时,高于60万元的部分,可提成1.5%,高于100万元时,超过100万元的部分按1%提成,从键盘输入当月利润I,求应发放奖金总数?
题目分析
本题难度不大,类似于生活中的“电费阶梯型收费”,着重考察的是 if…else if …else 的应用,即假设当前利润为 X ,那么在 X 前的提成设定,均需要考虑到哦,而不是只考虑离 X “向下取档”或者说是“最近的一档提成规则”,有小伙伴私信说解题时通过率很低很低,其实是忽略了这里的问题,那么本题的相关代码如下:
#include<stdio.h>
int main(){
float lirun = 0;
float jiangjin = 0;
scanf("%f", &lirun);
if (lirun <= 100000){
jiangjin = lirun * 0.1;
}
else if (100000 < lirun && lirun <= 200000){
jiangjin = 100000*0.1 + (lirun - 100000)*0.075;
}
else if (200000 < lirun && lirun <= 400000){
jiangjin = 100000*0.1 + 100000*0.075 + (lirun - 200000)*0.05;
}
else if (400000 < lirun && lirun <= 600000){
jiangjin = 100000*0.1 + 100000*0.075 + 200000*0.05 + (lirun - 400000)*0.03;
}
else if (600000 < lirun && lirun <= 1000000){
jiangjin = 100000*0.1 + 100000*0.075 + 200000*0.05 + 200000*0.03 + (lirun - 600000)*0.015;
}
else{
jiangjin = 100000*0.1 + 100000*0.075 + 200000*0.05 + 200000*0.03 + 400000*0.015 + (lirun - 1000000)*0.01;
}
printf("奖金: %f", jiangjin);
}
本地运行结果如下:
| No.3 题目:一个整数,它加上100后是一个完全平方数,再 加上168又是一个完全平方数,请问该数是多少?
题目分析
在本题中,我们只知道待求目标为一个整数,且这个整数分别 加上 100 和 268 后均为完全平方数 \<本处请仔细审题!!!>,由于只知道是整数,且并没有划定这个整数的界限,所以本题考察的其实是对于循环 while 和 for 的运用,且在本题中,如果您只需要最终的答案,您可以直接使用 while循环 ,若您需要一段完整的代码,您可以在使用 while循环 圈定最终答案的范围之后再次使用 for循环 编程,以得到一段能正确输出答案且不存在死循环的代码。
回归本题,我们不妨假设这个整数为 X,则根据题目规则我们可以得到:
$$(X + 100 + 168) – (X + 100) = 168 $$
也就是两个平方数之差为 168 ,当然这个角度并不能为我们解题提供太大的帮助,因为范围还是比较大且用嵌套循环的话运行速度堪忧(bushi ),那么已知本题的核心解题工具为循环,结合循环语句,我们应当怎样更简单有效地解决本为题呢?
其实关键还是在 一个整数,它加上100后是一个完全平方数,再 加上168又是一个完全平方数 这句话上面,我们可以根据这句话的逻辑关系和两个变量构建一个等式:
int x = sqrt(i + 100);
int y = sqrt(i + 100 + 168);
i+100 == x*x && i+268 == y*y
我们知道,在C语言中,如果变量的数据类型为整形,则不管为该变量赋值何种数字类型,最终都只会保留整数部分,即:
1, int x = 3.5; --> x = 3
2, int x = sqrt(5); --> x = 2
3, int x = sqrt(4); --> x = 2
则根据这三点关系,我们可以编写代码:
#include<stdio.h>
int main(){
int i = 0;
while (i <= pow(2, 32)-1){
int x = sqrt(i + 100);
int y = sqrt(i + 268);
if ((x*x == (i + 100) ) && (y*y == (i + 268))){
printf("%d\n", i); // 输出符合条件的数字
}
i ++;
}
}
当然上述代码是一个无限循环,意味着他将会一直执行下去,这只是有利于我们打印所有满足条件的值,到这里可能会有小伙伴会问,为什么这个值是有限的呢?
其实这个答案就藏在二次函数 $y = x^2$ 的图像中,如果我们取 $x∈Z(整数)$,您就会发现当 X 逐渐增大时,点与点之间的距离只会越来越大,而不是存在某个上限阈值(比如168或者268),因此,我们几乎可以判断本题的答案个数一定是有限的,且答案分布范围应该不会很大,当我们执行上述代码,将会得到:
等待程序运行一会,发现cmd窗口只打印出上图三个数字,也就是说,这三个数字大概率就已经是本题的答案了。
到此本题答案已经明了了,如果您需要一个漂亮的程序,可以将上述的 while循环 替换成 for循环 ,只要您设定的 for循环 变量的范围比答案的最后一位 1581 大的话,那当然是没有问题的喽😆😆😆
最后本题可以参考的 for循环 实现如下:
| No.4 题目:输入某年某月某日,判断这一天是这一年的第几天?
题目分析
本题是所有的编程初学者都绕不开的一道“小坎”,由于是入门题,因此在本题中我们不考虑 “年份、月份、日期不正确” 等问题,即默认输入的年-月-日都是正确的,本题在C语言中,其核心考点为 switch…case… 语句功能及其应用;在常识上,其考察我们 有关 平年闰年的判断规则 ,那么接下来,我将对于本题的一些常见的疑点列举如下:
- 1,平年和闰年是什么?应该怎么判断?如何将判断逻辑体现在程序设计中?
- 2,本题选择用 if……else if ……else…… 进行解题可以吗?
首先,我们先来聊聊第一个点,平年和闰年是什么?
平年和闰年是公历(格里高利历)中用于调整天文年与日历年差异的两种年份类型。以下是它们的区别和判断方式的详细介绍:
1、平年与闰年的定义
1.1 平年
全年共有 365 天,2 月份有 28 天。未满足闰年条件的年份均为平年。1.2 闰年
全年共有 366 天,2 月份有 29 天。多出的一天(2 月 29 日)用于修正地球公转周期(约 365.2422 天)与日历年(365 天)的误差。其次,我们再来说说上面提到的 公历(格里高利历) 其中 “记载” 的平闰年判断方法:
① 年份能否被 400 整除? → 是 → 闰年
② 否则,能否被 100 整除? → 是 → 平年
③ 否则,能否被 4 整除? → 是 → 闰年
④ 否则 → 平年
从上我们可以总结出两条用于判断平年还是闰年的规律,即:
- 年份能够被400整除
- 年份能被4整除但不能被100整除
这也就能解释一部分同学的疑惑:
– 能被400整除的不是一定能被4整除吗?
– “能被4整除但不能被100整除” 的这个条件条件在第一个条件下是不是显得有些别扭,好像是为了故意把 400 这个类别单独划分出去才设定的规则,总感觉其似乎有些 “多余” 。
– 为什么不直接使用 **year % 4 0 这个作为最终的条件,因为这个条件看起来非常契合上面的两条**
在了解完公历纪年法之后,集合上述平闰年的判断说明,存在上述3点疑惑的小伙伴现在应该已经明了了吧
至于本题是否可以选择用 if……else if ……else…… 进行解题,答案当然是可以的,只是需要写的判断条件会繁琐一些,本处还是选择使用较为简洁的 switch……case ,并不是博主懒,而是应该把这个宝贵的机会留给 作为初学者但是动手能力强又爱自己实践码代码 的你们呐!!(属实是用心良苦了 )
既然如此,由于本部分代码难度不大,那我们就直接上代码吧:
- 1,平闰年判断,沿用上面总结出来的规律
bool is_run(int year){
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)){
return true;
}
return false;
}
- 2,switch……case部分,用于累计计算到当前月份为止一共有多少天,并在此基础上加上当前月份的日期:
switch(m){
case 1:
cnt +=d;
break;
case 2:
cnt += 31+d;
break;
case 3:
cnt += 31 + 28 + d;
break;
case 4:
cnt += 31 + 28 + 31 + d;
break;
case 5:
cnt += 31 + 28 + 31 + 30 + d;
break;
case 6:
cnt += 31 + 28 + 31 + 30 + 31 + d;
break;
case 7:
cnt += 31 + 28 + 31 + 30 + 31 + 30 + d;
break;
case 8:
cnt += 31 + 28 + 31 + 30 + 31 + 30 + 31 + d;
break;
case 9:
cnt += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + d;
break;
case 10:
cnt += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + d;
break;
case 11:
cnt += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + d;
break;
case 12:
cnt += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + d;
break;
default:
printf("None day!");
break;
}
那么本题的完整代码就如下了,如果初学者不明白
“`bool is_run(int year)“` 本部分作用的,这里就作为一个前瞻预习作业了,请自行了解 “`C语言-函数“` 这一部分的内容,因为函数体内容比较简单,预习完看懂应该问题不大,如果您是这样的初学者,当您预习完毕之后,建议修改本部分代码,尝试将函数体内的内容移到 “`main“` 函数中,如果代码能够正确运行,则表示您已经基本了解掌握函数封装这部分的内容了!!🥳🥳🥳
当然如果您感觉理解有些吃力,或者在修改代码时出现其他您暂时解决不了的问题,欢迎私信或在下方评论区讨论哦!
/*
题目:输入某年某月某日,判断这一天是这一年的第几天?
*/
#include<stdio.h>
bool is_run(int year){
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)){
return true;
}
return false;
}
int main(){
int y,m,d = 0;
int cnt = 0;
printf("请按照以下格式输入:Year-Month-Day\n");
scanf("%d-%d-%d",&y, &m, &d);
switch(m){
case 1:
cnt +=d;
break;
case 2:
cnt += 31+d;
break;
case 3:
cnt += 31 + 28 + d;
break;
case 4:
cnt += 31 + 28 + 31 + d;
break;
case 5:
cnt += 31 + 28 + 31 + 30 + d;
break;
case 6:
cnt += 31 + 28 + 31 + 30 + 31 + d;
break;
case 7:
cnt += 31 + 28 + 31 + 30 + 31 + 30 + d;
break;
case 8:
cnt += 31 + 28 + 31 + 30 + 31 + 30 + 31 + d;
break;
case 9:
cnt += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + d;
break;
case 10:
cnt += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + d;
break;
case 11:
cnt += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + d;
break;
case 12:
cnt += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + d;
break;
default:
printf("None day!");
break;
}
if ((is_run(y))&& m >= 3){
cnt += 1;
}
printf("%d-%d-%d 是第 %d 天", y, m , d, cnt);
}
那么本题到这里也就算是结束了,对于一开始提到的 输入的“年、月、日”等信息不正确 的问题,这其实是一个关乎程序鲁棒性(容错性)的问题,此类问题在编程竞赛中也是常见的 “坑点” 之一,如果您觉得本题较为简单,那不妨可以动手试试处理这个问题哦!
| No.5 题目:输入三个整数x,y,z,请把这三个数由小到大输出。
题目分析
题中要求我们将输入的三位数按照从小到大的顺序输出,目的就是让我们将给定的三位数进行从小到大排序,本处我们提供两种方向:
- 1,比较-赋值法
- 2,比较-交换法
我们首先来看第一种 比较-赋值 法:
已知确定的两个数 a 和 b 则其和 a+b 的值也是确定的,假设已知其和为 C ,有一值 a ,则可以通过 c-a 的方式确定 b 的值。
将这个思想应用于本题,即我们首先需要确定最大值和最小值,再通过 三数之和 减去最大值和最小值,进而确定中间的那位数,如何从三位数中确定最值是一个比较简单的问题,这里我们选择通过 逐个比较 的方式确定,同时引入 三目运算符 的使用,巩固对于三目运算符的应用。
具体的实现逻辑如上,由于实现比较简单,我们直接上代码:
#include<stdio.h>
int main(){
int x,y,z = 0;
int num1, num2, num3 = 0;
scanf("%d %d %d",&x, &y, &z);
int sum = x + y + z;
int tmp = 0; // 临时存储比较时产生的中间值
tmp = x>y ? x : y;
num1 = tmp>z ? tmp : z;
tmp = x<y ? x : y;
num3 = tmp<z ? tmp : z;
num2 = sum - num1 - num3;
printf("三数从小到大的顺序为:\n");
printf("%d %d %d", num3, num2, num1);
}
我们再来看第二种 比较-交换 法,本方法通过三次比较实现,核心在于交换两个变量的值。
对于 交换 这点我需要额外提一下,C语言的变量就像是现实生活中的容器,比如喝水的杯子,而变量的值则是杯子中的水,现在我将为你讲一个关于变量、变量值和杯子的故事
假设现在有两个颜色不一样杯子,一个装有可口可乐,一个装有开口可乐,你那位爱整蛊的朋友将装有开口可乐的杯子递给你,然后急着去上厕所了,很不幸这个想法被你的读心术窥探到了,现在你有一个 “恶毒” 的想法,你想要你的朋友“自食恶果”(jiejiejie),由于你的朋友记住了杯子的颜色,所以直接调换两人的杯子是不合理的,因为马上就会被你的朋友发现!
但是这难不倒聪明机灵的你,你直接掏出来第三个杯子,并将开口可乐倒进了这个第三个杯子,再将朋友杯子中的可口可乐倒进了自己的杯子,最后将第三个杯子中装有的开口可乐倒进了朋友的杯子,现在你已经完成了完美调换两个杯子中的饮料了!你那位上厕所回来的朋友看见杯子颜色正确,于是毫不犹豫的喝下了开口可乐,最终自食恶果!大快人心!!!(bushi )
现在你已经听完这个这个故事了,应该已经学会了交换两个变量值的方法了吧?🥴🥴🥴
没学会其实也没有关系,我们来看下面的代码,从实践中学习:
#include<stdio.h>
int main(){
int x,y,z = 0;
int num1, num2, num3 = 0;
scanf("%d %d %d",&x, &y, &z);
if (x > y){
int tmp = x;
x = y;
y = tmp;
}
if (y > z){
int tmp = y;
y = z;
z = tmp;
}
if (x > z){
int tmp = x;
x = z;
z = tmp;
}
printf("三位数从小到大是:\n");
printf("%d %d %d", x, y, z);
}
有小伙伴对这三次比较存在质疑,这三次比较是否存在特定的顺序呢?例如,按照代码中的写法,我们是否可以先比较y和z,再比较x和z,最后比较x和y呢?
那么本部分作为一个小小的思考题,如果您也有这部分的疑问,不妨动手修改代码,我知道 作为初学者但是动手能力强又爱动手实践码代码 的你肯定不会放过这次机会的!
那么以上就是本期 C语言从初识到竞赛精通 No.1-No.5 的全部内容了,如果您在阅读本文的过程中有所收获,或者有任何宝贵的建议和想法,欢迎通过邮箱、微信或者留言等方式给我留言交流,您的每一次建议都将是我前进的动力!