<一>if语句
一个简单函数可以有多条语句,但这些语句总是从前到后顺序执行的。除了顺序执行之外,有时候我们需要判断条件,然后根据判断的结果执行相对应的后续代码,在C语言中可以用分支语句(Selection Statement)实现,如:if语句、if..else语句、switch语句,下面举例:
if(x != 0)
{
 printf("x is nonzero.\n");
}
这里if语句的条件,x!=0意思是如果x不等于0,这执行{}花括号里的语句,否则不执行{}语句,直接跳到}后面。其实,if(x)和if(x!=0)是等价的,x值等于0为假,x为非0的值为真。if和控制表达式改变了程序的控制流程(control Flow),不再是从前到后顺序执行,而是根据条件执行不同的语句,这种控制流程称为分支(Branch)。
知识扩展,关系运算符和相等性运算符
运算符 含义
== 等于
!= 不等于
> 大于
< 小于
>= 大于或等于
<= 小于或等于
注意一下几点:
1.这里的==表示数学中的相等关系,相当于数学中的=号,而数学中的等号(=)在C语言中是赋值运算符,两者的含义完全不同。
2.if里面表达式所表示的关系成立则值为真(True),否则为假(False),在C语言中分别用int型的1和0表示。如果为真,则值为1;同理,如果为假,则值为0。举个例子:如果if(x>0),如果x的值1,则为真,执行if花括号里面的语句。如果x=-1,则为假,跳到if花括号后面执行接下来的语句。
3.在数学中a<b<c表示b既大于a又小于c,但作为C语言表达式却不是这样。以上几种运算符都是左结合,什么是左结合呢?因为这些运算符有些不是同等级的优先符,同一优先级别共同存在的时候,都是从左往右执行的。这里说到关系运算符(Relational Operator)(>、<、>=、<=)属于第6优先级的双目运算符,而相等运算符(Equality Operator)(==和!=)属于第7优先级双目运算符,属于左结合。相等性运算符的优先级低于关系运算符
4.这些运算符的两个操作数应该是相同类型的,两边都是整型的,两边都是整型或者是浮点型可以做比较,但两个字符串不能做比较。

和if语句相关的语法规则如下:
语句 → if (控制表达式) 语句
语句 → { 语句列表 }
语句 → ;
在C语言中,任何允许出现语句的地方既可以是由分号结尾的语句,也可以是由{}括起来的若干条语句或声明组成的语句块(Statement Block)。加分号表示一个语句的结束;如果是单分号表示一条空语句(Null Statement).
1、以下程序段编译能通过,执行也不出错,但是执行结果不正确(根据第 3 节 “程序的调试”的定义,这是一个语义错误),请分析一下哪里错了。还有,既然错了为什么编译能通过呢?
int x = -1;
if (x > 0)
 printf("x is positive.\n");
分析一下分支语句:初学者有些认为,给x初始化,x定义为整型,分配存储空间,然后把-1常量值赋给x,接着if语句判断-1 > 0为假,然后执行printf语句输出x is positive换行。但实现上编译器不会这样子执行,if(x>0)判断为假,其实什么也没输出,因为if语句在没有花括号的情况下默认,把第一个分号的语句作为if语句为真后,执行的语句。如果在printf("x is positive.\n");后再加一行printf("x x x x\n");则最后输出的结果是:x x x x

其实上面的程序可以等价于:
int x = -1;
if (x > 0)
{
 printf("x is positive.\n");
}
如果想要输出:x is positive
则可以这样写
int x = -1;
if (x > 0)
{
 ;
 }
else
{
 printf("x is positive.\n");
 
}
<二>if/else语句
if语句还可以带一个else子句,如:
if(x%2==0)
 printf("x is even.\n");
else
 printf("x is odd.\n");
