重构循环体中的多个goto语句

时间:2015-07-05 13:58:07

标签: c# goto flow conditional

我正在努力将以下fortran 77子程序复制到C#方法中。主要问题是我试图摆脱fortran的goto陈述。

对于C#转换的Fortran看起来很好,但goto语句仍然存在。有没有办法可以用条件或其他方式替换所有这些?谢谢。

这是fortran子程序:

C PROGRAM TEMP
      subroutine TEMP (acl,adu,aeff,c,cair,cb,cbare, 
     + cclo,count1,csum,di,ed,emcl,emsk,enbal, 
     + enbal2,ere,erel,esw,eswdif,eswphy,eswpot, 
     + evap,facl,fcl,fec,feff,food,h,hc,he,ht,htcl,icl,j, 
     + mbody,p,po,r1,r2,rbare,rcl, 
     + rclo,rclo2,rdcl,rdsk,rob,rsum,sex,sigm,sw,swf,swm, 
     + ta,tbody,tcl,tcore,tmrt,tsk,v,vb,vb1,vb2, 
     + vpa,vpts,wetsk,wd,wr,ws,wsum,xx) 
      real acl,adu,aeff,c(0:10),cair,cb,cbare, 
     + cclo,csum,di,ed,emcl,emsk,enbal, 
     + enbal2,ere,erel,esw,eswdif,eswphy,eswpot, 
     + evap,facl,fcl,fec,feff,food,h,hc,he,ht,htcl,icl, 
     + mbody,p,po,r1,r2,rbare,rcl, 
     + rclo,rclo2,rdcl,rdsk,rob,rsum,sigm,sw,swf,swm, 
     + ta,tbody,tcl,tcore(1:7),tmrt,tsk,v,vb,vb1,vb2, 
     + vpa,vpts,wetsk,wd,wr,ws,wsum,xx 
      integer count1,count3,j,sex 
      wetsk = 0. 
      adu = 0.203 * mbody ** 0.425 * ht ** 0.725 
      hc = 2.67 + ( 6.5 * v ** 0.67) 
      hc = hc * (p /po) ** 0.55 
      feff = 0.725 
C 
      facl = (- 2.36 + 173.51 * icl - 100.76 * icl * icl + 19.28 
     + * (icl ** 3.)) / 100. 
C 
      if (facl .gt.1.) facl = 1. 
      rcl = (icl/6.45)/facl 
      if (icl.ge.2.) y = 1. 
      if ((icl .gt. 0.6) .and. (icl .lt. 2.)) y = (ht - 0.2) / ht 
      if ((icl .le. 0.6) .and. (icl .gt. 0.3)) y = 0.5 
      if ((icl .le. 0.3) .and. (icl .gt. 0.)) y = 0.1 
      r2 = adu * (fcl - 1. + facl) / (2. * 3.14 * ht * y) 
      r1 = facl * adu / (2. * 3.14 * ht * y) 
      di = r2 - r1 
C TEMPERATURE
      do 90 j = 1,7 
      tsk = 34. 
      count1 = 0 
      tcl = (ta + tmrt + tsk) / 3. 
      count3 = 1 
      enbal2 = 0. 
   20 acl = adu * facl + adu * (fcl - 1.) 
      rclo2 = emcl*sigm *((tcl+273.2)** 4.-(tmrt+273.2)** 4.)*feff 
      htcl = 6.28 * ht * y * di / (rcl * alog(r2/r1) * acl) 
      tsk = 1. / htcl * (hc * (tcl - ta) + rclo2) + tcl 
C RADIATION 
      aeff = adu * feff 
      rbare = aeff * (1.-facl) * emsk * sigm * 
     + ((tmrt + 273.2) ** 4. - (tsk + 273.2) ** 4.) 
      rclo = feff * acl * emcl * sigm * 
     + ((tmrt + 273.2) ** 4. - (tcl + 273.2) ** 4.) 
      rsum = rbare + rclo 
