自学内容网 自学内容网

Goto到另一个函数内部

Goto到另一个函数内部的用法,在现存的高级语言中基本上已经绝迹了。但并非异想天开。也没有特别复杂。现在来探讨一下。

要允许Goto到另一个函数内部,首先要有语法的支持。假设这样写吧:

func daily(n)
{
while(n>0) {
n--;
switch(iday) {
case 0:
case_sunday: print "Sunday"; iday=1; break;
case 1:
case_Monday:  print "Monday"; iday=2; break;
case 2:
case_tuesday:  print "Tuesday"; iday=3; break;
case 3:
case_wednesday:  print "Wednesday"; iday=4; break;
case 4:
case_thursday:  print "Thursday"; iday=5; break;
case 5:
case_friday:  print "Friday"; iday=6; break;
case 6:
case_saturday:  print "Saturday"; iday=0; break;
}
}
}

goto daily(31).case_friday;

这个goto的意思是调用函数daily(31),但是从标号case_friday处开始执行。打印Friday开始31天的星期历。这里函数看作了标号的结构体。这样函数就不再是唯一入口的代码块了。

在实现上也不是特别困难。原来函数调用的地方,只要稍作修改:

struct exprval e_fcall(int fi, struct node *paras, int *exception)
{
        struct funxat *f;
        struct node *p;
        struct exprval e;
        int i;
        struct exprval ret;
        struct exprval *argtab = NULL;


        f = &userfunc[fi];
        p = paras;
        i=0;
        while(p) {
                p = p->left;
                ++i;
        }
        if (i != f->paras) {
                printf("function %s(...) need %d paras, but given %d\n",
                        f->name, f->paras, i);
                *exception =1; goto exception_out;
        }

        if(f->paras>0) {
                argtab = (VALUE_TYPE *)Malloc(sizeof(VALUE_TYPE)*f->paras);
        }
        p = paras;
        for(i=f->paras-1; i>=0; --i) {
                e = e_eval(p->right, exception); EXCEPTION_CHK;
                argtab[i]= e;
                p= p->left;
        }

        if (f->loop == f->warning) {
                printf("waring: func %s(...) nest called in %d levels\n",
                        f->name, f->loop);
                f->warning = terminate_loop -(terminate_loop -f->warning)/4;
        }

        if (f->loop >terminate_loop) {
                printf("exception: func %s(", f->name);
                for(i=0; i<f->paras; i++) {
                        if(i>0) printf(",");
                        e = argtab[i];
                        if (e.type==0) {
                                printf("~%d", e.u.value);
                        }
                        else {
                                printf("~%lf", e.u.d_value);
                        }
                }
                printf(") is terminated!;\n");
                *exception =1;
                goto exception_out;
        }

        f->loop++;

        alloc_context(f);
        for(i=0; i<f->paras; i++) {
                stk->e[top].bp[i] =argtab[i];
        }

        execute_e_ls(f->syntree, 0, exception); //.. ..............
        ret = stk->e[top].ret;
        free_context();
        f->loop--;
        if (f->loop==0) {
                f->warning= terminate_loop - (terminate_loop/4);
        }

exception_out:
        if (argtab) free(argtab);
        if (*exception==1) {
        }
        return ret;
}

改为:

struct exprval e_fgoto(int fi, struct node *paras, char *sgoto, int *exception)
{
...
i = labelfind(f, sgoto, strlen(sgoto));
if(i<0) {
*exception =1;
goto exception_out;
}
        execute_e_ls(f->syntree, f->labeltab[i], exception); 
        ...
}

函数增加goto的目标label参数,原来的execute_e_ls(f->syntree, 0, exception); 变为带goto标记的execute_e_ls(f->syntree, f->labeltab[i], exception);

这样做可能毫无意义,也可能…。偶尔,有一天你会想把几个不同实现的排序代码封装到一个sort()函数中,又允许使用时调用各自的功能:

func sort(array, first, last)
{
bubble_sort:
...
return;

quick_sort:
...
if(...)  goto sort(array, first, middle-1).quick_sort;
if(...)  goto sort(array, middle+1, last).quick_sort;
return;
}

可以用goto sort(array, first, last).quick_sort;来调用快速排序。当然,这局部是个递归,它也是用同样的句法来调用自己。

如果增加一个函数参数来选择怎么样?

func sort(array, first, last,select)
{
if(select==1) goto bubble_sort;
if(select==2) goto quick_sort;

bubble_sort:
...
return;

quick_sort:
...
if(...)  sort(array, first, middle-1, select);
if(...)  sort(array, middle+1, last, select);
return;
}

这样当然可以…。不过多了一个参数,以及一些选择语句。开销也可以忍受。不过在递归过程中这样写,让人不快。

最后,如果函数有返回值呢?只要允许到变量的一个赋值语句就可以了:

goto n = fib(i).lable1;

原文地址:https://blog.csdn.net/aaasssdddd96/article/details/136392352

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!