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.

We start with the code below to copy one string to another. In anticipation of the fact that the indexes of s1 and s2 will diverge, we create separate indexes for each of them. We also start with a while-loop because we will be modifying the indexes many times within the loop. If we used a for-loop instead, our code would be hard to follow.

    /* expand:  expand short hand notations in s1 into the equivalent list in s2 */
    void expand(char s1[], char s2[])
    {
        int i, j;
    
        i = j = 0;
        while (s1[i] != '\0')
            s2[j++] = s1[i++];
        s2[j] = '\0';
    }

A shorthand notation is of the format a-b and the following conditions must be met in order for it to be valid:

  1. a and b must both be letters (upper or lowercase) or digits
  2. a must come before b

If s1[i] represents a, the following condition will be true when a notation is found:

s1[i+1] == '-' && (islower(s1[i]) && islower(s1[i+2]) || isupper(s1[i]) && isupper(s1[i+2]) || isdigit(s1[i]) && isdigit(s1[i+2])) && s1[i] < s1[i+2]

When we come across a valid shorthand notation, we assign the value of s1[i] to the variable c, whose value will be repeatedly incremented and appended to s2 until it reaches s1[i+2], at which point i will be incremented by three so that the rest of the shorthand notation is skipped. Because our code reads notations all at once, leading and trailing dashes will cause no issues.

    /* expand:  expand short hand notations in s1 into the equivalent list in s2 */
    void expand(char s1[], char s2[])
    {
        int c, i, j;
    
        i = j = 0;
        while (s1[i] != '\0') {
            if (s1[i+1] == '-' && (islower(s1[i]) && islower(s1[i+2]) ||
                isupper(s1[i]) && isupper(s1[i+2]) || isdigit(s1[i]) &&
                isdigit(s1[i+2])) && s1[i] < s1[i+2]) {
                c = s1[i];
                while (c <= s1[i+2]) {
                    s2[j++] = c;
                    ++c;
                }
                i += 3;
            } else
                s2[j++] = s1[i++];
        }
        s2[j] = '\0';
    }