实用经验 39 “悬挂”else引起的问题

本文探讨了C++编程中常见的悬挂else问题,解释了问题的根源及为何容易导致逻辑错误。通过示例代码,展示了如何通过正确的括号使用和良好的编程风格来避免这一问题。此外,还提到了BashShell语言的if-else实现作为对比,并讨论了在C++中使用宏定义来模拟BashShell的方法,但指出该方法可能带来的阅读难度。最后,强调了采用总是使用大括号的编码风格是解决悬挂else问题的最佳实践。
摘要由CSDN通过智能技术生成

“悬挂”else问题,应该是我们最熟悉不过的一个问题了。此问题也不是C/C++所独有。即使有多年软件开发经验的资深程序员也常常深受其害。

我们首先理解一下,什么是“悬挂”else问题?为了使我的描述更形象、你更容易理解;我们看下面这个例子。

#include <stdio.h> 

int main() 
{ 
	int x = 0;
	int y = 1;
	if(x == 0) 
		if(y == 0)  printf("x == 0 && y == 0\n"); 
	else 
		printf("x!=0\n"); 
	return 0; 
} 

这段代码的本意我想应该是:对于x=0这种情形,如果y=0输出“x==0 && y==0”,否则程序不做任何处理。对于x!=0这种情形,程序输出“x!=0”。

但是,这段代码实际执行情况也许会让你大惊失色。原因在于c++从C继承了这条规则:else始终与同一对括号内最近的未匹配的if结合。按照这条规则,上面这段代码实际被执行的逻辑应该是这样的:

int x = 0;
int y = 1;
if(x == 0) 
{
	if(y == 0)
	{
	   printf("x == 0 && y == 0\n"); 
	}
	else
	{
		printf("x!=0\n");
	}
}
return 0; 

从这段代码,我们可看出:如果x不等于0,程序将不会做任何处理操作,直接return0;。如果要得到原本由代码缩进所体现的编程者的本意,程序应该修改成整这样:

int x = 0;
int y = 1;
if(x == 0) 
{
	if(y == 0) 
		printf("x == 0 && y == 0\n");
}
else
{ 
	printf("x!=0\n"); 
}
return 0; 

可以看出,现在else与第一个if结合,即使它距离第二个if更近也是如此。因为这时第二个if已经被一对大括号“封装”了。

现在我们对“悬挂”else问题已经彻底了解,然而如何避免此问题呢?我们先把这个问题放到一旁,看一下Bash Shell语言的if-else实现方式。Bash shell脚本语言在if语句后使用了收尾定界符来显示地说明if语句结束。我们看下面这段脚本代码:

#!/bin/sh
if [ ${SHELL} = "/bin/bash" ]; then 
if [$LOGNAME!= “root”]; then
       echo “you need to be root to run this script” >&2
    fi
else 
echo "your login shell is not bash but ${SHELL}" 
fi

像上述这种fi强制首尾符完全避免了“悬挂”else问题,而付出的代价仅仅是程序稍微变长了一点儿。

在C++中,我们也可以通过宏定义达到Bash shell所达到的效果。考虑下面这种实现:

#define IF      {if(
#define THEN    ) {
#define ELSE    } else {
#define FI       }}

这样,上例中的C++程序可改写成:

IF  x == 0  THEN 
     IF  y == 0  THEN 
           printf("x == 0 && y == 0\n");
     FI
ELSE 
     printf("x!=0\n");
FI

这种方案确实解决了“悬挂”else问题,我想如果你是一个未接触过bash shell脚本语言的新手,我想当你看到这段代码时,你肯定会抓狂。我们可这么总结这种方案:这种方案所带来的问题比它所解决的问题更糟糕。

但是,对于“悬挂”else问题有更好的解决方案吗?答案是有的。解决这一问题最佳方案是让我们不屑的优秀的编码风格。也就是在if和else之后加上一对大括号,不论if-else之间有几条语句,也不论else后有几条语句。看下面这种编码解决方案:

int x = 0;
int y = 1;
if(x == 0) 
{
	if(y == 0) 
	{
		printf("x == 0 && y == 0\n");
	}
}
else
{ 
	printf("x!=0\n"); 
}
return 0;

请谨记

  • 良好的编程风格不仅可以给人惬意的感觉,让人赏心悦目。重要的是在某些情况下可避免编程陷阱,如“悬挂”else问题。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值