Wie am besten in die Konsole Zeichen ausgeben?

Für Fragen von Einsteigern und Programmieranfängern...
Nixsager
Beiträge: 168
Registriert: Sa 8. Okt 2016, 08:38
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Polska

Wie am besten in die Konsole Zeichen ausgeben?

Beitrag von Nixsager »

Hi

Wie gibt man am besten Zeichen in der Konsole aus?
Wenn man über den rechten Rand schreibt, wird die Ausgabe am Anfang der nächsten Zeile fortgeführt.
Der Quellcode von Free Vision ist mir zu hoch, ich habe nur was von MoveBuf mitbekommen.

Zuerst dachte ich daran, die Ausgabe der Zeichen abzubrechen wenn die Zeichenausgabe über den rechten Rand hinaus gehen würde, aber das würde viele Änderungen mit vielen Abfragen am Quellcode bedeuten.

Dann dachte ich daran, meine Unit die für die Textausgabe zu kopieren, und so so anzupassen das in einem Array die Zeichen ausgegeben werden, und erst im Abschluss den Inhalt des Arrays in die Konsole auszugeben.

Wie stellt man so was am besten an?

Gruß vom Nixsager.
Jeder der sagt, ich könnte programmieren, der hat noch weniger Ahnung vom programmieren als ich!!!

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

Re: Wie am besten in die Konsole Zeichen ausgeben?

Beitrag von Warf »

Über zu viele abfragen etc. würde ich mir keine Gedanken machen, dein Prozessor arbeitet im GHZ Bereich, das bedeutet das jeder Kern 1000000000+ Operationen pro Sekunde macht, eine Simple Abfrage sollte nicht mehr als 10 Operationen brauchen, da kannst du dir ausrechnen wie lange dein Prozessor wohl dafür brauchen würde :D
Außerdem braucht eine Abfrage deutlich weniger Zeit als der WriteLn Call, da dieser dein Programm kurzzeitig Suspendiert, das Betriebsystem aufruft, welches sich um die Ausgabe kümmert, und dann dein Programm wieder lädt. Dieser Vorgang, Contextwechsel genannt, braucht so viel mehr zeit als ein paar kleine Abfragen, das diese in der gesamtzeit kaum ins Gewicht fallen, deine Anwendung würde damit nicht signifikant langsamer werden.

Die Idee mit dem Array wäre wohl die Performance beste, da du nur einen Contextwechsel brauchst, aber entsprechend brauchst du natürlich mehr Speicher. Was bei Ram zahlen im GB Bereich allerdings auch Irrelevant ist, tatsächlich gilt in den meisten Fällen die Faustregel, Zeit ist wichtiger als Speicher, denn Speicher ist billig, Zeit nicht. Wichtig dabei wäre nur ein Statisches Array zu nehmen, da dynamische Arrays wiederum den gesamten performance Bonus durch das einsparen der Kontextwechsel relativieren würden.

Und wie schon am Anfang erwähnt, bei Prozessoren im GHz Bereich und Speicher im GB Bereich ist weder der Speicher noch die Performance wirklich ein Kriterium für die meisten Anwendungen. Da kommt es eher auf die Asymptotische Laufzeit an, aber das ist wiederum eine ganz andere Geschichte.

Allerdings verstehe ich nicht so ganz was du tun möchtest und wo dein Problem liegt, Und kann daher keinen wirklichen Ratschlag geben

Nixsager
Beiträge: 168
Registriert: Sa 8. Okt 2016, 08:38
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Polska

Re: Wie am besten in die Konsole Zeichen ausgeben?

Beitrag von Nixsager »

Warf hat geschrieben:dein Prozessor arbeitet im GHZ Bereich
Warf hat geschrieben:Was bei Ram zahlen im GB Bereich allerdings auch Irrelevant ist.

Zwar der Rechner auf dem ich arbeite, aber nicht der Rechner der als Mindestziel gedacht ist. Der Rechner hat so 4,7 MHz und 640 KB RAM.

