1. break语句
1.1 功能描述
使用范围
break语句用在for、while、do-while循环和switch分支的结构语句中。break用来使结构中的语句执行序列强行终止,也即终结该结构语句的执行,而转移到该结构语句的下条语句继续执行。
对于switch语句,break的用法在分支语句这一节已经有了阐述。在switch语句中,除了入口标记,所有的入口处理语句都是按顺序编排在一起的。为了从转入的处理中适时地退出,需要break语句一臂相助。我们曾经看到,适当组织爱所编排的入口语句,优雅地使用break,可以共享多个入口的语句以及简化编程。
对于循环语句,一般有它自己正常的结束条件判断。但是,根据循环结构的多样性,不定形式的循环结构可以在执行循环体的中途,结果条件语句的判定,执行break语句而退出。或者说,根据循环表达式的多样性,除了正常退出,还应该有由程序员自定义在遇到意外情况下的退出方式。C++语言所提供的break语句就是作为循环的另外一种退出方式。这种退出方式是在某种情况发生时的特殊行为,而不是无条件退出。所以循环中的break总是伴随着if语句,以检测某种情况是否发生。
虚设循环条件
我们在do-while循环中也已经看到过break语句的使用。
在while循环结构中,条件可以因为有了break语句而虚设:
while(条件)
{
//
}
等价于
while(1) //条件为1表示无限循环
{
if(!条件) break; //循环体的第一条语句
}
一些循环需要通过循环体计算才能产生循环条件,往往会虚设循环头上的条件。break退出循环的实现机制,把do-while结构的转换也包含在其中了。
2. 问题——寻找整数对
基本描述
给定整常数C为571,对于输入的整数对(X,Y),寻找满足计算式
(i²X+j²Y)%817==C
的整数对i和j(1≤i,j≤1000),并且要求i尽可能小。
输入描述
输入数据有若干整数对(X,Y)(1≤X,Y≤1000)。
输出描述
对应每对整数,在一行中输出其一对i,j满足基本描述的计算式。
样本输入
3 5 12 7
样本输出
6 16
3 153
3. 分析设计
解决框架
break在循环中的应用可以扩展到两重循环。通过设计,完成跳转两重循环的工作。
问题所给出的计算式中的“%”表示做除法之后取其余数。该表达式表示i的平方乘上X加上j的平方乘上Y,这个和数除上一个整常数817之后的余数要恰好等于整常数571.X和Y将在运行中循环读入,对每次给定的X和Y,都要寻找想要的i,j来满足表达式,并且对于可能有的多组解,取i最小的那组解。
该问题实际上是通过遍历搜索的方法来获得不定方程的解。
既然i和j的取值范围已经框定,那么i和j只要老老实实地在二重循环中扮演循环变量的角色,分别从1循环到1000即可。于是解决问题的框架是包含一个不断读入X和Y的循环:
#include<iostream>
using namespace std;
int main()
{
const int C = 571;
for(int X,Y; cin>>X>>Y;)
{
//查找符合表达式要求的数对i和j
}
}
在变量定义的语句之前加上const表示该实体为常量。常量为一旦初始化则不可再更改的量。而量为具有名字的实体。
跳出两重循环的结构
break语句的功能只能跳出当前循环。如要跳出两重循环,即如下代码所示,要在内循环跳至两重循环结束处:
for ( ; ; )
{
for( ; ; )
{
//……
if(条件) break;
//……
}
//break跳至此处
//……
}
//二重循环结束处
这样,为了跳出外循环,需要为break而设计跳转的代码。
首先,在外循环的前面定义一个跳转表示变量,初始化为假;然后,在内循环一旦需要执行break的条件满足时,立即置跳转变量为真;最后,在内循环的后面(循环出口,break要跳转到的地方),用if语句来检测跳转变量的真假值,若为真,则再执行一次break,否则就作为循环正常退出操作。
bool flag = flase;//首先定义逻辑型跳转变量flag
for( ; ; )
{
for( ; ;)
//...
if(条件){
flag = true;//然后若需退出两种循环,则置跳转变量为真
break;
}
//...
}
if(flag) break;
//...
}
//二重循环跳转处
退出二重循环的设计
寻找满足表达式计算要求的i和j数对相当于是在1000*1000的矩阵中寻找某个位置的元素。它是一个二重循环。因为一旦找到,马上就放弃整个寻找过程,即放弃整个二重循环,以便重新读取X和Y,再次投入寻找工作。所以需要持续中对二重循环的退出控制有强力的手段,以保证程序运行的效率。
将表达式的计算值作为A。在循环进入之初定义跳转变量flag=0,这是实现跳转手段的基本步骤。在寻找到i,j数对之时,需要将flag变量置1,这是必要的。然后在内循环退出之时,通过跳转变量值的判断,便能决定是否真的要跳转。其循环流程是:
//寻找数对i,j
int flag =0;//定义跳转变量标识变量
for(int i=1;i<=1000;i++){
for (int j=1;j<=1000;j++){
//计算获得A
if(A==C){
输出i和j
flag=1;//跳转标识置1
break;
}
}
if(flag) break;
}
跳转就意味着本次寻找过程的立即终止。
4. 实现寻找整数对代码
这里涉及多组X,Y数据,需要在退出二重循环后,继续输入X,Y和查找过程。把上述过程放在问题解决的框架中,就可以得到一种解决方法:
#include<iostream>
using namespace std;
int main(){
const int C = 571;
for(int X,Y;cin>>X>>Y; )
for(int i=1,flag=0;i<=1000;i++)
{
for(int j=1;j<=1000;j++)
if((i*i*X+j*j*Y)%817==C)
{
cout<<i<<" "<<"\n";
flag=1;
break;
}
if(flag) break;
}
}
跳转变量是在二重循环之内用来实现跳转的,所以可以放在二重循环之处定义。跳转变量处置设置可以随意,只要在想跳转处。设置一个与初值不同的值就可以在内循环之外通过差别比较而判断是否跳转。
这里的跳转无非是二重循环的跳转而已。那么多次循环的跳转怎么做呢?一般再复杂一些的过程,用函数来实现无疑。然而,即使是二重循环,这样的跳转也没有什么美感,这时候,goto语句可能就是正解了。