C CONVECT
      cbare = hc * (ta - tsk) * adu * (1. - facl) 
      cclo = hc * (ta - tcl ) * acl 
      csum = cbare + cclo 
C CORE
      c(0) = h + ere 
      c(1) = adu * rob * cb 
      c(2) = 18. - 0.5 * tsk 
      c(3) = 5.28 * adu * c(2) 
      c(4) = 0.0208 * c(1) 
      c(5) = 0.76075 * c(1) 
      c(6) = c(3) - c(5) - tsk * c(4) 
      c(7) = - c(0) * c(2) - tsk * c(3) + tsk * c(5) 
      c(8) = c(6) * c(6) - 4. * c(4) * c(7) 
      c(9) = 5.28 * adu - c(5) - c(4) * tsk 
      c(10) = c(9) * c(9) - 4. * c(4) * 
     + (c(5) * tsk - c(0) - 5.28 * adu * tsk) 
C 
      if (tsk.eq.36.) tsk=36.01 
      tcore(7) = c(0) / (5.28 * adu + c(1) * 6.3 / 3600.) + tsk 
      tcore(3) = c(0) / (5.28 * adu + (c(1) * 6.3 / 3600.) / 
     + (1 + 0.5 * (34. -tsk))) + tsk 
      if (c(10) .lt. 0.) goto 22 
      tcore(6) = (- c(9) - c(10) ** 0.5) / (2. * c(4)) 
      tcore(1) = (- c(9) + c(10) ** 0.5) / (2. * c(4)) 
   22 if (c(8) .lt. 0.) goto 24 
      tcore(2) = (- c(6) + abs(c(8)) ** 0.5) / (2. * c(4)) 
      tcore(5) = (- c(6) - abs(c(8)) ** 0.5) / (2. * c(4)) 
   24 tcore(4) = c(0) / (5.28 * adu + c(1) * 1. / 40.) + tsk 
C TRANSPARENCE
      tbody = 0.1 * tsk + 0.9 * tcore (j) 
      swm = 304.94 * (tbody - 36.6) * adu / 3600000. 
      vpts = 6.11 * 10. ** (7.45 * tsk / (235. + tsk)) 
      if (tbody .le. 36.6) swm = 0. 
      swf = 0.7 * swm 
      if(sex .eq. 1) sw = swm 
      if(sex .eq. 2) sw = swf 
      eswphy = - sw * evap 
      he = 0.633 * hc / (p * cair) 
      fec = 1. / (1. + 0.92 * hc * rcl) 
      eswpot = he * (vpa - vpts) * adu * evap * fec 
      wetsk = eswphy / eswpot 
      if (wetsk .gt. 1.) wetsk = 1. 
      eswdif = eswphy - eswpot 
      if (eswdif .le. 0.) esw = eswpot 
      if (eswdif .gt. 0.) esw = eswphy 
      if (esw .gt. 0.) esw = 0. 
C DIFFERENCE
      rdsk = 0.79 * 10. ** 7. 
      rdcl = 0. 
      ed = evap / (rdsk + rdcl) * adu * (1 - wetsk) * (vpa-vpts) 
C VB 
      vb1 = 34. - tsk 
      vb2 = tcore(j) - 36.6 
      if (vb2 .lt.0.) vb2 = 0. 
      if (vb1 .lt.0.) vb1 = 0. 
      vb = (6.3 + 75. * (vb2)) / (1. + 0.5 * vb1) 
C BALANCE
      enbal = h + ed + ere + esw + csum + rsum + food 
C COVER
      if (count1 .eq.0) xx = 1. 
      if (count1 .eq.1) xx = 0.1 
      if (count1 .eq.2) xx = 0.01 
      if (count1 .eq.3) xx = 0.001 
      if (enbal .gt. 0.) tcl = tcl + xx 
      if (enbal .lt. 0.) tcl = tcl - xx 
      if ((enbal .le. 0.) .and. (enbal2 .gt. 0.)) goto 30 
      if ((enbal .ge. 0.) .and. (enbal2 .lt. 0.)) goto 30 
      enbal2 = enbal 
      count3 = count3 + 1 
