C-do{.}while(0);可以从代码中删除,不包括嵌套的if-else用法
C - do{..} while(0); can be removed from code excluding usage nested if else?
do{…}while(0)
do{}while(0)的用法是因为,我不想使用长if-elses嵌套的条件语句。我最终在失败时中断并退出循环,并保证我的函数至少会被遍历一次。
现在,代码警告工具出现了问题,我在使用do时收到了警告{...}while(0)
嵌套if(){}else{}的用法可读性较差,非常复杂。并且让代码具有死代码。
如果我排除嵌套的if(){}else{}和do{}while(0),我们是否用其他方法让代码可读并具有可理解的逻辑;
if(status_of_funcA_ok != funcA())
{ //failure}
else if (status_of_funcB_ok != funcB())
{//failure}
else if (status_of_funcC_ok != funcC())
else
{//Great}
do{
if(status_of_funcA_ok != funcA())
break;
if (status_of_funcB_ok != funcB())
break;
if (status_of_funcC_ok != funcC())
break;
}while(0);
将do while{0}
循环的完整逻辑移动到一个函数,并用return
替换break
。并调用函数,而不是循环。
- 你不必担心美丽
- 编译器也不必抱怨
do while{0}
更重要的是,通过添加一点模块化,程序可能会更可读。
无论如何,在执行此操作之前,最好检查您的编译器是否处于极其迂腐的模式,您可能需要关闭该模式。这可能会消除警告。
ss。
附言:你似乎不需要函数的返回值,但你可以用它来获得哪个函数成功的线索。
我也在使用这个模式,对于那些想知道的人来说,这里有一个抽象的例子:
do // while(0) for break
{
state1 = 0;
if (cond1())
{
if (cond2())
break;
state1 = opA();
}
if (cond3() || state1 && state1->cond4())
break;
...
Triumph(state1, ...);
// often here: return
}
Failure(state1, ...);
我认为这在以下情况下是有效的:
- 你有一个很长的序列(比如说,>~6个条件)
- 条件很复杂,并且你使用/建立了重要的状态,所以你不能将元素隔离为函数
- 您所处的环境对异常不友好,或者您的
break
代码路径为实际上不是例外
你能做些什么:
使警告静音毕竟这只是一个警告,我看不出会被这个警告抓住的"典型错误"(比如键入0而不是您的条件)
现在,这太傻了。警告的典型错误是例如while (a1!=a1)
而不是while (a1!=a2)
。[/edit]
分解函数,将状态移动到类
这将把上面的代码转换为:
struct Garbler
{
State1 state1;
bool Step1()
{
state1 = 0;
if (cond1())
{
if (cond2())
return false;
state1 = opA();
}
return true;
}
bool Step2()
{
return cond3() || state1 && state1->cond4();
}
..
void Run()
{
if (Step1() && Step2() && ... && Step23())
Triumph(state1, ...);
else
Failure(state1, ...);
}
}
这可以说是可读性较差的,更糟糕的是,您将序列拆开,这可能会导致一个非常可疑的类(其中成员只能按特定顺序调用)。
Scopeguards
这可能允许将破发转换为更可接受的早期回报:
state1 = 0;
ScopeGuard gFailure = MakeGuard(&Failure, ByRef(state1), ...);
if (cond1())
{
if (cond2())
return;
state1 = opA();
}
if (cond3() || state1 && state1->cond4())
return;
// everything went ok, we can dismiss the scopeguard
gFailure.Dismiss();
Triumph(state1, ...);
它们可以用C++0x更优雅地编写,保留流,但解决方案也不那么灵活,例如,当Failure()
无法轻松隔离为单个函数时。
嵌套的if-else语句可能会变得非常不可读,但我认为使用do{..}while(0);作为替代品会更糟糕。这是非常非传统的,任何其他阅读它的人都不会真正将其与if-else语句联系起来。
您可以做一些事情来提高嵌套if-else语句的可读性。一些建议是:
-
优化你的逻辑-当你"重构"你的逻辑时,有时你可以去掉很多if子句,比如对相同的项进行分组。
-
use switch()-与if-else语句相比,switch通常更可读。您可以将枚举与每个案例相关联,并且可以切换此项。
-
用函数封装复杂逻辑
您可以使用goto
而不是do {} while(0)
和break
。这是不可读的,也不是好的做法。我认为,对于每一种特定的情况,都有一种更好的方法来避免深层的if/else结构。例如,有时使用函数调用会有所帮助:
例如,而不是:
if(status_of_funcA_ok != funcA())
{ //failure}
else if (status_of_funcB_ok != funcB())
{//failure}
else if (status_of_funcC_ok != funcC())
else
{//Great}
你可以写:
if (check_funcs() == 0) {
great();
}
int check_funcs() {
if (status_of_funcA_ok != funcA())
return -1;
if (if(status_of_funcB_ok != funcB()))
return -2;
if (if(status_of_funcC_ok != funcC()))
return -3;
return 0; /* great */
}
有时,您可以使用exit()
。
此外,在c++中,您可以使用throw()
和try/catch
:
try {
/* */
throw (this error);
/* */
throw (that error);
} catch (this error) {
} catch (that error) {
}
如果有更多条件需要检查,请避免使用if{} else{},
最佳做法是用switch case
替换if-else条件
- 为什么示例代码访问IUnknown中已删除的内存
- 你能检查一下为什么在这个代码中从链接列表中删除项目不起作用吗
- 从 C 样式字符串中删除子字符串 "in place" 在C++代码中
- 是否可以使用 C++ 中的模板减小删除代码大小
- 删除C++继承中虚拟类成员的代码重复
- 当我从下面的代码中删除关键字 virtual 时,它可以正常工作,否则会出现错误。在这里"virtual"字的意义是什么?
- 删除继承中的代码重复?
- 从排序数组中删除重复项,具有不同代码方式的相同解决方案具有不同的输出
- G++ 发出警告,要求删除一个代码的数组,但不删除另一个代码的数组
- 删除原子多线程代码中的容器
- 使用 ostream 变量删除代码重复
- 可视代码 删除函数括号内的空格
- Qt创建者-如何删除Clang代码模型
- 有没有一种预处理器的方法可以从调试符号中删除代码段
- 为什么在const和非const方法中删除代码重复不是不确定的行为
- While 循环 - 如何删除代码重复
- enable_if如何用于删除代码
- 是否可以使用十六进制编辑器从exe文件中删除代码?(c++)
- 为什么第一个值是2814,而不是在我删除代码块之后
- 使用-O3或-Ofast编译基准代码现实吗?还是会删除代码