A-Z等の省略記法を展開する

K&R本 演習3-3

文字列s1中のa-zのような省略記法を、それと等価な完全リストabc・・・xyzにしてs2中に展開する関数expand(s1,s2)を書け。大文字、小文字、数字を許し、a-b-cやa-z0-9や-a-zのような場合も処理できるようにせよ。先頭および最後の-は文字とみなすことにする。

#include <stdio.h>
#include <ctype.h>

void expand(const char *s,char *out) {
    int i;
    
    for(;*s;++s){
        if (islower(*s) && *(s+1) == '-' && islower(*(s+2)) ||
            isupper(*s) && *(s+1) == '-' && isupper(*(s+2)) ||
            isdigit(*s) && *(s+1) == '-' && isdigit(*(s+2)) ) {
            if ( *(s+2) - *s > 0 ) {
                for(i=*s;i<=*(s+2);++i) {
                    *out++ = (char)i;
                }
                s++;
            }
        }
    }
    
    *out = '\0';
}

int main (void) {
    char str[1000];
    expand("a-b-cddd-a-z0-9-",str);
    printf("%s",str);
    return 0;
}
$ main
abbcabcdefghijklmnopqrstuvwxyz0123456789

a-b-cの展開をどうしようか迷ったんだけど、これはa-bとb-cの二つであるという実装にした。つまり「abbc」となる。

あとif文の中が凄いことに。最初はもっとisalnum関数使ってシンプルな実装になってたんだけど「0-z」とかまで解釈されてしまってバグってたので大文字小文字数字で処理分けすることにしました。

模範解答が知りたいところですね。