if语句的规范化问题

前言

在日常的编程学习中,我们经常会因为编程的不规范造成一些莫名其妙的问题,此处着重说一下C语言if判断是否为零的问题

if语句的三种形式

第一种形式:if

1
if(表达式)语句
其语义为:如果表达式的值为真,则执行其后的语句,否则不执行该语句。

第二种形式: if-else

1
2
3
4
if(表达式)
语句1;
else
语句2;
其语义为:如果表达式的值为真,则执行语句1,否则执行语句2.

第三种形式: if-else-if形式

前两种一般都用于两个分支的情况。当有多个分支选择时,可采用if-else-if语句

1
2
3
4
5
6
7
8
9
  if(表达式1)
语句1;
else if(表达式2)
语句2;
else if(表达式3)
语句3;
...
else if(表达式n)
语句n;

其语义为:依次判断表达式的值,当出现某个值为真时,则执行其对应的语句。然后跳到整个if语句之外继续执行程序。 如果所有的表达式均为假,则执行语句n。然后继续执行后续程序。

上方则为if语句的三种基本形式,再次不多加赘述

if判断是否为零的问题及书写规范

表达式中存在多种变量类型,例如布尔变量、整型变量、浮点变量、指针变量。当他们与零比较时,存在不同的规范形式,

布尔类型(bool)

布尔类型的语义规定 非0为真,0为假
假设布尔变量的名字为flag,他和零值比较的标准if语句如下:

1
2
if(flag)  //表示flag为假
if(!flag) //便是flag为真

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<stdio.h>
int main()
{
int flag =2
if(flag)
{
printf("真\n");
}
else
{
printf("假\n");
}
return 0;
}

输出为:真
注意:此处如果用 flag!=1 也会输出同样的结果,他没有错,但是他不规范,此处bool变量可以,但不见得其他变量不会出错,而且会让人误认为flag是整型变量

整型变量

假设整型变量为value,它与零值比较的标准if语句如下:

1
2
if(value == 0)
if(value != 0)

不可用模仿bool变量的风格而写成:
if(value) //会让人误以为value是布尔变量
if(!value)

指针变量

指针变量的零值是空值NULL,即不指向任何对象。尽管NULL的值与0相同,但是两者的意义不同。

1
2
3
4
5
6
7
8
#include<stdio.h>
int main()
{
int* p = NULL;
if(p != NULL)
*p = 20;
return 0;
}

此处程序运行无结果,是因为指针变量为空(主要展示指针变量如何与零作比较)
注意两点:
①指针变量在不知道怎么初始化是就初始化为空指针NULL;
②指针变量使用前一定要判断指针变量的有效性,不为空才使用,为空不使用;

浮点数和零比较

计算机表示浮点数(float和double类型)都有一个精度限制。对于超出了精度限制的浮点数,计算机会把它们的精度之外的小数部分截断。因此本来不相等的两个浮点数在计算机中就可能变成相等的了。
例如该程序:

1
2
3
4
5
6
7
8
9
10
11
#include(stdio.h)
int main()
{
double i = 20;
double j = i/7.0;
if(j*7.0 == i)
printf("equal\n");
else
printf("not equal\n");
return 0;
}

这段代码在vs2013的编译环境下的运行结果是 equal 但是当把他放在gcc4.4版本中的linux去运行,则结果为 not equal ,所以此程序可能会在不同的地方出现不同的结果,这是因为浮点数在内存中可能不能精确地保存,为了避免这样的意外发生,我们便要规范化程序
那么如何对两个浮点数进行比较?
如果两个同符号浮点数之差的绝对值小于或等于某一个可接受的误差(即精度),就认为它们是相等的,否则就是不相等的。
修改程序

1
2
3
4
5
6
7
8
9
10
11
12
#include<stdio.h>
#define exp 0.0000000001
int main()
{
double i = 20;
double j = i/7.0;
if((j*7.0-i)>-exp&& (j*7.0-i)<exp)
printf("equal\n");
else
printf("not equal\n");
return 0;
}

此时不论在哪里运行的结果都会相同
附一道例题:解一元二次方程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#define EXP 0.0000000001
#include<math.h>
#include<stdio.h>
int main()
{
float a=0.0,b=0.0,c=0.0;
scanf("%f%f%f", &a, &b, &c);
if(a>-EXP && a<EXP)
{
printf("不是一元二次方程\n");
}
else
{
float disc = b*b-4*a*c;
if(disc>-EXP && disc<EXP)
{
printf("有一个实根:%f\n", (-b)/(2*a));
}
else if(disc>=EXP)
{
printf("有两个根:%f %f\n",
((-b)+sqrt(disc))/(2*a),
((-b)-sqrt(disc))/(2*a));
}
else
{
printf("无解\n");
}
}
return 0;
}

在if语句中还应注意以下问题

1.在三种形式的if语句中,在if关键字之后均为表达式。 该表达式通常是逻辑表达式或关系表达式,但也可以是其它表达式,如赋值表达式等,甚至也可以是一个变量。
2.else 总是与它前面最近的if配对。

1
2
3
4
5
6
7
8
9
10
11
12
#include<stdio.h>
int main()
{
int a = 0;
int b = 2;
if(a == 1)
if(b == 2)
printf("hehe\n");
else
printf("haha\n");
return 0;
}

猜想一下代码结果~ → 运行后会发现什么结果是什么输出都没有 ,原因便是else的悬空,此处的else其实是跟在第二个if后面的,结果第一个条件都没有进来所以自然轮不到第二个if-else语句,改成下面这样便一目了然

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<stdio.h>
int main()
{
int a = 0;
int b = 2;
if(a == 1)
{
if(b == 2)
printf("hehe\n");
}
else
{
printf("haha\n");
}
return 0;
}

3.在if语句中,条件判断表达式必须用括号括起来,在语句之后必须加分号
4.在if语句的三种形式中,所有的语句应为单个语句,如果要想在满足条件时执行一组(多个)语句,则必须把这一组语句用{}括起来组成一个复合语句。但要注意的是在}之后不能再加分号。