Zeile einrücken bei der Ausgabe auf der Konsole



  • @manni66
    ok danke für deine Antwort! Ich setzte mich jetzt dran und probiere ein wenig aus! 🙂



  • Du musst herausfinden,
    wie breit deine Konsole ist (Anzahl Zeichen),
    wie viele Zeichen deine ZEilen/Zeitangabe hat,
    wie lang der Text ist, den du ausgeben sollst.

    Etwas rechnen und dann die Ausgabefunktion entsprechend benutzen.

    Nimmst du cout oder printf?



  • @dirkb
    Meine Konsole ist 237 Zeichen breit und für die Datumangabe brauche ich bis zu 34 Zeichen.
    Der Text den ich ausgeben soll, ist immer unterschiedlich lang. Mal passt er auch in die Zeile und mal nicht.
    Für die Ausgabe verwende ich cout .



  • Ich hab hier noch ein Schnipsel was ich mir mal gespeichert habe (habs nicht selbst geschrieben). Das könnte dir zumindest bei Windows helfen:

    #include <Windows.h>
    
    
    void SetWindow(int Width, int Height) {
    
    	_COORD coord;
    	coord.X = Width;
    	coord.Y = Height;
    
    	_SMALL_RECT Rect;
    	Rect.Top = 0;
    	Rect.Left = 0;
    	Rect.Bottom = Height - 1;
    	Rect.Right = Width - 1;
    
    	HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE);      // Get Handle
    	SetConsoleScreenBufferSize(Handle, coord);            // Set Buffer Size
    	SetConsoleWindowInfo(Handle, TRUE, &Rect);            // Set Window Size
    }
    
    
    
    int main() {
    
    	SetWindow(128, 64);
    	return 0;
    }
    


  • @zhavok
    Ich bin mir nicht ganz sicher, wie ich diesen Code benutzen soll...Ich glaub ich hab nicht ganz verstanden wie er funktioniert. Kannst du mir da vielleicht eine kleine Hilfestellung geben?



  • @honeybee
    Du kopierst dir einfach die SetWindow Funktion mit in deinen Code. In deiner main-Funktion rufst du sie dann auf. Du kannst darüber das Fenster der Konsole vergrößern. Das ganze funktioniert über die Windows API. Nun hast du mehr Platz für deinen Text. Das war doch dein Anliegen oder?



  • @zhavok
    Ne nicht ganz. Das Fenster meiner Konsole hat ja schon die maximal Größe und geht über den ganzen Bildschirm. Aber mein Text, den ich ausgebe, ist immer noch zu lang und wird deswegen automatisch abgeschnitten und der Rest wird in der nächsten Zeile ausgegeben. Diese Zeile würde ich gerne einrücken, sodass sie in der selben Höhe anfängt wie der Text in der Zeile davor.



  • Du musst die Länge Deiner Ausgabe für Zeilennummer, Datum und Zahlencode berechnen (addieren).
    Dann ermittelst Du die Gesamtlänge Deiner Zeile: Obige Länge + Länge Deines Strings.
    Wenn diese Gesamtlänge Zeilenlänge überschreitet, gibst Du entsprechend weniger Zeichen von Deinem String aus (substr).
    In der nächsten Zeile gibst Du dann entsprechend der Länge von Zeilennummer, Datum und Zahlencode (siehe erster Satz) Leerzeichen oder '-' oder was auch immer aus.
    Danach dann den Rest Deines Strings (substr).



  • Vielleicht die Zeichen einzeln ausgeben, mitzählen und machst dann einen Zeilenumbruch.
    Die maximale Zeilen- und Spaltenanzahl bekommst Du mit

    GetLargestConsoleWindowSize( hndl ).X;
    GetLargestConsoleWindowSize( hndl ).Y;
    //hndl ist das obige HANDLE
    

    Es gibt auch die Möglichkeit für die aktuelle Zeilen- und Spaltenanzahl, aber ich meine auch, Du solltest das lieber in eine Datei schreiben. Auch eine Text-Datei oder so.



  • @honeybee sagte in Zeile einrücken bei der Ausgabe auf der Konsole:

    Meine Konsole ist 237 Zeichen breit und für die Datumangabe brauche ich bis zu 34 Zeichen.

    Es gibt Modifier für cout, mit denen du eine Mindestlänge oder auch eine Maximallänge festlegen kannst.

    Da gibst du das Datum mit Mindestlänge (35) aus und dann den Text mit Maximallänge (202).
    Ist der Text länger als 202 Zeichen, dann gibst ein Leerzeichen mit Mindestlänge aus und dann maximal 202 Zeichen ab Stelle 202.
    Ist der Resttext länger als 202 Zeichen, dann ab Stelle 404, usw



  • Log-Meldungen auf ne fixe Konsolenbreite zu formatieren finde ich komisch.
    Was ich mal gemacht habe, wo ich sehr glücklich damit war, war mehrzeilige Log-Meldungen (also welche die wirklich Zeilenumbrüche enthalten) so zu formatieren wie hier im Kopfposting beschrieben. Das verbessert IMO sehr die Übersichtlichkeit von Logfiles - hilft beim Überfliegen. Allerdings auch nur wenn man in dem Text-Editor/-Viewer den man verwendet das automatischen Umbrechen von langen Zeilen ausgeschaltet hat.

    Ich würde dir in diesem Fall also empfehlen den Rat von @manni66 zu befolgen:

    Dann frag doch mal nach, was du genau machen sollst.



  • @honeybee sagte in Zeile einrücken bei der Ausgabe auf der Konsole:

    @manni66
    Breiter kann man die Konsole nicht ziehen, die geht schon über das ganze Fenster.

    In dem Fall, sag doch einfach Deinem Betreuer er solle sich einen größeren Bildschirm kaufen:D

    Spaß beiseite, ich würde keine Zeilennummern reinschreiben, weil das jeder ansatzweise taugliche Texteditor anzeigt bzw. anzeigen kann.

    Vielleicht noch eckige Klammern um das Zeug wie Datum etc. und dann finde ich hebt sich der Text in der nächsten Zeile auch besser ab.

    [2017-09-12 1234] "irgendein langer Text"
    [2017-09-12 2345] "nooooooooooooccch
    ein längerer Text"
    [2017-09-12 3456] "irgendein langer Text"

    Wenn das nicht gefällt, wäre die nächste Lösung Notepad++ runterladen und eine User-Defined language anlegen, die das Logfile highlighted. Ist super einfach, habs zum ersten Mal gemacht und geht in 2 Minuten. Ist nicht weniger windows-abhängig als in der Konsole rumfrickeln.

    Wenn das immer noch nicht passt (dann wird aber die Konsolenausgabe auch nicht passen) kann man darüber nachdenken eine HTML Tabelle zu generieren.

    LG



  • Danke für alle eure Antworten! Ich habe es jetzt erstmal so gelöst, wie ich es bei @Belli und @DirkB verstanden habe. Vermutlich werde ich es aber irgendwann nochmal ändern weil das Format ja jetzt abhängig von der Fenstergröße ist.
    Hier meine Lösung (Ich habe versucht es zum Verständnis etwas zu kürzen):

     void testV1::ausgebenderDatei()
    {
    string aktDatum;
    int aktFehlercode;
    string aktText;
    int textSize;
    
    //Schleife zum Durchlaufen von my_file(Array wo meine Daten gespeichert sind)
    for (int i=0; i<1000; i++)
    {
    //Laufvariable linksbündig ausgeben
    cout << setiosflags(ios::left) << setw(4) << i << "  " << resetiosflags(ios::left);
    
    //Methoden um Daten aus der i-ten-stelle von my_file zu bekommen
    aktDatum = getDatum();
    aktFehlercode = getFehlercode();
    aktText = getText();
    
    textSize = aktText.size();
    
    //Ausgabe von Datum & Fehlercode
    cout << Datum << "  ";
    cout.file('0'); //Leerstellen mit 0 füllen
    cout.file(' ');
    
    //bei Ueberschreiten der Zeilenlänge(203 Stellen)
       if(textSize > 203)
         { 
          int AnzahlvonZeilenText = TextSize /202 +1;
          for (int y = 0, y< AnzahlvonZeilenText; y++)
          {
           // String auftrennen sooft wie die Anzahl an benötigten Zeilen in string mit 202 Zeichen
            string s;
            s = aktText.substr(y * 202, 202);
            cout << s;
            
           //bei einem string der kleiner ist als 202 zeichen sind keine Leerzeichen notwendig
            if (s.size() <202)
            {
              break;
            }
           //Leerzeichen um Text einzuruecken
           for (int l = 0; l< 35 ; l++)
           {
             cout << "  ";
           }
          }
    cout << endl;
    }
    //Ausgabe bei kleinen Textzeilen
    else
    {
    cout << aktText << endl;
    }
    }
    }
    


  • @honeybee sagte in Zeile einrücken bei der Ausgabe auf der Konsole:

    //Leerzeichen um Text einzuruecken

    Da reicht ein Leerzeichen mit einer Mindestbreite von 35 (bzw) die aktuelle Länge) Zeichen aus.

    Und die maximale Textlänge (202) gehört zumindest in eine (globale) Konstante.
    (besser wäre die aktuelle Konsolenbreite)

    Und spiel mal mit den Grenzbereichen (201, 202 und 203 lange Zeilen) rum, ob das passt.



  • @dirkb sagte in Zeile einrücken bei der Ausgabe auf der Konsole:

    Da reicht ein Leerzeichen mit einer Mindestbreite von 35 (bzw) die aktuelle Länge) Zeichen aus.

    Gute Idee, da wäre ich gar nicht drauf gekommen!

    @dirkb sagte in Zeile einrücken bei der Ausgabe auf der Konsole:

    (besser wäre die aktuelle Konsolenbreite)

    würdest du die aktuelle Konsolenbreite vorher festlegen? ähnlich wie @Zhavok es vorgeschlagen hat?
    Oder kann man es auch so lösen, dass sich das Format anpasst(also sich die Konstante ändert), nachdem ich das Programm gestartet habe, und dann erst auf den knopf zum maxmieren des Fensters klicke?



  • @honeybee sagte in Zeile einrücken bei der Ausgabe auf der Konsole:

    Oder kann man es auch so lösen, dass sich das Format anpasst(also sich die Konstante ändert), nachdem ich das Programm gestartet habe, und dann erst auf den knopf zum maxmieren des Fensters klicke?

    Klar. Dann ist es aber keine Konstante mehr sondern eine Variable.

    Aber da wäre es sinnvoll, diesen Wert vom Ereignis "Fenstergröße geändert" steuern zu lassen.



  • @dirkb sagte in Zeile einrücken bei der Ausgabe auf der Konsole:

    Aber da wäre es sinnvoll, diesen Wert vom Ereignis "Fenstergröße geändert" steuern zu lassen.

    Ich hab versucht nachzulesen wie man so etwas verwirklichen kann, finde aber nichts sinnvolles. Kannst du noch genauer sagen wie du sowas mache würdest? Oder kennst du ne Seite wo ich das nachlesen kann?



  • Naja, für den Anfang könntest Du einfach vor jeder Ausgabe Deiner Daten die Konsolenbreite in Zeichen auslesen ...



  • @belli
    Danke für deine Hilfe! Es ist noch nicht die perfekte Lösung, weil ich ja nach durchlaufen des Programms die Leerzeichen schon gesetzt habe und wenn ich dann das Fenster maximiere sie einfach mitten im text liegen aber immerhin kann ich jetzt vorher die Größe meines Fensters festlegen.
    Für alle die es interessiert... ich habe jetzt folgende neue Methode in meinem Code eingefügt und anstelle der 202 die ich oben benutzt habe, setze ich jetzt "breite" in meiner Methode zum ausgeben der Datei ein.

     int columns, breite;
    void test::groesseDerKonsole()
    {
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    GetConsoleScreenBufferInfo(GeStdHandle(STD_OUTPUT_HANDLE), &csbi);
    columns = csbi.srWindow.Right - csbi.srWindow.Left + 1; //Spaltenbreite
    breite = columns -35;
    }
    


  • Mhm ... Du könntest natürlich auch der Konsole eine von Dir gewünschte, unveränderliche Größe geben ...