C 
      if (count3 .gt. 200) goto 30 
      goto 20 
   30 if ((count1 .eq.0.).or.(count1.eq.1.).or.(count1.eq.2.)) then 
         count1 = count1 + 1. 
         enbal2 = 0. 
         goto 20 
      end if 
C 
      if (count1 .eq. 3.) then 
C 
         if ((j .eq. 2) .or. (j .eq. 5)) goto 40 
         if ((j .eq. 6) .or. (j .eq. 1)) goto 50 
         if (j .eq. 3) goto 60 
         if (j .eq. 7) goto 70 
         if (j .eq. 4) goto 80 
      end if 
   40 if (c(8) .lt. 0.) goto 90 
      if ((tcore(j) .ge. 36.6) .and. (tsk .le. 34.050)) goto 80 
      goto 90 
   50 if (c(10) .lt. 0. ) goto 90 
      if ((tcore(j) .ge. 36.6) .and. (tsk .gt. 33.850)) goto 80 
      goto 90 
   60 if ((tcore(j) .lt. 36.6) .and. (tsk .le. 34.000)) goto 80 
      goto 90 
   70 if ((tcore(j) .lt. 36.6) .and. (tsk .gt. 34.000)) goto 80 
      goto 90 
   80 if ((j .ne. 4) .and. (vb .ge. 91.)) goto 90 
      if ((j. eq. 4) .and. (vb .lt. 89.)) goto 90 
      if (vb .gt. 90.) vb = 90. 
C LOSSES
      ws = sw * 3600. * 1000. 
      if (ws .gt.2000.) ws = 2000. 
      wd = ed / evap * 3600. * (-1000.) 
      wr = erel / evap * 3600. * (-1000.) 
      wsum = ws + wr + wd 
      goto 100 
   90 continue 
  100 return 
      end 

这是C#尝试复制上部fortran子程序:

using System;

