I would like to create a small function, which should show the current status in percentage in the console. The function should only show the current value in the line.
So I have to remove the last output. Is that possible? The best case would be some ANSI C stuff, the program should work on linux and windows.
I have found some escape sequences like "\033[J", but it dose not work.
Edit
Well I tried it with:
void PrintProcessBar(int i, int n) {
float ratio = i / (float)n;
printf("%.3d\b\b", (int)(ratio * 100));
fflush(stdout);
}
But it just print lots of zeros... What went wrong? If I use three \b I get nothing.
Solution
float ratio = (i / (float)n) * 100;
printf("\b\b\b\b");
fflush(stdout);
printf("%.3d%c", (int)ratio, 37);
fflush(stdout);
i = current position.
n = max runs.
I use 4 \b because, at the first call of the function it will remove 4 spaces.
Greetz.
\b is the escape sequence for backspace. you can use it with spaces to delete a line.
For example:
printf("98%");
fflush(stdout);
// sleep some time
printf("\b\b\b99%");
fflush(stdout);
This should print 98%, and then replace it with 99%.
What you look for is \r it is Carriage Return. Makes the carriage go back to the beginning of the line. Do not use \n as it will go down one line.
Because \r does not delete text but simply allows you to overwrite, you have to make sure you print enough text (spaces if you need) to clear your line.
Related
I want to make a quizgame with a countdown. The problem is; when I use system cls all the prints are going. I tried using printf("/ b"). In that case, I can't get data from the user because the system is in the loop.
Can I keep the question output and count down and get input from the user?
Here this is my countdown code:
int v=30;
while(v!=0) {
printf("\n\t%d",v);
v--;
sleep(1);
system("cls");
}
If I understand your question, and you just want to display a countdown in the same location on the screen, then for terminals that support VT100 emulation (and some earlier VTXX versions), you can just use ANSI escapes to control the cursor visibility and a carriage-return ('\r') to return cursor position to the original starting point. If you use the field-width modifier for your integer output, you don't even need the ANSI escape to clear to end-of-line. If you have variable number of characters that are part of your countdown, you can use the ANSI escape to clear to end-of-line to ensure all text is erased each iteration.
For example you could do:
#include <stdio.h>
#include <unistd.h>
int main (void) {
int v = 30;
printf ("\033[?25l"); /* hide cursor */
while (v--) {
printf (" countdown: %2d\r", v); /* print, CR */
fflush (stdout); /* flush stdout */
sleep (1);
}
printf ("\033[?25h\n"); /* restore cursor, \n */
}
If you did have additional text after the countdown number that varied in length with each iteration, you could use:
printf (" countdown: %2d\033[0k\r", v); /* print, clear to end, CR */
which includes the clear to end-of-line escape \033[0k.
The two additional ANSI escapes used above are \033[?25l (hide cursor) and \033[?25h (restore cursor).
The fflush(stdout); is necessary because output in C is line-buffered by default. Without fflush(stdout);, all output would be buffered until a '\n' was encountered -- making all text appear at once.
Give it a try. If you have a VT compatible terminal, it will work fine. But note, the reason ANSI escapes are discouraged is they are not portable. Not all terminals support VT emulation (but a lot do...) See ANSI Escape sequences - VT100 / VT52 for additional escape sequences.
If you are developing a full fledged terminal app with numerous inputs and outputs formatted on the screen, you are better served using a library that provides that capability, such as ncursees etc..
The possible soulution:
I won't put the sleep.
I would ask the user inside the loop and after every answer i would v-- .
#include <stdio.h>
int main (void) {
int v=10;
char *name;
while(v!=0){
printf("Whats your name? ");
scanf("%s", &name);
printf("\nyour name is %s", &name);
printf("\n");
printf("\n\t%d",v);
printf("\n");
v--;
}
return 0;
}
Why do we use \r and \b in C? I know that \b makes "hello\bworld" into "hellworld". but we can just write "hellworld" instead of "hello\bworld". So, what purpose does it serves in a program? This question describes what \b do , but doesn't clarify why it is used.
Its' to a large degree just historical reasons. Many characters can actually be traced back to analogue typewriters! In the past, you had computers with matrix printers instead of monitors. In those days, bold font was achieved by printing something twice in the same location.
For example, in Linux we use the character \n for a new line, but in Windows it is \r\n so what is those characters? Well \n (newline) is to move the head of the typewriter one line down and \r is the carriage return, which returns the typewriter carriage to the beginning of the line.
Many of these characters are not used very much anymore. They are mostly considered legacy. They are not really that useful in modern programming. You can use \b to go back and overwrite stuff that you have previously written, but today you would use libraries like ncurses to achieve the same thing. In the old days, you could actually use these to get pretty exact positioning of stuff, but on modern terminal emulators, that's no longer the case. For instance, old terminals had fixed sizes. The sizes may not have been standardized, but they did not change during runtime and were the same for the same machine every time you run a program.
I could consider using \b and \r if I wanted to write a cli application with some kind of progress bar. Example:
#include <stdio.h>
#include <unistd.h>
int main(void) {
int n = 0;
while(n<=100) {
printf("\rProgress: %d\%", n);
fflush(stdout);
sleep(1);
n+=10;
}
}
You could achieve the same thing with \b instead of \r, but mostly it's easier to just reprint the whole line. I cannot see any situation where I would use \b in code.
A similar thing can be done if you want to simulate human writing in a text based game. But I would say that these kind are mostly for the case where you don't have the time and/or energy to learn how to use proper modern methods.
Let's look at the first 32 characters in the ascii table:
0 Null char
1 Start of Heading
2 Start of Text
3 End of Text
4 End of Transmission
5 Enquiry
6 Acknowledgment
7 Bell
8 Back Space
9 Horizontal Tab
10 Line Feed
11 Vertical Tab
12 Form Feed
13 Carriage Return
14 Shift Out / X-On
15 Shift In / X-Off
16 Data Line Escape
17 Device Control 1 (oft. XON)
18 Device Control 2
19 Device Control 3 (oft. XOFF)
20 Device Control 4
21 Negative Acknowledgement
22 Synchronous Idle
23 End of Transmit Block
24 Cancel
25 End of Medium
26 Substitute
27 Escape
28 File Separator
29 Group Separator
30 Record Separator
31 Unit Separator
Almost all of these have been replaced by other things. For instance by higher level protocols, like tcp and such, but also by libraries like ncurses. In C, the null character is useful for strings, but it could have been solved in other ways, like making it possible to retrieve the size of an array when it's passed to a function.
You use them to overwrite something you wrote previously. You wouldn't normally use them in the same string, but in different output calls, e.g.
printf("hello");
fflush(stdout); // need to flush because we didn't write a newline
// do some stuff here
printf("\rgoodbye\n"); // This replaces hello
Those escape sequences are used today mainly for creating some kind of CLI-"GUI", for CLI-"animations", like showing a "loading progress" and some special tricks.
In the past those escape sequences were used mainly to control teleprinter and for punched cards.
For example, for deleting the last punched character on a punch card, you used:
putchar('\b'); putchar(127); /* DEL */.
\ris used to move the cursor in the beginning of above line and \n is used to move the cursor to beginning of next line.
#include <stdio.h>
#include <unistd.h>
#include<iostream>
using namespace std;
int main() {
cout<<"Hello";
cout<<"\r";
cout<<"Gone ";
}
Above program will not display Hello.
#include <stdio.h>
#include <unistd.h>
int main() {
int i=0;
int n=4;
char pattern[n];
pattern[0]=(char)179;
pattern[1]=(char)47;
pattern[2]=(char)196;
pattern[3]=(char)92;
long long int count=0;
while(count<100000000){
printf("%c",pattern[i]);
i=(i+1)%n;
printf("\r");
count++;
}
}
Test it by yourself.
\n" for new line
"\b" for a backspace, means if u print it, cursor will print and come back 1 character. For example.... cout<<"hello\bHi"; will print "HellHi". because after printing Hello, compiler found a \b escape sequence. so it came 1 character back (at 'o' of Hello) and stat printing Hi from o of Hello..... so u got HellHi instead of HelloHi.
'\r' is used for carriage return to come 1 line back or in start of line.
\b = it's purpose is backspace
\r = purpose is carriage return
\r is a carriage return character; it tells your terminal emulator to move the cursor at the start of the line.
The cursor is the position where the next characters will be rendered.
So, printing a \r allows to override the current line of the terminal emulator.
Whereas \b is backspace character it takes the cursor one character backward so that when you will type next thing the characters ahead of cursor will be overwritten.
Thus \b illustrates the working of backspace whereas carriage return simply moves the cursor to the starting of the current line.
Can You Explain Me This Code ....
What Is The Use Of \r In This Program
#include<stdio.h>
void main()
{
printf("This Is \r Amarendra Deo");
}
The \r has no inherit meaning for the C language, but terminals (aka console) can react to this character in different ways. The most common way for terminal is that carriage return sets the cursor at the start of the current line. So when you execute this line, you'll get
Amarendra Deo
Because printf will print This Is and the \r will set the cursor back to the beginning of the line and Amarendra Deo will overwrite whatever has been printed on that line. And since Amarendra Deo is longer than This Is, all you see is
Amarendra Deo
This is for example a very useful trick for when you want to print something
repeatedly on the same line, for example a status message:
for(size_t i = 0; i < 5; ++i)
{
printf("Processing task %d...\r", i+1);
fflush(stdout);
execute_task(i); // can take several seconds to finish
}
In that case you'll see the the Processing task ... text on the same line and it's a nice visual feature for the user. Try executing that for yourself (change the execute_task(i) with sleep(1) or something to make a delay).
I have a really weird problem with carriage return. I try to rewrite a line multiple times, it works fine if the line has no spaces and doesn't work if it has spaces. For instance this code
printf(" ");
printf("\rtest test");
printf(" ");
printf("\rtest test");
printf(" ");
printf("\rtest test");
printf(" ");
printf("\rtest test");
will type 4 lines "test test" while this code
printf(" ");
printf("\rtest");
printf(" ");
printf("\rtest");
printf(" ");
printf("\rtest");
printf(" ");
printf("\rtest");
will type a single line "test". What is the problem? I want to be able to rewrite any line disregard if it has spaces or not.
\r moves the cursor to the beginning of the physical line on the tty. If the previous print wraps the cursor to the next line (ie, the number of spaces + the number of characters in "text text" is larger than the width of the display), then the cursor is on the next physical line. You'll need to use more complex escape sequences to accomplish what you want. (ie, save/restore cursor position.) As an example (this is not portable, but works in many cases), you could do:
fputs( "\0337", stdout ); /* Save the cursor position */
printf( " ... " );
fputs( "\0338", stdout ); /* restore cursor position */
Note that if the cursor is at the bottom of the screen, this will probably not do exactly what you want. The position will be saved at the bottom of the screen, multiple lines of output will scroll, and the cursor will be restored to the bottom of the screen.
To print on a new line, use newline ('\n') not carriage-return.
The behaviour of '\r' on the console is to return to the start of the current line. In this case it is the large amount of space padding that was forcing a line wrap in the first instance.
In some cases a terminal can be configured to translate CR to CR+LF. Strictly '\n' is merely a LF character which moves down one line without returning to the start, but the normal behaviour for stdout is to translate that to CR+LF.
In most modern shells, you can hit the up and down arrows and it will put, at the prompt, previous commands that you have executed. My question is, how does this work?!
It seems to me that the shell is somehow manipulating stdout to overwrite what it has already written?
I notice that programs like wget do this as well. Does anybody have any idea how they do it?
It's not manipulating stdout -- it's overwriting the characters which have already been displayed by the terminal.
Try this:
#include <stdio.h>
#include <unistd.h>
static char bar[] = "======================================="
"======================================>";
int main() {
int i;
for (i = 77; i >= 0; i--) {
printf("[%s]\r", &bar[i]);
fflush(stdout);
sleep(1);
}
printf("\n");
return 0;
}
That's pretty close to wget's output, right? \r is a carriage-return, which the terminal interprets as "move the cursor back to the start of the current line".
Your shell, if it's bash, uses the GNU Readline library, which provides much more general functionality, including detecting terminal types, history management, programmable key bindings, etc.
One more thing -- when in doubt, the source for your wget, your shell, etc. are all available.
To overwrite the current standard output line (or parts of it) use \r (or \b.) The special character \r (carriage return) will return the caret to the beginning of the line, allowing you to overwrite it. The special character \b will bring the caret back one position only, allowing you to overwrite the last character, e.g.
#include <stdio.h>
#include <unistd.h>
int i;
const char progress[] = "|/-\\";
for (i = 0; i < 100; i += 10) {
printf("Processing: %3d%%\r",i); /* \r returns the caret to the line start */
fflush(stdout);
sleep(1);
}
printf("\n"); /* goes to the next line */
fflush(stdout);
printf("Processing: ");
for (i = 0; i < 100; i += 10) {
printf("%c\b", progress[(i/10)%sizeof(progress)]); /* \b goes one back */
fflush(stdout);
sleep(1);
}
printf("\n"); /* goes to the next line */
fflush(stdout);
Use fflush(stdout); because standard output is usually buffered and the information may not otherwise be immediately printed on the output or terminal
In addition to \r and \b, take a look at ncurses for some advanced control over what's on the console screen. (Including columns, moving around arbitrarily, etc).
A program running in a text terminal / console can manipulate the text displayed in its console in various ways (make text bold, move cursor, clear screen etc.). This is accomplished by printing special character sequences, called "escape sequences" (because they usually start with Escape, ASCII 27).
If stdout goes to a terminal which understands these escape sequences, the display of the terminal will change accordingly.
If you redirect stdout to a file, the escape sequences will appear in the file (which is usually not what you want).
There is no complete standard for escape sequences, but most terminals use the sequences introduced by VT100, with many extensions. This is what most terminals under Unix/Linux (xterm, rxvt, konsole) and others like PuTTY understand.
In practice, you would not directly hardcode escape sequences into your software (though you could), but use a library to print them, such as ncurses or GNU readline mentioned above. This allows compatibility with different terminal types.
It's done with the readline library... I'm not sure how it works behind the scenes but I don't think it has anything to do with stdout or streams. I suspect readline uses some sort of cryptic (to me, at least) terminal commands - that is, it cooperates with the terminal program that actually displays your shell session. I don't know that you can get readline-like behavior just by printing output.
(Think about this: stdout can be redirected to a file, but the up/down-arrow keys trick doesn't work on files.)
You can use carriage return to simulate this.
#include <stdio.h>
int main(int argc, char* argv[])
{
while(1)
{
printf("***********");
fflush(stdout);
sleep(1);
printf("\r");
printf("...........");
sleep(1);
}
return 0;
}
The program does this by printing special characters that the terminal interprets in a special way. The most simple version of this is (on most linux/unix terminals) to print '\r' (carriage return) to the normal stdout which resets the cursor position to the first character in the current line. So the thing you write next will overwrite the line you wrote previously. This can be used for simple progress indicators, for example.
int i = 0;
while (something) {
i++;
printf("\rprocessing line %i...", i);
...
}
But there are more complicated escape characters sequences that are interpreted in various ways. All kinds of things can be done with this, like positioning the cursor at a specific position on the screen or setting the text color. If or how these character sequences are interpreted depends on your terminal, but a common class supported by most terminals are ansi escape sequences. So if you want red text, try:
printf("Text in \033[1;31mred\033[0m\n");
The simplest way is to print to stdout the carriage return character ('\r').
The cursor will be moved to the start of the line, allowing you to overwrite its contents.