我有一个功能,需要分析数据包后的数据包,并决定做什么。 对于每个数据包,代码必须:
我的代码如下:
Packet p;
for (;;) {
int ret = receive(&p, time);
if (ret == TIMEOUT) {
log("timeout");
return TIMEOUT;
}
if (ret != 0) {
log("corrupted %d", ret);
continue;
}
if (p.type == ABORT) {
log("abort");
return ABORT;
}
ret = check(&p);
if (ret != 0) {
log("invalid %d", ret);
respond(&p, INVALID);
continue;
}
ret = execute(&p);
if (ret != 0) {
log("failure %d", ret);
respond(&p, FAILURE);
continue;
}
if (is_last(&p)) {
finalize(&p);
return 0;
}
}
这段代码是否有更好的结构化方式,不是不必要的嵌套或长期?
答案 0 :(得分:1)
您可以使用return
而不是在循环中使用多个break
并进行最终return
:
Packet p;
int ret;
for (;;) {
ret = receive(&p, time);
if (ret == TIMEOUT) {
log("timeout");
break;
}
if (ret != 0) {
log("corrupted %d", ret);
continue;
}
if (p.type == ABORT) {
log("abort");
break;
}
.
.
.
if (is_last(&p)) {
finalize(&p);
ret = 0;
break;
}
}
return ret;
答案 1 :(得分:0)
我觉得它看起来不错。它绝对没有不必要的嵌套,即使看起来“很长”也很简短 - 除非你想在receive()
,check()
和execute()
函数中移动日志。
答案 2 :(得分:0)
我会尽量避免从循环内部返回。 而是在函数结束时中断并返回单个返回值。 除此之外看起来还不错。
答案 3 :(得分:0)
这是个人偏好,但我个人不喜欢无限循环或continue
关键字。我会这样做:
Packet p = { /* some dummy init that doesn't flag islast() true */};
int ret = 0;
while (ret != TIMEOUT && p.type != ABORT && !islast(&p))
{
int ret = receive(&p, time);
if (ret != TIMEOUT)
{
if (ret != 0)
{
log("corrupted %d", ret);
}
else if (p.type != ABORT)
{
ret = check(&p);
if (ret != 0)
{
log("invalid %d", ret);
respond(&p, INVALID);
}
else
{
ret = execute(&p);
if (ret != 0)
{
log("failure %d", ret);
respond(&p, FAILURE);
}
}
}
}
}
if (ret == TIMEOUT)
{
log("timeout");
}
else if (p.type == ABORT)
{
log("abort");
ret = ABORT;
}
else
{
finalise(&p);
}
return ret;
我的版本看起来比你的版本复杂,但这是因为它更准确地反映了算法的结构。在我看来(这只是一个意见),像continue和break这样的关键词会混淆结构,不应该使用。
除此之外,另一个主要优点是,在我的版本中,您可以通过查看一个位置(即循环条件)清楚地看到导致循环退出的条件。此外,导致循环的条件完全在循环外处理 - 概念上是正确的位置。该功能也只有一个退出点。
答案 4 :(得分:0)
经验法则是避免一遍又一遍地重复使用同一个变量。如果它用于新的东西,请改为创建一个新的。例如,当我阅读您的代码时,我错过了ret
在此过程中重新定义的事实。另一个优点是,如果定义并立即使用某个值,您通常可以在较小的范围内定义它。
例如:
ret = execute(&p);
if (ret != 0) {
log("failure %d", ret);
respond(&p, FAILURE);
continue;
}
您可以将其重写为:
{
int ret_exe = execute(&p);
if (ret_exe != 0) {
log("failure %d", ret_exe);
respond(&p, FAILURE);
continue;
}
}
或者,如果您使用 C99或 C ++:
if (int ret_exe = execute(&p)) {
log("failure %d", ret_exe);
respond(&p, FAILURE);
continue;
}
答案 5 :(得分:0)
很多人不喜欢嵌套在if语句中的赋值,但我认为没有任何合理的依据。使用它们允许紧凑的代码如下(我没有声称是“最好的”;这是非常主观的):
for( ;; ){
Packet p;
int ret;
if( (ret = receive(&p, time)) == TIMEOUT ){
log("timeout");
return TIMEOUT;
}else if( ret != 0 ){
log("corrupted %d", ret);
}else if( p.type == ABORT ){
log("abort");
return ABORT;
}else if( (ret = check(&p)) != 0 ){
log("invalid %d", ret);
respond(&p, INVALID);
}else if( (ret = execute(&p)) != 0 ){
log("failure %d", ret);
respond(&p, FAILURE);
}else if( is_last(&p) ){
finalize(&p);
return 0;
}
}