C语言第三次博客作业---单层循环结构

一、PTA实验作业

题目1

1.实验代码

    int N,i;                            //N为用户数,i记录循环变量
    double height;                      //height放身高 
    char sex;                           //sex放性别F为女,M为男
    scanf("%d",&N);
    
    
    for(i=1;i<=N;i++){                  //循环执行N次
        scanf(" %c%lf",&sex,&height);   //%c前需加一个空格,否则每次%c读取的会是每次输入性别前的回车
        switch(sex){
        case 'F':
            height = 1.09*height;
            break;                      //跳出switch语句
        case 'M':
            height = height/1.09;
            break;
        }
        printf("%.2f\n",height);
    }

2.设计思路

  • 第一步:定义两个整形变量N放用户数,i记录循环次数。定义一个双精度浮点型变量height放身高。定义一个字符型变量sex放性别。

  • 第二步:进入循环结构,赋初值i=1,循环条件i<=N.

  • 第三步:读取一组数据sex,height.

  • 第四步:利用switch语句进入对sex判断的分支结构。

  • 第五步:如果sex为F,赋值height = 1.09*height,break结束该语句。

  • 第六步:如果sex为M,赋值height = 1.09/height,break结束该语句。

  • 第七步:switch语句结束后,输出身高height,执行i++。

  • 第八步:如果满足i<=N重复第三步。

  • 第九步:直到不满足循环条件跳出循环,程序结束。

3.本题调试过程碰到问题及解决办法

  • 答案错误:粗心将用户数定义为n.

  • %c数据读取错误导致部分正确
    在%c前缺少空格,导致第一次读入的性别为回车,第一组数据输出为0.00,第二组数据才开始读入正确的数值

  • 解决办法一
    在读取N时加入一个回车符\n,结果还是部分正确,并且这次是第一次读入数据正确,而第二次读入数据错误

最后在调试的过程中,我发现了问题:尽管在用户数N的读取后加入了回车符,来保证不会影响第一次性别的输入,但是当循环进入到第二次读取性别,%c读取的仍然是上一次操作中的回车,导致了出第一次外的其余数据均不能被读入。

  • 解决办法二
    在循环内进行改正:在%c前加空格。这次就保证了每一次循环的过程中都不会存在将回车误读为性别的错误了。

4.本题PTA提交列表

题目2

1.实验代码

    int num,a,n,s;                    //num放循环次数 
    
    
    s=0;                             //s赋初始值 
    scanf("%d %d",&a,&n);
    for(num=1;num<=n;num++){           
        s=10*s+a*num;
    }
    printf("s = %d",s);

2.设计思路

  • 第一步:定义四个整型变量num放循环次数,a,n,s.

  • 第二步:循环前对s赋初始值。

  • 第三步:读取输入的a,n

  • 第四步:进入循环num赋值为0,循环条件为num小于等于n,且num每次递增一。

  • 第五步:循环内容为赋值s等于10s+anum。

  • 第六步:重复第四五步,直至num大于n,结束循环。

  • 第七步:输出s.

3.本题调试过程碰到问题及解决办法

  • 本题没有碰到问题
  • 调试

4.本题PTA提交列表

题目3

1.实验代码(非最佳,下方有改正后的)

	int n,number,num;                  //number放数字,num放循环次数 
	int min;                           //min放最小值 
	
	scanf("%d %d",&n,&number); 
    min=number;                        //将第一个值赋给min 
    for(num=1;num<=n;num++){           //num赋初值1,循环条件num小于等于n,num每次递增一 
      if(num==n){                      //判断num是否等于n。若num等于n,即为最后一次循环,则判断min与最后一个数的大小
        if(min>=number){                
    		min=number;                 
    		break;
		}
      }
      else{                            //若不等,则继续读取下一个数,再判断大小关系 
    	scanf("%d",&number);
    	if(min>=number){
    		min=number;	
    	}
		}
		
	}
	printf("min = %d",min);
    

