diff options
author | zlg <zlg@zlg.space> | 2013-04-18 01:25:48 -0500 |
---|---|---|
committer | zlg <zlg@zlg.space> | 2013-04-18 01:25:48 -0500 |
commit | 215387b5bbe730cf758be29fd306bf3ed7a89454 (patch) | |
tree | 2a71c438eb94315e0f2ebee96bf25dd4b993a9b1 /ch3 | |
parent | Solve Exercise 3-2: escape/unescape (diff) | |
download | knr-215387b5bbe730cf758be29fd306bf3ed7a89454.tar.gz knr-215387b5bbe730cf758be29fd306bf3ed7a89454.tar.bz2 knr-215387b5bbe730cf758be29fd306bf3ed7a89454.tar.xz knr-215387b5bbe730cf758be29fd306bf3ed7a89454.zip |
Solve Exercise 3-3: expand()
Diffstat (limited to 'ch3')
-rw-r--r-- | ch3/3-03_expand.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/ch3/3-03_expand.c b/ch3/3-03_expand.c new file mode 100644 index 0000000..b0a4011 --- /dev/null +++ b/ch3/3-03_expand.c @@ -0,0 +1,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; +} |