ソースコードと因数分解
ちょっと長文書くぞ巡回 - いろきゅう.jp // Programmable maiden traumend 〜夢見るPG〜 の中ほどから続き
プログラマに因数分解の概念は必要だと私は思います。即興の例であんまり良くないのですが^^;
ある値の配列から、最小値・最大値を取得したい場合…
int main() { // いろきゅうお兄さんな数値列 int anValues[] = { 1, 6, 9, 0, 2, 3 }; size_t nValueArraySize = sizeof(anValues) / sizeof(anValues[0]); int nMinValue; int nMaxvalue; // 最小値検索 nMinValue = anValues[0]; for(size_t i = 1; i < nValueArraySize; ++i) { if(anValues[i] < nMinValue) nMinValue = anValues[i]; } // 最大値検索 nMaxValue = anValues[0]; for(size_t i = 1; i < nValueArraySize; ++i) { if(anValues[i] > nMaxValue) nMaxValue = anValues[i]; } return 0; }
なんて書いてしまう人もいるかとは思いますが、ここは「配列を走査している」「なんか比較して値を取得してる」という共通部分に着目し、このアルゴリズムの部分を外部の関数に出しちゃう訳ですよ。すると
int ReturnMinValue(int l, int r) { return l < r ? l : r; } int ReturnMaxValue(int l, int r) { return l > r ? l : r; } int ScanValue(const int* anValueArray, size_t nArraySize, int (*fnBinary)(int, int)) { // エラーチェックしてないけどまぁいいや^^; -> ぬるぽとか int nRetValue = anValueArray[0]; for(size_t i = 1; i < nArraySize; ++i) nRetValue = fnBinary(nRetValue, anValueArray[i]); return nRetValue; } int main() { // いろきゅうお兄さんな数値列 int anValues[] = { 1, 6, 9, 0, 2, 3 }; size_t nValueArraySize = sizeof(anValues) / sizeof(anValues[0]); int nMinValue; int nMaxvalue; // 配列と比較用関数を渡して、最小値と最大値検索 nMinValue = ScanValue(anValues, nValueArraySize, &ReturnMinValue); nMaxValue = ScanValue(anValues, nValueArraySize, &ReturnMaxValue); return 0; }
こんな具合。「なんじゃこりゃ!悪化しとるやん!」なんて思われるかもしれませんが、実際の作業中は関数単位で物事考えていく訳ですから(割と自論^^;)
int main() { // いろきゅうお兄さんな数値列 int anValues[] = { 1, 6, 9, 0, 2, 3 }; size_t nValueArraySize = sizeof(anValues) / sizeof(anValues[0]); int nMinValue; int nMaxvalue; // 配列と比較用関数を渡して、最小値と最大値検索 nMinValue = ScanValue(anValues, nValueArraySize, &ReturnMinValue); nMaxValue = ScanValue(anValues, nValueArraySize, &ReturnMaxValue); return 0; }
を頭の中で管理すればよくなります。ScanValue という値を取得する為の処理を(あんまり適してない関数名だなぁ)名前を付けて外部に出した事により、元のfor文つかってごにょごにょしてるコードよりずっと分りやすくなってると私は思います。
この「共通部分を見つけ出して外に出す」という点で「ソースコードの因数分解」だと私は思ってるんですが、どーでしょーか。…少なからず因数はおかしいかも。
ちなみにですが、同様でもっと高機能な関数は C++ に標準で定義されているので^^;、私が書くとしたら
template<typename T, size_t N> size_t GetArraySize(T (&t)[N]){ return N; } int main() { // いろきゅうお兄さんな数値列 const int anValues[] = { 1, 6, 9, 0, 2, 3 }; const int* pValuesEnd = anValues + GetArraySize(anValues); const int nMinValue = *std::min_element(anValues, pValuesEnd); const int nMaxvalue = *std::max_element(anValues, pValuesEnd); return 0; }
とか。
stlが絡んできたら
int main() { typedef std::vector<int> TIntVect; // なんか値が入るとする TIntVect stlVect; const TIntVect::value_type nMinValue = *std::min_element(stlVect.begin(), stlVect.end()); const TIntVect::value_type nMaxValue = *std::max_element(stlVect.begin(), stlVect.end()); return 0; }
とかいう感じですかねー。:P
参考 / 元のコード
int main() { // いろきゅうお兄さんな数値列 int anValues[] = { 1, 6, 9, 0, 2, 3 }; size_t nValueArraySize = sizeof(anValues) / sizeof(anValues[0]); int nMinValue; int nMaxvalue; // 最小値検索 nMinValue = anValues[0]; for(size_t i = 1; i < nValueArraySize; ++i) { if(anValues[i] < nMinValue) nMinValue = anValues[i]; } // 最大値検索 nMaxValue = anValues[0]; for(size_t i = 1; i < nValueArraySize; ++i) { if(anValues[i] > nMaxValue) nMaxValue = anValues[i]; } return 0; }