public static class GlobalMembers_TEMP
{

//C PROGRAM TEMP
// --------------------------------------------
    public static void TEMP(acl, adu, aeff, c, cair, cb, cbare, cclo, count1, csum, di, ed , emcl , emsk , enbal , enbal2 , ere , erel , esw , eswdif , eswphy , eswpot , evap , facl , fcl , fec , feff , food , h , hc , he , ht , htcl , icl , j , mbody , p , po , r1 , r2 , rbare , rcl , rclo , rclo2 , rdcl , rdsk , rob , rsum , sex , sigm , sw , swf , swm , ta , tbody , tcl, tcore , tmrt , tsk , v , vb , vb1 , vb2 , vpa , vpts , wetsk , wd , wr , ws , wsum , xx)
    {
        float acl;
        float adu;
        float aeff;
        float[] c = new float[11];  // ???
        float cair;
        float cb;
        float cbare;
        float cclo;
        float csum;
        float di;
        float ed;
        float emcl;
        float emsk;
        float enbal;
        float enbal2;
        float ere;
        float erel;
        float esw;
        float eswdif;
        float eswphy;
        float eswpot;
        float evap;
        float facl;
        float fcl;
        float fec;
        float feff;
        float food;
        float h;
        float hc;
        float he;
        float ht;
        float htcl;
        float icl;
        float mbody;
        float p;
        float po;
        float r1;
        float r2;
        float rbare;
        float rcl;
        float rclo;
        float rclo2;
        float rdcl;
        float rdsk;
        float rob;
        float rsum;
        float sigm;
        float sw;
        float swf;
        float swm;
        float ta;
        float tbody;
        float tcl;
        float[] tcore = new float[7];   // ???
        float tmrt;
        float tsk;
        float v;
        float vb;
        float vb1;
        float vb2;
        float vpa;
        float vpts;
        float wetsk;
        float wd;
        float wr;
        float ws;
        float wsum;
        float xx;
        int count1;
        int count3;
        int j;
        int sex;
        wetsk = 0.0;
        adu = 0.203 * mbody * *0.425 * ht * *0.725;
        hc = 2.67 + (6.5 * v * *0.67);
        hc = hc * (p / po) * *0.55;
        feff = 0.725;
        //C rcl = icl / 6.45
        facl = (-2.36 + 173.51 * icl - 100.76 * icl * icl + 19.28 * (icl * *3.0)) / 100.0;
        //C
        if (facl > 1.0)
        {
            facl = 1.0;
        }
        rcl = (icl / 6.45) / facl;
        if (icl >= 2.0)
        {
            y = 1.0;
        }
        if ((icl > 0.6)) && ((icl < 2.0)) 
        {
            y = (ht - 0.2) / ht;
        }
        if ((icl <= 0.6)) && ((icl > 0.3)) 
        {
            y = 0.5;
        }
        if ((icl <= 0.3)) && ((icl > 0.0)) 
        {
            y = 0.1;
        }
        r2 = adu * (fcl - 1.0 + facl) / (2.0 * 3.14 * ht * y);
        r1 = facl * adu / (2.0 * 3.14 * ht * y);
        di = r2 - r1;
        //C TEMPERATURE
        for (90 j = 1, 7)
        {
            tsk = 34.0;
            count1 = 0;
            tcl = (ta + tmrt + tsk) / 3.0;
            count3 = 1;
            enbal2 = 0.0;
    g20:
            acl = adu * facl + adu * (fcl - 1.0);
            rclo2 = emcl * sigm * ((tcl + 273.2) * *4.0 - (tmrt + 273.2) * *4.0) * feff;
            htcl = 6.28 * ht * y * di / (rcl * alog(r2 / r1) * acl);
            tsk = 1.0 / htcl * (hc * (tcl - ta) + rclo2) + tcl;
            //C RADIATION
            aeff = adu * feff;
            rbare = aeff * (1.0 - facl) * emsk * sigm * ((tmrt + 273.2) * *4.0 - (tsk + 273.2) * *4.0);
            rclo = feff * acl * emcl * sigm * ((tmrt + 273.2) * *4.0 - (tcl + 273.2) * *4.0);
            rsum = rbare + rclo;
            //C CONVECT
            cbare = hc * (ta - tsk) * adu * (1.0 - facl);
            cclo = hc * (ta - tcl) * acl;
            csum = cbare + cclo;
            //C CORE
            c[0] = h + ere;
            c[1] = adu * rob * cb;
            c[2] = 18.0 - 0.5 * tsk;
            c[3] = 5.28 * adu * c[2];
            c[4] = 0.0208 * c[1];
            c[5] = 0.76075 * c[1];
            c[6] = c[3] - c[5] - tsk * c[4];
            c[7] = -c[0] * c[2] - tsk * c[3] + tsk * c[5];
            c[8] = c[6] * c[6] - 4.0 * c[4] * c[7];
            c[9] = 5.28 * adu - c[5] - c[4] * tsk;
            c[10] = c[9] * c[9] - 4.0 * c[4] * (c[5] * tsk - c[0] - 5.28 * adu * tsk);
            //C
            if (tsk == 36.0)
            {
                tsk = 36.01;
            }
            tcore[7] = c[0] / (5.28 * adu + c[1] * 6.3 / 3600.0) + tsk;
            tcore[3] = c[0] / (5.28 * adu + (c[1] * 6.3 / 3600.0) / (1 + 0.5 * (34.0 - tsk))) + tsk;
            if (c[10] < 0.0)
            {
                goto g22;
            }
            tcore[6] = (-c[9] - c[10] * *0.5) / (2.0 * c[4]);
            tcore[1] = (-c[9] + c[10] * *0.5) / (2.0 * c[4]);
    g22:
            if (c[8] < 0.0)
            {
                goto g24;
            }
            tcore[2] = (-c[6] + Math.Abs(c[8]) * *0.5) / (2.0 * c[4]);
            tcore[5] = (-c[6] - Math.Abs(c[8]) * *0.5) / (2.0 * c[4]);
    g24:
            tcore[4] = c[0] / (5.28 * adu + c[1] * 1.0 / 40.0) + tsk;
            //C TRANSPARENCE
            tbody = 0.1 * tsk + 0.9 * tcore[j];
            swm = 304.94 * (tbody - 36.6) * adu / 3600000.0;
            vpts = 6.11 * 10.0 * *(7.45 * tsk / (235.0 + tsk));
            if (tbody <= 36.6)
            {
                swm = 0.0;
            }
            swf = 0.7 * swm;
            if (sex == 1)
            {
                sw = swm;
            }
            if (sex == 2)
            {
                sw = swf;
            }
            eswphy = -sw * evap;
            he = 0.633 * hc / (p * cair);
            fec = 1.0 / (1.0 + 0.92 * hc * rcl);
            eswpot = he * (vpa - vpts) * adu * evap * fec;
            wetsk = eswphy / eswpot;
            if (wetsk > 1.0)
            {
                wetsk = 1.0;
            }
            eswdif = eswphy - eswpot;
            if (eswdif <= 0.0)
            {
                esw = eswpot;
            }
            if (eswdif > 0.0)
            {
                esw = eswphy;
            }
            if (esw > 0.0)
            {
                esw = 0.0;
            }
            //C DIFFERENCE
            rdsk = 0.79 * 10.0 * *7.0;
            rdcl = 0.0;
            ed = evap / (rdsk + rdcl) * adu * (1 - wetsk) * (vpa - vpts);
            //C VB
            vb1 = 34.0 - tsk;
            vb2 = tcore[j] - 36.6;
            if (vb2 < 0.0)
            {
                vb2 = 0.0;
            }
            if (vb1 < 0.0)
            {
                vb1 = 0.0;
            }
            vb = (6.3 + 75.0 * (vb2)) / (1.0 + 0.5 * vb1);
            //C BALANCE
            enbal = h + ed + ere + esw + csum + rsum + food;
            //C COVER
            if (count1 == 0)
            {
                xx = 1.0;
            }
            if (count1 == 1)
            {
                xx = 0.1;
            }
            if (count1 == 2)
            {
                xx = 0.01;
            }
            if (count1 == 3)
            {
                xx = 0.001;
            }
            if (enbal > 0.0)
            {
                tcl = tcl + xx;
            }
            if (enbal < 0.0)
            {
                tcl = tcl - xx;
            }
            if ((enbal <= 0.0)) && ((enbal2 > 0.0)) 
            {
                goto g30;
            }
            if ((enbal >= 0.0)) && ((enbal2 < 0.0)) 
            {
                goto g30;
            }
            enbal2 = enbal;
            count3 = count3 + 1;
            //C
            if (count3 > 200)
            {
                goto g30;
            }
            goto g20;
    g30:
            if ((count1 == 0.0))
            {
                || ((count1 == 1.0)) || ((count1 == 2.0))
                {
                count1 = count1 + 1.0;
                enbal2 = 0.0;
                goto g20;
                }
            }
            //C
            if (count1 == 3.0)
            {
                //C
                if ((j == 2))
                {
                    || ((j == 5)) goto g40;
                }
                if ((j == 6))
                {
                    || ((j == 1)) goto g50;
                }
                if (j == 3)
                {
                    goto g60;
                }
                if (j == 7)
                {
                    goto g70;
                }
                if (j == 4)
                {
                    goto g80;
                }
            }
    g40:
            if (c[8] < 0.0)
            {
                goto g90;
            }
            if ((tcore[j] >= 36.6)) && ((tsk <= 34.050))
            {
                goto g80;
            }
            goto g90;
    g50:
            if (c[10] < 0.0)
            {
                goto g90;
            }
            if ((tcore[j] >= 36.6)) && ((tsk > 33.850))
            {
                goto g80;
            }
            goto g90;
    g60:
            if ((tcore[j] < 36.6)) && ((tsk <= 34.000))
            {
                goto g80;
            }
            goto g90;
    g70:
            if ((tcore[j] < 36.6)) && ((tsk > 34.000))
            {
                goto g80;   
            }
            goto g90;
    g80:
            if ((j != 4)) && ((vb >= 91.0)) 
            {
                goto g90;
            }
            if ((j.eq.4)) && ((vb < 89.0))
            {
                 goto g90;
            }
            if (vb > 90.0)
            {
                vb = 90.0;
            }
            //C LOSSES
            ws = sw * 3600.0 * 1000.0;
            if (ws > 2000.0)
            {
                ws = 2000.0;
            }
            wd = ed / evap * 3600.0 * (-1000.0);
            wr = erel / evap * 3600.0 * (-1000.0);
            wsum = ws + wr + wd;
            goto g100;

        }
    g100:
        return;
    }
}

