呼ばれたコマンド名によって処理分けする

K&R本 演習7-1

argv[0]にあるどんな名前で呼ばれたかにより、大文字を小文字に、あるいは小文字を大文字に変換するプログラムを書け。

なんだか凄いトリッキーな処理ですね。実行したときの名前によって処理分けするなんて本来ならやっちゃいけなさそうな感じです。

演習なのでとりあえずやってみます。

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

int main (int argc,char *argv[]) {
    char *name = *argv;
    size_t len = strlen(name);
    int c;
    int (*to)(int) = NULL;
    
    if ( len > 7 ) {
        len -= 7;
        name += len;
    }
    
    if ( strcmp(name,"tolower") == 0 ) {
        to = tolower;
    }
    else if ( strcmp(name,"toupper") == 0 ) {
        to = toupper;
    }
    else {
        puts("unknown command error");
        return 1;
    }
    
    while( (c=getchar()) != EOF ) {
        putchar((*to)(c));
    }
    
    return 0;
}
$ cl /Fetoupper.exe main.c
$ cat main.c | toupper
#INCLUDE <STDIO.H>
#INCLUDE <CTYPE.H>
#INCLUDE <STRING.H>

INT MAIN (INT ARGC,CHAR *ARGV[]) {
    CHAR *NAME = *ARGV;
    SIZE_T LEN = STRLEN(NAME);
    INT C;
    INT (*TO)(INT) = NULL;

    IF ( LEN > 7 ) {
        LEN -= 7;
        NAME += LEN;
    }

    IF ( STRCMP(NAME,"TOLOWER") == 0 ) {
        TO = TOLOWER;
    }
    ELSE IF ( STRCMP(NAME,"TOUPPER") == 0 ) {
        TO = TOUPPER;
    }
    ELSE {
        PUTS("UNKNOWN COMMAND ERROR");
        RETURN 1;
    }

    WHILE( (C=GETCHAR()) != EOF ) {
        PUTCHAR((*TO)(C));
    }

    RETURN 0;
}

できました。最初に7引いたりしてる処理は「$ ./toupper」で呼ばれると「./」がargv[0]に含まれるのでそうしています。

それにしても凄い処理です。