2011
12/9
第15回 演習のヒント
演習のヒント
課題0(練習)
解答例は提示済み.解答例をそのまま提出すれば6点.実行結果を変えないように自分で書き換えられたら最大12点.
//課題0解答例 #include <stdio.h> int main(void) { int input,output; scanf("%d",&input); //scanfを使うことで,キーボードからinputへ入力 output = input * 16; //inputを使った計算式を計算して,結果をoutputへ代入 printf("%x\n",output); //printfを使うことで,outputの内容を画面に出力 return 0; }
課題1
10/25の練習シートの4.に解答例が書いてある.
//10/25の練習シートの4.(穴埋め問題) #include <stdio.h> int main(void) { //変数の宣言をするところ ____________________________________________ //課題1では半径,距離,角度 _____________________ //半径=5; 半径は固定値 scanf(__________________________________ ); // xの値を入力.“ 必要な書式 ”, 変数名, ... //プログラムの本体(計算式など)を書くところ ___________________________________________ //角度=計算式 printf(_________________________________ ); // “必要な書式”, 出力したい計算結果 return 0; }
課題2
大枠のプログラムは次のようになる.
#include <stdio.h> int main(void) { int cmd; scanf("%d",&cmd); //scanfで命令cmdを入力 if(エラーになる条件) printf("エラーの表示"); else if( // // この部分でifとelseを組み合わせて,問題の要求に適合するように出力をprintfする. // //すべての条件に合わなかった時 printf("No\n"); return 0; }
ここで,解き方としては次の二つが考えられる.
方針1. 課題2のページにあるように,出力は8通りしかない.そこでその8通りになるような条件式を7つ考える.(最後の一つはelseで済む)
if(出力1になるような条件) printf("出力1"); else if(出力2になるような条件) printf("出力2"); else if .... ... else if(出力7になるような条件) printf("出力7"); else printf("出力8");
ただし,条件式は緻密に考える必要がある.例えば,"Up"とだけ表示する条件は,2の倍数であることだけではなく,3の倍数ではないこと,5の倍数ではないこと,マイナスの数ではないことも条件となる.この場合の条件式は次のようになる.
(cmd%2==0 && cmd%3!=0 && cmd%5!=0 && cmd>=0)
方針2. すべての場合分けのフローをちゃんと考える.課題2にあるようにマイナスの数かどうか,2の倍数かどうか,3の倍数かどうか,5の倍数かどうか,順番に全部質問してその結果の枝分かれを考える.どのように枝を選択しても少なくとも先ほどの4つの質問が全部されるように気をつけてフローを考える.
マイナスの数か? YES -> Errorと表示 ->終了 NO -> 2の倍数か YES -> Upと表示 -> 3の倍数か? YES/NOと以下に続く... NO -> 3の倍数か? YES/NOと以下に続く...
上記のフローを完成させ,下に書いたプログラム例のように質問?のところをひとつのif文に置き換えれば,プログラムが完成する.
if(マイナスの数か?) { //YESのところ printf("Error\n"); //ここで終了 } else { //NOのところ if(2の倍数か?) { printf("Up"); if(3の倍数か?) { } else { } } else { if(3の倍数か?) { } else { } } }
課題3
#include <stdio.h> int main(void) { double t,v,y,ylimit; //時間,速度,落下距離,目的落下距離 scanf("%lf",&ylimit); //scanfを使うことで,キーボードから目的落下距離ylimitへ入力 for(t=0.0; 終了条件 ; t+=0.1) //時間は0.1秒おきに計算,0->0.1->0.2->0.3->... { v = t秒後の落下速度の計算式; y = t秒後の落下距離の計算式; } printf("%lf\n",v); //ylimitを越えた瞬間の落下速度を表示 return 0; }
課題4
#include <stdio.h> int gcd(int m, int x); //m>xとしてmとxの最大公約数を求めて返す関数 int main(void) { int m,n,g; m=9699690; scanf("%d", &n); g = gcd( m, n); printf("%d\n",g); } int gcd(int m,int x) { /* ユークリッドの互助法を使って最大公約数を求める Step 1. もしx=0であればreturn m;として終了 Step 2. mをxで割った余りをrとする Step 3. m=x, x=rとして、Step 1.へ */ }
課題5
#include <stdio.h> int find(char str[]); //文字配列strの中から文字パターン"abc"を探してその位置(先頭からの文字数)を返す int main(void) { int x; char str[999]; //最大999文字まで scanf("%s", str); x = find( str); printf("%d\n",x); return 0; } int find(char str[]) { int no; s=1; for(no=0; str[no]!=\0 ; no++) switch(s) { case 1: if(str[no]が'a'だったら) s = 状態1から遷移する先の状態番号; else s = 1; //状態1のまま break; case 2: 状態2から遷移する条件と,遷移先を同様にプログラム break; case ... 以下必要な状態 case ゴールの状態 成功したときの処理 break; } }
課題6
#include <stdio.h> int fill(int x, int y); int input[9][9] = { {0,1,1,0,0,0,0,0,0}, {1,1,0,1,1,1,1,1,0}, {0,0,0,0,1,0,1,0,0}, {1,1,0,0,1,1,1,0,0}, {1,0,0,0,1,1,0,0,0}, {0,0,0,0,0,1,0,0,0}, {0,1,1,1,1,1,1,0,1}, {0,1,0,0,0,0,0,1,0}, {1,0,0,0,0,0,0,1,0} }; int output[9][9] = { {0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0}, }; int main(void) { int x,n; scanf("%d", &x); //xをキーボードから入力 n = fill(x, x); //座標x,xから塗りつぶすことにする printf("%d\n",n); return 0; } int fill(int x, int y) { int left,right,up,down; 座標(x,y)がinputの範囲外であればダメ(0を返す) inputの座標(x,y)を調べる.黒(1)でなければダメ(0を返す) outputの座標(x,y)を調べる.すでに出力があれば(1ならば)ダメ(0を返す) そうでないなら outputの(x,y)を黒(1)に置き換える. 自分の上下左右を調べる. つまり,left = fill(x-1, y); right = fill(x+1,y); up = fill(x,y-1); down = fill(x,y+1); 返値は,left+right+up+down+1; //+1は自分自身の1画素分 }