意外と難問なのよ!?(question:1146195011)

 キチョーが会社の一番若いエンジニアに出題する練習問題なら、これは結構な含蓄を入れた出題文かも知れない。

計算する

 出題文中の「計算する」は素直に“文意の通りに解釈”させるものとして、「C言語で作成されたプログラムに実行時に計算させよ」の意味の筈だ。
 その意味では、2番の後半の答案と3番以外は全く計算していないと言えるので、キチョーが出題者で出題者の意図に沿って採点するなら100点満点中50点は減点するだろう。
 2番/3番にしても、普通の最適化で計算されなくなる可能性が充分に高そうなので、10点くらいは減点するかも知れない。
 確実に計算させるには、やはり足し算,引き算,…の関数を作るべきかと思われる。


int Tashizan( int a, int b )
{// aとbとの和を戻す
return a + b;
}

int main( void )
{
int r;
// 和の計算をする
r = Tashizan( 15, 3 );

 上記ではmain()関数のほうは、模範解答例にはなっていない。
 模範解答を示す場合はTashizan()関数をstaticにしたい感じもするトコロであるが、そうすると関数間の最適化が発動したときには計算されなくなるかも知れないし勝手にインライン化されるかも知れない*1ので敢えてグローバル関数にしておく。

表示する

 出題文中の「ディスプレイに表示する」は、キチョーが出題するなら「標準出力に表示する」と綴る。オリジナルの出題は多分その意味でよい筈だが、そうではないかも知れぬ。
 例えば10問も20問も「標準出力に表示する」と出題した後に「ディスプレイに表示する」が1問だけ混じっていたら、それは矢張り他ならぬディスプレイへ出力せねばならないだろう。
 他ならぬディスプレイが出題の意図の場合は、出題者とその生徒の住んでいる環境によって模範解答が変わるだろう。
 Windowsのダイアログをポップアップさせるのが良いかも知れないし、cprintf()のようなものを使うのが正解かも知れない。場合によっては「標準エラー出力に表示する」ことが出題文中の「ディスプレイに表示する」にぴったりかも知れない。

そのほかの採点ポイント

 「出題文をよく読め」と言うことと「意図を汲み取れ」と言うことは重要なポイントであって、「タイトル」とは何かを如何に良く考えたか?は、加点減点の対象にしたい。
 その意味だと5番の回答者さんの「3に対して15との計算は行ってません」はポイントが高い。キチョーが出題者なら、答案にこれを添え書いた者へは加点するだろう。
 交換法則が通じる和と積は兎も角、差/商/剰余の対象を「15と3の」と説明して良かったものか?
 会社の一番若いエンジニアにこれを出題した時に期待される態度は、答案を作る前に「仕様確認」をして来ることだったろう。
 出題文が完璧である必要も理由もない。意図を汲み取るコトと確認をすると言うコトとは、すぐにもいつでも訓練が必要な事柄なのだから。*2
 他の採点ポイントとして、関数の分け方のセンスも問えるだろうし、#defineの使い方(及びこの問題でそれを使うかどうか)のセンスも問えるだろう。
 以上のような観点で、模範解答を作ってみる。


#include

// ----------------------------------------
// 各種計算関数
// ----------------------------------------
int TashizanCore( int a, int b )
{// aとbとの和を戻す
return a + b;
}

int HikizanCore( int a, int b )
{// aとbとの差を戻す
return a - b;
}

int KakezanCore( int a, int b )
{// aとbとの積を戻す
return a * b;
}

int WarizanCore( int a, int b )
{// aとbとの商を戻す
return a / b;
}

int JouyozanCore( int a, int b )
{// aとbとの剰余を戻す
return a % b;
}

// ----------------------------------------
// 各種計算をして結果を表示
// ----------------------------------------
int Tashizan( int a, int b )
{// aとbとの和を計算して表示
fprintf( stderr, "和:%d\n", TashizanCore( a, b ) );
}

int Hikizan( int a, int b )
{// aとbとの差を計算して表示
fprintf( stderr, "差:%d\n", HikizanCore( a, b ) );
}

int Kakezan( int a, int b )
{// aとbとの積を計算して表示
fprintf( stderr, "積:%d\n", KakezanCore( a, b ) );
}

int Warizan( int a, int b )
{// aとbとの商を計算して表示
fprintf( stderr, "商:%d\n", WarizanCore( a, b ) );
}

int Jouyozan( int a, int b )
{// aとbとの剰余を計算して表示
fprintf( stderr, "剰余:%d\n", JouyozanCore( a, b ) );
}

// ----------------------------------------
// 全体を制御する部分
// ----------------------------------------
void Main( int a, int b )
{// 練習問題○○の回答プログラムの本来の仕事

// 和を計算して表示
Tashizan( a, b );

// 差を計算して表示
Hikizan( a, b );

// 積を計算して表示
Kakezan( a, b );

if( 0 != b )
{// 割り算系が計算可能な場合
// 商を計算して表示
Warizan( a, b );

// 剰余を計算して表示
Jouyozan( a, b );
}
}

int main( void )
{// 練習問題○○の回答プログラム

// プログラムの自己紹介(標準出力へ)
printf( "和、差、積、商、剰余の計算プログラム" );

// 本来の仕事をする
Main( 15, 3 );

// 正常終了する
return 0;
}

 こんなに長くなるのか?書き殴った状態なので、エラーが混じっているかも知れない。

*1:関数間の最適化はそれを誇る製品があるが、関数のインライン化はC言語では普通は勝手には行なわれない

*2:オリジナルの出題がコンピュータの専門会社の要員の訓練のための出題だったかどうかは知らない