printf() \t option

Viewed 157285

When you are printing a tab character to the standard output using printf in C, it outputs some space which is apparently 4 characters in length.

printf("\t");

Is there a way by which I can control the tab width in the above case?

3 Answers

If your terminal supports proper ANSI escape sequences, there are escape sequences to set tab stops to any location on the screen. The escape sequence ESC [ 3 g clears all tab stops, the escape sequence ESC H sets the tab stop at a specific location.

Below is an POSIX example C program that provides a function that set's tab stops to the specified count of spaces. First all existing tabs are removed, then spaces are printed and in proper locations the tab stop is set. Then the cursor is rewind back to the start of the line.

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <termios.h>

int writestr(int fd, const char *s) {
    return write(fd, s, strlen(s)) == (ssize_t)strlen(s) ? 0 : -1;
}

int set_tab_stops(unsigned distance) {
    assert(distance > 0);
    // Using stdout here, stderr would be more reliable. 
    FILE *file = stdout;
    const int fd = fileno(file);
    // We have to flush stdout in order to use fileno.
    fflush(file);
    // Get terminal width.
    // https://stackoverflow.com/questions/1022957/getting-terminal-width-in-c
    struct winsize w = {0};
    if (ioctl(fd, TIOCGWINSZ, &w) < 0) return -__LINE__;
    const unsigned cols = w.ws_col;
    // Remove all current tab stops.
    if (writestr(fd, "\033[3g") < 0) return -__LINE__;
    // Do horicontal tabs each distance spaces.
    for (unsigned i = 0; i < cols; ++i) {
        if (i % distance == distance - 1) {
            if (writestr(fd, "\033H") < 0) return -__LINE__;
        }
        if (writestr(fd, " ") < 0) return -__LINE__;
    }
    // Clear the line and return to beginning of the line.
    if (writestr(fd, "\033[1K\033[G") < 0) return -__LINE__;
    return 0;
}

int main() {
    set_tab_stops(10);
    printf("1\t2\t3\t4\n");
    set_tab_stops(5);
    printf("1\t2\t3\t4\n");
}

With xfce4-terminal the program outputs:

1        2         3         4
1   2    3    4
Related