aboutsummaryrefslogtreecommitdiff
path: root/ch3/3-03_expand.c
blob: b0a4011635fcccfc5af991d81195b420f0f44c99 (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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <stdio.h>
#include <ctype.h>

/* The C Programming Language: 2nd Edition
 *
 * Exercise 3-3: Write a function expand(s1,s2) that expands shorthand
 * notations like 'a-z' in the string s1 into the equivalent complete list
 * 'abc...xyz' in s2. Allow for letters of either case and digits, and be
 * prepared to handle cases like 'a-b-c' and 'a-z0-9' and '-a-z'. Arrange that
 * a leading or trailing '-' is taken literally.
 *
 * Answer: This one was fun. The trick is to target dashes, since they have the
 * special behavior. From there, you decide what to do based on context. Once
 * you've determined that the characters on both sides of the dash are letters
 * OR numbers - no mixing - you store both values and put'em through a loop to
 * output the range. There are a few edge cases to watch out for, but it's
 * pretty simple to account for them.
 *
 * A limitation of my expand() is leading and trailing dashes are only output
 * once. You can lead or trail with > 1 dash and it will truncate it to only 1.
 * This could be seen as a bug or a feature. I haven't decided.
 */

void expand(char s1[], char s2[]) {
	int i, j;
	char start = 0;
	char end = 0;
	for (i = 0, j = 0; s1[i] != '\0'; i++) {
		if (s1[i] == '-') {
			if ((isalpha(s1[i - 1]) && isalpha(s1[i + 1])) || (isdigit(s1[i - 1]) && isdigit(s1[i + 1]))) {
				start = s1[i - 1];
				end = s1[i + 1];
				start = tolower(start);
				end = tolower(end);
				if (start == s2[j - 1]) {
					start++;
				}
				while (start <= end) {
					s2[j++] = start++;
				}
			} else {
				if (i == 0 || s1[i + 1] == '\0') {
					s2[j++] = '-';
				}
			}
		}
	}
	s2[j] = '\0';
}

int main() {
	char foo[21] = "A-Z";
	char bar[21] = "0-9";
	char baz[21] = "A-g-N";
	char fob[21] = "2-5-9";
	char woot[21] = "-a-f0-36-9b-h-";
	char derp[21] = "a-28-t";
	char dest[61] = "";

	printf("%26s\n", "INPUT |  OUTPUT");
	printf("%27s\n", "-----------------");

	expand(foo, dest);
	printf("%16s => %s\n", foo, dest);

	expand(bar, dest);
	printf("%16s => %s\n", bar, dest);

	expand(baz, dest);
	printf("%16s => %s\n", baz, dest);

	expand(fob, dest);
	printf("%16s => %s\n", fob, dest);

	expand(woot, dest);
	printf("%16s => %s\n", woot, dest);

	expand(derp, dest);
	printf("%16s => %s\n", derp, dest);

	return 0;
}