问题:for循环是否能够涵盖所有情况?
for循环中,我们其实默认的是初始条件满足循环条件的情况。
我们以插入到线性表中的数据为例:
//此处以排除i超限及内存不足以插入数据的情况。
以下仅分析,在线性表的第一个位置 至 最后一个位置+1
其中,i的值从1至length+1;
分析:
1)因为i的值从1至length+1;q的位置为L.elem至L.elem+length;
即q的位置范围已定,可以是这个范围内的任意值。L.elem<=q<=L.elem+length
再看p=L.elem+L.length-1; p指向的是表最后一个元素。如length=0,则p指向的是线性表的L.elem-1的位置。
L.elem-1<=p<=L.elem+L.length-1;
q,p的位置指向如下所示:
2)再看 for循环条件,p>=q,
执行循环体的情况是:p>=q,即:L.elem+L.length-1>=L.elem+i-1-------------->L.length>=i ,i最小是1,故L.length最小为1;所以,当L.length为0时为进入for循环。
不执行for循环的情况有两种:
a.一开始条件就不满足,直接没进入for循环;//q指向2的时候以及length为0的情况
b.进入到for循环中了,随着循环的进行,条件不满足了跳出了循环;//p<q的时候
3)我们来分析一下for循环体,我们知道for循环是多个if的叠加,只有满足条件才会进行循环,循环条件是p>=q,也就说是,for循环体中的内容是在该条件下成立的。
for循环体的作用:*(p+1)=*p; 这条语句的作用是把q到p的元素都向后移了一下。这期间,不论q<p 或 q==p都会执行操作,且不会造成内存的溢出(前面说过,执行for循环前已经判断过了)。
q>p的时候,循环条件不满足,跳出循环。
4)再看for循环外的语句:*q = e;//这条语句的作用是将q指向的位置重新赋值为e。这条语句在不进入for循环和for循环退出后都会执行:如是不进入for循环的情况(如下图中在表尾插入)还有如是空表的时候插入数据(如下下图所示),即:直接执行*q = e;满足要求的。
a.在表尾插入数据,不会执行for循环:
b.空表的时候,也不会执行for循环:
如果是执行了for循环,然后退出for循环后,执行*q = e;同样满足要求。
小结:for循环解决的是线性表中有1~n个元素且要插入的位置在1-n的情况;
1)如在第n+1个位置插入元素的话,是不需要挪动元素的,循环体是不需要执行的。
2)如线性表中0个元素,则只需要在第1个位置插入元素,也不需要挪动元素。
上面的结论依据:
1)p指向的是最后一个元素n,q指向的是要插入的元素位置n+1,p>=q不成立,不会进入循环。
2)p指向L.elem-1,q指向L.elem+1-1 = L.elem,p>=q不成立,不会进入循环。
另:以下例子为线性表以下标的形式写的程序。
for(int i=temp->length-1; i>=n-1;i--)//转化为数组的下标,最后一个下标和第n个下标
{
temp->list[i+1]= temp->list[i];
}
temp->list[i+1]= value;
分析:1<=n<=temp->length+1,所以当length等于0的时候,n=1,此时i>=n-1不成立,并不会进入到循环体。
当n= temp->length+1的时候,i>=n-1不成立,并不会进入到循环体。
总结:这个例子跟for(int i=1;i<10;i++){sum += i;}这种例子不同的是,for(int i=1;i<10;i++){sum += i;}中i是定值,10也是个定值,所以不会存在其他的情况,即循环初始值,循环条件都是已确定的值,但是线性表的例子,这两个值都是不定的,所以,情况就复杂一些。
那么怎么才能最终保证所有的情况都包含到且for循环体中不会出现溢出的情况呢?
我们这么去想,for循环体的作用是将前一个变量值赋给后一个变量值,故首先,得有值才行,故排除了length为0的情况;
然后,要插入的位置需要在1-n这个范围内,才需要挪动变量值,所以有排除了在length+1的位置插入数据的情况。
所以,就不要担心for循环会出现的各种意外情况了。