Warf hat geschrieben:Allerdings verstehe ich nicht so ganz was du tun möchtest und wo dein Problem liegt, Und kann daher keinen wirklichen Ratschlag geben

Er dachte, das hätte ich gut erklärt? :?
Ich bin ja gerade dabei eine MessageBox zu bauen. Und wenn die, breiter als die Zeile ist, oder soweit nach rechts positioniert ist das sie um den Zeilenrand geht, dann wird die Textausgabe am Anfang der nächsten Zeile fortgeführt.

Warf hat geschrieben:Die Idee mit dem Array wäre wohl die Performance beste

Das glaube ich auch. Und so wird der Quellcode nicht komplexer, auch wenn er durch die Zusätzlich Unit größer wieder, da ich eine Unit für die direkte Textausgabe habe und ein für die Textausgabe in dem Array.

Warf hat geschrieben:da du nur einen Contextwechsel brauchst

Das muss ich später wohl noch ein paar Fragen stellen. Hört sich an, als müsste ich mit Zeigern arbeiten. So muss ich im Grunde nicht die Daten kopieren, sondern gebe nur eine neue Adresse der Daten an. Aber das würde nur bei internen arbeiten Sinn machen. Für die Textausgabe müsste ich die Daten trotzdem kopieren. Oder manipuliere am Grafiksystem rum.
Zuletzt geändert von Nixsager am So 30. Okt 2016, 14:21, insgesamt 1-mal geändert.
Jeder der sagt, ich könnte programmieren, der hat noch weniger Ahnung vom programmieren als ich!!!

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

Re: Wie am besten in die Konsole Zeichen ausgeben?

Beitrag von Mathias »

Zwar der Rechner auf dem ich arbeite, aber nicht der Rechner der als Mindestziel gedacht ist. Der Rechner hat so 4,7 MHz und 640 KB RAM.

Ich nehme mal an, es handel sich dabei um einen 8088, welcher im Real-Modus läuft.
Wie gibt man am besten Zeichen in der Konsole aus?
Das heisst hier eigentlich nicht Konsole, sondern einfach Text-Modus.
Bei Konsole denken alle an das Text-Fenster Windows oder Linux.

Wen das so ist, würde ich direkt ins VRAM schreiben, etwas schnellere wirst du nicht finden.
Wie das geht könnte ich dir schon helfen.

Bis du nicht der Turbo-Pascal Programmierer ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Nixsager
Beiträge: 168
Registriert: Sa 8. Okt 2016, 08:38
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Polska

Re: Wie am besten in die Konsole Zeichen ausgeben?

Beitrag von Nixsager »

Mathias hat geschrieben:Ich nehme mal an, es handel sich dabei um einen 8088, welcher im Real-Modus läuft.

Na ja, mein Ziel ist es, das mein Programm bzw. meine Units auch auf so einem System laufen können. Auch wenn keiner mein fertiges Programm jemals wirklich nutzen wird.

Mathias hat geschrieben:Das heisst hier eigentlich nicht Konsole, sondern einfach Text-Modus.
Bei Konsole denken alle an das Text-Fenster Windows oder Linux.

Ich weiß. ;)
Ich habe es einfach mal Konsole genannt, weil das Prinzip ist das Selbe, und das ist hier ein Free Pascal-Forum, und da arbeiten wohl eher welche für die Konsole als für Dos und den Textmodus.

Mathias hat geschrieben:Wen das so ist, würde ich direkt ins VRAM schreiben, etwas schnellere wirst du nicht finden.
Wie das geht könnte ich dir schon helfen.

Das ist relativ einfach mit Mem, MemL und MemW.
Aber dann müsste vorher überprüfen wo der Video-RAM liegt.
Ich nutze dafür in meiner Unit den Interrupt 10h.
Und da taucht auch wieder das Problem mit dem Zeichnen über den Rand auf.

Mathias hat geschrieben:Bis du nicht der Turbo-Pascal Programmierer ?

