Autor Beitrag
galagher
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2562
Erhaltene Danke: 46

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Di 19.05.09 17:35 
Hallo!

Ich bin dabei, einen Befehlsinterpreter wie COMMAND.COM (nur besser :wink: ) zu schreiben, und nun hänge ich beim goto.
Das Prinzip ist einfach: Ich lade die abzuarbeitende Datei in eine TStringList und gehe Zeile für Zeile durch:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
echo 1  //es soll 1 ausgegeben werden

goto END  //überspringe alle weiteren "echo"-Befehle ...

echo 2
echo 3

:END  //... und gehe da hin
echo end  //es soll end ausgegegben werden

Das Ganze läuft in einer for-Schleife. Daher ist es einfach, zeilenweise zu arbeiten, aber wie stellt man den for-Zähler höher? Wie könnte man das machen?

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 19.05.09 17:40 
Den Schleifenzähler verändern ist nicht möglich. Und dein Konzept mit Goto sieht auch sehr sehr unübersichtlich und vermutlich unnötig langsam aus.

Was du machen kannst ist mit Continue zum nächsten Durchlauf der Schleife zu gehen, also den Rest des aktuellen Durchlaufs zu überspringen.
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2562
Erhaltene Danke: 46

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Di 19.05.09 17:53 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Den Schleifenzähler verändern ist nicht möglich.
Ich weiss. Das ist es ja - man braucht irgendwie einen zweiten Zähler...

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Und dein Konzept mit Goto sieht auch sehr sehr unübersichtlich und vermutlich unnötig langsam aus.
In Stapeldateien gibt es aber nun mal goto, und - na klar ist das unübersichtlich! Und was langsam betrifft - bei meinetwegen 20 Zeilen Stapeldatei-Code ist was wohl egal! Abgesehen davon, interpretiert mein Programm sowieso jeden Befehl, und interpretierter Code ist immer langsam(er)!

