初心者のためのC#プログラミング本格入門75 - バグ退治と賢い条件判断
前回で明らかになったバグは、「マイナス値を解析できない」です。このバグを修正するには、場所を特定せねばなりません。特定する方法はいくつもありますが、初心者の方がやりやすい手法は、呼び出しメソッドをたどっていく方法です。実際にやってみましょう。
最初のメソッドは、AnalyzeExpressionですね。これはOKだと思います。このメソッドのコードを読むと、数値を取り出すのはAddValuesメソッドだという事が分かります。さらにAddValuesメソッドのコードを読むと、TryValueメソッドで一つの値を決定している事が分かります。つまり、AnalyzeExpression → AddValues → TryValueの順番でバグを探したわけです。コメントを書いているので、容易にたどれたと思います。この例からもわかると思いますがコメントがあると便利です。
さて、ここからが本題です。バグの場所に検討をつけたので、核心に迫りましょう。TryValueメソッドは、数字の初めと終わりを記録してから、文字列から数値を取り出しています。この処理方式をよく考えると、「-10」の様なマイナス値の符号を、数値を表す文字列の先頭だと見做していない事が分かります。何故ならば、前回のテストMinusValueCheckにて、0以上の値が返されているからです。目で確認したい人は、テストコードの「if ( this.target.Values[ 0 ] >= 0 )」部分にブレークポイントを設定して、止まったら画面下にあるローカルウィンドウを見てみましょう。
ローカルウィンドウで確かめる方法は、「this」の横に表示されている+をクリックして、ツリーを展開していきます。この場合、this → target → Values とツリーを展開していくと値が10になっている事を確認できます。ローカルウィンドウは便利なので、使い方を練習しておきましょう。
バグの原因とおよその場所が分かったら後は簡単です。マイナス符号がついていたら数値の一部と看做す事にしましょう。早速、自分でプログラミングしてみて下さい。これから模範解答を示します。
static System.Tuple 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 )
{
//マイナス値かどうか確認
if ( i != 0 & inputValue[ i - 1 ] == '-' )
{
startIndex = i - 1;
}
else
{
startIndex = i;
}
startFlag = true;
}
}
else if ( startFlag == true )
{
//数字が途切れたら位置を記録してループ終了
endIndex = i;
break;
}
}
//他は同じなので省略
では、ブレークポイントの設定を解除してから、デバッグ実行してみて下さい。エラーが表示されます。表示されたエラー文をよく読んで下さい。「if ( i != 0 & inputValue[ i - 1 ] == '-' )」の場所でインデックスが云々と表示されます。これは、インデックスである変数iが0の時に1減算してから、配列にアクセスしたのが原因で発生するエラーです。普通の人は「あれおかしいな。変数iが0でない事を確認しているぞ。」と考えるでしょう。でも、if文内のAND論理演算に落とし穴があります。それは、両方の条件を判定してしまう点です。両方を判定しまうとなると、配列の-1の場所にアクセスしてしまいます。これは非常に問題ですね。
この問題を解決するには、察しがいい人はif分を入れ子(if文の中で再びif分を記述)気付くでしょう。こんな具合です。
//マイナス値かどうか確認
if ( i != 0 )
{
if ( inputValue[ i - 1 ] == '-' )
{
startIndex = i - 1;
}
else
{
startIndex = i;
}
}
else
{
startIndex = i;
}
でもこれ、読み難いですよね。もっと簡潔なコードを書きたいのが人情というものでしょう。こんな場合にC#には、短絡評価という文法があります。それを使うと・・・
//マイナス値かどうか確認
if ( i != 0 && inputValue[ i - 1 ] == '-' )
{
startIndex = i - 1;
}
else
{
startIndex = i;
}
「&&」と二回アンパサンド記号を記述しています。たったそれだけでOKです。なんてエコなんでしょうか。簡潔なコードは善です。短絡評価を積極的に使いましょう。C#の文法は多くて覚えられないとか、あんなに文法があったら難しいと思っている初心者の方が多いと思います。でも、短絡評価の例をみると分かりますが、C#の文法は冗長な記述を簡潔にするためにあります。ひとまず少数の文法を学んで、コードが冗長で面倒に感じたら新しい文法を覚えたらいいのです。