2 个答案:

答案 0 :(得分:2)

您可以尝试将此代码转换为状态机,其中每个状态代表循环内的单个goto。

为此,您需要将您的方法转换为一个类,它包含所有参数和变量作为类字段,并且有一个构造函数初始化相应的字段,并(可选)运行“方法”。

我不会转换您的方法,因为它太大了作为一个例子,但我会给你以下内容:

原始未转换的方法:

public static void Do(Int32 param1, Int32 param2)
{            
    Int32 loopI;
    Int32 outBefore, 
        outAfter,
        outGoto1 = 0,
        outGoto2 = 0;
    Int32[] outValues = new Int32[7];

    Console.WriteLine("METHOD:");

    Console.WriteLine("DoBeforeLoop");
    outBefore = param1 + param2;

    Boolean wasInGoto2 = false;

    for (loopI = 0; loopI < 7; loopI++)
    {
        Console.WriteLine("Iteration {0}", loopI);

        Console.WriteLine("FortranLoopMethodState.LoopCycleStart");
        outValues[loopI] = loopI;

    goto1:
        Console.WriteLine("FortranLoopMethodState.Goto1");
        outGoto1 = loopI + param1;

        if (wasInGoto2)
        {
            wasInGoto2 = false;
            goto end;
        }

        wasInGoto2 = true;
        Console.WriteLine("FortranLoopMethodState.Goto2");
        outGoto2 = loopI + param2;
        goto goto1;
    end:
        DoNothing(); // We don't use break, do we?
    }

    Console.WriteLine("DoAfterLoop");
    outAfter = param1 - param2;

    Console.WriteLine(outGoto1);
    Console.WriteLine(outGoto2);
}

