2009-08-26 11 views
37

Chcę, aby pasek postępu dla mojego zastosowania terminala, który działa podobnie jak:Jak zaktualizować wydrukowanej wiadomości w terminalu bez przedruku (Linux)

[XXXXXXX  ] 

która dałaby wizualne wskazanie, ile czasu pozostało jeszcze zanim proces się zakończy.

wiem, że mogę zrobić coś jak drukowanie coraz więcej X, dodając je do łańcucha, a potem po prostu printf, ale to będzie wyglądać:

[XXXXXXX  ] 
[XXXXXXXX  ] 
[XXXXXXXXX  ] 
[XXXXXXXXXX ] 

czy coś takiego (oczywiście można grać z odstępy.) Ale nie jest to wizualnie estetyczne. Czy istnieje sposób aktualizacji wydrukowanego tekstu w terminalu za pomocą nowego tekstu bez ponownego drukowania? To wszystko pod linuxem, C++.

Odpowiedz

40

spróbuj użyć \r zamiast \n podczas drukowania nowej "wersji".

for(int i=0;i<=100;++i) printf("\r[%3d%%]",i); 
printf("\n"); 
+0

działa jak urok, dzięki – ldog

8

Powiedziałbym, że biblioteka taka jak ncurses byłaby używana do takich rzeczy. Curses pomaga przesuwać kursor po ekranie i rysować tekst i tym podobne.

NCurses

+6

Brzmi jak przesada tutaj. –

+1

Tak, prawdopodobnie ... tylko sugestia, jeśli ktoś chce w przyszłości mieć więcej ochoty;) – KFro

+3

Tak ... może być gra w PONG, podczas gdy czekamy na pasek postępu. : D – kjfletch

6

coś takiego:

std::stringstream out; 
for (int i = 0; i< 10; i++) 
{ 
    out << "X"; 
    cout << "\r" << "[" << out.str() << "]"; 
} 

sneaky bit jest znak powrotu karetki „\ r”, które powoduje, że kursor, aby przejść do początku linii, bez przechodzenia do następnego linia.

1

"\ r" spowoduje powrót karetki. Wyobraźmy sobie drukarkę wykonującą powrót karetki bez podawania do wiersza ("\ n"). Spowoduje to przywrócenie punktu zapisu do początku linii ... a następnie ponowne wydrukowanie zaktualizowanego stanu na początku oryginalnej linii.

1

Jest to inny język, ale pomocna może być this question. Zasadniczo, znak escape \ r (carriage Return, w przeciwieństwie do \ n Newline) przenosi cię z powrotem na początek aktualnej drukowanej linii, dzięki czemu możesz zastąpić to, co już wydrukowałeś.

1

Inną opcją jest drukowanie po jednym znaku na raz. Zazwyczaj stdout jest linia buforowane, więc trzeba zadzwonić fflush (stdout) -

for(int i = 0; i < 50; ++i) { 
    putchar('X'); fflush(stdout); 
    /* do some stuff here */ 
} 
putchar('\n'); 

Ale to nie ma piękny kończącej „]”, który wskazuje zakończenie.

3

Inni już wskazali, że można użyć \r, aby powrócić do początku bieżącego wiersza i zastąpić całą linię.

Inną możliwością jest użycie znaku Backspace ("\ b"), aby usunąć kilka spacji i zastąpić tylko te spacje. Może to mieć kilka zalet. Po pierwsze, oczywiście unika się konieczności regeneracji wszystkiego w linii, co czasami może być lekko bolesne (choć jest to dość niezwykłe). Po drugie, można uniknąć problemów z wyświetlaniem danych, które (na przykład) kurczą się podczas pisania - na przykład, jeśli wyświetlasz odliczanie od 100 do 0, z \r musisz być ostrożny nadpisanie całej poprzedniej długości, lub odliczanie będzie od (na przykład) od 100 do 990 (tj. pozostawiając nietknięte poprzednie "0").

Należy jednak pamiętać, że podczas gdy back-space w linii zwykle działa, backspace na początku linii może lub nie może przesunąć pozycji kursora/zapisu z powrotem do poprzedniej linii. W większości praktycznych celów możesz poruszać się tylko w obrębie jednej linii.

Powiązane problemy