Countdown - Steuerseqeuenzen



  • He Leute,

    ich bin derzeit dabei ein programm zu schrieben was in regelmßigen abständen eine Aktualisierung von Daten auf den Bildschirm bringt. Damit man erkennt, dass das Programm noch lebt möchte ich ein Countdown einbauen. Mit dem angezeigt wird wie lange es noch bis zur Aktualisierung dauert.
    Dies soll mit Steuer Sequenzen auf einer UNIX Maschine erfolgen. Dabei soll immer nur eine Zeile gelöscht werden und sozusagen neu geschrieben werden. Ein komplettes löschen des Bildschirms ist nicht erwünscht. Daher auch die Wahl auf die Steuer Sequnzen. Ich habe es mal auf das minimalste reduziert um das Problem zu erkennen:

    printf("\033[s"); // Speichern der Cursor Position
    printf("noch %i sekunden",j);
    printf("\033[M"); //Loeschen der Zeile
    printf("\033[u"); // Zurück springen an gespeicherte Postion
    sleep(1);
    j++;
    printf("noch %i sekunden",j);

    Das Problem bei der ausgabe ist nur, dass er das erste Printf völlig ignoriert und einfach drüber springt er gibt nur den letzten printf aus?
    Habt ihr eine Idee woran das liegen könnte?



  • EDIT: Ich glaube, das war Quatsch... 🤡

    Zeig mal mehr Code, du hast ja sogar deine Schleife weggekürzt.



  • Nein das sind Sekunden,
    Ich seh die Sekunde Pause bzw habe ich auch schon mit 2Sekunden probiert.
    An dem Sleep kann es nicht liegen
    eine Ausgabe wie :
    printf("Noch %i Sekunden\n",j);
    sleep(1);
    j++;
    printf("Noch %i Sekunden",j);

    funktioniert mit einem abstand von einer Sekunde. Allerdings erfolgt dann ja die Ausgabe in der nächsten zeile und das möchte ich nicht.

    //Edit:

    printf("\033[s");

    for (j = 10; j <= 0; j--){

    printf("Bis zur naechsten Aktualisierung noch %i sekunden",j);
    printf("\033[M");
    printf("\033[u");
    sleep(1);
    }

    Die Schleife habe ich daher gekürzt, weil ich auf das minimalste gehen wollte um das Problem zu loesen. 10 ist auch nur ein Testwert dieser wird dann noch ersetzt.
    Hierbei bekomme ich gar keine Anzeige, da ja beim letzten Durchlauf die Zeile gelöscht wird und niochts mehr zur Anzeige gebracht wird. Aber auch die "Zwischenanzeigen" werden nicht beachtet.

    //Edit2:

    Problem gelöst, für alle diejenigen die auf ähnliches stossen sollten, ich habe das ganze mit fprintf(stderr,"noch %i sekunden" ,j); gelösst.
    Printf scheint fuer solche Formatierungsgeschichten nicht sonderlich geeignet zu sein.



  • Bist du dir sicher, dass deine Escape-Sequenzen in C gültig sind?

    \033undsoweiter sieht mir nach bash-Ausdrücken aus.

    Anders gesagt: Bedenke, was ein "\0" in C ist - eine binäre Null beendet einen Stringausdruck.



  • Anselm schrieb:

    Bist du dir sicher, dass deine Escape-Sequenzen in C gültig sind?

    Manche Konsolen ersetzen diese Escape-Sequencen z.B. durch Farben, oder eben Reset des Cursors.

    Allerdings vergisst der Thread-Ersteller hier, dass in C mit dem \ Zeichen auch Escape-Sequencen eingeleitet werden. "\0" wird also keinesfalls das \ Zeichen ausgeben, sondern das 0 byte. Richtig wäre also "\\003[M". Dies ist aber keinesfalls portabel! Unter Windows z.B. funktionieren diese Escape-Sequenzen nicht.



  • Das was ich benutze sind auch Escape Sequenzen ich glaube ich habe mich mit Steuersequenzen falsch ausgedrückt.
    Aber ich denke das \033 richtig ist anstelle von \003
    Zumindestens, habe ich dies bei mehreren Sachen schon gesehen und bei mir funktioniert es auch nur so.



  • rodie schrieb:

    Das was ich benutze sind auch Escape Sequenzen ich glaube ich habe mich mit Steuersequenzen falsch ausgedrückt.
    Aber ich denke das \033 richtig ist anstelle von \003
    Zumindestens, habe ich dies bei mehreren Sachen schon gesehen und bei mir funktioniert es auch nur so.

    Es geht darum, dass du mit '\' einen Backslash in den String packst und nicht mit '\0' den String beendest. Richtig wäre also "\\033[s".



  • nein, printf("\033[s" ist korrekt (und genauso gültig wie printf("\x1b[s"), da man ein ESC-Zeichen schreiben will, mit \\033 würde man \033 bekommen (4 Zeichen statt eins).
    D.h. 033 (was 27 bzw. 0x1b entspricht) wird hier "gescaped", printf schreibt einfach den Byte mit diesem numerischen Wert. Ich habe in meinen Bibliotheken

    #define CU_COLOR_NORMAL     "\033[0m"
    #define CU_COLOR_RED        "\033[0;31m"
    #define CU_COLOR_GREEN      "\033[0;32m"
    #define CU_COLOR_YELLOW     "\033[0;33m"
    ...
    

    und kann die Farben einfach so verändern:

    printf(CU_COLOR_RED "das ist rot" CU_COLOR_NORMAL " und ab hier"
     "wieder normal\n");
    

    Siehe:

    int main(void)
    {
        int val = -1; 
    
        printf("\033[0;31mDAS IST ROT");
        printf("\033[0m\n");
    
        printf("\\033[0;31mDAS IST ROT");
        printf("\033[0m\n");
    
        return 0;
    }
    

    Ausgabe:

    DAS IST ROT
    \033[0;31mDAS IST ROT
    

    wobei die erste Zeile wirklich rot ist.

    @rodi: zu deiner Frage in deinem ersten Post: da du "\n" nicht ausgibst, kann es lange dauern, bis printf tatsächlich die Daten in die Konsole ausgibrt. einfach fflush(stdout); nach jedem printf hinzufügen. Ich würde aber dein Countdown so machen (viel einfacher):

    j = 10;
    while(j)
    {
    
      printf("\r\033[Mnoch %i sekunden",j);
      fflush(stdout);
      sleep(1); 
      j--; 
    }
    printf("\r\033[MDie Zeit ist abgelaufen.\n");
    

Anmelden zum Antworten