这里的%是取模(Modulo)运算符,x%2表示x除以2所得的余数(Remainder),C语言规定%运算符的两个操作数必须是整型的。但如果操作数中有负数,结果应该是正是负呢?C99规定,如果a和b是整型,b不等于0,则表达式(a/b)*b+a%b的值总是等于a,这个公式可以用具体值代替,假设a=3,b=2,则(3/2)*2+3%2=3==>1*2+1=3;若a=-3,b=2,则(-3/2)*2+ -3%2 = -3,编译器编译这样的程序原则是:-(3/2)+(2*(-1)-1)%2= -3;再如:a=3,b=-2,则(3/-2)*(-2)+3%(-2)=3==>-3/2*(-2)+(-2*(-1)+1)%-2=3 可以得到一个结论:%运算符的结果总是与被除数同号
可以编写简单的代码测试
#include <stdio.h>
int main()
{
        int a=-3,b=2,x=3,y=-2;
        printf("%d\n",a%b);
        printf("%d\n",x%y);
        return 0;
}
运行结果是
-1
1
回到我们上面的if...else语句中,例子判断x的奇偶性(Parity),看x除以2的余数是否为0,如果为0打印x is even.,如果不是0则打印x is odd.,读者应该能看出else在这里的作用了,如果在上面的例子中去掉else,则不管x是奇是偶,printf("x is odd.\n");总是执行。为了让这条语句更有用,可以把它封装(Encapsulate)成一个函数:
void print_parity(int x)
{
 if (x % 2 == 0)
  printf("x is even.\n");
 else
  printf("x is odd.\n");
}
把语句封装成函数的基本步骤是:把语句放到函数体中,把变量改成函数的参数。这样,以后要检查一个数的奇偶性只需调用这个函数而不必重复写这条语句了,例如:
print_parity(17);
print_parity(18);
#include <stdio.h>
void print_parity(int x)
{
 if (x % 2 == 0)
  printf("x is even.\n");
 else
  printf("x is odd.\n");
int main()
{
 print_parity(15);
 print_parity(16);
 return 0;
}
if或if...else语句的嵌套,下面说一下if ..else 语句的嵌套
if (x > 0)
 printf("x is positive.\n");
else if (x < 0)
 printf("x is negative.\n");
else
 printf("x is zero.\n");
C语言规定,else总是和它上面最近的一个if配对
如:
if(A)
 if(B)
  c;
 else
  D;
如果想要第一个if和else配对则可以这样写:
if(A)
{
 if(B)
  C;
}
else
{
 D;
}
习题
1、写两个表达式,分别取整型变量x的个位和十位。
2、写一个函数,参数是整型变量x,功能是打印x的个位和十位。
#include <stdio.h>
int main()
{
        int x,a,b;
 printf("plase input x:\n");
 scanf("%d",&x);
        a=x-x/10*10;
        b=x/10;
        printf("%d,%d\n",a,b);
        return 0;
}

#include <stdio.h>
void print_xx(int c)
{
        int a,b;
        a=c-c/10*10;
        b=c/10;
        printf("%d,%d\n",a,b);
                                                                    
}
int main()
{
        int x;
        printf("plase input x:\n");
        scanf("%d",&x);
        print_xx(x);
        return 0;
}
<三>布尔代数
数学中的a<b<c,在C语言是用下列方法表示的:
if (a < b) {
 if (b < c) {
  printf("b is between a and c.\n");
 }
}
也可以用逻辑与(Logical AND)运算符表示两个条件同时成立:
if (a < b && b < c) {
 printf("b is between a and c.\n");
}
两个表达式为真才为真。
AND的真值表
A B A AND B
0 0 0
0 1 0
1 0 0
1 1 1
这种表称为真值表(Truth Table)。注意逻辑与运算的操作数以非0表示真以0表示假,而运算结果以1表示真以0表示假(类型是int),我们忽略这些细微的差别,在表中全部以1表示真以0表示假。C语言还提供了逻辑或(Logical OR)运算符,写成两个|线(Pipe Sign),逻辑非(Logical NOT)运算符,写成一个!号(Exclamation Mark),它们的真值表如下:
表 4.3. OR的真值表
A B A OR B
0 0 0
0 1 1
1 0 1
1 1 1
 
表 4.4. NOT的真值表
A NOT A
0 1
1 0
逻辑或表示两个条件只要有一个为真,它们做逻辑或运算的结果就为真逻辑非运算符只有一个操作数,称为单目运算符(Unary Operator),以前讲过的加减乘除、赋值、相等性、关系、逻辑与、逻辑或运算符都有两个操作数,称为双目运算符(Binary Operator),只有两个条件都为假,逻辑或运算的结果才为假。逻辑非的作用是对原来的逻辑值取反,原来是真的就是假,原来是假的就是真。
关于逻辑运算的数学体系称为布尔代数(Boolean Algebra),以它的创始人布尔命名。在编程语言中表示真和假的数据类型叫做布尔类型,在C语言中通常用int型来表示,非0表示真,0表示假[6]。布尔逻辑是写程序的基本功之一,程序中的很多错误都可以归因于逻辑错误。

习题
1、把代码段
if (x > 0 && x < 10);
else
 printf("x is out of range.\n");
改写成下面这种形式:
if ( x<=0 || x>=10)
 printf("x is out of range.\n");
2、把代码段:
if (x > 0)
 printf("Test OK!\n");
else if (x <= 0 && y > 0)
 printf("Test OK!\n");
else
 printf("Test failed!\n");
改写成下面这种形式:
if (x <= 0 && y <= 0)
 printf("Test failed!\n");
else
 printf("Test OK!\n");

3、有这样一段代码:
if (x > 1 && y != 1) {
 ...
} else if (x < 1 && y != 1) {
 ...
} else {
 ...
}
要进入最后一个else,x和y需要满足条件x=1 || y=1。
4、以下哪一个if判断条件是多余的可以去掉?这里所谓的“多余”是指,某种情况下如果本来应该打印Test OK!,去掉这个多余条件后仍然打印Test OK!,如果本来应该打印Test failed!,去掉这个多余条件后仍然打印Test failed!。
if (x<3 && y>3)
 printf("Test OK!\n");
else if (x>=3 && y>=3)
 printf("Test OK!\n");
else if (z>3 && x>=3)
 printf("Test OK!\n");
else if (z<=3 && y>=3)
 printf("Test OK!\n");
else
 printf("Test failed!\n");

判断一下:
(1)当x<3和y>3为真,则输出第一个 Test Ok
(2)当x>=3,y>3为假,则执行第二个if语句,x>=3&&y>=3符合条件输出第二个Test Ok,第三个if语句,如果z为真输出test ok,如果z为假第四条语句也输出 test ok
(3)如果x<3和y=3或y<3为假,则执行第二个if语句,x>=3&&y>=3不符合条件,则执行第三个if语句,z>3&&x>=3,为假,执行第四个if语句,z<=3&&y>=3,如果y=3是y表达式为真,判断z,如果z<=3则为真,输出Test Ok,否则为假。执行输出Test Failed!.如果y<3则直接输出,Test Failed,不用判断z表达式是否为真。
(4)如果x>=3和y=3或y<3为假,则执行第二个if语句,当y=3是输出Test Ok;如果y!=3这执行第三条if语句,z为真输出Test Ok,为假则输出Test failed!,
else if (x>=3 && y>=3)
 printf("Test OK!\n");
总结:上面是多余的if判断语句
<四>switch语句
switch语句可以产生具有多个分支的控制流程。它的格式是:
switch (控制表达式) {
case 常量表达式: 语句列表
case 常量表达式: 语句列表
...
default: 语句列表
}
例如以下程序根据传入的参数1~7分别打印Monday~Sunday:
#include <stdio.h>
void print_day(int day)
{
        switch(day){
                case 1:
                        printf("Monday\n");
                        break;
                case 2:
                        printf("Tueseday\n");
                        break;
                case 3:
                        printf("Wednesday\n");
                        break;
                case 4:
                        printf("Thursday\n");
                        break;
                case 5:
                        printf("Friday\n");
                        break;
                case 6:
                        printf("Saturday\n");
                        break;
                case 7:
                        printf("Sunday\n");
                        break;
                default:
                        printf("Illegal day number!\n");
                        break;
                                                                    
                                                                    
        }
        printf("finsh.\n");
}
                                                                    
int main(void)
{
        print_day(3);
        print_day(-1);
        print_day(9);
        return 0;
}
如果传入的参数是3,则从case3分支开始执行,先是打印相应的信息,然后遇到break跳出switch语句块。C语言规定各case分支的常量表达式必须互不相同,如果控制表达式不等于任何一个常量表达式,则从default分支开始执行,通常把default分支写在最后,但不是必须的。使用switch语句要注意几点:
1.case后面跟表达式的必须是常量表达式,这个值和全局变量的初始值一样必须在编译时计算出来。
2.第 2 节 “if/else语句”讲过浮点型不适合做精确比较,所以C语言规定case后面跟的必须是整型常量表达式。
3.进入case后如果没有遇到break语句就会一直往下执行,后面其它case或default分支的语句也会被执行到,直到遇到break,或者执行到整个switch语句块的末尾。通常每个case后面都要加上break语句,但有时会故意不加break来利用这个特性,例如:
#include <stdio.h>
void print_day(int day)
{
        switch(day){
                case 1:
                        printf("Monday\n");
                       
                case 2:
                        printf("Tueseday\n");
                      
                case 3:
                        printf("Wednesday\n");
                       
                case 4:
                        printf("Thursday\n");
                        break;
                case 5:
                        printf("Friday\n");
                       
                case 6:
                        printf("Saturday\n");
                       
                case 7:
                        printf("Sunday\n");
                       
                default:
                        printf("Illegal day number!\n");
                       
                                                                    
                                                                    
        }
        printf("finsh.\n");
}
                                                                    
int main(void)
{
        print_day(3);
        print_day(-1);
        return 0;
}
 
 
我的《Linux C编程一站式学习》学习总结..