Ich verweise mal auf meine Signatur. ;)
Ich arbeite mit Turbo Pascal, aber als Programmieren würde ich das nicht bezeichnen. Mich könnte man eher als Scriptkiddie bezeichnen.
Jeder der sagt, ich könnte programmieren, der hat noch weniger Ahnung vom programmieren als ich!!!

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

Re: Wie am besten in die Konsole Zeichen ausgeben?

Beitrag von Mathias »

Und da taucht auch wieder das Problem mit dem Zeichnen über den Rand auf.

Dann mache es doch so, zwei if-Abfragen pro String-Ausgabe.

Code: Alles auswählen

program Project1;
uses
  Crt;
 
const
  satz = 'Ich bin ein sehr langer Satz';
var
  i: integer;
 
  procedure OutTextXY(x, y: integer; s: ShortString);
  var
    l: integer;
  begin
    if x > 80 then begin
      Exit;
    end;
    GotoXY(x, y);
    l := 80 - WhereX + 1;
    if l < byte(s[0]) then begin
      s[0] := char(l);
    end;
    Write(s);
  end;
 
begin
  for i := 1 to 10 do begin
    OutTextXY(i + 60, i * 2, satz);
  end;
  repeat
  until KeyPressed;
end.

Ein Wermuttropfen hat dies aber trotzdem, sobald UTF8 und ähnliche String verwendet, geht dies nicht mehr. Aber zum Glück hat man dieses Problem mit TP nicht.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Jole
Beiträge: 114
Registriert: Fr 4. Jul 2014, 14:39
OS, Lazarus, FPC: Linux
CPU-Target: amd64

Re: Wie am besten in die Konsole Zeichen ausgeben?

Beitrag von Jole »

Mathias hat geschrieben:Wen das so ist, würde ich direkt ins VRAM schreiben, etwas schnellere wirst du nicht finden.
Wie das geht könnte ich dir schon helfen.

TP schreibt mit Write/WriteLn standardmäßig direkt in den VRAM! Um das zu verhindern, muss die variable "DirectVideo", die sich in der Unit CRT befindet, auf False gesetzt werden.

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

Re: Wie am besten in die Konsole Zeichen ausgeben?

Beitrag von Mathias »

TP schreibt mit Write/WriteLn standardmäßig direkt in den VRAM! Um das zu verhindern, muss die variable "DirectVideo", die sich in der Unit CRT befindet, auf False gesetzt werden.
Dies war aber trotzdem niemals so schnell, wie man direkt ins VRAM schrieb. Writeln hat noch recht Overhead.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Nixsager
Beiträge: 168
Registriert: Sa 8. Okt 2016, 08:38
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Polska

Re: Wie am besten in die Konsole Zeichen ausgeben?

Beitrag von Nixsager »

Ihr vergisst, das 'Write' Steuerzeichen interpretiert. Und wenn man ein Zeichen nutzen will, das auch ein Steuerzeichen ist, dann hat man ein Problem.
Denkt an das ♪-Zeichen. Mit Write springt man dann zur nächsten Zeile da da Zeichen den Zeilenvorschub ausführt, aber wenn man es in den Video-RAM schreibt, erhält man einen Notenschlüssel.
Jeder der sagt, ich könnte programmieren, der hat noch weniger Ahnung vom programmieren als ich!!!

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

Re: Wie am besten in die Konsole Zeichen ausgeben?

Beitrag von Mathias »

Ihr vergisst, das 'Write' Steuerzeichen interpretiert. Und wenn man ein Zeichen nutzen will, das auch ein Steuerzeichen ist, dann hat man ein Problem.

Das Problem kannte ich auch, entweder VRAM oder eine int 10 Funktion nehmen,
So nebenbei hatte Write noch eine Problem, versuche mal ein Zeichen ganze rechts unten zu schreiben.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Nixsager
Beiträge: 168
Registriert: Sa 8. Okt 2016, 08:38
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Polska

