C博客作业02--循环结构
| 这个作业属于哪个班级 | C语言--网络2011/2012 |
| ---- | ---- | ---- |
| 这个作业的地址 | C博客作业00--循环结构 |
| 这个作业的目标 | 学习循环结构内容,包括for循环、while循环、循环嵌套
| 名字 | 黎钊涵
目录
- 0.展示PTA总分(0----2)
- 1.本章学习总结(2分)
- 1.1 for循环语句
- 1.2 while、do while循环语法
- 1.3 跳出循环相关语句break\continue
- 1.4 循环嵌套
- 1.5 学习体会
- 2.编程技巧总结(2分)
- 2.1 小知识点
- 2.2 找最大值最小值问题
- 2.3 字母大小写转化问题
- 2.4 字符转化为数字问题
- 2.5 四则运算问题
- 3.PTA实验作业(6分)
- 3.1 数列求和问题
- 3.1.1 题目
- 3.1.2 我的思路
- 3.1.3 代码展示
- 3.2 图形打印问题
- 3.2.1 数据处理
- 3.2.2 我的思路
- 3.2.3 代码展示
- 3.3 介绍printf调试如何检查错误
- 3.3.1 单步调试截图
- 3.3.2 代码截图
- 3.3.3 PTA提交列表及说明
- 3.1 数列求和问题
- 4.关于龟兔赛跑问题的认识、理解及感悟
0. 展示PTA总分
1.本章学习总结
1.1 for循环语法
for 循环语句的一般形式为:
for (表达式 1;表达式 2;表达式 3)
{
循环体语句;
}
注意,表达式之间用分号“;”隔开而不是逗号“,”
执行顺序:表达式1→表达式2→循环体语句→表达式3→表达式2→循环体语句→表达式3.....重复这个过程,直到表达式2不满足,则结束循环
例:
int c=1;
for (i=1;i<=3;i++)
{
c=c+1;
}
第一次循环,将1赋值给i,接着判断i<=3成立,进入循环体,c=c+1则c=2,然后i自身加1,则i=2,
第二次循环,i=2,此时i<=3依然成立,进入循环体,c=c+1,则c=3,然后i自身加1,则i=3,
第三次循环,i=3,此时i<=3依然成立,进入循环体,c=c+1,则c=4,然后i自身加1,则i=4,
此时i的值已经不满足条件i<=3,所以循环到此结束
1.2 while循环和do-while循环
while语句的一般形式是:
while (表达式)
{
循环体语句;
}
例:
我的思路:
首先,本题需要设置多个变量,如输入实数x,循环变量j、n等,且由于题面复杂,对于不同变量在不同位置起到的不同作用要有清晰认识,否则容易混淆,导致题目难度再度增加
其次,本题循环条件只有一个,就是最后一项的绝对值大等于0.00001,当最后一项的绝对值小于0.00001时,结束循环
最后,本题考察了知识的融合能力,很明显本题是一道数学问题,需要用到幂函数,又需要做持续性的循环动作,则需要将幂函数和while循环组合在一起进行程序设计方能解题
代码如下:
#include<stdio.h>
#include<math.h>
int main()
{
double x;
int i;
int j;
int n=0;
double temp=1, a=1, b=1;
double sum=0;
scanf("%lf", &x);
while(temp>=0.00001)
{
temp=a*1.0/b;
sum=sum+temp;
n++;
a=pow(x,n);
b=1;
for(j=1;j<=n;j++)
{
b=b*j;
}
}
printf("%.4f", sum);
return 0;
}
而do while语句与其类似:
do
{
语句
}
while(表达式);
例:
int i=1;
int c=1;
do
{
i++;
c=c+1;
}
while(i<=2);
执行如下:
先做do,i自身加1,则i=2,c=c+1,则c=2,
再进入while判断,此时i<=2成立,则再做do,i自身加1,则i=3,c=c+1,则c=3
再次判断,此时i<=2不成立,结束循环
可以发现,两者虽然相似,但也存在不同,主要在于,while是先判断再进入循环,do while是先做一次循环再判断
1.3 跳出循环相关语句break\continue
1、break语句作用是跳出全部循环,不管循环条件还满不满足,都直接跳出循环,而continue语句作用则是不执行剩下所有语句,直接结束本次循环,进行下一次的循环判断
2、break语句可以用于循环语句,也可以用于分支语句(switch),而continue语句只能用于循环语句
例1:
for(i=1;i<=3;i++)
{
if(i%3=0)
{
break;
}
}
printf("%d", i);
执行如下:
第一次循环,i=1,判断i<=3成立,i%3=0不满足,则i自身加1,i=2
第二次循环,i=2,判断i<=3成立,i%3=0也不满足,则i自身加1,i=3
第三次循环,i=3,判断i<=3成立,i%3=0满足,则break,结束整个循环,而不会继续进行循环让i自身加1得到i=4
例2:
for(i=1;i<=5;i++)
{
if(i%3=0)
{
continue;
i=10;
}
}
printf("%d", i);
执行如下:
第一次循环,i=1,判断i<=5成立,i%3=0不满足,则i自身加1,i=2
第二次循环,i=2,判断i<=5成立,i%3=0也不满足,则i自身加1,i=3
第三次循环,i=3,判断i<=5成立,i%3=0满足,则continue,跳过i=10,即不执行此语句,进行下一次循环,i自身加1,i=4
最终输出结果是6,在整个循环过程中,都跟“i=10;”这条语句无关,因为它前面有continue,直接跳过
1.4 循环嵌套
循环嵌套,就是一条语句里面还有另一条语句,例如 for 里面还有 for,while 里面还有 while,或者 for 里面有 while,while 里面有 if-else,利用嵌套结构可以更容易地解决问题,但如果设计不好,也会使问题更复杂,循环嵌套有内循环和外循环之分,先执行内循环,后执行外循环,且外循环每执行一次,内循环都要执行一轮
例:
int i=1;
int c=1;
for(i=1;i<=3;i++)
{
while(c<=2)
{
c=c+1;
}
}
执行如下:
第一次循环,i=1,判断i<=3成立,则进入while循环,此时c满足条件c<=2,则c=c+1,c=2,i自身加1,i=2,
第二次循环,i=2,判断i<=3成立,则进入while循环,此时c仍然满足条件c<=2,则c=c+1,c=3,i自身加1,i=3,
第三次循环,i=3, 判断i<=3成立,则进入while循环,此时c不满足c<=2这一条件,所以c值确定为3,i自身加1,i=4,
因为i=4,判断i<=3不成立,所以不进行第四次循环,结束本轮循环,最终i值为4,c值为3
1.5 学习体会
1、循环体结构并非固定死板,而是可以灵活多变,分析问题后选择合适的循环体或是循环嵌套体来设计解决方案,才能更好地解决问题
2、进行循环嵌套设计时,需要注意内外循环的先后顺序,内先外后,如果刚开始不懂如何设计,可以在编译器上大胆尝试,实践才能出真知
3、需要跳出循环的时候,可以用不只一个break跳出循环
2.编程技巧总结
2.1 小知识点
-
当运算结果为小数时,需要注意表达式中的各项数据是否为浮点型,避免如1/2=0这样的情况,影响运算结果,此式需写成1.0/2
-
可以根据变量的大小来确定变量的范围,如若数据长度为32位,则变量类型为整型或长整型或单精度浮点型
-
对于一些隐含规律的问题,如典型的数列求和问题,应立即想到相关解决方法,即运用循环体来设计解法,而对于其他看似没有规律或者与循环/循环嵌套无关的问题,可以做尝试,看循环知识能否解决,能解决的话,速度如何,代码量如何,综合比较选择最优解法
2.2 找最大值问题
输入一组数找出最大值,其实是利用条件判断if else的知识来设置程序,可以先令第一个数的值为最大值max,接下来一次一次的输入其他数,以第二个数为例,若小于第一个数,则不满足条件不交换数值,若第二个数大于第一个数,则将第二个数的值赋给max,这样max的值就是现在第一个数、第二个数之间最大的那个,当第三个数输入时,同理,也是简单判断,看是否需要交换数值,代码如下
scanf("%d", &max);
if (num>max)
{
max = num;
}
最小值问题同理,代码如下
scanf("%d", &min);
if (num<min)
{
min = num;
}
这种解题思路就是作比较,重复地作比较,做两个数之间的比较,永远只比较两个数,不管总共有多少个数,都不影响两个数的比较,无论有多少数,总有比完的时候
2.3 字母大小写转化问题
法一:ASCII码法,由于大小写字母ASCII码存在的关系,a的ASCII码是122,A的ASCII码是90,所以小写字母转化成大写字母,只需要小写字母减去32即可,代码如下
char ch;
scanf("%c", &ch);
ch=ch-32
printf("%c", ch);
又因为空格“ ”的ASCII码为32,所以用小写字母减空格也行,代码如下
char ch;
scanf("%c", &ch);
ch=ch-' ';
printf("%c", ch);
同理,大写字母转化为小写字母就是,大写字母加32或空格,代码如下
char ch;
scanf("%c", &ch);
ch=ch+' ';//ch=ch+32;也可行
printf("%c", ch);
法二:字符型变量法
定义一个字符型变量ch
若ch=ch+'a'-'A';则结果是大写变为小写
若ch=ch+'A'-'a';则结果是小写变为大写
2.4 字符转化为数字问题
字符转化为数字只需要让字符减去0字符,即可得到整型数字
代码如下
char ch;
int num;
scanf("%c", &ch);
num = ch-'0';
这里需要注意的是,减去的0是字符而不是数字,所以表达式是'0'
2.5 四则运算问题
其实四则运算问题用到的是前面的switch case知识,每种计算方式对应一种计算符号,再对应相应的计算表达式,代码如下
int a,b,c;
char ch;
scanf("%c", &ch);
switch(ch)
{
case '+': a=b+c;break;
case '-':a=b-c;break;
case '*':a=b*c;break;
case '/':a=b/c;break;
}
3.PTA实验作业
3.1 数列求和问题
3.1.1 题目
3.1.2 我的思路
首先,这是一道数学问题,需要用到数学函数,开头定义要有<math.h>,分析规律后发现需要用到的是幂函数pow
其次,这是一道循环问题,只要当n<=N,循环就一直进行,并且这是一个简单的单循环,只需要重复做一个动作即可
最后,这是一道幂函数和循环知识相结合的综合问题,需要巧妙设计程序进行求解,考察知识的融合运用能力
3.1.3 代码展示
#include <stdio.h>
#include <math.h>
int main()
{
double partialSum=0;
double N;
int n;
double item=0;
scanf("%lf", &N);
for (n=1; n<=N; n++)
{
item = pow((-1), (n - 1)) * (n / (2.0 * n - 1));
partialSum = partialSum + item;
}
printf("%.3f", partialSum);
return 0;
}
这里注意最终输出的浮点型数值,是保留三位小数的数值,所以要用%.3f来表示
3.2 图形打印问题
3.2.1 数据处理
首先可以发现不同行的*数量不同,则行数需要设置一个变量,设为row
其次可以发现,在不同的点位输入的符号不同,则需要设置一个变量控制输入的东西,设为row1
其实刚开始我有想过是不是要设置两个变量,分别输入空格“ ”和星号“*”,后来被我放弃了,因为无论是空格还是星号,都在一行中,并且是间隔不间断的,所以就像奇偶数一样,可以用一个变量连续地进行输入,事实证明的确如此
3.2.2 我的思路
图形总共有7行,则7就为循环结束时的条件,上半部分(前3行)是逐个递增,下半部分(后4行)是逐个递减,并且每两个间有一个空格,上一行与下一行的是对应在一条轴线上的,由此可以设置两个变量,一个变量是行数,一个变量控制输入的东西是空格“ ”还是星号“*”
3.2.3 代码展示
#include<stdio.h>
#include<math.h>
int main()
{
int row1;
int row;
for(row=0;row<7;row++)
{
if(row<=3)
{
for(row1=0;row1<5-row;row1++)
{
printf(" ");
}
for(row1=0;row1<1+2*row;row1++)
{
printf("*");
}
}
if(row>3)
{
for(row1=0;row1<5-(6-row);row1++)
printf(" ");
for(row1=0;row1<1+2*(6-row);row1++)
printf("*");
}
printf("\n");
}
return 0;
}
3.3 介绍printf调试如何检查错误
printf调试相对于单步调试来说,优点在于可以把每一个计算值都罗列出来,非常清晰,便于查错纠正
例:我们以计算4的阶乘为例
#include <stdio.h>
int main()
{
int n=0;
scanf("%d", &n);
int i,f=1;
for(i=1; i<=n; i++)
{
f=f+i;
}
printf("4!=%d/n", f);
return 0;
}
其实这很明显是段错误的代码,因为f=f+i,所以这段代码的实际作用是做累加运算,且输出结果是4!=11那么运行发现错误后使用printf调试,在for循环内加上一个表达式"printf("i=%d, f=%d\n", i, f);"即可,让每一次的i值和f值都输出,容易发现错误,代码如下
#include <stdio.h>
int main()
{
int n=0;
scanf("%d", &n);
int i,f=1;
for(i=1; i<=n; i++)
{
f=f+i;
printf("i=%d, f=%d\n", i, f);
}
printf("4!=%d/n", f);
return 0;
}
这样运行就会出现
i=1,f=2
i=2,f=4
i=3,f=7
i=4,f=11
4!=11
所以可以发现从一开始就已经错了,错在计算式f=f+i,应该改成f=f*i,这样再用printf调试运行,发现过程和结果都正确
3.3.1 单步调试截图
3.3.2 代码截图
3.3.3 PTA提交列表及说明
说明:自己尝试作答的时候未能理清题意,无法正确设计循环体及表达式,导致格式错误,耗费大量时间思考分析并且逐步调试后最终找到原因,定义一个临时变量temp=a,成功解决问题
4.关于龟兔赛跑问题的认识、理解及感悟
4.1 认识
这个问题真是让我印象深刻,先是在课上思考,丈二和尚摸不着头脑,之后听老师的讲解,似懂非懂,然后在实验室里琢磨了老半天,不得甚解,最后回宿舍看超星课程,一遍没看懂,关键是设置变量,以及临界条件,实在把我整懵圈了,还好最后看了三遍,才堪堪掌握
首先是命名问题,在实验课的时候由于代码量不够,将变量命名得十分随意,什么abcd,经过老师的指导后才懂得要养成良好的命名习惯,掌握驼峰命名法并正确使用,比如乌龟跑的距离可以命名为turtleDis,就是turtleDistance(乌龟距离)的缩写,这样命名简单也容易理解
其次是数据处理问题,由于题面给出了一个总时间T,而乌龟和兔子运动还有一个耗时,所以需要再设置一个时间time,循环结束条件就是time>T;由于time一开始就为1,所以相当于两者都已经跑了一分钟,则兔子跑的总距离=第一分钟跑的9+后面跑的距离,乌龟同理;接下来有一个很重要的条件判断就是兔子是否停下来,分析题面可知每10分钟比较一次,兔子如果跑的更远就休息30分钟,30分钟内兔子运动距离为0,运动表达式不需要更改,只需要让时间+30,这个地方是一个非常容易出错的点,时间+30,刚开始可能不影响整个过程,但是,快到终点的时候呢?一旦在这30分钟内,乌龟到达了终点,乌龟运行的距离不就没有达到之前它30分钟运动的那么多了吗?没错,所以需要进一步比较这个时间+30与总时间的大小,再根据大小决定是否更改乌龟运动距离的表达式,理清这一易错点之后,题目就不难了
最后展示代码
#include <stdio.h>
int main()
{
int turtleDis=0;
int rabbitDis=0;
int totalTime;
int time;
scanf("%d", &totalTime);
for (time = 1; time <= totalTime; time++)
{
rabbitDis = rabbitDis + 9;
turtleDis = turtleDis + 3;
if (time % 10 == 0)
{
if (rabbitDis > turtleDis)
{
if (time + 30 > totalTime)
{
turtleDis = turtleDis + 3 * (totalTime - time);
break;
}
else
{
turtleDis = turtleDis + 3 * 30;
time = time + 30;
}
}
}
}
if (turtleDis > rabbitDis)
{
printf("@_@ %d", turtleDis);
}
else if (turtleDis < rabbitDis)
{
printf("^_^ %d", rabbitDis);
}
else if (rabbitDis = turtleDis)
{
printf("-_- %d", turtleDis);
}
return 0;
}
4.2 理解
就我个人而言对这道题的理解是,首先它出现“每10分钟...”“每分钟...”的字眼,就暗示了需要用到循环知识来解题;其次它在循环的基础上进一步考察了循环结束条件,本道题循环结束条件并不单一,不同于平常的普通循环题,这道题中时间+30跟总时长的关系很容易被忽略;再者本道题还有一个小细节就是第一分钟,由于time初始值为1,所以第一分钟跑的距离要加上;最后是输入输出等格式问题,也需要注意
4.3 感悟
这道题带给我最大的感悟就是关于循环体本身,何时进入循环,何时结束循环,有什么条件,条件是否唯一等问题的思考,包括进入循环又需要判断什么,判断做出的下一步动作又是什么,每个动作对循环又有什么影响,种种问题都需要冷静地思考分析,今后随着代码量的增加这种感觉毫无疑问会更加强烈,因为需要考虑的东西越来越多,在做这道题目的时候,除了本身对知识点掌握不好之外,就发现自己对于问题本身的分析确实存在较大不足,进步空间还是很大的,与专业知识无关的这些问题自己没有考虑进去,实在是不应该,接下来继续努力吧