关于goto。

zhengjiankang 2011-04-29 12:05:21
有个问题。
下面这种情况。
如何不用goto做到。

#include <stdlib.h>

#define step(i) (1 << i)

int con_x(int i)
{
return rand() % (i + 1);
}

int con_y(int i)
{
return rand() % (i + 2);
}

int main()
{
int init_mask = 0;
int status = 0;

int* ptr1 = 0;
int* ptr2 = 0;
float* ptr3 = 0;
float* ptr4 = 0;
char* ptr5 = 0;
char* ptr6 = 0;

if (con_x(1))
{
ptr1 = (int*)malloc(sizeof(int));
init_mask |= step(1);
}
else
{
status = 1;
goto cleanup;
}

if (con_y(2))
{
ptr1 = (int*)malloc(sizeof(int));
init_mask |= step(2);
}
else
{
status = 1;
goto cleanup;
}

// ...

cleanup:

if (init_mask & step(1))
{
free(ptr1);
ptr1 = 0;
}

if (init_mask & step(2))
{
free(ptr2);
ptr1 = 0;
}

// ...

return status;
}


本人比较菜。
想不到好办法。
因为condition可能是任意的函数调用。
而用到的resource也可能是任意的调用引起的。
...全文
335 20 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
www_adintr_com 2011-04-29
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 zhengjiankang 的回复:]

回6楼。
也许你没注意我最后写的那2句话。
condition可能是任意调用。
也就是说。
如果有个con_z(int, int);
那你的函数指针数据还有效么。
[/Quote]
不好意思,确实没注意到.
如果只是从语法上避免 goto 的话还可以这样:


...
for(int i = 0; i < 1; ++i)
{
if (con_x(1))
{
ptr1 = (int*)malloc(sizeof(int));
init_mask |= step(1);
}
else
{
status = 1;
break;
}

if (con_y(2))
{
ptr1 = (int*)malloc(sizeof(int));
init_mask |= step(2);
}
else
{
status = 1;
break;
}
...
}

...

不过这样和用 goto 差不多.
最好好是抽函数出来, 参数太多可以都放到一个结构体里面, 然后传递结构体的指针作为参数.
可以这里是 C 版,如果是 C++ 版, 这个肯定应该封装成对象了. 在 C 里也就借鉴一下对象的思想吧.
Meteor_Code 2011-04-29
  • 打赏
  • 举报
回复
还是这样写吧,这用法太傻了
还是喜欢goto

if(iFlag)
if (con_x(1))
{
ptr1 = (int*)malloc(sizeof(int));
init_mask |= step(1);
}
else
{
status = 1;
iFlag = 0;
}
if(iFlag)
if (con_y(2))
{
ptr1 = (int*)malloc(sizeof(int));
init_mask |= step(2);
}
else
{
status = 1;
iFlag = 0;
}
Meteor_Code 2011-04-29
  • 打赏
  • 举报
回复
我用goto从没出过错,为什么不用呢?不用也有个办法,但没goto灵活,日本人写代码的风格,如下,说实在的,够2的

int iFlag;
iFlag = 1;

if (con_x(1) && iFlag)
{
ptr1 = (int*)malloc(sizeof(int));
init_mask |= step(1);
}
else
{
status = 1;
iFlag = 0;
}

if (con_y(2) && iFlag)
{
ptr1 = (int*)malloc(sizeof(int));
init_mask |= step(2);
}
else
{
status = 1;
iFlag = 0;
}

if (!iFlag )
{
//错误处理
}
zhengjiankang 2011-04-29
  • 打赏
  • 举报
回复
回6楼。
也许你没注意我最后写的那2句话。
condition可能是任意调用。
也就是说。
如果有个con_z(int, int);
那你的函数指针数据还有效么。
yuimo 2011-04-29
  • 打赏
  • 举报
回复
cleanup部分改成与各i函数
李亚超 2011-04-29
  • 打赏
  • 举报
回复
goto,魔鬼.......
www_adintr_com 2011-04-29
  • 打赏
  • 举报
回复


....
float* ptr4 = 0;
char* ptr5 = 0;
char* ptr6 = 0;

typedef int (*con_f)(int);
con_f conlist[] = { con_x, con_y /*, ... */ };

for(int i = 0; i < sizeof(conlist) / sizeof(conlist[0]); ++i)
{
int x = i + 1;
if(conlist[i](x))
{
ptr1 = (int*)malloc(sizeof(int));
init_mask |= step(x);
}
else
{
status = 1;
break;
}
}


if (init_mask & step(1))
{
free(ptr1);
ptr1 = 0;
}

.....
zhengjiankang 2011-04-29
  • 打赏
  • 举报
回复
我也觉着合理啊。
只是如果有更好的方案。
当然可以用更好的方案咯。
就想叫yoko 2011-04-29
  • 打赏
  • 举报
回复
我也觉得这种情况用goto很合理
其实很多地方说应该避免goto其原因是避免程序流程混乱不清晰
这里不存在这个问题
berkowitz 2011-04-29
  • 打赏
  • 举报
回复
想完全逃避goto似乎不太现实,我向来使用goto来进行内存释放工作。约定跳转的目标名称,然后都用一个宏定义代替goto
zhengjiankang 2011-04-29
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 pathuang68 的回复:]

把cleanup下面相关代码,写成一个函数不就OK了吗?
[/Quote]

那么你那个cleanup函数要传多少个参数呢?
所有的资源标识符都在主函数里面。。。
pathuang68 2011-04-29
  • 打赏
  • 举报
回复
把cleanup下面相关代码,写成一个函数不就OK了吗?
  • 打赏
  • 举报
回复
我的改法

if (con_x(1) || con_y(2))
{
ptr1 = (int*)malloc(sizeof(int));
if(con_x(1))
init_mask |= step(1);
else if(con_x(2))
init_mask |= step(2);
}
else
{
status = 1;
}

//如果下面的注释没有语句的话这样改是可以的。
// ...
//cleanup:

if (init_mask & step(1))
{
free(ptr1);
ptr1 = 0;
}

if (init_mask & step(2))
{
free(ptr2);
ptr1 = 0;
}

// ...

ouyh12345 2011-04-29
  • 打赏
  • 举报
回复
while (1)
{
if (...)
{
break;
}
...
if (...)
{
break;
}
...
return 0;
}
....clean
return 1;
张小毛 2011-04-29
  • 打赏
  • 举报
回复
中j8问题,受不了了
pathuang68 2011-04-29
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 pathuang68 的回复:]

把cleanup下面相关代码,写成一个函数不就OK了吗?
[/Quote]

额,没仔细看题。
心里在想着别的事情,不在状态。sorry
我真的是琦琦 2011-04-29
  • 打赏
  • 举报
回复

switch(a)
{
case 1:
{
//do something
a = 2;
}
break;
case 2:
{
//do something
//finish doing
return 1;//从这里返回这个switch
}
break;
case 3:
{
//do something
a = 2;
}
break;
}

这个需要while执行这个函数了,当完成后就返回
赵4老师 2011-04-29
  • 打赏
  • 举报
回复
也可以atexit函数或者__try __finally
Meteor_Code 2011-04-29
  • 打赏
  • 举报
回复
ls太聪明了

do
{
if()
{
}
else
{
break;
}
}
while(0);

这样就可以了

70,020

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