Exercise 1-20

Write a program detab that replaces tabs in the input with the proper number of blanks to space to the next tab stop. Assume a fixed set of tab stops, say every n columns. Should n be a variable or a symbolic parameter?

Firstly, n should be a symbolic parameter, because it remains constant throughout the program.

To know where the next tab stop is, we need to know in which column the tab character is in. To do this, we create an integer variable col and increment it after reading in and printing a character. We reset it to zero every time we come across a newline.

    #include <stdio.h>
    
    /* detab:  replace tabs with spaces */
    main()
    {
        int c;
        int col;    /* current column */
    
        col = 0;
        while ((c = getchar()) != EOF) {
            putchar(c);
            ++col;
            if (c == '\n')
                col = 0;
        }
        return 0;
    }

Next, we define the symbolic constant TABWIDTH to represent how many columns are in between tab stops. If the character we read in is not a tab, we copy it to the output; if it is, we print a sequence of spaces whilst updating col using a loop until we reach the next tab stop. When we do, col % TABWIDTH will be equal to zero. In case our tab character is already at the start of a tab stop, we print a space and increment col prior to executing the loop.

    #include <stdio.h>
    
    #define TABWIDTH 4  /* columns between tap stops */
    
    /* detab:  replace tabs with spaces */
    main()
    {
        int c;
        int col;    /* current column */
    
        col = 0;
        while ((c = getchar()) != EOF) {
            if (c == '\t') {
                if (col % TABWIDTH == 0) {  /* already at start of tab stop */
                    putchar(' ');
                    ++col;
                }
                for (; col % TABWIDTH != 0; ++col)
                    putchar(' ');
            } else {
                putchar(c);
                ++col;
            }
            if (c == '\n')
                col = 0;
        }
        return 0;
    }