Ich meine das so:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
  {Die Liste wcdList zeilenweise abarbeiten}
  for i := 0 to wcdList.Count-1 do
  begin
  //if GetWord(LowerCase(wcdList[i]), 1) = 'goto' then
  //ja - was hier tun? Genau das ist ja meine Frage!
   
   try
    if not (wcdList[i] = ''then  //Leerzeilen ignorieren
    begin
     if not (wcdList[i][1] = ';'and not  {Anmerkungen und ...}
      (GetWord(LowerCase(wcdList[i]), 1) = 'rem'and not
      (wcdList[iwcdline][1] = ':'then    {... Kennungen (für goto) nicht ausgeben,}
       RxRichEdit1.Lines.Add(wcdList[i]);  {alle anderen Einträge schon!}

     if not (wcdList[i][1] = ':'then
      CommandExecute(wcdList[i]);  {Befehl mit Prozedur CommandExecute ausführen}
    end;  {end von "if not (wcdList[i] = '') then"}

   except
    ErrorText(sGeneralError);
    break;
   end;
  end;


user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Was du machen kannst ist mit Continue zum nächsten Durchlauf der Schleife zu gehen, also den Rest des aktuellen Durchlaufs zu überspringen.
Habe continue bisher nicht mal gekannt...

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 19.05.09 17:57 
user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
In Stapeldateien gibt es aber nun mal goto
:oops:
Ich hatte das goto als dein Vorhaben zur Umsetzung in Delphi verstanden. Dass es in Batchdateien benutzt wird, ist klar. Tut mir leid.

Was das Problem betrifft:
Wie wäre es mit einer while-Schleife? ;-)

Da kannst du den Schleifenzähler beliebig verändern, wobei das dann auch kein Zähler, sondern ein Zeiger auf die aktuelle Zeile wäre. Und genau das brauchst du ja.
Und sobald du über die letzte Zeile hinaus bist, bricht die Schleife ab.
Dunkel
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 682

Mac OS X Snow Leopard
Xcode 3.1
BeitragVerfasst: Di 19.05.09 17:59 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Den Schleifenzähler verändern ist nicht möglich.

Nichts ist unmöglich!

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var 
  i: Integer; 
begin
  for i := 1 to 20 do 
    begin
      Inc(Integer(Pointer(@i)^));
      // so nimmt i nur gerade Werte an, da eine Zeile höher mit ein wenig Pointer-Unsinn die Schleifenvariable händisch um 1 erhöht wird, zusätzlich zur automatischen Schleifen-Inkrementierung
    end;


Schön ist das nicht, führt zu nahzu unwartbaren Code, weil nicht auf dem ersten Blick erkennbar ist, was wirklich passiert, und überhaupt und sowieso. Vergesst das am Besten wieder ganz schnell, bloß NIE benutzen!! :?

_________________
Ich streite einsam mich mit dieser Oberflächenwelt
Gutes sei ein löblich Brot von dem ich zehre - bis zum Tod [Das Ich - Im Ich]
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 19.05.09 18:01 
Ja, mit solchen Tricks kommt man auch teilweise an private Properties usw., und mit Assembler in die Schleife eingestreut geht das natürlich auch. :mrgreen:
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Di 19.05.09 18:37 
Welche Programmiersprache brauch denn GOTOs??? Nur Come From ist das Wahre!

Und zu deinem Problem: Befehlsinterpreter sollten nicht mit einer FOR-Schleife arbeiten, sondern mit einem Instruction Pointer, der bei Sprüngen ggf. angepasst wird.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2562
Erhaltene Danke: 46

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Di 19.05.09 18:53 
Meine Lösung sieht nun Folgendes vor: Der unten stehende Code ist die Schleife, die die Datei zeilenweise abarbeitet, aber es gibt auch eine andere Prozedur mit Namen _goto, die die Integer-Variable g ändert. Leider komme ich auch im Delphi-Code nicht ohne goto aus, denn irgendwie muss ich ja erreichen, dass die Schleife erneut mit dem neuen g-Wert beginnt!

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
  g := 0;  {g ist eine global Interger-Variable}

  WCD:

  for i := g to wcdList.Count-1 do
  begin
    if not (wcdList[i] = ''then
    begin
     try
      if not (wcdList[i][1] = ';'and not  {Anmerkungen und ...}
             (GetWord(LowerCase(wcdList[i]), 1) = 'rem'and not
             (wcdList[i][1] = ':'then  {... Kennungen (für goto) nicht ausgeben,}
       RxRichEdit1.Lines.Add(wcdList[i]);  {alle anderen Einträge schon!}

      if not (wcdList[i][1] = ':'then
       CommandExecute(wcdList[i]);

     except
      ErrorText(sGeneralError);
      break;
     end;

     if (GetWord(LowerCase(wcdList[i]), 1) = 'goto'then
      goto WCD;  {dort hat g bereits einen neuen Wert, der in einer Prozedur _goto zugewisen wird}
    end;  {end von "if not (wcdList[i] = '') then"}
  end;  {end von "for i := g to wcdList.Count-1 do"}


ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure _goto(sCmd, sSwitch, sParam: String; iCount: Byte);
var
  i: Integer;
begin
 for i := 0 to wcdList.Count-1 do
 begin
  if ':'+sParam = wcdList[i] then  {sParam ist das Sprungziel}
   begin
    g := i;
    break;
   end;
 end;
end;

... Ja, und richtig gemütlich wird's vermutlich, wenn ich in meinem Programm beim if angelangt bin!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 19.05.09 20:10 
user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
Leider komme ich auch im Delphi-Code nicht ohne goto aus, denn irgendwie muss ich ja erreichen, dass die Schleife erneut mit dem neuen g-Wert beginnt!
Was hast du denn gegen das bereits angesprochene while? :lol:
Eine for-Schleife ist explizit dafür gedacht möglichst effizient den Wertebereich einmal in einer Richtung durchzugehen. Für alles andere ist diese spezielle Schleife nicht geeignet, dafür gibt es while oder repeat.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mi 20.05.09 09:00 
Darf ich Schadensersatz für diese Missbräuchliche Nutzung von goto verlangen???

Um das mal dem Fragesteller zu zeigen, was gemeint ist:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
While not EndOfProgram do
Begin
    Cmd := GetCmdAt(InstrPtr);
    ProcessCommand(Cmd);
end;


That's it ;-)

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2562
Erhaltene Danke: 46

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Mi 20.05.09 19:59 
Ok, danke euch! Mal sehen, wie ich das goto im Delphi-Code wegbekomme!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
ffgorcky
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 573

WIN XP/2000 & 7Prof (Familie:Win95,Win98)

BeitragVerfasst: Mi 20.05.09 20:59 
Also ich denke, wenn Dein Interpreter GOTO liest, dann müsste er doch nur in der Datei (also Deinem Memo, oder wie auch immer Du das zur Bearbeitung lädst) nach einem Punkt - also einer Zeile - suchen, der auf jeden Fall mit Doppelpunkt anfängt und das Wort beinhaltet, welches hinter goto steht und dort dann weiter arbeitet.
Aber einfacher wäre es, wenn Du das GoTo wirklich ganz weglassen könntest - was aber leider nicht immer so wirklich einfach ist.
Yogu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: Mi 20.05.09 21:02 
user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
Welche Programmiersprache brauch denn GOTOs??? Nur Come From ist das Wahre!

Das ist einfach nur genial :rofl: Bau ich sofort in meine Scriptsprache ein!

Die ist übrigens auch gar kein so schlechter Vergleich, schau dir mal den Interpreter dieses Tutorials an. Das Grundprinzip ist dort auch:

Register P zeigt auf den Befehl, der als nächstes interpretiert werden soll. Der Befehl GOTO (dort heißt er JMP) verändert einfach diesen Wert. Um zu wissen, wo sich denn welches Label versteckt, solltest du ganz am Anfang alle Labels in einer Liste bzw. in einem Array sammeln. Dann kannst du ganz einfach diese Liste durchsuchen. Das wäre sicherlich performanter als immer die komplette Datei abzuklappern.
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2562
Erhaltene Danke: 46

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Do 21.05.09 08:44 
user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
Befehlsinterpreter sollten nicht mit einer FOR-Schleife arbeiten, sondern mit einem Instruction Pointer, der bei Sprüngen ggf. angepasst wird.
:?: Wie sieht so etwas denn aus? Ein Beispiel?

user profile iconYogu hat folgendes geschrieben Zum zitierten Posting springen:
Um zu wissen, wo sich denn welches Label versteckt, solltest du ganz am Anfang alle Labels in einer Liste bzw. in einem Array sammeln. Dann kannst du ganz einfach diese Liste durchsuchen. Das wäre sicherlich performanter als immer die komplette Datei abzuklappern.

Mal im Einzelnen: Die Datei ist in einer TStringList, da so zeilenweises Abarbeiten einfach ist - bis auf goto. Dann muss nämlich der Zähler geändert werden, und das erreicht man (zugegebenermassen unelegant), indem man die Liste ab jener Zeile, die das Label enthält, erneut abarbeitet.
Also: es kommt ein goto, das auf ein Sprungziel in der 10. Zeile verweist. Verlasse die Liste und lies sie erneut, diesmal aber nicht ab Zeile 0, sondern ab 9.
ausblenden Delphi-Quelltext
1:
for i := g to List.Count-1 do  //am Anfang ist g 0, ein goto ändert g auf einen dem Sprungziel entspr. Wert					


Ok, man kann das "Delphi-Code-goto" vermeiden, indem man den Code umstrukturiert, das kriege ich sicher hin. Aber mich interessiert, wie man das mit dem Instruction Pointer bewerkstelligt.

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 21.05.09 08:48 
user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
:?: Wie sieht so etwas denn aus? Ein Beispiel?
Hat er doch schon geschrieben. ;-)
Du nimmst eine Integervariable, die dir die aktuelle Zeile angibt und setzt die auf 0. Danach gehst du in einer while-Schleife die Befehle durch und erhöhst die aktuelle Zeile immer um 1. Und bei goto setzt du den Wert auf die entsprechende Zeile, und es geht dort weiter.
Die while-Schleife lässt du laufen, solange die aktuelle Zeile kleiner als die Anzahl der Zeilen ist. Ist die letzte zeile abgearbeitet springt der Zähler eins weiter und ist nicht mehr kleiner, dann bricht die Schleife ab.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Do 21.05.09 12:33 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
:?: Wie sieht so etwas denn aus? Ein Beispiel?
Hat er doch schon geschrieben. ;-)

Wenigstens einer liest meine Posts ...
:flehan: :flehan: :flehan:

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2562
Erhaltene Danke: 46

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Do 21.05.09 19:25 
user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
:?: Wie sieht so etwas denn aus? Ein Beispiel?
Hat er doch schon geschrieben. ;-)

Wenigstens einer liest meine Posts ...
:flehan: :flehan: :flehan:

Ja, hast du bereits geschrieben :oops: - und ich habe es bereits umgesetzt - sieht gleich viel besser aus ohne das plumpe goto im Delphi-Code!

Danke!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!