第五章 循环结构课后反思

本章重点、难点:

一、for语句

1、for语句的一般形式:

for(<初值表达式>;<条件表达式>;<循环变量表达式>) { <循环体语句> } 2、for语句的重要特征
  • <初始表达式>可以省略,但需保留(;),同时在for之前必须给循环控制变量控制变量赋值,形式为:
    <初始表达式>;
    for(;<条件表达式>;<循环表达式>)
    <循环体语句>
  • <条件表达式>一般不能省略,否则为无限循环
  • 3个表达式均省略,即for( ; ; 😉,为无限循环,程序中要避免这种事情发生。

二、while与do-while语句

1、while语句的一般形式:

while(<条件表达式>) { 循环语句 循环变量表达式 }

2、while语句的重要特征

  • 环变量表达式>用来更新计算循环变量的值,一般情况下,<循环体语句>应该是用一对花括号括起来的复合语句,其中至少要有两条语句。
  • 若<循环体语句>中没有<循环变量表达式>,而只有循环语句,则有可能会使程序出现无限循环而发生错误。
  • 由于while循环是先判断<循环表达式>的值,后决定是否执行<循环体语句>,因此,<循环体语句>有可能一次也没有执行。
  • 在一般情况下,for和while可以互相转换

3、do-while语句的一般形式:

do { <循环体语句> }while(<条件表达式>);

4、do-while语句的特征

  • 一般情况下,一定要有可以使<条件表达式>的值为假的语句,否则会使程序出现无限循环
  • do-while语句中的<循环体语句>的执行不同于for和while语句,它的<循环体语句>会先执行一次,因为是先执行<循环体语句>,后判断<条件表达式>。
  • 在某些情况下,while和do-while可以互相转换

三、break语句与continue语句

1、break语句既可用于分支结构,又可用于循环结构,其作用是跳出控制结构语句。
2、continue语句不会终止循环,而是在<循环体语句>没有执行完的情况下,结束当前循环,提前进入下一循环。

课后反思

一、对于上课时的i=i++问题的解决

1、实验代码如下:

#include<stdio.h>
main()
{
	int i=1,sum=0;
	while(i<=100)
	{
		sum=sum+i;
		i=i++;
	}
	printf("sum=%d\n",sum);
}

  在编译的时候,程序并不会报错,理应在运行的时候出现的结果为“sum=5050”,但是,运行后结果如下:

  为此,我问了几个朋友以及查阅大量资料,我的理解如下。

2、i++不能做左值?

(1)首先说左值和右值的定义:
  变量和文字常量都有存储区,并且有相关的类型。区别在于变量是可寻址的(addressable)对于每一个变量都有两个值与其相联:
  1).它的数据值,存储在某个内存地址中。有时这个值也被称为对象的右值(rvalue,读做are-value).我们也可认为右值的意思是被读取的值(read value)。文字常量和变量都可 被用作右值。
  2).它的地址值——即存储数据值的那块内存的地址。它有时被称为变量的左值(lvalue,读作ell-value)。我们也可认为左值的意思是位置值location value文字常量不能被用作左值.

(2)首先对于i++的实现是:
int temp;
temp = i;
i = i+1;
return temp;
而++i的实现是:
i = i+1;
return i;
所以对于我们提出来的问题已经能得到解决了:
  i++=5; 是错误的是因为i++返回的是编译器自动分配的临时变量temp,而这个temp并不是你程序中定义的可寻址变量的引用 ,也就是说你不能通过地址对它进行操作.(换句话说就是不能作为左值)++i=5;是正确的就是因为其返回值就是i;

3、用实验代码来解释
代码如下:

#include<stdio.h>
main()
{
	int i=0;
    i=i++;
	printf("i的值为%d\n",i);
}

  根据我们通常所知道的后自增先使用后增加的道理,i++在使用后i自身会增加一个数值,初始值为0时,自增后就是1,那么输出的结果应该是1.但实际上这题的结果却是0。

  这是因为开发工具在处理i = i++时, 会建立一个临时变量来接收i++的的值,然后返回这个临时变量的值,返回的值再被等号左边的变量接收了,这样就是说i虽然自增了但是又被赋值了0,这样输出的结果自然就是0了。
  不妨我们用temp临时变量来接收i++的值,来看一下结果。

#include<stdio.h>
main()
{
	int i=0;
	int temp;
    temp=i++;
	printf("i的值为%d\n",i);
	printf("temp的值为%d\n",temp);
} 

  可以看到temp的结果就是0,也就是说赋值号右边传递过来的是i未自增前的值,这符合后自增运算符先使用后增加的原则,这时候我们再输出一下i的值。
