[gelöst]Variable in einem Konsolenprogramm korrigieren

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Seppel
Beiträge: 2
Registriert: Do 26. Okt 2023, 17:25

[gelöst]Variable in einem Konsolenprogramm korrigieren

Beitrag von Seppel »

Liebes Forum,
ich bin seit heute hier neu und versuche folgendes in einem Konsolenprogramm mit der Crt Unit zu programmieren:
Mit write eine Variable auf die Konsole ausgeben, um dann mit den Pfeiltasten und der Backspacetaste die Variable zu korrigieren und sie dann neu einzulesen, also wie bei einem TEdit. Ich krieg aber den Cursor nicht bewegt.

Hier der Beispielcode:

begin
readln(variable);

write(variable); //um mit den Pfeiltasten das falsche Zeichen anzusteuern und es zu löschen.
// Geht aber nicht. Wie programmiert man so was?

...
Danke für Eure Hilfe
Zuletzt geändert von Seppel am Sa 28. Okt 2023, 12:29, insgesamt 1-mal geändert.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1354
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Variable in einem Konsolenprogramm korrigieren

Beitrag von fliegermichl »

Man kann mit ReadKey einen Tastendruck einlesen.
Die Backspacetaste hat dabei den Wert #8. Mit Write(^h) kann man den Cursor eins nach links versetzen.
Hier ein kleines Beispiel:

Code: Alles auswählen

program Project1;
uses crt;
var s : string;
    c : char;
