循环条件和循环结束条件与while和for对你想法的干扰
昨天翻炒一下C语言。
得到一个题目,我傻,调试一晚上,无解。
题目如下:
编写函数strend(s,t)。如果字符串t出现在字符串s的尾部,该函数返回1;否则返回0。
我的想法是:
t和s同时从尾部自减,比较其值,遇到不等则立即跳出循环。
伪代码应该如下(代码清单-1)
char *s_end;// 假设已经获得s的尾部
while(1){
if(*t_end--!=*s_end--)
return 0;
看出来了,这里缺少终止条件,终止条件是:当t_end==t的时候,也要退出循环,表示是相等的
那么代码应该如下(代码清单-2)
while(!(t_end==t)){
if(*t_end--!=*s_end--)
return 0;
}
return 1;
不妨换一种想法:
在t的范围内,如果遇到*t与*s的值不一样的时候,立即返回。
那么代码应该如下:(代码清单-3)
char *s_end;//假设已经获得s的尾部
while(t_end-->=t){
if(*t_end!=*s_end--)
return 0;
}
熟悉自增自减操作的朋友,应该看出来,代码清单-3是错误的。
修改后(代码清单-4)
while(t_end-->=t){
if(*t_end!=*--s_end)//here!!
return 0;
}
return 1;
(*1其实代码清单-4依然是错的,文末再谈)
这时,不妨看看代码清单-2和代码清单-4
代码清单-2的条件是
代码清单-5:
!(t_end==t)
描述为: 当t_end==t的时候,退出循环。
代码清单-4的条件是
代码清单-6:
t_end-->=t
描述为:若不在t的范围内,则退出循环。
好,那么这文章到底要说什么?
其实,写代码和写文章一样。
代码清单-5更加合适while思维。
代码清单-6则更合适for的思维。
用for改写代码清单-6:
代码清单-7:
for(;t_end>t;t_end--,s_end--){
if(*t_end!=*s_end)//here
return 0;
}
return 1;
为什么说对想法有干扰?
当需要重复做一件事的时候(比如查找),通常都会用循环。
而循环我认为是这样的:
不停的查找,如果找到就不找了,找完也不找了。
而对于程序,我认为是这样的:
while not found, then check the next one!
写做代码
while(!found) check;这样表达很不好,因为没有check next one的动作。
所以
for(;!found;next) check it!;
来看看while的语法和描述
while(表达式)
语句
描述:先求表达式的值。如果其为真非0,则执行语句,再次求该表达式值 ,直到表达式的值为假(0)为止。(C语言程序设计 第二版*新版 P49)
而人和代码的差异就在于表达式的真假是如何描述的。
首先,查找这个问题,分为三个判断
1、找到了。
2、还没找到。
3、找完了。
不停的找可以表达为:while(1)
如果找到可以表达为:if(1) found
找完了可以表达为:while(false)
看,找完了的表达是while(false)
而我,常常会把不停的找放进去false里面,其实是不对的。
正确的解释应该是:
while(!停) //如代码清单-5,然而,不知道是脑袋容易忘还是什么的,我常常忘记了!。
写到这,这文章算完了,感觉有点裹脚布。
补充:
(*1为什么代码清单-4是错的?)
原因是自减符号!
回忆:
a=i++;//先取值后自增(表达式后自增)
a=++i;//先自增后取值(表达式时自增)
那么考虑代码清单-4的代码
while(t_end-->=t){
if(*t_end!=*--s_end)//here!!
这个时候,t_end已经不是在尾部了,也就是说比较的时候,缺少了一个值。