2.设计思路(非最佳,下方有改正后的)

  • 第一步:定义number放数字,num放循环次数,min放最小值。

  • 第二步:读取输入数据个数n和第一个数据number,将第一个数据number赋值给最小值min。

  • 第三步:进入循环num赋初值1,循环条件num小于等于n,num每次递增一。

  • 第四步:利用if语句判断num是否等于n。

  • 第五步:若num等于n,即为最后一次循环,则再次利用if语句判断min与最后一个数的大小。

  • 第六步:否则继续读入下一个数据。并利用if语句判断min,number的大小关系

  • 第七步:若min大于等于number,赋值min等于number.

  • 第八步:否则,min值不变继续读入下一个数据。

  • 第九步:重复第四五六七步骤。直到num大于n时结束循环。

  • 第十步:输出最小值。

3.本题调试过程碰到问题及解决办法

  • 答案错误:赋值时写成number=min,一直没找到错误

  • 解决办法:改为min=number

  • 部分正确:当循环到最后一个数字时,循环体内仍有scanf读取输入,可是已经是最后一个数字,导致程序卡在循环内。

  • 解决办法一:加入一个if语句判断没一次的循环是否还需要读取下一个数字。以保证最后一次循环能够顺利结束。

  • 解决办法二(最佳):将循环条件改为小于等于n-1,因为在循环前已经读入了一个数据,所以循环内只剩下n-1个数据可读。我第一次循环条件定为小于等于n,导致我在调试过程中总会卡在最后一次的循环上,第一次的改正在循环内加了个if语句的判断,十分复杂。

	int n,number,num;                  //number放数字,num放循环次数 
	int min;                           //min放最小值 
	
	scanf("%d %d",&n,&number); 
    min=number;                        //将第一个值赋给min 
    for(num=1;num<=n-1;num++){           //num赋初值1,循环条件num小于等于n-1,num每次递增一 
                        
    	scanf("%d",&number);
    	if(min>=number){
    		min=number;	
        }
		}
		
	
	printf("min = %d",min);

改正后最佳算法:

  • 第一步:定义number放数字,num放循环次数,min放最小值。

  • 第二步:读取输入数据个数n和第一个数据number,将第一个数据number赋值给最小值min。

  • 第三步:进入循环num赋初值1,循环条件num小于等于n-1,num每次递增一。

  • 第四步:读取输入的数据,如果最小值大于等于该数据,赋值最小值等于该数据。

  • 第五步:重复第四步。

  • 第六步:循环结束后输出最小值。

4.本题PTA提交列表

题目4

1.实验代码

    int N,count=0,number,Number;          //定义count记录输入次数,number为随机数,Number为用户猜数 
    scanf("%d%d",&number,&N);
    do {                                  //利用do while循环,if语句判断每次Number与number的大小关系以及输出语句 
       count++;
	   scanf("%d",&Number);
           if(Number<0){                  //当用户猜数小于0时,break跳出循环 
               break;
    }
	        else if(Number<number){
               printf("Too small\n");
    }
	        else if(Number>number){
               printf("Too big\n");
    }
	        else
               break;
    }
	while(Number>=0);
    
    if(Number>=0){                         //当用户猜数大于等于0时,进入判断 
        switch(count){                     //用switch语句判断输入次数count及对应输出的语句 
            case 1:
               printf("Bingo!");
               break;
            case 2:
            case 3:
               printf("Lucky You!");
               break;
    }
    }
    if (count>3&&count<=N){               //用if语句判断特殊情况:当输入次数大于3小于N时,大于N时以及用户猜数小于0时对应输出的语句 
        printf("Good Guess!");
    }
	    else if(count>N){
            printf("Game Over");
    }   else if(Number<0){
            printf("Game Over");
}
    

2.设计思路

  • 第一步:定义整型变量N放规定次数,count放输入次数并赋初值为0,number为随机数,Number为用户猜数

  • 第二步:输入随机数与规定次数。

  • 第三步:利用do while循环,每次输入次数count累加一,if语句判断每次Number与number的大小关系以及输出语句。

  • 第四步:重复第三步,直至用户猜数小于0.结束循环。

  • 第五步:利用if语句以及switch语句判断当用户猜数大于等于0时,输入次数分别为1,2,3时分别输出的语句。

  • 第六步:利用if语句判断当输入次数大于3时的特殊情况。

  • 第七步:若输入次数大于3小于等于N,输出Good Guess!

  • 第八步:若输入次数大于N,输出Game Over。

  • 第九步:若用户猜数小于0,输出Game Over。

