We first define the symbolic constant TABWIDTH
to
represent how many columns are between tab stops, and col
which keeps track of which column we are on by incrementing after a
character is read in and printed, and resetting to zero whenever a
newline is read in.
#include <stdio.h>
#define TABWIDTH 4 /* columns between tab stops */
/* entab: replace strings of spaces with tabs */
main()
{
int c;
int col; /* current column */
col = 0;
while ((c = getchar()) != EOF) {
putchar(c);
++col;
if (c == '\n')
col = 0;
}
return 0;
}
Whenever we come across a blank, we enter a while
-loop
that continues to run as long as the subsequent character is also a
blank. During every iteration, we increment a variable called
blanks that keeps track of how many consecutive blanks we
come across. If a tab character is entered, or
col + blanks
reaches the next tab stop and
blanks is greater than one (otherwise single blanks could
get converted to tabs), we print a tab character and reset
blanks to zero. We also make sure to print a tab character
if a single blank that reached a tab stop and was buffered is
superseded by more blanks (e.g abc d; notice how the
first blank reaches a tab stop [four in this case] but there is more
whitespace afterward implying this is an indent.) Once we exit the
loop, we print any leftover blanks and continue reading in more input.
#include <stdio.h>
#define TABWIDTH 4 /* columns between tab stops */
/* entab: replace strings of spaces with tabs */
main()
{
int c;
int col; /* current column */
int blanks; /* number of consecutive blanks */
col = blanks = 0;
while ((c = getchar()) != EOF) {
while (c == ' ' || c == '\t') {
/* account for previously skipped single blanks */
if ((col + blanks) % TABWIDTH == 0 && blanks == 1) {
putchar('\t');
++col;
blanks = 0;
}
++blanks;
/* do not print tab character in place of single blank */
if (((col + blanks) % TABWIDTH == 0 && blanks > 1) || c == '\t') {
putchar('\t');
col = col + (TABWIDTH - col % TABWIDTH);
blanks = 0;
}
c = getchar();
}
while (blanks > 0) {
putchar(' ');
--blanks;
}
putchar(c);
++col;
if (c == '\n')
col = 0;
}
return 0;
}
Note: the expression TABWIDTH - col % TABWIDTH
is
equal to the number of characters needed to reach the tab column
because col % TABWIDTH
is equal to the number of
characters after the last tab stop.
Note: it is a good idea to not convert single blanks that lie on a tab stop because otherwise, regular blanks could get converted to tabs.