why do we use \r and \b in C? - c

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.

Related

What are the effects of "\t" , "\r" and "\b" in c?

I'm a little confused about the following code:
#include <stdio.h>
int main()
{
printf("\nab");
printf("\bsi");
printf("\rha");
return 0;
}
When I execute the program on Linux, it prints
ha
But when I execute it on Xcode, it prints
absi
ha
I am a little confused about "\t", "\b" and "\r", and I can't figure out how the program works.
\t refers to a tab character, \r to a carriage return (think of a typewriter), and \b to a nondestructive backspace. As crvv pointed out, the same output is always sent to stdout: "\nab\bsi\rha". However, your terminal and XCode will produce different output (by choice).
Your terminal will do the following: it sees the \n, goes to a new line, it sees ab and "stores" that, but then it sees \b, so it performs a nondestructive backspace. This basically means the cursor, aka the point where new characters are written, goes back one space:
Initially:
ab
^
After encountering \b:
ab
^
Note that the cursor is now under b, so it will be overwritten if any subsequent characters result.
Next, it reads in s and then i, so we get:
asi
^
Next, it reads in \r. This is the carrage return, which on old typewriters would return the cursor to the beginning of the line. So now we have:
asi
^
Finally, it reads in ha, and because the cursor is under a, ha will overwrite as:
hai
^
Here's the thing. Note that your cursor is still under i. It is not under the next empty space, after the i. Because your program printf does not print anything after printf("\rha"), when the terminal prints your output, the cursor will remain under i.
So, what is the next thing your terminal outputs? Usually, it's the normal prompt, i.e. yourname#ubuntu. This overwrites the i, hence, you will see something like hayourname#ubuntu.
Xcode, on the other hand, does things a little differently. It consumes the \b, so the cursor doesn't go back a character, and the \r is treated as a newline, hence:
absi
ha
The program always writes "\nab\bsi\rha" to its stdout.
The difference comes from how this is displayed.
You can use gcc hello.c && ./a.out | xxd to see it.
00000000: 0a61 6208 7369 0d68 61 .ab.si.ha
\r is CR (carriage return) code. It returns the cursor to the start of line. You have "ab", then \b which is backspace. Following "si" will overwrite "b" and you have "asi". Then \r goes to the start of line and "ha" is printed in the place of "as" - the result is "hai". But the cursor is after "s" and when Bash prompt is displayed, it replaces "i" because it is the first free position after cursor. And you see "ha{prompt-message}". Add \n after \rha to see "hai".

How to get the cursor position in a C program using termcap, without writing a character?

