zoukankan      html  css  js  c++  java
  • 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 跳出循环相关语句breakcontinue
      • 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 跳出循环相关语句breakcontinue

    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("
    ");
        }
        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 ", 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
    ", 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 感悟

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

  • 相关阅读:
    Markdown基础语法
    Java是什么
    myBatis框架_关于怎么获得多表查询的总记录数
    关于Could not load driverClass ${jdbc.driverClassName}问题解决方案
    java中String与StringBuffer拼接的区别
    部分标签
    基础标签 网页分类
    入坑小开头
    完整版的OpenLDAP搭建全过程
    测试Linux下tcp最大连接数限制
  • 原文地址:https://www.cnblogs.com/jmlzh/p/14022102.html
Copyright © 2011-2022 走看看