Ich schreibe ein Konsolenprogramm in C ++, um eine große Datei herunterzuladen. Ich kenne die Dateigröße und starte einen Arbeitsthread zum Herunterladen. Ich möchte eine Fortschrittsanzeige anzeigen, damit es kühler aussieht.
Wie werden verschiedene Zeichenfolgen zu unterschiedlichen Zeiten, aber an derselben Position in cout oder printf angezeigt?
wget
Prozesses ist keine Option?Antworten:
Sie können einen "Wagenrücklauf" (\ r) ohne Zeilenvorschub (\ n) verwenden und hoffen, dass Ihre Konsole das Richtige tut.
quelle
man termios
)#include <termios.h>
, versuche das unter M $ Windows :) Wie auch immer, danke für den Tipp, ich werde das wahrscheinlich unter Linux versuchen.Verwenden Sie bei einer festen Breite Ihrer Ausgabe Folgendes:
float progress = 0.0; while (progress < 1.0) { int barWidth = 70; std::cout << "["; int pos = barWidth * progress; for (int i = 0; i < barWidth; ++i) { if (i < pos) std::cout << "="; else if (i == pos) std::cout << ">"; else std::cout << " "; } std::cout << "] " << int(progress * 100.0) << " %\r"; std::cout.flush(); progress += 0.16; // for demonstration only } std::cout << std::endl;
http://ideone.com/Yg8NKj
[> ] 0 % [===========> ] 15 % [======================> ] 31 % [=================================> ] 47 % [============================================> ] 63 % [========================================================> ] 80 % [===================================================================> ] 96 %
Beachten Sie, dass diese Ausgabe eine Zeile untereinander angezeigt wird , aber in einem Terminalemulator (ich denke auch in der Windows-Befehlszeile) in derselben Zeile gedruckt wird .
Vergessen Sie am Ende nicht, eine neue Zeile zu drucken, bevor Sie weitere Inhalte drucken.
Wenn Sie die Leiste am Ende entfernen möchten, müssen Sie sie mit Leerzeichen überschreiben, um beispielsweise etwas kürzeres zu drucken
"Done."
.Das gleiche kann natürlich auch
printf
in C gemacht werden; Das Anpassen des obigen Codes sollte einfach sein.quelle
Für eine
C
Lösung mit einer einstellbaren Breite des Fortschrittsbalkens können Sie Folgendes verwenden:#define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" #define PBWIDTH 60 void printProgress(double percentage) { int val = (int) (percentage * 100); int lpad = (int) (percentage * PBWIDTH); int rpad = PBWIDTH - lpad; printf("\r%3d%% [%.*s%*s]", val, lpad, PBSTR, rpad, ""); fflush(stdout); }
Es wird ungefähr so ausgegeben:
75% [|||||||||||||||||||||||||||||||||||||||||| ]
quelle
';'
am Ende des ersten sollte es keine geben#define
!Schauen Sie sich boost progress_display an
http://www.boost.org/doc/libs/1_52_0/libs/timer/doc/original_timer.html#Class%20progress_display
Ich denke, es kann das tun, was Sie brauchen, und ich glaube, es ist eine reine Header-Bibliothek, also nichts zu verlinken
quelle
Sie können ein Wagenrücklaufzeichen (
\r
) drucken , um den Ausgabe- "Cursor" zurück zum Anfang der aktuellen Zeile zu bewegen.Schauen Sie sich für einen differenzierteren Ansatz etwas wie ncurses an (eine API für textbasierte Konsolenschnittstellen).
quelle
'\b'
zum Bewegen des Cursors um eine Position nach links.Ich weiß, dass ich diese Frage etwas spät beantworte, aber ich habe eine einfache Klasse erstellt, die genau das tut, was Sie wollen. (Denken Sie daran, dass ich
using namespace std;
vorher geschrieben habe.):class pBar { public: void update(double newProgress) { currentProgress += newProgress; amountOfFiller = (int)((currentProgress / neededProgress)*(double)pBarLength); } void print() { currUpdateVal %= pBarUpdater.length(); cout << "\r" //Bring cursor to start of line << firstPartOfpBar; //Print out first part of pBar for (int a = 0; a < amountOfFiller; a++) { //Print out current progress cout << pBarFiller; } cout << pBarUpdater[currUpdateVal]; for (int b = 0; b < pBarLength - amountOfFiller; b++) { //Print out spaces cout << " "; } cout << lastPartOfpBar //Print out last part of progress bar << " (" << (int)(100*(currentProgress/neededProgress)) << "%)" //This just prints out the percent << flush; currUpdateVal += 1; } std::string firstPartOfpBar = "[", //Change these at will (that is why I made them public) lastPartOfpBar = "]", pBarFiller = "|", pBarUpdater = "/-\\|"; private: int amountOfFiller, pBarLength = 50, //I would recommend NOT changing this currUpdateVal = 0; //Do not change double currentProgress = 0, //Do not change neededProgress = 100; //I would recommend NOT changing this };
Ein Beispiel zur Verwendung:
int main() { //Setup: pBar bar; //Main loop: for (int i = 0; i < 100; i++) { //This can be any loop, but I just made this as an example //Update pBar: bar.update(1); //How much new progress was added (only needed when new progress was added) //Print pBar: bar.print(); //This should be called more frequently than it is in this demo (you'll have to see what looks best for your program) sleep(1); } cout << endl; return 0; }
Hinweis: Ich habe alle Zeichenfolgen der Klassen veröffentlicht, damit das Erscheinungsbild der Leiste leicht geändert werden kann.
quelle
Eine andere Möglichkeit könnte darin bestehen, die "Punkte" oder ein beliebiges Zeichen anzuzeigen. Der folgende Code gibt die Fortschrittsanzeige [Art des Ladens ...] alle 1 Sekunde als Punkte aus.
PS: Ich schlafe hier. Überlegen Sie zweimal, ob es um Leistung geht.
#include<iostream> using namespace std; int main() { int count = 0; cout << "Will load in 10 Sec " << endl << "Loading "; for(count;count < 10; ++count){ cout << ". " ; fflush(stdout); sleep(1); } cout << endl << "Done" <<endl; return 0; }
quelle
Hier ist eine einfache, die ich gemacht habe:
#include <iostream> #include <windows.h> using namespace std; int barl = 20; int main() { system("color 0e"); cout << "["; for (int i = 0; i < barl; i++) { Sleep(100); cout << ":"; } cout << "]"; }
quelle