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提交列表及说明
  • 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 感悟

这道题带给我最大的感悟就是关于循环体本身,何时进入循环,何时结束循环,有什么条件,条件是否唯一等问题的思考,包括进入循环又需要判断什么,判断做出的下一步动作又是什么,每个动作对循环又有什么影响,种种问题都需要冷静地思考分析,今后随着代码量的增加这种感觉毫无疑问会更加强烈,因为需要考虑的东西越来越多,在做这道题目的时候,除了本身对知识点掌握不好之外,就发现自己对于问题本身的分析确实存在较大不足,进步空间还是很大的,与专业知识无关的这些问题自己没有考虑进去,实在是不应该,接下来继续努力吧

posted @ 2020-11-22 22:53  走去干饭  阅读(194)  评论(0编辑  收藏  举报