3.本题调试过程碰到问题及解决办法

  • 理解题目有偏差:由于题目繁琐复杂,研究了很久的题目意思,也在纸上将每种情况写下进行分类,最后不断用调试工具将各类情况整合完备。

  • 部分正确

在DEV中运行题目给出的数据,结果正确,而且由于条件分支过于复杂,并没有直接找出错误所在,最后我换了一组数据并且利用了调试找出了问题所在:忘记讨论用户猜数小于0的特殊情况。

4.本题PTA提交列表

二、截图本周题目集的PTA最后排名。

三、本周学习总结

1.你学会了什么?

课本中:

  • do-while语句:又一种循环语句。它首先执行循环体语句,然后在检查循环控制条件,直到表达式值为假,循环结束,执行循环外的语句。它适合于先循环后判断循环条件的情况,使用该语句可以保证循环至少会进行一次。

  • 三种循环语句:
    for和while语句都是在循环前先判断条件,只有满足条件才会进入循环,如果一开始不满足条件,则循环一次都不执行。
    while和do-while语句要记得再循环前赋初值。
    循环次数确定首选for语句,否则通过其他条件控制循环,使用while和do-while语句。

  • break和continue语句:
    break语句强制结束循环,可与if语句和switch语句配套使用。
    continue语句是跳过后面的语句继续循环,它只能用于循环语句。

  • 内循环与外循环的区别及如何调试发现错误。

  • 多重循环嵌套的灵活使用。

做题中:

  • scanf中%c的使用:%c会读入空格、回车、跳格等空白字符。进行输入时,会输入一个回车符作为结束,这个时候在输入缓存里就把这个回车字符存在里面了。当你要再读入一个字符时,就会默认先把缓存里的回车符读入。所以%c前固定加空格,就可以利用格式化的输入跳过一个字符,达到目的。

  • 多数值循环时的循环条件:像本次PTA中的统计学生成绩和输出最小值这两个题,都需要再循环中读取多个数据,如果不将循环条件搞清楚,就会导致循环卡住。

2.本周的内容,你还不会什么?

  • 循环嵌套并不熟练,并且没有理解透彻。
  • 循环语句以及循环条件的确定。尤其是存在内外循环错误。
  • 多数值的输出,现在只会一次一次的输出。

3.分支结构上机考试总结。

(1)哪些地方错了,为什么?

  • 12-24小时制:这一题中没有将12点单独分出来,导致结果部分正确。
  • 成绩转换:虽然考试时利用if语句做出来,但是很繁琐浪费时间。下去以后我又用switch语句重新做了一遍。这也说明了我对switch语句的运用还不够熟练。
  • 计算油费:在考试过程中由于读题审题花费时间长,导致在最后一题上剩余的时间不多,加上自己对字符型变量的表达不够规范,并没有做出这一题。下去以后我又将书本上的字符型变量的内容看了几遍,才独立的做出了这一题。

(2)后续要怎么找程序错误?

  • 在后续的写代码过程中,我会更多的使用调试来检查程序中难以发现的错误,并且在调试过程中换用不同类型的数据来检验程序完全正确。相信在有了这样的习惯之后,会帮助我在今后编写更加复杂繁琐的代码中,更快更高效的发现错误并且改正错误。

(3)对自己成绩满意么?不满意的话要怎么改进?

  • 并不满意:这次的上机测试让我意识到虽然在平时的PTA做题过程中,自己说是可以准时完成任务,但是当遇到不会做的题时,我总是会先放下回过头来再做,这就导致我没有养成在做题中对时间严格要求以及认真审题的良好习惯。因此在测试时,不仅读题审题慢,而且做题效率低,才导致做到最后一题只剩下不到十分钟的时间。

  • 改进:在平时做题过程中慢慢要求自己在规定时间内完成题目。提高做题效率,尤其是在审题方面多下功夫。还有就是对各种基本语句的书写要规范。

posted @ 2017-11-02 13:50  limb171004  阅读(393)  评论(4编辑  收藏  举报