【C言語】
不要なelseを削除しよう!
(No-else-return)

warning: do not use ‘else’ after ‘return’

警告:return直後のelseは要らない
[readability-else-after-return]


■1.修正元ソース(非推奨)

char    *f1(char    *line){
	if (!strchr(line, '/')) {
		if (!strchr(line, '*')) {
			return addid(1,line);
		}
		return addid(2,line);
	}
	return addid(3,line);
}   

ぱっと見、何やってるか分からない。

2.else を追加

char    *f2(char *line){
    if (!strchr(line, '/')) {
        if (!strchr(line, '*')) {
            return addid(1,line);
        } else {
            return addid(2,line);
        }
    } else {
        return addid(3,line);
    }
}

経路漏れが無いのはわかるが、
まだ何やってるか分かりにくい。

3.条件を逆にして否定形!を使わない(やや推奨)

char *f3(char *line){
    if (strchr(line, '/')) {
        return addid(3,line);
    } else {
        if (strchr(line, '*')) {
            return addid(2,line);
        } else {
            return addid(1,line);
        }
    }
}

否定形が無いほうが分りやすい。

4.else if を使う


char *f4(char *line){
	if (strchr(line, '/')) {
        return addid(3,line);
    } else if (strchr(line, '*')) {
        return addid(2,line);
    } else {
        return addid(1,line);
    }
}

だいぶ分りやすくなった。

5.不要なelseを削除しよう!(推奨)

char *f5(char *line){
    if (strchr(line, '/'))  
        return addid(3,line);  
    if (strchr(line, '*'))  
        return addid(2,line);
    return addid(1,line);
}

不要な else を削除すると、
筆者でもわかる
単純明快な構造となった。

6.まとめ(コンパイル可能な全コード)

#include    <stdio.h>
#include    <string.h>
#include    <assert.h>
char    *addid(int id,char *line);
//リファクタリング元ソース
char    *f1(char    *line){
	if (!strchr(line, '/')) {
		if (!strchr(line, '*')) {
			return addid(1,line);
		}
		return addid(2,line);
	}
	return addid(3,line);
}   
// else を追加
char    *f2(char *line){
    if (!strchr(line, '/')) {
        if (!strchr(line, '*')) {
            return addid(1,line);
        } else {
            return addid(2,line);
        }
    } else {
        return addid(3,line);
    }
}    
//条件を逆にして否定形!を使わない
char *f3(char *line){
    if (strchr(line, '/')) {
        return addid(3,line);
    } else {
        if (strchr(line, '*')) {
            return addid(2,line);
        } else {
            return addid(1,line);
        }
    }
}
// else if を使う
char *f4(char *line){
	if (strchr(line, '/')) {
        return addid(3,line);
    } else if (strchr(line, '*')) {
        return addid(2,line);
    } else {
        return addid(1,line);
    }
}
// else を使わない
char *f5(char *line){
    if (strchr(line, '/'))  
        return addid(3,line);  
    if (strchr(line, '*'))  
        return addid(2,line);
    return addid(1,line);
}
int main(void){
    char *input = "/usr/include/stdio.h";
    FILE *fp = fopen(input,"re");
    char    buf[BUFSIZ];
    while(fgets(buf,BUFSIZ,fp) != NULL){
        char *s1 = f1(buf);
        char *s2 = f2(buf);
        char *s3 = f3(buf);
        char *s4 = f4(buf);
        char *s5 = f5(buf);
        printf("%s",s1);
        if(strcmp(s1,s2)!=0)    assert(0);
        if(strcmp(s1,s3)!=0)    assert(0);
        if(strcmp(s1,s4)!=0)    assert(0);
        if(strcmp(s1,s5)!=0)    assert(0);
    }
    fclose(fp);
}
//行頭にID追加
char *addid(int id,char *line){
    static char buf[BUFSIZ];
    sprintf(buf,"%d:%s",id,line);
    return buf ;
} 

f1()関数~f5()関数まで
やってる事は皆同じである事を
検証するプログラムです。

筆者はf5()関数が一番わかりやすのですが、
皆さんはどれが一番わかりやすいですか?