aboutsummaryrefslogtreecommitdiff
path: root/ch1/1-21_entab.c
blob: 2833520d587f9cf09c00041c3029d7f35a91cecd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <stdio.h>

/* The C Programming Language: 2nd Edition
 *
 * Exercise 1-21: Write a program `entab` that replaces strings of blanks by
 * the minimum number of tabs and blanks to achieve the same spacing. Use the
 * same tab stops as for `detab`. When either a tab or a single blank would
 * suffice to reach a tab stop, which should be given preference?
 *
 * Answer: A blank. A tab character that comes after (tabstop - 1) blanks makes
 * little-to-no sense and could mess up alignment in some environments.
 */

#define TABWIDTH 8

int main(void) {
	int column, c, spaces;
	spaces = column = 0;
	while ((c = getchar()) != EOF) {
		// First thing's first, advance by a column.
		column++;

		if (c == ' ') {
			/* Add to 'spaces' immediately, we'll decide if it needs to be
			 * output later.
			 */
			spaces++;

			if (column % TABWIDTH == 0 && spaces > 0) {
				putchar('\t');
				spaces = 0; // No spaces are left when we tab!
			}

		} else {
			/* Be sure to output any leftover spaces when we come across a
			 * non-space character. This should allow for spaces between words
			 * that don't fall along the tabstop lines.
			 */

			while (spaces > 0) {
				putchar(' ');
				spaces--;
			}

			// As usual, reset things on a newline.
			if (c == '\n') {
				column = 0;
				spaces = 0;
			}

			// Now we can output whatever it is.
			putchar(c);
		}
	}
	return 0;
}