Re: Wie am besten in die Konsole Zeichen ausgeben?

Beitrag von Nixsager »

Mathias hat geschrieben:So nebenbei hatte Write noch eine Problem, versuche mal ein Zeichen ganze rechts unten zu schreiben.

Wenn du meinen ersten Post nochmals liest, merkt du, da ich da das Problem habe. Nur das das Problem eine andere Ursache hat.

Am einfachsten, scheint es mit einem Array zu sein, und wenn man sich die 8088 Flex-Demo anschaut, ist das auch nicht so schlimm.
Nur das Problem ist, das das Programm immer einem Speicher von der Größe des Arrays braucht. Und wenn dann man noch andere Daten hat, kommt es schnell zu einem Stapelspeicherüberlauf.
Aber so ist es einfacher. anstatt bei Label, Button und sonstige Objekte eine Abfrage einzubauen um zu überprüfen ob das Zeichen über die Zeilenbreiten gehen würde.

So nebenbei, ich hätte nicht gedacht, das ich bei TP so schnell an Grenzen stoßen würde.
Jeder der sagt, ich könnte programmieren, der hat noch weniger Ahnung vom programmieren als ich!!!

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

Re: Wie am besten in die Konsole Zeichen ausgeben?

Beitrag von Mathias »

Ich habe so in der Schnelle einen Speed-Test gemacht, die Differenz ist ziemlich genau das 4-fache.
Als Kompiler cabe ich den Cross8086 verwendet.
Mit Assembler könnte man vielleicht noch mehr rausholen.

Code: Alles auswählen

program Project1;
uses
  SysUtils, Crt;
 
procedure OUTTextXYVRAM(x,y:integer; s:shortstring);
var
  i, ofs:integer;
begin
  ofs := x * 2 + y * 160;
  for i:=0 to Byte(s[0]) -1 do begin
//    Mem[$B800:ofs + i * 2]:=Byte(s[i + 1]);
//    Mem[$B800:ofs + i * 2 + 1]:=$56;
    MemW[$B800:ofs + i * 2]:=Byte(s[i + 1]) + $56 shl 8;
  end;
end;
 
procedure OUTTextXYCrt(x,y:integer; s:shortstring);
var
  i:integer;
begin
  GotoXY(x, y);
  TextAttr := $65;
  Write(s);
end;
 
var
  z1, z2, t:TDateTime;
  i :integer;
 
begin
  t := now;
  for i := 0 to 1000 do begin
    OutTextXYCrt(10, 15, 'Hello World !');
  end;
  z2 := now - t;
 
  t := now;
  for i := 0 to 1000 do begin
    OutTextXYVRAM(10, 15, 'Hello World !');
  end;
  z1 := now - t;
 
  GotoXY(1,1);
  TextAttr := 15;
  Writeln('VRAM: ', z1, '  Crt: ', z2);
 
  Readln;
end.
 
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Jole
Beiträge: 114
Registriert: Fr 4. Jul 2014, 14:39
OS, Lazarus, FPC: Linux
CPU-Target: amd64

Re: Wie am besten in die Konsole Zeichen ausgeben?

Beitrag von Jole »

Mathias hat geschrieben:
TP schreibt mit Write/WriteLn standardmäßig direkt in den VRAM! Um das zu verhindern, muss die variable "DirectVideo", die sich in der Unit CRT befindet, auf False gesetzt werden.
Dies war aber trotzdem niemals so schnell, wie man direkt ins VRAM schrieb. Writeln hat noch recht Overhead.

Das stimmt, WriteLn gibt ja nicht einfach nur Text aus, sondern muss den ggf. erst noch zusammen bauen (Variable u.s.w). Für die normale Textausgabe reicht das alle mal.
Nixsager hat geschrieben:Ihr vergisst, das 'Write' Steuerzeichen interpretiert. Und wenn man ein Zeichen nutzen will, das auch ein Steuerzeichen ist, dann hat man ein Problem.
Denkt an das ♪-Zeichen. Mit Write springt man dann zur nächsten Zeile da da Zeichen den Zeilenvorschub ausführt, aber wenn man es in den Video-RAM schreibt, erhält man einen Notenschlüssel.

