円滑なデバッグを
プログラミングにおけるデバッグ…それはなるべく避けたいもの。
たとえ、注意を払っていても、ミスはする。
競技プログラミングなら尚更、高速コーディングが必要になり、
デバッグ作業は付き物である。
そこで、デバッグが必要となる原因要素を挙げてみる。
まずは典型的で有名なものを。
【実行したら異常】
・配列外アクセス (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追記)
以上を確認すれば、ほとんど解決すること。
ただ、慣れないうちは、時間がかかるかもしれない。