初心者のためのC#プログラミング本格入門34 - 細かいメソッドをまとめて使いやすくしよう
前回の予告通り、「自由に計算式を指定して計算するプログラム」を強化する方法について考えてみます。先ずは処理全体の流れをおさらいします。
- コンソール画面から計算式を取得する。
- 計算式を分解して「数値1」「演算子」「数値2」を取得する。
- 数値1と数値2を実際の数値へと変換する。
- 変換した数値1と数値2、そして得られた演算子を元に計算を実行する。
- コンソール画面に、計算式と計算結果を出力する。
- ユーザーに計算を続けるか尋ねる。
- 計算を続ける場合は手順1へ戻る。
- 計算を終了する場合はここでプログラムを終了する。
この中で2が課題となっています。ですが、心配は要りません。今まで学んできた事を活用すれば実現可能です。2をAnalyzeExpressionメソッドとして作成します。Analyze(解析)となっているのは、分解にしてしまうとメソッドの使い方が限定されると考えたからです。解析にしておくと色々な用途に使えます。
では、AnalyzeExpressionメソッドを作成してみましょう。
static System.Tuple<bool, char, int[], int>
AnalyzeExpression( string inputValue )
{
//数値を取り出す
string tmp = inputValue;
bool loopFlag = true;
int[] values = new int[ 100 ];
int count = 0;
do
{
System.Tuple<bool, int, string> value = TryValue( tmp );
loopFlag = value.Item1;
if ( loopFlag == true )
{
++count;
int index = count - 1;
values[ index ] = value.Item2;
tmp = value.Item3;
}
} while ( loopFlag == true );
//符号を取り出す
System.Tuple< bool, char, string> signInfo = GetSign( tmp );
char sign = signInfo.Item2;
//結果を返す
bool success = count != 0 & signInfo.Item1 == true;
System.Tuple<bool, char, int[], int> result =
new System.Tuple<bool, char, int[], int>(
success, sign, values, count );
return result;
}
static System.Tuple<bool, char, string>
GetSign( string inputValue )
{
//演算子の位置を探す
int index = -1;
for ( int i = 0; i < inputValue.Length; i++ )
{
char sign = inputValue[ i ];
if ( sign == '+' | sign == '-' |
sign == '*' | sign == '/' | sign == '%' )
{
index = i;
break; //見つかったらループを止める
}
}
//演算子を取り出す
if ( index == -1 )
{
System.Tuple<bool, char, string> error =
new System.Tuple<bool, char, string>(
false, 'E', inputValue );
return error;
}
char outputValue = inputValue.Substring( index, 1 )[ 0 ];
//取り出した演算子以外の文字列を取得
string remain = inputValue.Remove( index, 1 );
//結果を返す
System.Tuple<bool, char, string> result =
new System.Tuple<bool, char, string>(
true, outputValue, remain );
return result;
}
static System.Tuple<bool, int, 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 ] ) )
{
//初めて数字が出たら位置を記録
if ( startFlag == false )
{
startIndex = i;
startFlag = true;
}
}
else if ( startFlag == true )
{
//数字が途切れたら位置を記録してループ終了
endIndex = i;
break;
}
}
//数値を取り出す
int count = endIndex - startIndex;
string outputValueString =
inputValue.Substring( startIndex, count );
int outputValue = 0;
bool success =
int.TryParse( outputValueString, out outputValue );
if ( success == false )
{
System.Tuple<bool, int, string> result =
new System.Tuple<bool, int, string>(
false, 0, inputValue );
return result;
}
//取り出した数値以外の文字列を取得
string remain = inputValue.Remove( startIndex, count );
//結果を返す
System.Tuple<bool, int, string> result1 =
new System.Tuple<bool, int, string>(
true, outputValue, remain );
return result1;
}
ちょっと長いですが、今まで学んできた「System.Tuple」、「配列」、「ループ」をマスターしていれば作成できます。学習する前だと手順2をどうやって作成すればいいのか分からなかったと思いますが、ちゃんと学習すれば出来るようになります。C#プログラミングは簡単な事柄の組み合わせなのです。このメソッドの使い方は・・・
static void Main()
{
//値を取得
string inputValue = " 0 + 1 + 2 + 3 + 4 + 5 ";
System.Tuple<bool, char, int[], int> result =
AnalyzeExpression( inputValue );
if ( result.Item1 == false )
{
string error = inputValue + "は有効な式ではありません。";
System.Console.WriteLine( error );
return;
}
char sign = result.Item2;
int[] values = result.Item3;
int count = result.Item4;
//取得した結果を表示
string message = "文字列【" +
inputValue + "】に含まれる情報は";
System.Console.WriteLine( message );
System.Console.Write( "符号:" );
System.Console.WriteLine( sign );
System.Console.Write( "数値:" );
for ( int i = 0; i < count; i++ )
{
System.Console.Write( values[ i ] + " " );
}
System.Console.WriteLine();
}
TryValue、GetSignなどといった細かい機能を持つメソッドよりも、使いやすい事が分かると思います。プログラミングは柔軟性が求められるので、細かな処理をするメソッドが必要になります。しかし、使う側からしてみれば、細かいメソッドだと面倒だと感じる場面があります。そういった場面も考え、使いやすいメソッドを考えるのがよいプログラマーです。
細かいメソッドを纏めた使いやすいメソッドも作成しましょう。プログラミングはプログラムの細かさを(粒度)コントロールする側面を持っています。熟練者は粒度の扱いが上手です。粒度の扱いになれるのが熟練者への道です。
今回は以上で終わりです。次回「自由に計算式を指定して計算するプログラム」を完成させます。