写在前面
趁着暑假赶紧把C语言的习题也补了 也欢迎看到这篇博客的小灯们来到华南农业大学喵 专栏里还有后续其他部分课程的学习笔记
如何提交自己的代码
首先给各位说一下这门课程的要求,首先是我们学校的校内OJ,我们计算机类专业的学生用的是前面这个链接,别的学院选修课或者转专业用的应该是另外一个,登录的初始账号和密码都是自己的学号,后续可以进行修改。平时的程序类的课后作业和考试以及之后的程序设计校赛都在这个平台进行。
进去之后长这个样子,确实比较简陋
在左边的实验里面选对应的课程就可以看到课后习题了,第一次进入系统先去高级程序语言设计里面的实验1填一个问卷,可以直接升5级
如何编写自己的代码
然后是我们使用的IDE,上课老师做演示一般是使用CodeBlocks,优点在于不需要怎么配置,缺点在于不能怎么配置,不支持装插件,界面也很简陋
当然如果你不喜欢这个很土的页面,也懒得在学完C语言之后学其他语言还要换IDE花时间适应的话,你还有其他更酷炫的选择,我说的就是CLion,不推荐VS Code主要还是觉得新手配置麻烦过头了,而且我也不常用
打开官网,你肯定会发现这个软件要钱,没关系,接下来就向你介绍如何申请学生白嫖特权
学生认证
来到我们学校的网络服务中心 在最左边点击开通邮箱,虽然说是随便取名字,但是亲测输入学号除外的任何内容作为邮箱地址都会申请失败
回到JetBrains官网,在这里进入申请页面
申请方式选择官方文件,填进你刚刚申请好的校园邮箱,上传的学生证或者校园卡的照片,去学信网申请一个电子认证码填进去,一周内你就可以在校园邮箱看到申请成功的消息了。直接用你的校园邮箱登录CLion就可以使用了,等待成功的这段时间刚好有一个月的试用期,可以先用着
Github的学生认证也是同理,如果想要白嫖Copilot的AI辅助代码功能可以去申请一下
网课资源
陈湘骥教授(下称bsc)非常鼓励我们在这门课提前学习,他推荐我们去看的是翁恺教授的网课,让我们提前看,每节课课前要报一下自学进度,他在前期过渡几周之后的上课节奏就会非常快,不提前学一点的话可能会有一些吃力,当然翁凯老师的课确实是独一档了,免费还讲得这么好有什么理由不看看呢
实验1 C语言程序初步
6567 The first C Program
恭喜你在开学前完成了非常完备的准备工作,完成上面的操作,熟悉一下学校的系统你就已经击败80%的同学了,当然如果你真的那么好学!我们也可以直接开始C语言的学习
首先是我们的第一道题,照着题目给的这个图片把代码打上去然后运行即可,CodeBlocks的运行按钮已经告诉你们了,CLion的运行按钮是那个绿色的开始键,非常的清晰明朗(
1001 计算a+b
然后我们就要开始语法的学习了,首先作为一段程序,我们肯定是有一些命令的语句的,但是如何让计算机能够看懂呢?我们需要引入库,也就是最上面的#include <stdio.h> 如果不先include这么一下的话,你在底下写的大部分函数电脑都是看不懂的,你的代码也就只是一段文本文档而已,在之后的学习中我们还会学习很多的库,我们现在要知道的是,想让你的程序从点运行之后弹出来的黑框里面读入你输进去的东西以及输出东西上去所需要的scanf和printf语句,都需要你先引用stdio.h这个库
scanf和printf,顾名思义,就是在黑框里面读入和输出,具体使用方法如下
scanf("%d",&a);
printf("%d",a);
当程序运行到scanf那一句的时候,就需要你在黑框里面打进去一个数字,然后你的这个数字就会被存在a这个名字下面被程序继续使用,而当运行的printf那一句的时候,就会把存起来的a这个名字代表的数字显示在黑框上面
而外面这个框和int main是什么意思呢?就是说只有写在这个框里的内容才会跑起来,至于后续更复杂的函数相关呢,我们留到后面实验9再细说
那么这一题就直接这样写就可以了
#include <stdio.h>
int main()
{
int a, b;
scanf("%d%d", &a, &b);
int c=a+b;
printf("%d", c);
return 0;
}
11126 输出a与b中的较大值
与上面的同理,大于小于也是可以直接使用的
#include <stdio.h>
int main()
{
int a, b;
scanf("%d%d", &a, &b);
if(a > b)
printf("%d",a);
else
printf("%d",b);
return 0;
}
而这里新出现的if和else是啥呢?我想如果你高考考的是英语,那你一定知道if就是如果的意思,else就是否则的意思,所以这段代码你直接用你双一流的英语水平就可以直接看懂了,if和else也同样不需要你提前引用任何的库
实验2 基本类型与运算
上一章我们简单了解了一些基本的语法知识,但是那个int到底是什么呢,我们将在这一章详细学习数据类型的相关知识 具体的可以看这篇文章的第一节 后面的数组之类的我们后续再了解
总而言之,在C语言里面主要的数据类型有这些(标识符就是你在scanf和printf里面的双引号内应该写的内容)
类型名称 | 标识符 |
---|---|
int | %d |
long long | %lld |
float | %f |
double | %lf |
char | %c |
除了数据类型,还有运算相关的知识,想来也就是加减乘除大于小于嘛,但是在计算机的世界里我们还有一种运算叫做取模,符号是%,具体作用就是求两个整数相除之后的余数。除此之外,不同数据类型的运算也会有所不同,具体的你也可以在上面的那个文章里面看到
1117 变量定义,按要求完成程序
看了上面的文章,想来你可以很轻松的填上这道题的两个空
int a,b;
float i,j;
6568 在显示屏上显示指定字符
在C语言中,有一些标识符,比如\n标识回车,那么假如我真的只是想单纯地输出\n这两个字符怎么办呢,我们发现打\总是不会出现,我们有一些特殊的语言规范
假如我想输出\,那么我就要打两个斜杠,这样就会避免标识符的冲突
如果你是CodeBlocks用户就需要在打代码的过程中小心一点,但如果是CLion的话,你的编辑器会自动帮你修正这个问题,当你把C:\ABC.TXT复制进去之后,你会发现他自动变成了两个斜杠,自己打的过程如果你忘打了斜杠他也会自动变色提醒你修改,就像这样
言归正传,这一题你只需要注意多打一个斜杠才能正确输出就行了
#include <stdio.h>
int main()
{
printf("C:\\ABC.TXT\n");
return 0;
}
1119 基本运算,写出程序运行结果
问这个代码的运行结果是什么,我们一句一句看
#include <stdio.h>
int main()
{
int a,b,c;
float d=15,e,f;
a=35%7;//a是35除以7的余数,也就是0
b=15/10;//虽然15/10确实是1.5,但是b是int类型,所以会自动舍去小数部分,所以b是1
c=b++;//这一行其实做了两件事,我们要从前往后看,先把b的值赋给c,然后b再自增1,所以c是1,b是2
e=15/10;//我们从后往前看,15和10都是整数,所以算出来的结果还是整数1,把整数1赋给e,所以e是1.0
f=d/10;//d是float类型,10是int类型,所以d/10是float类型,所以f是1.5
printf("%d %d %d %f %f %f\n",a,b,c,d,e,f);
}
那么答案也就昭然若揭了
0,2,1,15.000000,1.000000,1.500000\n
1118 赋值表达式与赋值语句,写出程序运行结果
这题和上一题类型一样 这题我们还引入了char类型也就是字符,英文的字符和中文不同,一共就那么多个,所以我们给每一个字符标上序号,在本地存储的时候才能将字符先变成对应的序号,然后再存下这个序号的二进制表示,这就是ASCII码
#include <stdio.h>
int main()
{
float a;
int b,c;
char d,e;
a=3.5;
b=a;//由float强行变成int,会丢失小数部分,所以b是3
c=330;
d=c;//我们看上面的ASCII码表,330比最后的那个126还要大,在126之后又从1开始,所以d是对应74的‘J’
e='\141';//141是八进制,对应的是十进制的97,对应的是ASCII码表的‘a’
printf("%f %d %d %c %c\n",a,b,c,d,e);
}
那么答案也就是
3.500000,3,330,J,a\n
实验3 基本输入与输出
这一章,我们终于开始细究好像我们每一个代码都用了的scanf和printf函数了
1126 字符的输入与输出
#include <stdio.h>
int main()
{
char c;
scanf("%c",&c);
printf("%c",c);
return 0;
}
1127 计算加法
#include <stdio.h>
int main()
{
int a,b;
scanf("%d+%d",&a,&b);
printf("%d",a+b);
return 0;
}
1014 求圆面积
虽然输入的时候没有小数点,但是我们一样可以直接把他存到浮点数类型的变量里面。
顺带一提,自己写代码的时候推荐使用double,虽然比float多打一个字母,但是在之后写一些复杂代码的时候出错的概率会小很多
#include <stdio.h>
int main()
{
double r,s;
scanf("%lf",&r);
s=3.14159*r*r;
printf("%.2f\n",s);
}
1015 计算摄氏温度值
这一题需要注意一下上一章最后一题我们提到过的数据类型的强制转换,如果你直接写9/5的话他们算出来会是1,因为小数位会被直接抹去,所以我们要写成9.0/5.0表示他们是浮点数,当然也可以像下面的代码这样直接拿原本的数字乘5再除以9,因为f是double类型所以一直不会出错
算式内的每一次计算中途如果只涉及到整数类型的数据,那么算出来的结果也仍然会是整数类型
#include <stdio.h>
int main()
{
double f,c;
scanf("%lf",&f);
c=5*(f-32)/9;
printf("%.2lf\n",c);
}
11127 各位数字
我们仔细思考一下,一个三位数的百位数字其实就是他整除100的结果,而各位数字则是他对10取模的结果,所以答案也就不难出来了
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
printf("%d\n%d",n/100,n%10);
return 0;
}
单元测试1 计算路程
#include <stdio.h>
int main()
{
double a,t;
scanf("%lf%lf",&a,&t);
double s=0.5*a*t*t;
printf("%.2lf\n",s);
}
单元测试2 圆柱体的表面积
#include <stdio.h>
int main()
{
double PI=3.14159;
double r,h;
scanf("%lf%lf",&r,&h);
double S=2*PI*r*r+2*PI*r*h;
printf("%.2lf\n",S);
}
实验4 选择结构
这一章同样会详细介绍我们之前就用过很多次的if和else语句,使用方法也非常清晰明了,if后面括号里面填如果,然后大括号填要干什么,如果需要否则那就再写一个else,再一个大括号,当然我们还可以用else if来在else的基础上做进一步的限制
然后要多提一句的是代码里面我们的一些比较符号的规范
代码符号 | 表示含义 |
---|---|
== | = |
!= | ≠ |
>= | ≥ |
<= | ≤ |
&& | 并且 |
|| | 或者 |
与此同时还有switch-case这么个怪东西,简单来说就是在你的if-else要处理一个像开关档位之类的东西的时候写起来会非常的麻烦(但不是不能写),用这个东西写会比较方便
但是,在实际项目的过程中,switch-case没有if-else那么优秀的拓展性,说人话就是后来人改你的代码的时候还要找那个变量在哪。在算法竞赛的过程中,又因为break和default之类的层数处理非常容易出错(反正我就写错被队友骂过),所以在任何时候都不是非常推荐使用
1018 数的排序
#include <stdio.h>
int main()
{
int a,b,c;
scanf("%d,%d,%d",&a,&b,&c);
int first,second;
if(a>b){
first=a;
second=b;
}
else{
first=b;
second=a;
}
int max,min;
if(first>c)
max=first;
else
max=c;
if(second>c)
min=c;
else
min=second;
int full,mid;
full=a+b+c;
mid=full-max-min;
printf("%d,%d,%d",min,mid,max);
}
1016 字符变换
注意观察之前的ASCII码表,发现小写字母和大写字母的对应值相差32
(当然如果你翻过课本最后的函数表的话你会发现可以用tolower()之类的函数快捷处理)
#include <stdio.h>
int main()
{
char a,b,c,d,e;
scanf("%c%c%c%c%c",&a,&b,&c,&d,&e);
if(a>64&&a<91)
a=a+32;
if(b>64&&b<91)
b=b+32;
if(c>64&&c<91)
c=c+32;
if(d>64&&d<91)
d=d+32;
if(e>64&&e<91)
e=e+32;
printf("%c%c%c%c%c",a,b,c,d,e);
return 0;
}
1019 数的整除
一个数能不能整除另一个数其实就看他们的取模是不是为0即可
#include <stdio.h>
int main()
{
int a,b,c,d,e;
scanf("%d %d %d %d %d",&a,&b,&c,&d,&e);
if(a%27==0)
printf("YES\n");
else
printf("NO\n");
if(b%27==0)
printf("YES\n");
else
printf("NO\n");
if(c%27==0)
printf("YES\n");
else
printf("NO\n");
if(d%27==0)
printf("YES\n");
else
printf("NO\n");
if(e%27==0)
printf("YES\n");
else
printf("NO\n");
return 0;
}
1020 正负奇偶判断
奇偶的判断也就是是不是2的倍数,所以模2即可
注意负的奇数模2会得出-1,只判断1的话会出错
#include <stdio.h>
int main()
{
int a;
scanf("%d",&a);
if(a>0)
printf("positive\n");
else
printf("negative\n");
if(a%2==0)
printf("even");
else
printf("odd");
return 0;
}
1023 简单计算器
这题我没记错的话测试的数据有点问题,那就顺便说一下return吧,return是代表立即终止这个大括号的所有代码的运转,后面跟的这个值会被存到日志里,方便你后期查看的时候知道当时运行的时候走的是那个return,就我们初学者来说随便写多少都无所谓,只要你别故意写个浮点类型或者一个超级大的数就行
#include <stdio.h>
int main()
{
float a, b, c;
char op;
scanf("%f %c %f", &a, &op, &b);
switch (op)
{
case '+':
c = a + b;
break;
case '-':
c = a - b;
break;
case '*':
c = a * b;
break;
case '/':
if (b != 0) {
c = a / b;
} else {
printf("error\n");
return 1;
}
break;
default:
printf("error\n");
return 1;
}
printf("result=%.2f", c);
return 0;
}
1007 判断平方数
虽然简单但是前天队长打牛客多校的时候还想不起来怎么写来着(
对于一个整数类型的数,如果他开方后(因为是整数所以自动向下取整了)的数如果平方还等于他自己那么他就是一个平方数
那么如何去对一个数取开方呢,我们就要介绍另外一个新的库了,叫做<math.h>,里面包括但不限于取对数,取三角函数,取开方,取n次方,取绝对值等一大堆数学符号,只需要引用这个库,然后对照课本附录的表格使用即可
#include <stdio.h>
#include <math.h>
int main() {
int a;
scanf("%d", &a);
int b = sqrt(a);
if (b * b == a) {
printf("Y\n");
} else {
printf("N\n");
}
return 0;
}
1017 求数的位数
因为数字很小,我们也还没有学习循环,所以我们可以这么理解,比9大的那至少是两位数,比99大的至少是三位数,以此类推嘛
#include <stdio.h>
int main()
{
int n,place;
scanf("%ld",&n);
if(n>99999999)
place=9;
else if(n>9999999)
place=8;
else if(n>999999)
place=7;
else if(n>99999)
place=6;
else if(n>9999)
place=5;
else if(n>999)
place=4;
else if(n>99)
place=3;
else if(n>9)
place=2;
else
place=1;
printf("%ld\n",place);
}
1120 判断点是否在圆上
一个点在圆上也就是点到圆心的坐标等于半径那么这个点就在圆上,首先这个距离可能是负数嘛,我们在math.h里面有一个取绝对值的函数,绝对的英文是absolute嘛,所以这个函数就是abs(),但是对于浮点数,有一些特殊的处理方式,所以他们有个专属的取绝对值的函数叫fabs()
然后你会发现按照之前的说法用==,程序会报错,为什么呢?因为浮点数理论上有无限位小数,所以不能做相等的比较,你的计算机不敢赌后续可能会出现的某个小数位不一样了,所以干脆摆烂了。这个时候题目上说的根据小数精读来判断就有用了,我们比较两个数的时候,要把他们相减,然后看差值是否小于一个精读值,比如这题要求的精读是小数点后三位,那么我们需要的就是让比较的两个数的差值的绝对值小于等于0.001
#include <stdio.h>
int main()
{
float a,b;
scanf("%f,%f",&a,&b);
float doublea,doubleb,S,delta;
doublea=a*a;
doubleb=b*b;
S=doublea+doubleb;
delta=fabs(S-1);
if(delta<0.001)
printf("Y");
else
printf("N");
return 0;
}
实验5 循环结构(一)
你,是否因为代码太长而心力憔悴?你,是否因为重复内容过多而深感手酸?你的救星,来了!
终于,我们学习到了循环结构!其中包括for循环和while循环,还有一个不常用的do-while循环 ,顾名思义,他们可以帮你循环进行一些操作,具体的可以点进上面的两个蓝链看一看
虽然这一章原则上只涉及到while循环,但我建议你两个一起学方便理解
1024 计算阶乘
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int i=1;
int result=1;
//循环 每次使i加一并且和之前的result乘起来
while(i<=n)
{
result=result*i;
i=i+1;
}
//输出结果部分
printf("%d",result);
return 0;
}
1025 计算简单数列和
#include <stdio.h>
int main()
{
int n,i=1;
double son=2,mother=1,middle;
scanf("%d",&n);
double xiang,result=0;
while(i<=n)
{
xiang=son/mother;
result=result+xiang;
middle=son;
son=mother+son;
mother=middle;
i=i+1;
}
printf("%.4lf",result);
return 0;
}
1044 输出最小值
就连scanf和printf也可以放进循环里面让他循环读入数据
#include <stdio.h>
int main()
{
int a,b,n=1;
scanf("%d %d",&a,&b);
while(n<=9)
{
n=n+1;
if(a<=b)
{
a=a;
scanf("%d",&b);
}
else
{
a=b;
scanf("%d",&b);
}
}
printf("%d",a);
return 0;
}
1030 字符变换
这题放在这里个人觉得有点小问题,不过还是用循环写了一个本地跑起来会很奇怪但是可以通过oj评判的题,具体的正解应该要等我们学习数组相关知识才能解决
#include <stdio.h>
int main()
{
char c;
while (scanf("%c",&c) ,c!= '\n')
{
if (c >= 'A' && c <= 'Z')
{
c = c + ('a' - 'A');
}
printf("%c",c);
}
return 0;
}
1037 计算数列和
#include <stdio.h>
int main()
{
int n,i=1;
double son=2,mother=1,middle;
scanf("%d",&n);
double xiang,result=0;
while(i<=n)
{
xiang=son/mother;
result=result+xiang;
middle=son;
son=mother+son;
mother=middle;
i=i+1;
}
printf("%.4lf",result);
return 0;
}
1029 求最大公约数
#include <stdio.h>
int main()
{
int m,n,max;
scanf("%d,%d",&m,&n);
if(m>n)
max=m;
else
max=n;
int i=max;
while(m%i!=0 || n%i!=0)
i=i-1;
printf("%d",i);
return 0;
}
1031 统计单词个数
注意此题有坑,有的单词之间可能打了好几个空格
#include <stdio.h>
int main()
{
char c;
int i=0,judge=0;
while (scanf("%c",&c) ,c!= '\n')
{
if (c == ' '&&judge==0)
{
i=i+1;
judge=1;
}
if(c !=' '&&judge==1)
{
i=i;
judge=0;
}
else
{
i=i;
judge=judge;
}
}
i=i+1;
printf("%d",i);
return 0;
}
1042 百万富翁
#include <stdio.h>
int main()
{
int day=0;
double m,times=1,boss=0,normal=0,today;
scanf("%lf",&m);
while(boss<=normal)
{
day=day+1;
today=0.02*times;
boss=boss+today;
normal=m*day;
times=times*2;
}
day=day+1;
printf("%d",day);
return 0;
}
单元测试1 二进制数中1的个数
#include <stdio.h>
int main()
{
int i;
scanf("%d",&i);
int count=0;
while(i)
{
if(i%2==1)
count++;
i=i/2;
}
printf("%d",count);
}