■■ C++プログラミングのガイドライン ■■
平成7年4月4日作成
平成7年4月5日一部変更
平成8年11月25日サンプルプログラム追加
平成15年8月25日C++版に書き直し
本ガイドラインでは、C++言語を用いたプログラミングを効果的に行うための
注意事項をまとめている。主要な記述は構造化プログラミングの概念に従って
いるが、オブジェクト指向プログラミングを行う場合でもこれらの注意事項は
同様に適用される。
プログラミング概論・演習 I & II におけるC++プログラミングに当たっては、
以下で示すガイドラインに従ったプログラミングを行なうこと。
なお、他の講義・実験・演習・卒業論文などにおいても、効果的なプログラミ
ングを行なうために、このガイドラインを遵守することを推奨する。
■ サンプルプログラム ■
-
-
プログラミングに当たっての心構え
- 自分にも他人にも分かりやすいプログラムの作成を心掛ける。そのため
にプログラムが冗長になることは許容する。(ただし、必要のないことは書か
ない)
- プログラム中で使用している機能は十分理解する。理解していない機能
は、バグの原因に極めてなりやすい。
- コンパイラの警告メッセージは無視しない。警告が出た場合には、その
理由を考え、警告メッセージを消すように努力する。
- プログラムの修正は正当な(他人に説明できる)理由がある場合にのみ行
なう。エラーメッセージを消すために試みに修正しない。また、試みに修正し
てみてから後で動作を確認する癖をつけない。
プログラム作成の系統的な方法
- 以下に、プログラム作成を行なうための系統的な手順を示す。実際のプ
ログラミングの際に参考にすると良い。
- ステップ1 プログラム(関数)の設計と検査
- プログラムの入出力を明確にする。
- プログラムに名前をつける。
- アルゴリズムを(日本語で)記述する。
- アルゴリズムに必要なデータを定義する。
- 以上の作業を反復確認する。
- ステップ2 プログラム(関数)のコーディング
- プログラムの宣言部を書く。
- アルゴリズムの各行を高水準のコメントとする。
- それぞれのコメントの下に対応するコードを埋め込む。
- アルゴリズムとコードが一貫しているか確認する。
- 以上の作業を反復確認する。
- ステップ3 コードの検査
- プログラム(関数)を机上で実行する。他のプログラマに動作を説明する。
- 机上での動作確認の後、コンパイルする。
- コンパイルエラーを修正する。
- プログラムを実行してテストする。
- エラーが発見されれば、デバッギングを行なう。(デバッギングの項を参
照すること)
- 直前のステップが完了してから、次のステップに進むこと。
デバッギングについて
- コンパイラのエラーメッセージを良く読む。
- アルゴリズムやプログラムを読み直して、机上でデバッグを行なう。
- 予定に反するプログラムの出力値や、デバッガなどによって調べたおか
しな変数値からエラーの原因を予想する。
- デバッガを用いて上記のバグの予想が正しいことを確認する。
- プログラムを他人に説明することでバグが発見されることも多い。
- バグの原因が特定されないうちは、ソースコードを不用意に修正しない。
- 以前に行なった修正が正しいものであったことを確認する。
コンパイラについて
- コンパイラのエラーメッセージは、警告(warning)も含めて無視しない。
- ANSI規格のC++言語を用いる。
-
プログラムの書式
- C++プログラムの一般形式は、以下の書式に従うこと。
#include ファイルの宣言
#define による定数定義
typedef による型の定義
関数のプロトタイプ宣言
大域変数の定義
main 関数の定義
その他の関数の定義
実行文のレイアウトについて
- 一行には一つの実行文だけを書く。
- インデンテーションを行なう。(4タブ利用。{, } のレイアウトは K&R
スタイルを用いる。)
- 互いに関連の深い文の並び毎に空白行で区切る。
- 空白行で区切られた文の並び毎にコメントをつける。
- コメントでは、コードの動作を説明するのではなく、コードの意図を説
明する。
-
関数の定義について
- 関数は一つだけの機能を果たすように設計する。
- 関数の機能をコメントする。
- main を除くすべての関数はプロトタイプ宣言する。
- 関数内で使用するデータだけを引数として渡す。
- 関数の引数は最大7個程度に限定する。それ以上の数の引数を渡す必要が
ある場合には、構造体や配列などの構造化データを利用する。
- 原則として、引数で与えられていない大域変数をアクセスしない。
- 大域変数をアクセスする関数は、その旨をコメントする。
- 値を返すように宣言されている関数は、必ず return文で値を返す。
- 関数内のreturn文の使用は、できるだけ少なくなるように工夫する。
- 戻り値のある関数を呼び出したルーチンは、戻り値を検査する。
coutについて
- 一行に表示されるメッセージは、原則として一つの coutで
書く。
- 複数行に渡るメッセージを一つのcoutで出力しない。
データ入力について
- データ入力には原則としてcinを用いる。
- 文字データは get関数で読む。
- 文字列データは getline関数で読む。
-
定数、変数、関数の命名について
- 下線で始まる名前をつけない。
- 変数名と関数名は原則として小文字を使用する。
- 定数名は大文字を使用する。
- 変数/定数の使用目的と一致した名前をつける。
- 関数の機能と一致した名前をつける。
- 複数の単語からなる名前は大文字や下線を用いて単語の区切りを明示す
る。
- 1(イチ)とl(エル)、0(ゼロ)とo(オー)とO(大文字オー)のような間違いや
すい文字に注意する。
定数の定義について
- 定数は #define マクロを用いて定義する。
- 定数の使用目的についてコメントをつける。
変数の定義について
- 一行に一つの変数を定義する。
- 一つの変数はただ一つの目的のために使用する。
- 変数の使用目的についてコメントをつける。
変数の使用について
- それぞれの変数は、使用される位置の近くで初期化する。
- 定義された変数は、すべて使用する。使用しない変数は、定義しない。
- 真に大域的であることが必要な変数を除き、すべての変数は局所的に定
義する。
- 大域変数を定義した場合には、それをアクセスするための関数をいくつ
か定義し、その関数(アクセスルーチン)だけに大域変数をアクセスさせる。
演算子について
- 演算子の優先順位を明確にするために、括弧 (, ) を使用する。
- 条件演算子の代わりに if文を使用する。
- コンマ式は for文の頭部でのみ使用する。
型変換について
- コンパイラによる自動型変換は、自明なもの(例:int→long、float→double)を除いて使用しない。
- 型変換が必要な場合には、明示的にキャストする。
typedefについて
- 変更される可能性のあるデータの種類毎に異なった型を使用する。
- 型の名前はプログラミング言語の型名に基づくものでなく、その型のデー
タが扱っている対象に基づいたものを使用する。
整数型/浮動小数点型データについて
- ゼロによる除算を行なう可能性がないことを確認する。
- 整数除算を含む式は、余りを切り捨てることに注意する。
- 整数型データにおいては、オーバーフローに注意する。
- 浮動小数点型データにおいては、アンダーフロー、桁落ち、丸め誤差に
注意する。
- 浮動小数点型データの等号による比較を避ける。
数値、文字、文字列について
- プログラム中に 0 と 1 以外の数値が出現する場合には、定数で置き換
える。
- プログラム中に文字リテラルや文字列が出現する場合には、定数文字/定
数文字列で置き換える。
- 文字型の値を整数値としては使用しない。やむを得ない場合には明示的
にキャストする。
- 文字列の大きさは (文字数+1) バイトであることに注意する。
配列について
- 配列の添字の値が常に 0 と (要素数-1) の間の整数値を取っていること
を確認する。
- 多次元配列を使用する場合、配列の添字が正しいことを確認する。
ポインタについて
- ポインタの使用は、他に方法がない場合に限定する。
- ポインタ操作を行なう関数を定義して、ポインタ操作を他のコードから
分離する。
- ポインタが参照するデータが有効であることを確認する。
-
構造化プログラミングについて
- 構造化された制御構造(ブロック、if-else, switch, while, for,
do-while)だけを使用する。
- 上記以外の制御構造(goto, break, continue)は、他に方法がない場合に限っ
て使用する。
if文について
- 通常発生する場合の処理は、if節に書く。
- 例外的な事象の処理は、else節に書く。
- 不等号を用いた条件判定において、等号が成立する場合の分岐が正しい
ことを確認する。
- 条件判定部における代入文を使う場合には、十分確認する。
switch文について
- caseラベルの順序は、該当する頻度の高い順とする。同一頻度と考えら
れる場合には、アルファベット順など組織的な順序づけを行なう。
- defaultラベルは、予期しない場合を検出するために必ず最後におく。
- break文のないswitch文は使用しない。(例外:文が空の場合)
if-then-else-if 構造について(多岐条件文)
- 条件判定の順序は、該当する頻度の高い順とする。同一頻度と考えられ
る場合には、アルファベット順など組織的な順序づけを行なう。
- 条件判定において、すべての場合を尽くしていることを確認する。
- switch文で書けるならば多岐条件文を使用しない。
- 入れ子のif文を使用する場合には、中括弧 {, } を使用して if と else
の対応を明示する。
ループ一般について
- 一つのループでは、一つだけの機能を実現する。
- ループには、必ず先頭から入る。
- 空のループを避ける。
- ループを制御する変数には適当な名前をつける。
- ループがどんな場合にも終了することを確認する。
- ループの終了条件を明確にする。
- 無限ループを書く場合には、それを明示する。
- ループの入れ子は3レベル以下にする。それ以上になる場合には、関数を
用いて入れ子を浅くする。
- ループはソースリスト上で一目で見渡せる程度に短くする。
while / do-while文について
- ループの初期設定は、ループの直前で行なう。
- 条件式は、ループの終了判定のためだけに使用する。
- 条件式中の代入文は、特別な場合にのみ使用する。
- ループを制御するための文は、ループの頭部または尾部にまとめておく。
- whileループは条件が成立するまでの繰り返しに利用する。
for文について
- for文の頭部を次のように定義する。
for(式1; 式2; 式3)
- 式1 はループを制御するカウンタの初期設定のためだけに使用する。
- 式2 はループの終了判定のためだけに使用する。
- 式3 はカウンタの再設定のためだけに使用する。
- カウンタの値は式3 以外の文では変更しない。
- 与えられた回数の繰り返しを行なう場合にのみ forループを使用する。
whileループの代わりにforループを使用しない。
- forループを抜けた後のカウンタの値は参照しない。
-
- S. McConnell著、石川 勝 訳、「コードコンプリート - 完全なプ
ログラミングを目指して」、アスキー出版局、1994. (職業的プログラマがプ
ログラミングを効果的に行なうための基本的技術を、具体例を用いて詳しく解
説している。各章の最後についているチェックリストは、自分のプログラムの
善し悪しを判断するための基準として有用である。950ページ(定価7800円)の
厚い本だが読み易い。)
- 林 晴比古 著、「C/C++によるプログラミング・スタイルブック」、ソフ
トバンク、2000、1900円. (「分かりやすいプログラム、ひいてはバグの修正
が楽なプログラムを書くにはどうすれば良いか」という問題に対して、具体例
を挙げて説明している。)
- 結城 浩 著、「C言語プログラミングレッスン 入門編」、ソフトバンク.
(初心者がC言語を独学する際の入門書として良く書けている。説明は、「これ
でもか」と言う位に懇切丁寧である。)
- 内田 智史 編著、「C言語によるプログラミング(基礎編、応用編)」、オー
ム社. (「プログラミング概論 & 演習」の教科書として採用している。Cプロ
グラミングの基礎から実用的な応用に渡って丁寧に説明されている。)
- B.W.カーニハン,D.M.リッチー著、石田 晴久 訳、「プログラミング言
語C 第2版」、共立 出版. (C言語の設計者によって書かれた標準的な教科書で
ある。説明は非常に厳密だが、レベルは少し高い。)
- 馬場 勇 著、「ソフトウエア開発の実践技法」、技術評論社. (大規模な
ソフトウエアを作成する際に重要な、ソフトウエア設計論に関するやさしい教
科書。例題のプログラムはすべてC言語で書かれている。「ソフトウエア工学」
の教科書として採用している。)
Any questions and comments are welcome. Please contact to:
掛下 哲郎 (Tetsuro KAKESHITA) (kake@is.saga-u.ac.jp)