可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I want to make a progress bar for my terminal application that would work something like:
[XXXXXXX ]
which would give a visual indication of how much time there is left before the process completes.
I know I can do something like printing more and more X's by adding them to the string and then simply printf, but that would look like:
[XXXXXXX ]
[XXXXXXXX ]
[XXXXXXXXX ]
[XXXXXXXXXX ]
or something like that (obviously you can play with the spacing.) But this is not visually aesthetic. Is there a way to update the printed text in a terminal with new text without reprinting? This is all under linux, c++.
回答1:
try using \r
instead of \n
when printing the new "version".
for(int i=0;i<=100;++i) printf("\r[%3d%%]",i);
printf("\n");
回答2:
I'd say that a library like ncurses would be used to such things. curses helps move the cursor around the screen and draw text and such.
NCurses
回答3:
Something like this:
std::stringstream out;
for (int i = 0; i< 10; i++)
{
out << "X";
cout << "\r" << "[" << out.str() << "]";
}
The sneaky bit is the carriage return character "\r" which causes the cursor to move to the start of the line without going down to the next line.
回答4:
Others have already pointed out that you can use \r
to go back to the beginning of the current line, and overwrite the entire line.
Another possibility is to use the backspace character ("\b") to erase a few spaces, and overwrite only those spaces. This can have a couple of advantages. First, it obviously avoids having to regenerate everything in the line, which can sometimes be mildly painful (though that is fairly unusual). Second, it can avoid some pain in displaying data that (for one example) shrinks in size as you write it -- for example, if you're displaying a count-down from 100 to 0, with \r
you have to be careful about overwriting the entire previous length, or your countdown will go from (for example) 100 to 990 (i.e., leaving the previous "0" intact).
Note, however, that while back-space within a line normally works, a backspace at the beginning of a line may or may not move the cursor/write position back to a previous line. For most practical purposes, you can only move around within a single line.
回答5:
'\r' will perform a carriage return. Imagine a printer doing a carriage return without a linefeed ('\n'). This will return the writing point back to the start of the line... then reprint your updated status on top of the original line.
回答6:
It's a different language, but this question might be of assistance to you. Basically, the escape character \r (carriage Return, as opposed to \n Newline) moves you back to the beginning of your current printed line so you can overwrite what you've already printed.
回答7:
Another option is to simply print one character at a time. Typically, stdout is line buffered, so you'll need to call fflush(stdout) --
for(int i = 0; i < 50; ++i) {
putchar('X'); fflush(stdout);
/* do some stuff here */
}
putchar('\n');
But this doesn't have the nice terminating "]" that indicates completion.
回答8:
I've written this loading bar utility some time ago. Might be useful...
https://github.com/BlaDrzz/CppUtility/tree/master/LoadingBar
You can customise basically anything in here.
int max = 1000;
LoadingBar* lb = new LoadingBar(10, 0, max);
for (size_t i = 0; i <= max; i++)
{
lb->print();
lb->iterate();
}
cout << lb->toString() << endl;
Very simple and customisable implementation..