i也的确自增了一个值,这样就好理解为什么i = i++中输出第一个i为什么是0了,因为i在自增后又被等式右边的值覆盖了。也就是说这里的i的值发生了三次变化,第一次是我们定义i = 0;第二次就是i自增后变成了1;第三次就是i又被0值覆盖了。

4、总结

  其实i++或者++i,只有单句的话执行是add加法运算,如果i++有赋值动作的话类似于下列代码:
int result,temp;
int i=0;
temp=i;
result=temp+1;
i=result;
i=temp;
  简单说其实i=0;i=i++就是i=1然后i=0,其实i++这个i就已经变成了+1的结果了,但是呢加完后回写了没运算的值。
  所以说,在上课那个例子中i总是等于1,满足i<=100,while永远为真,使得while无限循环,电脑内存不够,"炸了“。根据i++不能做左值,++i能做右值,来看,代码如下都可以使程序运行。

#include<stdio.h>
main()
{
	int i=1,sum=0;
	while(i<=100)
	{
		sum=sum+i;
		i=++i;
	}
	printf("sum=%d\n",sum);
}

或者

#include<stdio.h>
main()
{
	int i=1,sum=0;
	while(i<=100)
	{
		sum=sum+i;
		i++;
	}
	printf("sum=%d\n",sum);
}

二、课本案例详解

1、例题中的几何图案

  之前我们学了一些几何图形的输出,例如直角三角形,等腰三角形的输出等。但是,这个不同于之前的图形,这个比之前的更复杂。我的思路是:将这个图形先补齐,再分块。

  因为之前我们所输出图形的代码都是一个for中嵌套两个for,所以我总想着这样做完

#include<stdio.h>
main()
{
	int i,j,k,l,m;
	for(i=1;i<=5;i++)
	{
		for(j=1;j<=5-i;j++)
		printf(" ");
		for(k=1;k<=5;k++)
		printf("*");
		printf("\n");
		for(l=1;l<=i-5;l++)
		printf(" ");
		for(m=1;m<=5;m++)
		printf("*");
		printf("\n");		
	}
} 

  我发现这和我预想的结果不一样,我再次分析了这张图。四个部分,第一个部分由空格组成;第二个部分由" * "组成,第三个部分由空格组成;第四个部分由" * "组成。想起老师课上讲的大循环里面是控制行,小循环里面控制了列。再反观自己的代码,我的代码大循环没有错。

#include<stdio.h>
main()
{
	int i,j,k,l,m;
	for(i=1;i<=5;i++)
	{
		for(j=1;j<=5-i;j++)
		printf(" ");
		for(k=1;k<=5;k++)
		printf("*");
		printf("\n");
	}
} 

  我发现,我前两个部分没有错,错的是后两个部分,使得我图案不能正常输出,我觉得要将第三第四个部分放在另外一个for的大循环之中,就像下面代码所示。

#include<stdio.h>
main()
{
	int i,j,k,l,m,n;
	for(i=1;i<=5;i++)
	{
		for(j=1;j<=5-i;j++)
		printf(" ");
		for(k=1;k<=5;k++)
		printf("*");
		printf("\n");		
	}
	for(n=1;n<=4;n++)
	{
		for(l=1;l<=n;l++)
		printf(" ");
		for(m=1;m<=5;m++)
		printf("*");
		printf("\n");			
	}

			
} 

运行结果如下:

  但是,我还发现了另外一种方法来输出这个图案,虽然可行但是偏移了我们的本意。代码如下:

#include<stdio.h>
main()
{
	int i,j,k,l;
	for(i=1;i<=5;i++)
	{
		for(j=1;j<=5-i;j++)
		printf(" ");
		printf("*****");
		printf("\n");
	}
	for(l=1;l<=4;l++)
	{
		for(k=1;k<=l;k++)
		printf(" ");
		printf("*****");
		printf("\n");
	}
} 

  总结一下,我觉得做这种图形的题目,首先要补齐图形,再划分图形,然后再敲代码。需要注意的是,for循环里面的<初始表达式>和<条件表达式>,因为这两个决定你的图形形状。

2、希望拓展的部分
  我希望老师可以穿插地讲一点关于程序设计中后面涉及到的问题,让我们更好地学习,例如:栈和堆,计算机的储存结构和代码的存放地址等,这样也可以让我们下课去查,为以后的学习减轻负担。

posted @ 2019-04-13 18:13  陆齐铭  阅读(392)  评论(0编辑  收藏  举报