0.展示PTA总分
单循环结构
嵌套循环
1.本章学习总结
1.1 学习内容总结
1.知道了while语句用于实现循环,且它的适用面更广,它的一般形式是:
2.知道了while语句中的表达式可以是任意合法的表达式,循环体语句可以包含for语句,且使用for语句可以更清晰
3.知道了需要用特殊的数值比如负数或0来作为结束标志应该怎么写
4.知道了fflush()
可以清除空格
5.知道了while
和do while
的区别:
1.不同:
while语句是在循环前先判断条件,只有条件满足才会进入循环,如果一开始条件就不满足,则循环一次都不执行;而do-while语句是先执行循环体,后判断循环条件,所以至少会执行一次循环体。
2.相同:
do-while和while语句中的表达式都可以是任意合法的表达式,循环体语句只能是一条语句,使用时都要另外加初始化的部分,循环体语句都必须包含能最终改变条件真假性的操作。
6.知道了break语句
和continue语句
的区别:
1.break结束循环,而continue只是跳过后面语句继续循环。
2.break除了可以终止循环外,还用于switch语句,而continue只能用于循环。
7.了解了在嵌套循环中容易犯的错误就是:
循环初始化语句放错位置,混淆了内外层循环的初始化
8.知道了分支结构中语句只能执行一次,而循环结构中语句可以重复执行多次
9.认识到了三种循环的特色:
一般说来,如果事先给定了循环次数,首选for语句,它看起来最清晰,循环的4个组成部分一目了然;如果循环次数不明确,需要通过其他条件控制循环,通常选用 while语句或do- while语句;如果必须先进入循环,经循环体运算得到循环控制条件后,再判断是否进行下一次循环,使用do- while语句最合适。
10.知道了当题目没有指定输入数据的个数时,需要自己增加循环条件的两种途径:
① 先输入一个正整数n,代表数据的个数,然后再输入n个数据,循环重复n次,属于指定次数的循环,用for语句实现。
② 设定一个特殊数据(伪数据)作为循环的结束标志,由于成绩都是正数,选用个负数作为输入的结束标志。由于循环次数未知,考虑使用 while语句。
1.2 本章学习体会
- 通过这一段时间的学习,我认识到了循环结构的使用,但是进入这一阶段,我的疑虑越来越多,一个PTA不断改进,可能错误还是不会变,为此我感到很焦虑,我也一直在问别人,看书,看视频,希望可以起到作用。
- 我还学会了运用printf的输出的调试方式,通过直接输出想要知道的答案,便于找出循环量较大时的问题所在。
- 在一些嵌套循环但是没有加{}的代码中,我不是很懂对应的条件,一层套一层容易乱。
- 我的代码量(不包括重复)
周 | 代码量(行) |
---|---|
4 | 241 |
5 | 506 |
6 | 771 |
7 | 842 |
累计 | 2360 |
2.PTA实验作业
2.1 题目名1
梅森数 (20 分)
形如2^n−1的素数称为梅森数(Mersenne Number)。例如2^2−1=3、2^3−1=7都是梅森数。1722年,双目失明的瑞士数学大师欧拉证明了2^31−1=2147483647是一个素数,堪称当时世界上“已知最大素数”的一个记录。
本题要求编写程序,对任一正整数n(n<20),输出所有不超过2^n−1的梅森数。
2.1.1 数据处理-伪代码
定义一个函数Mer来求2^n−1的值,
定义i,j来从小到大依次判断,
定义n为输入的正整数,
定义sum来记录2^n−1的值,
定义flag来控制输出,
定义count来记录梅森数的个数
给count赋初值
输入正整数n(n<20)
if (n == 2) 输出3\n
else
{
for i = 2到 i <= n, i++
{
此时flag = 1
调用函数Mer求出sum
for j = 2到 j < sum, j++
{
if (sum % j == 0)
{
能整除,不是素数,则令flag = 0
跳出循环
}
}
if (flag == 1)
{
if (sum > 2)
{
当flag=1时,即不能被整除,说明是素数且符合梅森数,输出sum的值
count记录数值加1
}
}
}
if (count == 0)
{
当count记录为0时,即没有梅森数,则输出None\n
}
}
定义函数int Mer(主函数调用的形参n)
{
定义k从小到大依次判断,定义s使一直被乘,定义m用来储存函数结果
给s赋值2
给m赋初值2,因为有特殊情况
if (n == 0)
{
如果n为0,则m只能是0
}
else if (n == 1)
{
如果n为1,则m只能是1
}
else
{
for k = 2到 k <= n, k++
{
算m=2^m,一直到2^n
}
令m = m - 1,即相当于2^n-1
}
令函数结果m的值返回主函数
}
2.1.2 代码截图
2.1.3 造测试数据
输入数据 | 输出数据 | 说明 |
---|---|---|
6 | 正常数据 | |
0 | None | 最小n,输出为空集 |
2 | 3 | n=2, 只有一个梅森数 |
2.1.4 PTA提交列表及说明
提交列表说明:
1. 部分正确:sample等价,取最大n时,运用嵌套过多,导致运行超时,n=2, 只有一个梅森数时,未考虑到特殊情况,答案错误
2. 多种错误:i没有从1开始计算,最小n,输出为空集,答案错误,加上前面的错误
3. 部分正确:根据测试点2得出,n==2时只有3,考虑到此特殊情况,测试点2改正确
4. 编译错误:从vs复制到PTA时忘记去掉scanf_s的_s
5. 部分正确:把求sum重新定义一个函数,减少嵌套循环,减少运行时间,测试点1改正确
6. 部分正确:在vs调试后发现,最后判断是否有梅森数的条件语句应该放在else语句内,否则其他也会输出None,导致答案错误
7. 答案正确:在vs调试后发现,n<=1在前面不用再写,否则输出两个None,导致答案错误
2.2 题目名2
查询水果价格 (15 分)
给定四种水果,分别是苹果(apple)、梨(pear)、桔子(orange)、葡萄(grape),单价分别对应为3.00元/公斤、2.50元/公斤、4.10元/公斤、10.20元/公斤。
用户可以输入编号1~4查询对应水果的单价。当连续查询次数超过5次时,程序应自动退出查询;不到5次而用户输入0即退出;输入其他编号,显示价格为0。
2.2.1 数据处理-伪代码
定义一个函数Menu来输出菜单,因为不需要返回,函数类型是void,
定义choice为用户输入的编号,
定义i来从小到大依次判断
调用函数Menu输出菜单
for i = 1到i <= 5, i++
{
用户输入choice
用switch语句判断choice的数值
{
如果choice为1:
输出price = 3.00\n
跳出循环
如果choice为2:
输出price = 2.50\n
跳出循环
如果choice为3:
输出price = 4.10\n
跳出循环
如果choice为4:
输出price = 10.20\n
跳出循环
如果choice为0:
直接跳出循环
default:
剩余的,即在输入不合法时需要输出price = 0.00\n
跳出循环
}
if (choice == 0)
{
返回,退出for循环
}
}
定义函数void Menu()
{
菜单内容
}
2.2.2 代码截图
2.2.3 造测试数据
输入数据 | 输出数据 | 说明 |
---|---|---|
3 -1 0 2 | 不到5次而用户输入0,程序结束 | |
1 2 3 3 4 4 5 6 7 8 | 连续查询次数超过5次时,程序自动退出查询 | |
7 | 输入其他编号,显示价格为0 |
2.2.4 PTA提交列表及说明
提交列表说明:
1. 部分正确:输入选择后直接跳过switch语句,未执行中间过程
2. 编译错误:从vs复制到PTA时忘记去掉scanf_s的_s
3. 部分正确:由于前面的switch语句未执行,改变后运用自定义函数PutPrice函数,但仍然未执行输出价格的程序
4. 部分正确:运用for语句,令i从小到大依次判断
5. 部分正确:输入一个数后,不能输入下一个数
6. 部分正确:仔细阅读代码后,发现%d后vs中自动打出一个空格,导致不能输入下一个数
7. 部分正确:在输入不合法时需要输出price = 0.00,审题不仔细,应该加default
8. 答案正确:最后需要加if语句,因为当choice为0时,前面只能退出switch循环,不能退出for循环,还会继续for循环
2.3 题目名3
打印九九口诀表 (15 分)
下面是一个完整的下三角九九口诀表:
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
本题要求对任意给定的一位正整数N,输出从1*1到N*N的部分口诀表。
2.3.1 数据处理-伪代码
定义正整数N,让乘法口诀表输出的为1*1到N*N的部分,
定义第一个乘数num1,
定义第二个乘数num2,
定义两个数的乘积 result
输入正整数N
for num1 = 1到num1 <= N, num1++
{
for num2 = 1到 num2 <= num1,num2++
{
求出结果result
按照要求格式输出 %d*%d=%-4d
}
输出换行
}
2.3.2 代码截图
2.3.3 造测试数据
输入数据 | 输出数据 | 说明 |
---|---|---|
4 | 正常数据 | |
10 | 大于9*9,不对齐 | |
0 | 等于0时,无输出 |
2.3.4 PTA提交列表及说明
提交列表说明:
1. 部分正确:输出时格式不对,变成矩形输出
2. 多种错误:换行用i++来换行,即如果=i时,则输出\n,不知道怎么右边要占4位输出
3. 多种错误:改在最后输出\n来换行,但是结果仍然不正确
4. 部分正确:把输出\n提前到for语句中,结束一大轮循环中的一个小循环后则换行
5. 答案正确:%-4d可以使右边占4位,对比结果后发现,第一个乘数和第二个乘数位置反了,将num1和num2换一下
3.代码互评
3.1.1代码截图
赵禹琛同学代码
我的代码
3.1.2代码比较
1. 在禹琛同学的代码中,她运用了flag语句来控制输出,可以更容易地记录当前情况,而我的代码中直接用n来判断,我认为更容易读懂
2. 禹琛同学的代码中运用了两次scanf函数,而我运用了getchar()函数输入并且在while语句中,可以直接循环多次
3. 禹琛同学的代码条件顺序与我相反,但是比较简洁,我应该向她学习
3.2.1代码截图
申超同学代码
我的代码
3.2.2代码比较
1. 申超同学的思路很清晰,在for语句中各种硬币数量增加时可以从x出发,逐渐减少,而我则多想,认为x应该减去前面已有的,虽然申超同学的代码看起来比我的简单,但是在执行过程中,我的代码执行循环次数要比他的少,时间更短,但是我也应该向他学习他的思维方式
2. 申超同学运用的for循环比我的多一层,增加了时间
3. 申超同学的变量名称应该使用驼峰法,那样更具有可读性
缺月挂疏桐,漏断人初静。时见幽人独往来,缥缈孤鸿影。
惊起却回头,有恨无人省。拣尽寒枝不肯栖,寂寞沙洲冷。