2016-08-21 4 views
0

Für mein Offline-Signaturverifikationsprojekt verwende ich die Euler-Nummer als topologische Merkmale.Implementierung der GOTO-Anweisung

Ich gehe durch diese link und ich fand einen Pseudo-Code in dort und meine C# -Implementierung ist wie folgt:

public void eulers(bool[][] t) 
{ 
    int w2 = 0; 
    int wc = 0; 
    int eulers_number = 0; 
    int x = 2; 
    int y = 2; 

    while (y <= t.Length) 
    { 
     while (x <= t.Length) 
     { 
      bool p1 = t[x][y]; 
      bool p2 = t[x - 1][y]; 
      bool p3 = t[x][y - 1]; 
      bool p4 = t[x - 1][y - 1]; 
      if (p4 == true) 
      { 
       x++; 
      } 
      else if (p2 == false) 
      { 
      labelA: 
       if (p3 == true) 
       { 
        x = x + 2; 
       } 
       else if (p1 == false) 
       { 
        x++; 
        if (x <= t.Length) 
        { 
         goto labelA; 
         break; 
        } 
       } 
       else 
       { 
        w2++; 
        x++; 
        if (x <= t.Length) 
        { 
         goto labelB; 
         break; 
        } 

       } 
      } 
      else 
      { 
      labelB: 
       if (p3 == true) 
       { 
        wc++; 
        x = x + 2; 
       } 
       else if (p1 == false) 
       { 
        x++; 
        if (x <= t.Length) 
        { 
         goto labelA; 
         break; 
        } 
       } 
       else 
       { 
        x++; 
        if (x <= t.Length) 
        { 
         goto labelB; 
         break; 
        } 
       } 
      } 
     } 
     eulers_number = w2 - wc; 
     MessageBox.Show(eulers_number.ToString()); 
    } 

Beim Kompilieren es sagt labelA und labelB über Umfang sind. Ich weiß, dass es unmöglich ist, in diesem Stil zu verwenden, also habe ich versucht, den Code zu ändern, aber ich bin hier stecken geblieben. Wie kann ich diesen Code arbeiten lassen? Hier

+0

C# wird nicht zulassen, dass Sie nicht verwandte Blöcke eingeben (wie Sie gefunden haben). Warum basiert Ihre Implementierung nicht auf einem anderen Beispiel, das sich nicht auf "goto" -Aussagen stützt? Sicherlich ist der Link, den Sie gefunden haben, nicht der einzige Ort im Internet, an dem jemals eine Beschreibung des relevanten Algorithmus veröffentlicht wurde. Welche anderen Versionen haben Sie angeschaut? –

+0

Ich habe einen Algorithmus gefunden, aber das funktioniert nicht. Dies ist bei weitem der beste Algorithmus, den ich gründete, aber nicht implementieren kann. Ich suche nach anderen Lösungen im Internet, aber das Hauptproblem ist, dass ich nur begrenzte Zeit habe, um mein Projekt abzuschließen. – ascc

+1

Kurze Antwort - GOTO nicht in C# verwenden. Es macht den Code schwierig zu verstehen. Warum versuchen Sie nicht, den Abschnitt unter jedem Label in eine Methode zu extrahieren? Sie müssen die Variablen, die Sie ändern möchten, auf Klassenebene verschieben. –

Antwort

0

ist, was ich glaube, dass eine funktionierende Version von Ihrem Versuch sein, das Papier der Pseudo-Code zu übersetzen:

static int eulers(bool[,] pixel) 
{ 
    int w2 = 0; 
    int wc = 0; 
    int x = 1; 
    int y = 1; 
    int M = pixel.GetLength(0), N = pixel.GetLength(1); 

    while (y < N) 
    { 
     while (x < M) 
     { 
      if (pixel[x - 1, y - 1]) 
      { 
       x++; 
      } 
      else 
      { 
       bool labelA = !pixel[x - 1, y]; 

       while (true) 
       { 
        if (pixel[x, y - 1]) 
        { 
         if (!labelA) 
         { 
          wc++; 
         } 
         x = x + 2; 
        } 
        else if (!pixel[x, y]) 
        { 
         x++; 
         if (x < N) 
         { 
          labelA = true; 
          continue; 
         } 
        } 
        else 
        { 
         if (labelA) 
         { 
          w2++; 
         } 
         x++; 
         if (x < N) 
         { 
          labelA = false; 
          continue; 
         } 
        } 
        break; 
       } 
      } 
     } 

     y++; 
    } 

    return w2 - wc; 
} 

Im Hinblick auf die Bewältigung der goto Aussagen, entfernte ich sie durch einen winzigen Zustandsmaschine machen (mit einem einzelnen Umschaltzustand, dargestellt durch die Variable labelA, und mit einer while-Schleife statt dessen, damit der Ausführungsablauf zum Anfang des Blocks zurückkehren kann. Ein wichtiger Teil dieses Schritts war die Erkenntnis, dass die Codebausteine ​​labelA: und labelB: nahezu identisch waren, mit nur einem Unterschied, ob die Variablen wc und w2 für diese Iteration aktualisiert wurden, was ansonsten nur eine Schleife war.

nun, daß das, der Code in ihm einige anderen kritischen Fehler hatte:

  • Der Pseudocode Pixel von 1 bis M und 1 bis N für die x und y Werte zwischen Koordinatenwerten annimmt, die jeweils und einschließlich. Da C# -Arrays jedoch 0-basiert sind, müssen die Werte x und y entsprechend angepasst werden. Sie müssen bei 1 statt 2 beginnen und dürfen M und N nicht erreichen, sondern sind auf weniger als diese Werte beschränkt.
  • Ihr Code verwendet eine "jagged array". Dies ist nicht von Natur aus falsch, außer dass Sie auch die tatsächliche Grenze der Y-Koordinaten nicht korrekt bestimmt haben, sondern stattdessen den gleichen Wert wie für die X-Koordinaten verwenden (d. H. Sie haben t.Length anstelle von t[x].Length verwendet). Für diesen Typ von Algorithmus sind gezackte Arrays ineffizient und umständlich zu arbeiten, also ging ich voran und änderte es in ein einfaches zweidimensionales Array.
  • In Ihrem Code haben Sie den Wert der vier Pixel für die aktuellen Werte x und y in lokalen Variablen gespeichert. Sie haben diese Werte jedoch nicht aktualisiert, nachdem Sie den Wert x geändert haben. Daher würden nachfolgende Iterationen der goto -implementierten Schleife die falschen Pixelwerte verwenden. Ich entfernte die lokalen Variablen und änderte den Code, um einfach den Pixelwert direkt wiederzugewinnen, wann immer benötigt, unter Verwendung der aktuellen x und y Werte. Tatsächlich hat jedes einzelne Pixel in dieser Version des Codes nur einen Platz im Code, an dem es abgerufen wurde, so dass die lokalen Variablen sowieso nichts hinzugefügt hätten, selbst wenn es korrekt gewesen wäre, die Werte auf diese Weise zu speichern.
  • Sie konnten den Wert y nach dem Verlassen der inneren Schleife nicht erhöhen.

ich auch den Code ein wenig aufgeräumt, überflüssige break Aussagen zu entfernen (Sie können sie nach den goto Aussagen hatten), Ihre bool Vergleiche zu entfernen, anstatt nur mit dem bool Wertausdruck direkt, und das Verfahren zu ändern, um gebe den letzten Wert zurück, anstatt zu versuchen, ihn anzuzeigen (der Aufrufer kann das tun & hellip; mathematische Hilfsfunktionen wie diese sollten nicht auch für die Benutzerinteraktion verantwortlich sein).

Ohne Beispieldaten von Ihnen und erwartete Ausgabe, ich hatte keine Möglichkeit zu bestätigen, dass die Übersetzung korrekt ist. Was ich garantieren kann ist, dass diese Version näher an der korrekten Übersetzung des Papiers ist als Sie begonnen haben, und natürlich ist gültiger, kompilierbarer C# -Code. :)

Verwandte Themen