前回修正したコードは以下になる。
初期コード
#include <stdio.h>
int main(void) {
char inputCharactors[1000];
char outputCharactor;
int i = 0;
int modeFlag;
printf("暗号作成の時は0を\n暗号解読のときは1を\n終了するときは2を入力してください:");
scanf("%d",&modeFlag);
if (modeFlag == 0 || modeFlag == 1) {
if (modeFlag == 0)
printf("暗号化させたい文を入力してください\n");
else
printf("解読させたい文を入力してください\n");
scanf("%s",inputCharactors);
while (inputCharactors[i] != '\0') {
if (inputCharactors[i] >= 65 && inputCharactors[i] <= 77)
outputCharactor = inputCharactors[i] + 13;
else if (inputCharactors[i] >= 78 && inputCharactors[i] <= 90)
outputCharactor = inputCharactors[i] - 13;
else if (inputCharactors[i] >= 97 && inputCharactors[i] <= 109)
outputCharactor = inputCharactors[i] + 13;
else if (inputCharactors[i] >= 110 && inputCharactors[i] <= 122)
outputCharactor = inputCharactors[i] - 13;
else outputCharactor = inputCharactors[i];
printf("%c", outputCharactor);
i++;
}
i = 0;
}
else if (modeFlag == 2)
return 0;
else
printf("正しい数字を入力してください(怒)");
printf("\n");
}
変数名が意味を表すようになったため、多少の可読性向上が見られた。しかし、まだパッと見で理解しにくい部分が多いだろう。
今回は、表題にある通り「定数化」について考えていく。
目次
定数化について
まずは先ほどのプログラムを一部抜粋する。
if (inputCharactors[i] >= 65 && inputCharactors[i] <= 77)
outputCharactor = inputCharactors[i] + 13;
else if (inputCharactors[i] >= 78 && inputCharactors[i] <= 90)
outputCharactor = inputCharactors[i] - 13;
else if (inputCharactors[i] >= 97 && inputCharactors[i] <= 109)
outputCharactor = inputCharactors[i] + 13;
else if (inputCharactors[i] >= 110 && inputCharactors[i] <= 122)
outputCharactor = inputCharactors[i] - 13;
この処理の意図がすぐに理解できる人は、かなりのプログラミング経験者だと思う。この処理は、1文字ずつチェックし、以下のロジックを適用している。
- A〜Mの文字であれば+13してN〜Zに変換
- N〜Zの文字であれば-13してA〜Mに変換
このコードが分かりにくい理由は、「マジックナンバー(意味のある数値がプログラム内に直接記述されていること)」を使用しているからだ。
マジックナンバーの問題点
マジックナンバーを使うと、コードの可読性が下がるだけでなく、将来的な改修が困難になる。たとえば、「小文字は変換対象から除外する」という仕様変更を求められた場合、どの部分を修正すればよいのか判断しにくくなるだろう。
そこで、意味のある数値を定数化する。
修正後コード
#include <stdio.h>
const int SMALL_A = 97;
const int SMALL_M = 109;
const int SMALL_N = 110;
const int SMALL_Z = 122;
const int LARGE_A = 65;
const int LARGE_M = 77;
const int LARGE_N = 78;
const int LARGE_Z = 90;
const int ENCRYPT_NUMBER = 13;
enum ModeFlag {
ENCRYPT = 0,
DECRYPT = 1,
EXIT = 2
};
int main(void) {
char inputCharactors[1000];
char outputCharactor;
int i = 0;
int modeFlag;
printf("暗号作成の時は0を\n暗号解読のときは1を\n終了するときは2を入力してください:");
scanf("%d",&modeFlag);
if (modeFlag == ENCRYPT || modeFlag == DECRYPT) {
if (modeFlag == ENCRYPT)
printf("暗号化させたい文を入力してください\n");
else
printf("解読させたい文を入力してください\n");
scanf("%s",inputCharactors);
while (inputCharactors[i] != '\0') {
if (inputCharactors[i] >= LARGE_A && inputCharactors[i] <= LARGE_M)
outputCharactor = inputCharactors[i] + ENCRYPT_NUMBER;
else if (inputCharactors[i] >= LARGE_N && inputCharactors[i] <= LARGE_Z)
outputCharactor = inputCharactors[i] - ENCRYPT_NUMBER;
else if (inputCharactors[i] >= SMALL_A && inputCharactors[i] <= SMALL_M)
outputCharactor = inputCharactors[i] + ENCRYPT_NUMBER;
else if (inputCharactors[i] >= SMALL_N && inputCharactors[i] <= SMALL_Z)
outputCharactor = inputCharactors[i] - ENCRYPT_NUMBER;
else outputCharactor = inputCharactors[i];
printf("%c", outputCharactor);
i++;
}
i = 0;
}
else if (modeFlag == EXIT)
return 0;
else
printf("正しい数字を入力してください(怒)");
printf("\n");
}
この修正により、以下の改善が実現された。
- 文字コードを表す数値を定数化し、どの範囲の文字に+13または-13するのかが分かりやすくなった。
- 暗号化・解読のモードをenumで定義し、モードの判別が容易になった。
結果として、可読性が向上し、将来的な仕様変更にも対応しやすくなったと思う。
プログラム上のマジックナンバーを定数化しよう。
さて、次回はどのようにリファクタしようかな。