Das habe, zu mindest ich, nicht vergessen. Diese tatsache könnte man aber zur Ausgabe nutzen in dem man den Text schon mit Steuerzeichen versieht (CR/LF u.s.w). TP hat so schöne sachen wie "WINDOW", ist die Box gezeichnet, legt man den Ausgabebereich auf das innere der Box fest und braucht sich nicht mehr um das Positionieren des Textes zu kümmern (Fenster zurücksetzen nicht vergessen).
Mathias hat geschrieben:
Ihr vergisst, das 'Write' Steuerzeichen interpretiert. Und wenn man ein Zeichen nutzen will, das auch ein Steuerzeichen ist, dann hat man ein Problem.

Das Problem kannte ich auch, entweder VRAM oder eine int 10 Funktion nehmen,
So nebenbei hatte Write noch eine Problem, versuche mal ein Zeichen ganze rechts unten zu schreiben.

Ich gehe mal nicht davon aus das er seine MessageBox da unten hin bauen will.

Nixsager
Beiträge: 168
Registriert: Sa 8. Okt 2016, 08:38
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Polska

Re: Wie am besten in die Konsole Zeichen ausgeben?

Beitrag von Nixsager »

Jole hat geschrieben:Ich gehe mal nicht davon aus das er seine MessageBox da unten hin bauen will.

Wieso nicht? Wenn die MessageBox so groß wird wie Auflösung Textmodus.

Es geht auch darum um Fenster zu zeichnen. Ihr sieht es ja daran wenn ihr im TUI von FP ein Fenster verschiebt.
Jeder der sagt, ich könnte programmieren, der hat noch weniger Ahnung vom programmieren als ich!!!

Jole
Beiträge: 114
Registriert: Fr 4. Jul 2014, 14:39
OS, Lazarus, FPC: Linux
CPU-Target: amd64

Re: Wie am besten in die Konsole Zeichen ausgeben?

Beitrag von Jole »

Mathias hat geschrieben:Ich habe so in der Schnelle einen Speed-Test gemacht, die Differenz ist ziemlich genau das 4-fache.
Als Kompiler cabe ich den Cross8086 verwendet.
Mit Assembler könnte man vielleicht noch mehr rausholen.
 [/code]

Du vergisst aber das FP nicht mehr direkt in den VRAM schreibt, DirectVideo existiert, soweit ich weiß, nur noch aus Kompatibilitätsgründen. Der gleiche Test mit TP ergibt erst dann eine zeit Differenz wenn DirectVideo auf False gesetzt wird.
Nixsager hat geschrieben:
Jole hat geschrieben:Ich gehe mal nicht davon aus das er seine MessageBox da unten hin bauen will.

Wieso nicht? Wenn die MessageBox so groß wird wie Auflösung Textmodus.

Es geht auch darum um Fenster zu zeichnen. Ihr sieht es ja daran wenn ihr im TUI von FP ein Fenster verschiebt.

Er will doch nur wissen wie er Text in seine MessageBox schreiben kann, ohne das bei einem Zeilenumbruch der Text am linken Fensterrand fortgesetzt wird, sondern links in seiner MessageBox. Dafür bietet sich die Prozedur WINDOW an.

Ich persönlich kämme nie wieder auf die Idee Fenster, MsgBoxen u.ä. mit Write/WriteLn oder eigenen VRAM Prozeduren zu zeichnen. Warum nicht das nutzen was bereits vorhanden ist? Im TP Verzeichnis EXAMPLES\DOCDEMOS befindet sich der gesamte Quellcode für das Turbo Vision 2.0 Tutorial. Das Tutorial dazu kann man sich hier als PDF (Englisch) runter laden.

Antworten