初心者のためのC#プログラミング本格入門59 - 類似したプログラムとの差を考え改良していこう
前回のサンプルプログラムは、いくつか改良するべき点があります。その中で最も大きな違いは、呼び出すメソッドです。AddValuesメソッド内では、個々の値を取得するためにTryValueを呼び出しています。一方、DivisionAnalyzerメソッド内では、式を分解するためにCutExpressionメソッドを呼び出しています。その違いが成否の大部分を占めています。
その差を考えるために、両方のメソッドを見比べてみましょう。
static System.Tuple<bool, float, string> TryValue( string inputValue )
{
//各種変数を準備
int startIndex = 0;
int endIndex = inputValue.Length;
bool startFlag = false;
//数字の初めと終わりを記録
for ( int i = 0; i < inputValue.Length; i++ )
{
if ( System.Char.IsDigit( inputValue[ i ] ) == true )
{
//初めて数字が出たら位置を記録
if ( startFlag == false )
{
startIndex = i;
startFlag = true;
}
}
else if ( startFlag == true )
{
//数字が途切れたら位置を記録してループ終了
endIndex = i;
break;
}
}
//数値を取り出す
int count = endIndex - startIndex;
string outputValueString =
inputValue.Substring( startIndex, count );
float outputValue = 0;
bool success =
float.TryParse( outputValueString, out outputValue );
if ( success == false )
{
System.Tuple<bool, float, string> result =
new System.Tuple<bool, float, string>(
false, 0, inputValue );
return result;
}
//取り出した数値以外の文字列を取得
string remain = inputValue.Remove( startIndex, count );
//結果を返す
System.Tuple<bool, float, string> result1 =
new System.Tuple<bool, float, string>(
true, outputValue, remain );
return result1;
}
static System.Tuple<bool, string, string> CutExpression(
string expression )
{
//()記号の範囲を決定
int startIndex = -1;
int endIndex = -1;
for ( int i = 0; i < expression.Length; i++ )
{
char tmp = expression[ i ];
if ( tmp == '(' )
{
startIndex = i + 1;
continue;
}
if ( tmp == ')' )
{
endIndex = i;
break;
}
}
//エラー判定
if ( startIndex == -1 | endIndex == -1 )
{
System.Tuple<bool, string, string> error =
new System.Tuple<bool, string, string>(
false, expression, "" );
return error;
}
//()内の式を取り出す
int count = endIndex - startIndex;
string cutExpression = expression.Substring(
startIndex, count );
System.Tuple<bool, string, string> result =
new System.Tuple<bool, string, string>(
true, expression, cutExpression );
return result;
}
2つのプログラムを簡単に見比べるために、コメントを見てみましょう。そうすれば、2つのプログラムの違いが、大まかに分かります。TryValueメソッドにある「//取り出した数値以外の文字列を取得」に該当するプログラムが、CutExpressionメソッド内にはありません。という事は、「取り出した式以外の文字列を取得するプログラムが足りない事が分かります。足りないプログラムを足すと次の様になります。
static System.Tuple<bool, string, string> CutExpression(
string expression )
{
//()記号の範囲を決定
int startIndex = -1;
int endIndex = -1;
int parenthesis = -1;
for ( int i = 0; i < expression.Length; i++ )
{
char tmp = expression[ i ];
if ( tmp == '(' )
{
parenthesis = i;
startIndex = i + 1;
continue;
}
if ( tmp == ')' )
{
endIndex = i;
break;
}
}
//エラー判定
if ( startIndex == -1 | endIndex == -1 )
{
System.Tuple<bool, string, string> error =
new System.Tuple<bool, string, string>(
false, expression, expression );
return error;
}
//()内の式を取り出す
int count = endIndex - startIndex;
string cutExpression = expression.Substring( startIndex, count );
//取り出した式以外の文字列を取得
int coutCount = endIndex - parenthesis + 1;
string remain = expression.Remove( parenthesis, coutCount );
//結果を返す
System.Tuple<bool, string, string> result =
new System.Tuple<bool, string, string>(
true, remain, cutExpression );
return result;
}
これで完成に近づきました。まだ改良するべき点がありますが、次の改良は次回で行います。この様に初心者は、上手くいったプログラムと比較して改良する方法を採るとプログラミングがしやすいと思います。初心者の頃は、いきなり正しいプログラムを作ろうとしても大概は上手くいかないと思います。その頻度は違いますが、たとえプロであっても躓く事があるかと思います。
初心者の頃は、特にじっと考えているよりも、手を動かした方がうまくいく場合が多々あります。とはいえ、ただ闇雲に手を動かせばよいというものではありません。考えながら手を動かす必要があります。
その思考方法は多々ありますが、初心者が実行できるのが今回紹介した方法です。私も初心者の頃はこの思考方法を使って、既存のプログラムを弄って思考錯誤を繰り返し学習しました。人は成功と失敗を繰り返して成長します。何事も失敗を恐れて何もしなければ成功する可能性は0%です。
最後に一つ注意をかきます。個の思考方法を試す場合は、成功したプログラムをこまめに別の場所へ保存しておきましょう。間違ってプログラムを元に戻したい時に、成功したプログラムのファイルがなければ、元に戻せない恐れがあります。失敗を予想して予め手を打っておきましょう。
無策に失敗するのと、あらかじめ準備して失敗するのとでは、結果に天と地の差が生まれます。くれぐれも注意しましょう。