(TAT)chaN's Blog

情報科学へのアプローチ痕跡

円滑なデバッグを

プログラミングにおけるデバッグ…それはなるべく避けたいもの。

たとえ、注意を払っていても、ミスはする。

競技プログラミングなら尚更、高速コーディングが必要になり、

デバッグ作業は付き物である。

 

そこで、デバッグが必要となる原因要素を挙げてみる。

まずは典型的で有名なものを。

 

【実行したら異常】

・配列外アクセス (Array Index Out Of Bounds Exception)

  ※ 例 int a[10]; a[10] = 123;

・スタックオーバーフロー (Stack Overflow Exception)

  ※ 再帰しすぎ。return; が実行されない。

 

本題はここから。

「コーディングできてるはずなのに!なんで?」

という場合の、デバッグポイントを挙げてみる。

( 競技プログラミングでジャッジフィードバッグが不正解の時) 

 

 

 

デバッグポイント】

 

出力形式があっているか。(改行、大文字、小文字、要素数、桁数)

   ※ "YES" , "Yes" や "NG" , "NA" の出力ミス。 (5/6修正)

 

・入力制限下での最小値最大値での実行ができるか。(フローの処理、型は適当か)

   ※最大値で初期化すると、演算でフローしてる場合がある。

 

・稀にある特別な入力に対して実行できるか。(乱数による実験も視野に)

   ※マップであれば 1×□ , □×1 など試す必要がある。

 

浮動小数点の計算における誤差が発生していないか。

   ※宣言型と演算型の確認。自動キャスト注意。if(d1==d2) はNG。(7/5追記)

 

・値の初期化が間違っていないか。(必要か、本当に不要か)

   ※boolean型でのtrue,false混用、またintでの0,1初期化ミス。

 

データセット二つ目に対して実行できるか。(正常な場所での初期化)

   ※データセットの入れ替えでチェックすること。大域変数注意。(5/5修正)

 

・配列要素のインデックス指定ミスしていないか。(単純に i と j など)

   ※ i , j だけでなく x , y を使っている場合、ソースミスの場合あり。

 

・if文 や for文 の条件式はあっているか。(イコール = 時の処理 また == の指定)

   ※ i<N , i>=0 など配列外アクセス絞りでミスあるかも。

 

・ループ初回と最終回で想定外の挙動はしていないか。

   ※値の代入また出力より先にbreak,returnをしてしまう。

 

・i , 1 , l , I や 0 , O , o などの似た文字混用で指定ミスしていないか。

   ※条件式で i と 1 は意外と多い。

 

・入力値は正常に受け取れているか。(scanfの%cやnext()とnextLine()の注意)

   ※改行文字をどう扱うか。%cと%sの同時利用注意。

 

・終端文字 '\0' や ポインタ終端 NULL の記述ミスはないか。

   ※%sでの出力に終端文字が不適切の場合あり。

 

問題の意図にあっているか (違う処理をしている)

   ※出力順序、データの再利用範囲。

 

・問題だけでなくテストケースを確認する (ヒントがあるかも)

   ※手でトレースの必要を考える。

 

・問題解決のアルゴリズムのミスはないか(考えが甘いかも)

   ※計算の例外がある可能性あり。

 

・クラスがMainではない、またメインメソッド(関数)がない。(言語指定ミスも)

   ※競技プログラミングではジャッジの為のソース提出で指定がある。

 

文字リテラルに対しての処理。(文字だけでなく数字に対してチェック)

   ※文字から'0'を引いて整数値にし忘れる。 (5/5追記)

 

インクリメントの混用

   ※ ++i と i++ と i=i+1 は違う。ループまた再帰内でのインクリメント (6/2追記)

 

・条件式の実行階層や条件

   ※ else if と if での挙動違いミス (7/16追記)

 

データ構造の欠陥

   ※ 配列要素数 等の欠落 (7/21追記)

 

以上を確認すれば、ほとんど解決すること。

ただ、慣れないうちは、時間がかかるかもしれない。