您现在的位置是:首页 >技术杂谈 >7. 函数的流程控制网站首页技术杂谈
7. 函数的流程控制
在C++中,或是在任何编程语言中,都支持多种运行流程,一般分为下面三种:
- 线性结构:程序代码按顺序执行一次,完毕后退出
- 分支结构:程序代码按给定的条件选择运行路径,完毕后退出
- 循环结构:程序代码按给定的条件一直循环,直到被迫停止或是主动停止。
线性结构
线性结构不必多说,在前面几节中都是这样的结构,随便再摘一段代码放过来:
int add( int a, int b )
{
return a + b;
}
int main( int argc, char* argv[] )
{
int c = add( 10, 20 ); // 第一次调用add函数
int d = add( 16, 3 ); // 第二次调用add函数
std::cout << c << std::endl;
std::cout << d << std::endl;
return 0;
}
这就是典型的线性结构代码。
分支结构
再复杂一点,可以给程序增加一个选择,在C++中,可以使用“if”这个语句,它的组成分为四部分:
- if开始的代码
- ()对代码进行封装
- ()内的判断条件
- 条件不成立时的“else”或是“else if”路径,此处可选。
说到判断,在C++中,if语句接受的是一个布尔(bool)型的变量,这个类型的变量只能取两个值:true和false,可以这样定义:
bool value = false;
bool value2;
value2 = true;
在这里,bool, false, true, 都是C++里面的保留字,不能用做变量名,在C++中,还有很多保留字,以后有机会再一个一个说明。
true:表示真
false:表示假
if的使用:
#include <stdlib.h>
#include <stdio.h>
int main ( int argc, char *argv[] )
{
bool b = false; // 一般在定义变量时就要给它一个初始值,否则此变量的值不可预料。
if ( b )
{
printf("b is true!
");
}else // 有else执行路径的代码
{
printf("b is false!
");
}
}
编译输出:
b is false!
这样,这段代码就根据b的值到了不同的执行路径,此时另一段代码并没有被执行。
这里的判断条件是写死到代码中的变量,因为此值没有变化,那么程序的执行结果并没有发生变化,修改此段代码:
#include <stdlib.h>
#include <stdio.h>
int main( int argc, char *argv[] )
{
if ( argc < 2 ) // 在这里判断输入参数的数量是否大于两个,如果小于两个,就执行这一行的输出
{
printf("use this program like : %s param
", argv[0] );
}else
{
// 如果参数大于等于两个,就按顺序把参数打印出来
for ( int i = 1; i < argc; i ++ )
{
printf("param %d : %s
", i, argv[i] );
}
}
return 0;
}
编译后运行:
fosky@fosky-CW65S:~/workspace/cppbook$ ./testif
use this program like : ./testif param
fosky@fosky-CW65S:~/workspace/cppbook$ ./testif param1 param2
param 1 : param1
param 2 : param2
可以看到,此程序根据参数的个数选择了不同的执行路径,而且里面还多了个循环。
这里的判断条件是一个比较过程。那么可以做为判断条件的语句,只要是C++认为能计算出真假的内容都可以。
可以是一个变量,也可以是一个表达式,或是一些逻辑操作语句。
表达式
由运算符组成的语句,比如下面:
int a = 1;
int b = a + 1; // 表达式
if ( b ) // 没有else路径的判断
{
}
if ( a )
{
}
if ( a > b ) // 表达式
{
}
if ( a == b ) // 表达式
{
}
if ( ( b / 2 ) == 1 ) // 表达式
{
}
这段代码编译没问题,说明C++认为这些计算结果都可以转换为bool数据。
操作符
说到这里,就要补充一下C++的计算符,大概分为三类:
- 数学计算类型:加(+),减(-),乘(*),除(/),取余(%),自加(++),自减(–)
- 逻辑操作符:逻辑与(&&),逻辑或(||),取反( !),,大于(>),小于(<),大于等于(>=),小于等于(<=),等于(==),不等于(!=)
- 比特位操作符:按位与(&),按位或(|),异或(^),向左移位(<<),向右移位(>>)
数学计算操作符可以按数学中的含义理解,而计算顺序也同样和数学计算式相同。如下计算过程:
int c = 10 + 2 * 3;
print("%d
", c ); // 这里输出16,即先计算乘法,后计算加法
如果想调整计算顺序,需要使用括号把想优先计算的内容包起来:
int c = (10 + 2 ) * 3;
printf("%d
", c ); // 这里输出36
能参与表达式计算的内容有多种,不光是明显的变量,函数同样也可以放到表达式中,如下代码:
int fun( int a, int b )
{
return a + b;
}
int a = fun(10, 6 ) * 3;
int b = 6 + fun( 3, 6 ) * 2;
float f = fun( 3, 34 ) * 0.5; // 不同类型的变量也可以放到一起计算,C++自动把低精度的数据转换为更高精度的数值
这里函数和变量处于同样的地位,都被看做一个单一的变量,说到底,有返回值的函数在函数最后把计算结果返回了,这时候其实是临时产生了一个变量放在了表达式的对应位置。
同样,变量也可以放到表达式中,在以前的代码中已经多次使用。
C++数据类型的表达数值范围,一般顺序如下:
char < short < int < long < long long
int < float < double
如果有多种类型的数据在同一个表达式中参与计算,则在计算过程中自动进行数据类型的转换,当然这个转换并不影响原数据的值和类型,如下代码中:
int c = 10;
float f = 2.56;
float f2 = c + f; // 在这里,变量c先提升为float,然后再和f计算结果得到结果
布尔类型可以看做一个特殊的类型,所有的其它数据,只要不是0,一般都可以转换为bool类型的真,为0的值,或是表达式计算为0的值,都会转换为bool类型的假。
另一种数据类型,指针,同样可以做为条件判断的依据,同样的原则,指针的值为0, 结果为假,指针的值不为0,结果为真,一般指针的0值用NULL来表示。
如下代码中:
bool b = 10; // 此时b为真(true)
bool b1 = 0; // 此时b为假(false)
bool b2 = (3 > 5); // 逻辑判断为假,此时b为假
float *pf = NULL; // 定义一个指针变量,初始地址为NULL,空。
bool b3 = pf; // 这时b3的值为假
bool *pb = &b2; // pb这个指针指向了变量b2的地址
bool b4 = pb; // bp有值,则b4为真。
那么,做为“if”的判断条件,也可以是以上任意表达式:
int fun( int a, int b )
{
return a % b;
}
if ( fun ( 30, 4 ) )
{
printf("fun result is not zero!
");
}else
{
printf("fun result is zero!
");
}
以上代码通过判断fun函数的返回值来执行不同的代码。
循环结构
一般循环结构在C++中for或while这两个方式构建。
先看代码:
int c = 10;
for ( int i = 0; i < c; i ++ ) // 当i的值小于c的值时,输出i,在下一次循环时,i的值加1
{
printf("%d ", i);
}
此段代码输出:
0 1 2 3 4 5 6 7 8 9
可以看到,首先出现的是for关键字,后面跟着括号,而括号里面用”;”分成了三部分。
其中第一部分叫做循环的初始值,第二部分叫做循环的终止条件,第三部分则是变化部分。这三部分中,只有第二部分一定不能少,第一和第三部分都可缺失:
int c = 10;
int i = 0; // 初始值在循环外定义
for ( ; i < 10; )
{
printf("%d ", i);
i ++; // 变化在循环内产生,每次循环i 加 1.
}
for ( int k = 0; k < 5; )
{
printf("%d
", k );
k ++;
}
i = 0; // 这段代码上面部分已经定义了变量 i , 在这里只需要重新初始化
for ( ; i < 3; i ++ )
{
printf("%d ", i );
}
同样和if一样,条件判断部分也可以由各种各样的表达式代替,在这里就不一一举例了。
使用while构建的循环结果,分两种,while在前,while在后。
while在前,是先判断执行条件,符合条件后才会进入循环内。
int c = 10;
while( c > 0 ) // 只要c大于0,就执行while内部的代码,即输出c的值,然后c自减1.
{
printf("%d ", c );
c --;
}
while在后,是先执行循环内的代码,然后才判断执行条件,这样就会至少执行一次内部代码,如下:
int c = -1;
do
{
printf("%d
", c );
c --;
}while( c > 0 )
可以看到,此代码至少被执行一次,而不管变量c是什么值。
另外一个被广大程序员嫌弃的关键字"goto",其实也可以构建循环逻辑,只是不太长用,而且也容易把代码搞乱,因此不建议,不过这里也给出一个例子:
#include <stdlib.h>
#include <stdio.h>
int main( int argc, char *argv[] )
{
int c = 0;
LOOP: // 这里定义一个标签,goto语句的转向,需要这样的标签
c ++;
printf("%d ", c );
if ( c < 10 )
{
goto LOOP;
}
printf("
");
return 0;
}
编译运行:
fosky@fosky-CW65S:~/workspace/cppbook$ ./goto
1 2 3 4 5 6 7 8 9 10
关于代码的结构就说这么多,下一节主要再聊聊函数的调用。