考虑这个在实际工作之前检查错误的C结构:
int function(struct Context *context,struct Connection *conn)
{
int retval;
switch(0)
{
case 0:
retval = BUFFER_INACTIVE;
if(conn->mSocket == -1)
break;
retval = BUFFER_FULL;
/* Is there enough room to add ? */
if((context->mMaxBufferSize - conn->mSendPacketLength) < aPacketLength)
break;
/* Is the send packet buffer half sent? */
if(conn->mSendPacketLength > 0 && conn->mSendPacketPos != conn->mSendPacket)
break;
/* Do some work here */
retval = BUFFER_DONE;
}
/* Do some things before returning */
printf("%d",retval);
return retval;
}
你认为这是可读的吗?使用goto
或堆叠if()
的替代方案会更好吗?
答案 0 :(得分:5)
我从未见过切换解决方案,但我做过这样的事情:
do {
err = func();
if( err ) break;
err = func2();
if( err ) break;
...
} while( 0 );
if( err ) {
// handle errors
}
但是这和它之间的真正区别是什么:
err = func();
if( err ) goto done;
err = func2();
if( err ) goto done;
...
done:
if( err ) {
//handle errors;
}
第一个是第二个重写,以避免使用关键字goto
,我认为goto
解决方案更具可读性。我花了一段时间,但我设法让自己相信goto
不是总是邪恶。
最后,如果可能的话,我更喜欢使用if
语句,因为它使代码更具可读性,但如果需要,则goto
。
答案 1 :(得分:4)
我会说那不太可读。我认为使用if语句甚至是goto将是一种更合适的方法。使用goto不是世界末日,完全可以接受并适合错误处理。
答案 2 :(得分:0)
我建议您使用 while(true)而不是switch:
while(true)
{
retval = BUFFER_INACTIVE;
if(conn->mSocket == -1)
break;
retval = BUFFER_FULL;
/* Is there enough room to add ? */
if((context->mMaxBufferSize - conn->mSendPacketLength) < aPacketLength)
break;
/* Is the send packet buffer half sent? */
if(conn->mSendPacketLength > 0 && conn->mSendPacketPos != conn->mSendPacket)
break;
/* Do some work here */
retval = BUFFER_DONE;
break;
}
答案 3 :(得分:0)
另一种选择是将它包装在一个函数中并返回而不是破坏。这通常是一个坏主意,因为它最终会添加一个不必要的抽象层。但是,在某些情况下,它可以使事情变得更简单。
答案 4 :(得分:-1)
另一种方法是使用级联ifs:
u8 u8IsOk;
u8IsOk = Func1();
if(u8IsOk)
{
/* Do some stuff...*/
u8IsOk = Func2();
} /* if */
if(u8IsOk)
{
/* Do some stuff...*/
u8IsOk = Func3();
} /* if */
......等等。不如其他一些方法有效,但避免过多的嵌套,转到,中断,while(0)和多次返回。