Code Fix

中級

strcmpの戻り値を真偽値と勘違いして条件が逆になる

strcmpは文字列が等しいときに0を返します。if (strcmp(a, b))と書くと「等しくないとき」に真になり、多くの人が期待する「等しいとき」とは逆の分岐になります。

なぜエラーが出ないのか

出力: no match
(エラーなし)
Cは何も報告しません。コンパイルも実行も正常に完了するためです
出力: no match
実際の挙動 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  #include <stdio.h>
 2  #include <string.h>
 3  
 4  int main(void) {
 5      char name[] = "Taro";
 6      if (strcmp(name, "Taro")     ) {
                        ^
 7          printf("match\n");
 8      } else {
 9          printf("no match\n");
10      }
11      return 0;
12  }
出力: no match期待: match

strcmpは文字列が等しいときに0を返します。0はCでは偽なので、if(strcmp(...))とだけ書くと「一致しない」ときに真になってしまいます。等しいか調べたいときは== 0を付けます。

直し方: strcmp(name, "Taro")strcmp(name, "Taro") == 0 にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  #include <stdio.h>
 2  #include <string.h>
 3  
 4  int main(void) {
 5      char color[] = "red";
 6      if (strcmp(color, "red")     ) {
                        ^
 7          printf("is red\n");
 8      } else {
 9          printf("not red\n");
10      }
11      return 0;
12  }
出力: not red期待: is red

colorは実際に"red"と一致していますが、strcmpの戻り値をそのままifの条件にすると、一致(0)が偽と評価されるため逆の分岐に入ります。

直し方: strcmp(color, "red")strcmp(color, "red") == 0 にします。

この問題を解いてみる →

パターン3

 1  #include <stdio.h>
 2  #include <string.h>
 3  
 4  int main(void) {
 5      char cmd[] = "quit";
 6      if (strcmp(cmd, "quit")     ) {
                        ^
 7          printf("quit\n");
 8      } else {
 9          printf("continue\n");
10      }
11      return 0;
12  }
出力: continue期待: quit

cmdは"quit"そのものなのに、strcmpの結果を裸のままifに渡すと、意図と正反対の分岐に入ってしまいます。

直し方: strcmp(cmd, "quit")strcmp(cmd, "quit") == 0 にします。

この問題を解いてみる →

よくある誤解

「trueっぽい名前の関数はtrueで成功を表す」という直感はここでは裏切られます。strcmpの0は「差が無い」という意味であり、Cでは0は偽と評価されるため、素直にif(strcmp(...))と書くと「文字列が違うときに実行される」コードになってしまいます。等しいかどうかを見たいときはif (strcmp(a, b) == 0)と書きます。

まとめ

strcmpの戻り値を真偽値と勘違いして条件が逆になるは中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)