warning: comparisons like ‘X<=Y<=Z’ do not have their mathematical meaning
warning: result of comparison of constant X with boolean expression is always true
警告:if(X<=Y<=Z)に数学的意味はありません
[-Wtautological-constant-out-of-range-compare]
[-Wparentheses]
■if(X<=Y<=Z)で範囲の指定はできない
#include <stdio.h>
const char *grade(int x){
if(0 <= x <= 9) return "不可";
if(10 <= x <= 59) return "可";
if(60 <= x <= 79) return "良";
if(80 <= x <= 100) return "優";
return "採点不能";
}
int main(void){
for(int i = -1 ; i<=101;i++){
printf("%3d点は%s\n",i,grade(i));
}
}
自然言語に近い表現ですが
意図した動きをしません。
if(0 <= x <= 9)
↓
if((0<=x)<=9
↓
if(論理式<=9)
↓
if(真<=9)か
if(偽<=9)になる
↓
if(1<=9)
if(0<=9)のどちらかになるが、
どちらも、必ず成立する。
■数直線を意識した範囲の指定(推奨)
#include <stdio.h>
const char *grade(int x){
if(0 <= x && x <= 9) return "不可";
if(10 <= x && x <= 59) return "可";
if(60 <= x && x <= 79) return "良";
if(80 <= x && x <= 100) return "優";
return "採点不能";
}
int main(void){
for(int i = -1 ; i<=101;i++){
printf("%3d点は%s\n",i,grade(i));
}
}
意図した動きをします。
自然言語に近く数直線に近いイメージで
読みやすいと思います。
■超える、未満で範囲の指定
#include <stdio.h>
const char *grade(int x){
if(-1 < x && x < 10) return "不可";
if(9 < x && x < 60) return "可";
if(59 < x && x < 80) return "良";
if(79 < x && x < 101) return "優";
return "採点不能";
}
int main(void){
for(int i = -1 ; i<=101;i++){
printf("%3d点は%s\n",i,grade(i));
}
}
意図した動きをしますが
数字が
増えたり
減ったりで理解しずらいかも。
■変数を左辺に書く範囲の指定
#include <stdio.h>
const char *grade(int x){
if(x >= 0 && x <= 9) return "不可";
if(x >= 10 && x <= 59) return "可";
if(x >= 60 && x <= 79) return "良";
if(x >= 80 && x <= 100) return "優";
return "採点不能";
}
int main(void){
for(int i = -1 ; i<=101;i++){
printf("%3d点は%s\n",i,grade(i));
}
}
主語(変数)を左辺に書いたほうが
読みやすいと主張する人も多くいます。
■else ifでつないだ範囲の指定
#include <stdio.h>
const char *grade(int x){
const char *ret = "採点不能";
if(x < 0){
ret = "採点不能";
}
else if(0 <= x && x <= 9){
ret = "不可";
}
else if(10 <= x && x <= 59){
ret = "可";
}
else if(60 <= x && x <= 79){
ret = "良";
}
else if(80 <= x && x <= 100){
ret = "優";
}
else {
ret = "採点不能";
}
return ret ;
}
int main(void){
for(int i = -1 ; i<=101;i++){
printf("%3d点は%s\n",i,grade(i));
}
}
筆者が嫌いな
関数出口一つルールを守った修正例。
■最適化した範囲の指定
#include <stdio.h>
const char *grade(int x){
const char *ret = "採点不能";
if(x < 0){
ret = "採点不能";
}
else if(x <= 9){
ret = "不可";
}
else if(x <= 59){
ret = "可";
}
else if(x <= 79){
ret = "良";
}
else if(x <= 100){
ret = "優";
}
else {
ret = "採点不能";
}
return ret ;
}
int main(void){
for(int i = -1 ; i<=101;i++){
printf("%3d点は%s\n",i,grade(i));
}
}
最適化した修正例ですが、
if文の順番を変えると
意図した動きをしなくなります。
■gccの拡張機能を使った範囲の指定
#include <stdio.h>
const char *grade(int x){
switch(x){
case 0 ... 9: return "不可";
case 10 ... 59: return "可";
case 60 ... 79: return "良";
case 80 ... 100:return "優";
default: return "採点不能";
}
}
int main(void){
for(int i = -1 ; i<=101;i++){
printf("%3d点は%s\n",i,grade(i));
}
}
自然言語に一番近い分かりやすい表現ですが、
gcc/clangの拡張機能です。
拡張機能は
使用が禁止されている業界もあります。