第一次C博客作业
Q0.展示PTA总分
Q1.本章学习总结
1.1 学习内容总结
- 数据的输入和输出
- 列表了比较常见的几种数据类型;
- 有小数的在输出中可用如%.3f表示保留3位小数,也可以在前面加数字表示占的位数(找不到一个好的表示的词了)如%6.3f;
- 字符常量在使用时要记得加单引号。
数据类型 | 在scanf()中表示 | 在printf()中表示 | 备注 |
---|---|---|---|
int | %d | %d | 整型变量,计算时只保留整数 |
long | %ld | %ld | 长整型变量,现在和int基本一致? |
float | %f | %f | 单精度浮点数,可输入小数,但不常用 |
double | %lf | %f/%lf | 输出时默认带6位小数 |
char | %c | %c | 也可用getchar()输入,但注意两者都只能读入一个字符 |
- 数据处理中会运用的数学函数
- 开平方根:sqrt(x),x为被开方的数
- 取绝对值:fabs(x),x为被取绝对值的数
- 求幂:pow(x,n),x为底数,n为幂(e为底数则用exp(x),x为幂)
- 取e为底的对数:log(x)
- 注意:多次使用这些函数会影响程序的效率,有时候可以通过其他办法来避免使用这些函数。
- 分支结构(if/else-if/switch)
- 虽然三者都能进行分支但也有很多不同。
1.if-else需要判断每个分支。而switch只会进入满足条件分支,程序效率高。
2.若要对变量进行判断时,switch语句只能判断一个变量,而if语句可以用与和或号判断多个变量。
3.if语句可以判断变量是否在区间内,而switch只能判断变量的值是否为某个常量。
- 虽然三者都能进行分支但也有很多不同。
int main()
{
if (表达式1) //若表达式1为真则执行语句1,否则跳过
{
语句1;
}
if (表达式1) //若表达式1为真,执行语句1并跳出该else-if结构
{
语句1;
}
else if (表达式2) //若表达式1为假,则直接执行到这里,并与表达式2进行判断,为真执行语句2并跳出结构
{
语句2;
}
else //若表达式1、2都不符合则执行语句3
{
语句3;
}
/*要注意else与前面最近的if匹配,不是只看大括号的位置!!*/
return 0;
}
int main()
{
switch (表达式) //取该表达式的值与case中的常量表达式对比
{
case 常量表达式1:语句1; break; //若表达式的值=常量表达式1的值执行语句1并跳出switch语句
case 常量表达式2:语句2; break; //若表达式的值=常量表达式2的值执行语句2并跳出switch语句
...
default:语句n; break; //若表达式的值不符合上面任何一个,执行语句n
}
/* default在switch语句中并不是必须的。
break也不是必须的,但要注意在不用break语句的情况下,若表达式与常量表达式2的值相等,会执行语句2和后面所有的语句!*/
return 0;
}
- 循环结构(for/while/do-while)
- for一般用于知道循环次数的情况,while和do-while多用于循环次数不确定时,当然确定时也可以用。
- 当第一次进入循环就不满足条件时,for和while都不会执行循环,而do-while会执行一次。
- 部分情况下三种循环可以相互代替。
int main()
{
for (表达式1; 表达式2; 表达式3) //表达式1赋予初值,只执行一次;表达式2用于判断循环条件,为真执行循环体语句,否则结束循环;执行循环体语句后执行表达式3,然后回到表达式2
{
循环体语句; //需要被多次执行的内容
}
return 0;
}
int main()
{
while (表达式1) //每次执行循环前与表达式1判断,为真则执行循环,为假则跳出循环执行接下来的内容
{
循环语句1;
}
do
{
循环语句2;
} while (表达式2); //先执行一遍循环语句,再与表达式2判断,为真继续循环,为假跳出循环
/*所以无论如何,do-while循环一定会执行一次*/
return 0;
}
1.2 本章学习体会
- 因为前面部分自己有先自学过,在上课之前觉得问题不是很大,但实际在课堂和作业中会发现有些细节是之前根本没注意到的
- 个人觉得PTA/课堂派的部分作业可以在课堂上进行讲评
- 总结下来最重要的还是自己动手打代码,有些不会的必须得上手才能解决掉
- 然后代码量的话……嗯…因为我的PTA是9月19号才开通20号开始打题的,所以这两周打了很多题,就不统计了吧……?
(我觉得挺多的)
Q2.PTA实验作业
2.1 计算天数
2.1.1 数据处理
- 数据表达
- int year:用户输入的年份
- int month:用户输入的月份
- int day:用户输入的日期
- int total:用于统计总天数
- 数据处理
- 先用switch语句对month进行判断,按照输入的月份将total加上已经经过月份的天数
- 再对year进行判断是否为闰年,若为闰年且月份大于2,则天数+1
- 最后将total加上day即为所求天数
2.1.2 代码截图
2.1.3 本题可扩展功能
我的代码和该题的要求并不严谨,若输入的日期不正确,如输入32号或输入2019/02/29仍然可以输出正确的日期,该题可扩展先判断日期是否合法,若合法再输出天数
2.1.4 PTA提交列表及说明
虽然PTA提交列表里一遍过,但是在VS里面还是遇到一些问题的
Q1.纠结输入01、05这样子前面带0的数据怎么处理
A1.询问之后了解了int类型数据会自己处理掉前面的0
Q2.闰年判断错误
A2.判断顺序搞错,在能被4整除但不能被100整除这句话上加上括号就过了
2.2 二进制转十进制
2.2.1 数据处理
- 数据表达
- long num10:用于记录换算后的数
- int count:记录输入了几位数(从0开始)
- int flag:记录是否出现了不合法的数
- int i:用于数组
- char ch[100]:定义一个长度为100的数组储存输入的字符
- 数据处理
- 运用循环和数组将用户输入的每个字符存起来,遇到回车时停止
- 询问得知可以用这个方法转换进制:从最后一位开始算,依次列为第0、1、2...位,第n位的数(0或1)乘以2的n次方,得到的结果相加就是答案
- 将数组中的字符转换成数字,运用上面的方法转化
2.2.2 代码截图
2.2.3 本题可扩展功能
该题的功能已经较完善了,我就增添了一个十进制转二进制的功能(限定正数)
2.2.4 PTA提交列表及说明
Q1.多个1测试点过不了
A1.将代码中scanf改成了getchar,用字符来做这道题
Q2.第一个测试点过不了
A2.这个卡了很久,一直测试都没问题,还去问了老师测试数据是什么,然后发现因为我选择的数据正好都是从左往右读都一样(忽略首部的0)所以都没测出来错误。。
知道测试数据以后发现我的代码是从左往右读,而上面的方法是要求从右往左读(scanf就没有这个问题),所以一直出错。。最终用上了数组来倒序。。肯定有更简单的方法,只是我想不到。。
2.3 于龙遇见日期,又哭了
2.3.1 数据处理
- 数据表达
- int x,y,z:储存输入的三个数字
- int year,month,day:等待xyz给它们赋值,用于输出
- char a,b:只用于处理输入时的奇形怪状的符号
- 数据处理
- 先判断x y z的大小,将最大的赋给年份
- 然后按顺序,第一个在1-12间的赋值给月份(如果x是年份但在12以内也排除)
- 两个值赋给年份月份了,剩下的就是日期
- 最后在输出结果前做一堆判断。。
2.3.2 代码截图
2.3.3 本题可扩展功能
这题我真的想不到怎么扩展它了
只能说一下自己对这道题的感受了
首先就是题目的文字量很大,读了好多遍才知道他想要干啥
这道题难的不是对年月日的赋值和比大小什么的,而是对非法日期的判断真的很烦(还有测试点还看不出哪个错哪个对)
但是只是抢分的话这题目标还是比较明确的,几个比较简单的非法可以先写(有次我写完了分还没有只写了几行多)
还有就是代码量的问题,这题需要的代码行数比较多,进行改动的话一行行过去还是很麻烦的,有可能扫完一遍还剩个地方没改到
所以在这题中F11测试非常好用,添加监视一行行走下去,错误发现还是比较快的
但这道题总体还是没有偏离我们学的if-else分支,主要还是考察分支结构,if的条件能否写清楚,能否读通题目意思以及运气好不好能不能猜到测试点是什么
2.3.4 PTA提交列表及说明
(这题在test01题库中我看不到自己的提交情况?)
Q1.符号读不进去!
A1.刚开始做题时机房电脑的VS我还没有改SDL,用不了scanf,导致我用scanf_s的情况下中间的两个符号一直读不进去。所以以后打开VS第一件事还是得把SDL检查关了!
Q2.2月29号的判断!
A2.这个比较麻烦,很多与号和或号还有括号连接,绕的有点晕,又是少括号又是打错与或号的……
Q3.这个测试点是什么啊我怎么都过不去!
A3.看运气10个测试点对应着从它题目中的7个到他下面输入样例的3个(不说还真不知道)当时错着改着突然就过了也是有点惊讶……还是希望老师在这些地方能加点提示…
回归正题,要在没有31号的月份却输入了31号、闰年、没有按照顺序输入等这种小问题一个个排查,才能一步步改到正确答案
Q3.阅读代码
我选择了poj 1972 Dice Stacking
- 代码功能
- 首先输入骰子的组数,然后输入该组骰子的个数,再输入骰子每面的数字
- 输出该组骰子叠起来后的一整面数字的和最大的值(上面骰子的底面与其下面骰子的顶面点数相同,骰子可以在底部确定的情况下平面旋转)
- 代码优点和可以学习的地方
- 自定义了函数getmax()寻找这颗骰子的在这面的最大值
- 使用二维数组保存了每组骰子的每面数字,在后续使用中方便
- 使用嵌套循环计算和,外部循环先初始化,内部循环再叠加,十分清楚
- 使用了max()函数,比较一遍变量ans与max的大小再保存更大的数,不需要再繁琐的使用if-else语句
- for(scanf("%d",&T);T;T--)的写法十分新奇,可以自定义初始值,并且该for循环里中间的表达式又相当于T>0
- 开头的#include< cstdio>,#include< cstring>,#include< algorithm>和我们现在使用的都不同。经查阅似乎cstdio是将stdio.h的内容用C++头文件的形式表示出来(我们使用的stdio.h则是C标准函数库中的头文件),而cstdio中的函数又是在名称空间std中的,故在后面加上了using namespace std;
(我也有点晕)