转换方法:

public class ExecuteFortranMethod
{
    private enum FortranLoopMethodState
    {
        LoopCycleStart,
        Goto1,
        Goto2,
        LoopCycleEnded
    }

    #region Params

    private Int32 param1;
    private Int32 param2;

    #endregion


    #region Variables

    public Int32 loopI;
    public Int32 outBefore, 
        outAfter,
        outGoto1,
        outGoto2;
    public Int32[] outValues = new Int32[7];

    #endregion


    #region Constructors

    public ExecuteFortranMethod(Int32 param1, Int32 param2)
    {
        this.param1 = param1;
        this.param2 = param2;

        this.Invoke();
    }

    #endregion


    #region Methods

    private void Invoke()
    {
        Console.WriteLine("STATE MACHINE CLASS:");

        this.DoBeforeLoop();

        for (this.loopI = 0; this.loopI < 7; this.loopI++)
        {
            Console.WriteLine("Iteration {0}", this.loopI);

            var state = FortranLoopMethodState.LoopCycleStart;
            do
            {
                state = DoLoop(state);
            }
            while (state != FortranLoopMethodState.LoopCycleEnded);
        }

        this.DoAfterLoop();
    }

    #endregion


    #region "Method" body methods

    private void DoBeforeLoop()
    {
        Console.WriteLine("DoBeforeLoop");
        this.outBefore = this.param1 + this.param2;
    }

