トップへ
田村研究室

C言語入門

Introduction to Programming Language C

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画素分
}