begin
  ReadLn(s);
  Write(s);
  repeat
    c := ReadKey;
    if (c = #8) then
    begin
      Delete(s, Length(s), 1);
      Write(^h, ' ', ^h);
    end else
    if (c <> #13) then
    begin
      s := s + c;
      write(c);
    end;
  until c = #13;
  WriteLn('Am Ende ist ', s);
  ReadLn;
end.

Warf
Beiträge: 1878
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Variable in einem Konsolenprogramm korrigieren

Beitrag von Warf »

Das Problem, wenn du möchtest das sich die Konsole wie ein Edit verhält ist, das sich die Konsole in keiner weise wie ein Edit verählt.
ReadLn liest nicht einfach ein Was auf der Konsole steht, sondern die Konsole ist praktisch nur ein Visualisierungstool für Ein und Ausgabestreams.

ReadLn liest praktisch einfach nur Daten aus einer Eingabe datei ein, und WriteLn Schriebt daten in eine Ausgabedatei. Die Konsole kümmert sich dann darum Nutzereingaben in die Eingabedatei zu schreiben, und alles was vom Programm in die Ausgabedatei geschrieben wird darzustellen.
Es gibt grundsätzlich erst mal keinen wirklichen Zusammenhang zwischen der Eingabe und Ausgabedatei, sowie dem Status der Konsole, das Einlesen ist komplett unabhängig von dem was du vorher ausgegeben hast, oder was auf der Konsole bisher gedruckt wurde.

Das heist, du musst den Status des Konsolenfensters komplett selbst managen. Erschwerend kommt dabei hinzu das Konsolen normalerweise im Buffered Line Input Modus arbeiten, d.h. du bekommst normalerweise nicht mal einzelne Charactere übermittelt, sondern erst sobald die Zeile vollständig getippt wird. D.h. zwar siehst du in der Konsole was du grade tippst, aber dein Programm weis davon nix bis du enter drückst und alles auf einmal an dein Programm gesendet wird.
Dem gegenüber gibt es den Raw Input Modus, hierbei werden alle Tasten direkt und ungefiltert an dein Programm gesendet, aber dafür reagiert die Konsole nicht auf das was du tippst, d.h. der Nutzer sieht nicht was er eintippt (das muss dein Programm manuell anzeigen).

Kompliziert wird das ganze dann wenn du die CRT Unit benutzt, denn die CRT unit schaltet sich selbst, ungefragt, zwischen dein Programm und die Konsole. Sobald CRT in der Uses Klausel steht, liest ReadLn nicht mehr von der Eingabedatei, sondern von CRT, was intern einen eigenen Buffer von der EIngabedatei zieht. Gleichzeitig schaltet CRT die Konsole immer auf RAW modus, Printed eingaben aber selbständig aus um das Aussehen vom Buffered Modus zu simulieren.
Das verändert das Verhalten der Konsole massiv, vor allem im bezug auf Signal handling, und Input buffering und keyboard management. Das macht es mit der CRT Unit erstaunlich schwer komplexe Konsolenprogramme, wie z.B. eine Shell oder TUI anwendungen o.ä. zu schreiben.

Ich hab vor einigen Jahren mal was mit der CRT unit gemacht: https://github.com/Warfley/LazTextForms
Das TTFEdit z.B. ist eine Edit Artige Komponente für TUIs: https://github.com/Warfley/LazTextForms ... ls.pas#L61

Das gesagt, man kommt sehr schnell an die Grenzen der CRT unit, nicht nur Feature mäßig (sehr reduziertes Featureset, z.B. nur 16 Farben oder so), sondern auch Performancemäßig ist die CRT Unit (grade auf Windows) echt miserabel, deshalb hatte ich irgendwann mal eine eigene Bibliothek geschrieben: https://github.com/Warfley/LazTermUtils
Die praktisch die ganzen Probleme die die CRT Unit aufgrund des zwischenschaltens verursacht zu umgehen, bzw. sie nicht zu verstecken (hier im gegensatz zur CRT unit wird die Konsole nur auf Raw gestellt, wenn man explizit Raw auf True setzt, was das Verhalten der Konsole deutlich berechenbarer macht).

Langer Rede kurzer Sinn: Das was du machen willst ist absolut nicht Trivial, und da kannst du beliebig viel Zeit und Energie rein stecken. TUI Anwendungen zu bauen braucht extrem prezises State Management der Konsole, und es gibt relativ wenig hilfestellungen in form von Bibliotheken und co. Da du die Frage hier in Einsteigerfragen gestellt hast, muss ich sagen, das es leider (ich selbst finde TUI anwendungen genial) kein sehr Einsteigerfreundliches Thema ist

Mathias
Beiträge: 5929
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunc)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Variable in einem Konsolenprogramm korrigieren

Beitrag von Mathias »

Mit write eine Variable auf die Konsole ausgeben, um dann mit den Pfeiltasten und der Backspacetaste die Variable zu korrigieren und sie dann neu einzulesen, also wie bei einem TEdit. Ich krieg aber den Cursor nicht bewegt.
Den Cursor kann man mit GotoXY(x,y) beliebig in der Konsole positionieren.

Diese Beispiel ist mal einen Anfang.
Natürlich muss man bei einem Buchstaben "ch" noch in einen String reinpacken.

Code: Alles auswählen

uses
  crt;

var
  ch: char;
  cp: integer;
begin
  gotoxy(10, 10);
  cp := 10;
  repeat
    ch := ReadKey;
    if ch = #0 then begin   // Funktionstaste
      ch := ReadKey;
      case ch of
        #75: begin
          Dec(cp);
        end;
        #77: begin
          Inc(cp);
        end;
      end;
    end else if ch > #31 then begin
      Write(ch);
      Inc(cp);
    end;
    GotoXY(10, 5);
    WriteLn(byte(ch): 5); // Zeigt Taste an
    GotoXY(cp, 10);
  until ch = #27;  // ESC
end.    
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Seppel
Beiträge: 2
Registriert: Do 26. Okt 2023, 17:25

Re: Variable in einem Konsolenprogramm korrigieren

Beitrag von Seppel »

:) Vielen herzlichen Dank Euch allen! Ihr wart mir eine große Hilfe. Jetzt bin in ein ganzes Stück weiter.

Antworten