控制流

2018-09-12  本文已影响0人  漫游之光

语句与程序块

在表达式之后加上一个分号(;),它们就变成了语句。例如:

x = 0;
x++;
printf(...);

在C语言中,分号是语句的结束符。用一对花括号“{”于“}”把一组声明和语句括在一起就构成了一个复合语句(也叫做程序块),复合语句在语法上等价于单条语句。右花括号用于结束程序块,其后不需要分号。

if-else语句

if-else语句用于条件判定,其语法示例如下:

if(表达式)
    语句1
else
    语句2

其中else部分是可选的。该语句执行时,先计算表达式的值,如果其值为真,则执行语句1;如果其值为假,则不执行语句1,如果其有else,则执行语句2。

else-if语句

else-if语句是编写多路判定最常用的方法。其中的各表达式将被依次求值,一旦某个表达式结果为真,则执行与之相关的语句,并且终止整个语句序列的执行。其结构如下:

if(表达式)
    语句
else if(表达式)
    语句
else if(表达式)
    语句
else
    语句

例子:二分法查找

/* 二分查找,在v找x,n是数组长度 */
int binsearch(int x,int v[],int n){
    int low = 0;
    int high = n-1;
    int mid;

    while(low <= high){
        mid = low + (high - low)/2;/* 防止溢出 */
        if(v[mid] < x){
            low = mid + 1;
        }else if(v[mid] > x){
            high = mid -1;
        }else{
            return mid;
        }
    }
    return -1;
}

switch语句

switch语句是一种多路判定语句,它测试表达式是否与一些常量整数值中的某一个值匹配,并执行相应的分支动作。

switch(表达式){
    case 常量表达式:语句序列
    case 常量表达式:语句序列
    default:语句序列
}

每一个分支都由一个或多个整数值常量或常量表达式标记。如果某个分支与表达式的值匹配,则从该分支开始执行。各个分支表达式必须互不相同。如果没有哪一分支能匹配表达式,则执行标记为default的分支。default分支是可选的。如果没有default分支也没有其他分支与表达式的值匹配,则该switch语句不执行任何动作。
例子:

/* 把字符串t复制到s,将转义字符打出来 */
void escape(char s[],char t[]){
    int i;
    int j=0;
    for(i=0;t[i]!='\0';i++){
        switch(t[i]){
            case '\n':
                s[j++] = '\\';
                s[j++] = 'n';
                break;
            case '\t':
                s[j++] = '\\';
                s[j++] = 't';
                break;
            default:
                s[j++] = t[i];
        }
    }
    s[j] = '\0';
}

break语句将导致程序的执行立即从switch中退出。在switch语句中,case的作用只是一个标号,因此,某个分支中的代码执行完毕后,程序将进入下一个分支继续执行,除非在程序中显示地跳转。

while循环与for循环

在while循环语句

while(表达式)
    语句

中首先求表达式的值。如果其值为真非0,则执行语句,并再次求该表达式的值。这一循环过程一直进行下去,直到该表达式的值为假(0)为止,随后继续执行语句后面的部分。
for循环语句:

for(表达式1;表达式2;表达式3)
    语句

它等价于下列while语句:

表达式1;
while(表达式2){
    语句
    表达式3
}

但当while或for循环语句中包含continue语句时,上述二者就不一定等价了。
从语法角度看,for循环语句的3个组成部分都是表达式。最常见的情况是,表达式1与表达式3是赋值表达式或函数调用,表达式2是关系表达式。这三个组成部分的任何部分都可以省略,但分号必须保留。如果省略测试条件,即表达式2,则认为其值永远是真值。如果语句中需要执行简单的初始化和变量递增,使用for语句更合适一些,它将循环控制语句集中放在循环的开头,结构更紧凑,更清晰。
例子:

/* 将字符串逆序 */
void reverse(char s[]){
    int i,j;
    char temp;
    for(i=0,j=strlen(s)-1;i<j;i++,j--){
        temp = s[i];
        s[i] = s[j];
        s[j] = temp;
     }
}

逗号运算符“,”,也是C语言优先级最低的运算符,在for语句中经常会用到它。被逗号分隔的一对表达式将按照从左往右的顺序进行求值,各表达式右边的操作数的类型和值即为其结果的类型和值。某些情况下的逗号并不是逗号运算符,不如分隔函数参数的逗号,分隔声明中变量的逗号等,这些逗号并不保证各表达式从左至右的顺序求值。

do-while循环的语法形式如下:

do
    语句
while(表达式);

在这一结构中,先执行循环体中的语句部分,然后再求表达式的值。如果表达式的值为真,则再次执行语句。依次类推。当表达式变为假,则循环终止。
例子:

/* 将n转化为对应的字符串,并存储在s中 */
void itoa(int n,char s[]){
    int i = 0,sign = 0;
    unsigned int m;
    if(n<0){
        sign = 1;
        m = (unsigned int)(-n);
    }else{  
        m = (unsigned int)n;
    }
    do{
        s[i++] = m%10 + '0';
    }while((m/=10)>0);
    if(sign){
        s[i++] = '-';
    }
    s[i] = '\0';
    reverse(s);
}

break语句与continue语句

break语句可用于从for,while与do-while等循环中提前退出,就如同从switch语句中提前退出一样。continue语句用于使for,while或do-while语句开始下一次循环的执行。在while与do-while语句中,continue语句的执行意味着立即执行测试部分;在for循环中,这意味着控制转移到递增循环变量部分。
例子:

/* 删除字符串尾部的空格、制表符和换行符 */
void trim(char s[]){
    int n;
    for(n=strlen(s)-1;n>=0;n--){
        if(s[n]!=' '&&s[n]!='\n'&&s[n] != '\t'){
            break;
        }
    }
    s[n+1] = '\0';
}

goto语句与标号

goto语句用于跳转到标号标记的跳转位置。标号的命名通变量命名的形式相同,标号后面要紧跟一个冒号。标号可以位于对应的goto语句所在函数的任何语句的前面。标号的作用域是整个函数。从理论上讲,goto语句是没有必要的,实践中不适用goto语句也可以容易地写出代码。但是,在某些情况下goto语句还是用得着的。最常见的用法是终止程序在某些深度嵌套的结构中的处理过程,例如一次跳出两层或多层循环。例如:

for( ... ){
    for( ... ){
        ...
        if(disaster)
            goto error;
    }
}
error:
    处理错误情况

建议尽可能少地使用goto语句。

上一篇下一篇

猜你喜欢

热点阅读