I would like to know how to get the cursor position (x, y) in my program, without writing anything on the screen neither tracking it all the time.
I found out a way to get its position with this function (I don't check the return of read, write, etc here to write a smaller code on this subject but I do it in my program):
void get_cursor_position(int *col, int *rows)
{
int a = 0;
int i = 0;
char buf[4];
write(1, "\033[6n", 4); // string asking for the cursor position
read(1, buf, 4);
while (buf[i])
{
if (buf[i] >= 48 && buf[i] <= 57)
{
if (a == 0)
*rows = atoi(&buf[i]) - 1;
else
*col = atoi(&buf[i]) - 1;
a++;
}
i++;
}
}
This function gives me the exact cursor position (*rows = y, *col = x), but it writes on the screen.
How can I get the cursor position without writing anything on the screen?
(If the cursor is on one of the printed characters, it will overwrite it.)
Should echo be toggled before and after sending the escape sequence?
This is a school project, so I only can use termcap, I can't use ncurses functions, the only allowed functions are tputs, tgoto, tgetstr, tgetnum, tgetflag.
There are several problems:
canonical mode is buffered (see below)
the read is done on the file-descriptor for standard output (that may happen to work — sometimes — but don't count on it)
the read does not read enough characters to get a typical response
the response would have two decimal integers, separated by semicolon ;
the response would have a final character (which would become an issue if the read actually asked for enough characters...)
Further reading:
General Terminal Interface The Single UNIX ® Specification, Version 2
In canonical mode input processing, terminal input is processed in units of lines. A line is delimited by a newline character (NL), an end-of-file character (EOF), or an end-of-line (EOL) character. See Special Characters for more information on EOF and EOL. This means that a read request will not return until an entire line has been typed or a signal has been received. Also, no matter how many bytes are requested in the read() call, at most one line will be returned. It is not, however, necessary to read a whole line at once; any number of bytes, even one, may be requested in a read() without losing information.
XTerm Control Sequences
CSI Ps n Device Status Report (DSR).
Ps = 5 -> Status Report.
Result ("OK") is CSI 0 n
Ps = 6 -> Report Cursor Position (CPR) [row;column].
Result is CSI r ; c R
That is, your program should be prepared to read Escape[ followed by two decimal integers (with no fixed limit on their length), and two other characters ; and R.
By the way, termcap by itself will do little for your solution. While ncurses has some relevant capabilities defined in the terminal database:
# u9 terminal enquire string (equiv. to ANSI/ECMA-48 DA)
# u8 terminal answerback description
# u7 cursor position request (equiv. to VT100/ANSI/ECMA-48 DSR 6)
# u6 cursor position report (equiv. to ANSI/ECMA-48 CPR)
few programs use those, and in any case you would find it difficult to use the cursor position report in a termcap application.

C remove printf output

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.

How could I achieve gotoxy() in gcc

I am using gcc in ubuntu.so, I compile and execute in terminal. But In a online programming contest, they require the output as shown in diagram.
For that, if I use TURBOC I can get it using conio.h using gotoxy() to get spiral format of output. But in Ubuntu , How could I achieve this?
Assuming because it is a contest and they don't want dependencies like ncurses you could try to do it in memory.
Set up 2 dimensional array of char - lines and columns - say 24x80. Write your own version of gotoxy() which assigns values into the proper cells. When done plotting, print out the array of lines.
Use the ncurses library.
Here's an example, adapted from http://www.paulgriffiths.net/program/c/srcs/curhellosrc.html
#include <stdlib.h>
#include <stdio.h>
#include <curses.h>
int main(void) {
WINDOW * mainwin;
/* Initialize ncurses */
if ( (mainwin = initscr()) == NULL ) {
fprintf(stderr, "Error initialising ncurses.\n");
exit(EXIT_FAILURE);
}
move(10, 15);
addch('X');
refresh();
getch();
delwin(mainwin);
endwin();
refresh();
return EXIT_SUCCESS;
}
Further information is available here: http://invisible-island.net/ncurses/ncurses-intro.html#stdscr
Aside of ANSI escape sequences you might wish to investigate ncurses:
http://www.gnu.org/s/ncurses/
It all ultimately depends upon the capabilities of the terminal running the program, not the actual host, language, or library. Consider what happens redirecting program output to a file or to a printer.
conio.h API is more to do with a fixed console, with Unix like systems you usual deal with terminals which can be more varied such as resizable X-Terminals.
Determine how many lines of output you need. Allocate an array of "char *" with one entry per line of output needed. When you place a number use "realloc()" to increase the size of the line and fill from the old end to the new end with spaces (if necessary); then put your number at the right place in that line (in memory).
After you've build an array of string in memory; do a for loop that prints each line (and frees the memory you allocated).
You don't need "gotoxy()" or anything to control cursor position.
Since it isn't here yet, I just wanted to say about an example using ANSI escape sequences as Steve-o mentioned.
void gotoxy(int x, int y)
{
printf("%c[%d;%df", 0x1B, y, x);
}
I got it from here.
0x1B is hexadecimal for 27 in decimal and is the ASCII for ESC. The escape sequences start with it
%m;%nf moves the cursor to row n, column m.
The ANSI escape sequences are used "to control the formatting, color, and other output options on video text terminals"

How to overwrite stdout in C

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.

Resources