    private void DoAfterLoop()
    {
        Console.WriteLine("DoAfterLoop");
        this.outAfter = this.param1 - this.param2;
    }

    Boolean wasInGoto2;

    private FortranLoopMethodState DoLoop(FortranLoopMethodState state)
    {
        switch (state)
        {
            case FortranLoopMethodState.LoopCycleStart:
                {
                    Console.WriteLine("FortranLoopMethodState.LoopCycleStart");
                    this.outValues[this.loopI] = this.loopI;
                    return FortranLoopMethodState.Goto1;
                }
            case FortranLoopMethodState.Goto1:
                {
                    Console.WriteLine("FortranLoopMethodState.Goto1");
                    this.outGoto1 = this.loopI + this.param1;

                    if (this.wasInGoto2)
                    {
                        this.wasInGoto2 = false;
                        return FortranLoopMethodState.LoopCycleEnded;
                    }
                    return FortranLoopMethodState.Goto2;
                }
            case FortranLoopMethodState.Goto2:
                {
                    this.wasInGoto2 = true;
                    Console.WriteLine("FortranLoopMethodState.Goto2");
                    this.outGoto2 = this.loopI + this.param2;
                    return FortranLoopMethodState.Goto1;
                }
            default:
                throw new InvalidOperationException("The state is invalid");
        }
    }

    #endregion
}   

Program.cs的

Do(10, 20);
Console.WriteLine();

var result = new ExecuteFortranMethod(10, 20);

Console.WriteLine(result.outGoto1);
Console.WriteLine(result.outGoto2);

Console.WriteLine("Press any key");
Console.ReadKey(true);    

如您所见,输出是等效的。我不会准确描述如何转移实际方法,因为它是一个繁琐(但不是不真实)的任务,没有真正的快捷方式,当你阅读这个小小的例子时,大多数想法都会清楚。

PS1:虽然没有真正的缺点(除了编写一些可以为给定代码生成此类状态机类的小工具之外),您可以稍微简化手动作业regular expressions搜索和替换(Ctrl + F)。例如,将模式goto(\d+)替换为case State.Goto$1 {将替换所有带有switch case stubs的gotos。

P.S.2:如果有太多的开关案例(gotos),您可能希望用一些Dictionary lookup替换开关。

PS3: 正如许多人已经指出的那样,我仍然建议您尝试了解原始代码流并从头开始重写。 < / p>

答案 1 :(得分:1)

循环中的goto意味着两件事:

  • 停止循环的当前执行(这就像使用继续)
  • 跳过goto标签之前的所有内容(就像使用if)

理论上你可以使用一个大的switch语句,而不是在每种情况下使用一个大的switch语句(通过模式),​​而不是执行goto,你可以只设置开关值(创建一个变量)到正确的位置,而不是if语句。然后打电话给继续。

但是这将是相同的逻辑并导致使用gotos时遇到的相同问题。对于没有编写代码的人来说,这是不可理解的,可调试的,可维护的。 3-4个月后对同一个人来说甚至很难。

作为第一步,您应该尝试获取每个块并确定它究竟是什么,如果可能的话,将其提取到具有良好名称的方法/函数。

当你完成了你希望有一个巨大的goto混乱与其中的一些函数调用。尽量减少if语句的混乱。 g70看起来像是一个可能的候选者,因为它有条件地执行g80的东西或跳过它并继续在g90,但是没有仔细查看它。

一旦你达到那个级别,你也可以为每个goto标签制作执行图,一行(可能在电子表格中),然后记下哪些函数被调用,直到它到达另一个goto。

良好重构的基础是对问题的理解,所以也许采访编写pascal代码的人来解释它的作用可以帮到你很多。

一旦完成代码并确实做了什么,看看代码中的内容会很有趣!