情報科学演習
2014.12.01

Back to index page



  1. 本日の作業内容


  2. 前回の小テストの結果について

    今回はテストということもあってコンパイルエラーが出てしまいました.エラーとなる答案は採点しませんので,エラーの無いように注意してください.

    コンパイルエラー b1417 b1428 b1468

    また,番号と名前の無記入もありました.これも以後は注意してください.

    b1380

    プログラムとしてはほとんどの人が問題無く作成できていました.一部に変なものもありましたが,先週の実習を通して自分の間違いや良くないところに気づいたのでは無いかと思います.以下にはインデント(字下げ)のおかしかったものの例を2つだけ示します.自分のものもよく確認しておいて下さい.

    main()
    {
        srand((unsigned) time(NULL));
    
            int i;
    

    毎回のように指摘しているものですね.以前に作成したものをペーストしているので,スペースとTABが混在しています.気を付けましょう.21番.

    #include <stdio.h>
    
            main()
    {
                    int i;
    

    きちんと揃っていません.54番.

  3. 宿題の結果について

    今回は珍しく,前回の小テストの解答を提出している人が二人もいました.注意しましょう.

    b1412 b1302

    以下はいつものように問題のある解答の例です.参考にしてください.

            int a,b,i;
    

    変数は2つまでの指定しているのにあっさり無視ですか?過年度生に多かったのが残念です.

            for(;octa >= 0;){
                    printf("%8d / %d = %d\n",octa,di,octa / di);
                    octa /= di;
    
                    if(octa == 0){
                            octa = -1;
                    }
            }
    

    if 文は要らないですね.if 文なしで考えてください.

            for( ;i/num1>0 ;i/=num1)
                    printf("%8d / %2d = %d\n", i, num1, i/num1);
                    printf("%8d / %2d = %d\n", i, num1, i/num1);
    

    2つ目の printf for 文の外ですね.インデントもおかしいですが,式2を工夫すればこのような余分な処理は不要です.

            for( ;a>0 ; ){
                    printf("%d / %d = %d\n",a,b,a/b);
                    a/=b;
            }
    

    %d の部分に桁数を指定していないので表示が指定通りになっていません.かなり多く見られました.

    ここからはインデントに問題のある解答です.読みやすくわかりやすいプログラムとするために,インデントはきちんと実行してください.

            for(; n>0; ){
            printf("%8d / %d = %d\n",n, m, n/m);
            n = n/m;
            }
    

    インデント(字下げ)をまったく無視ですね.

            printf("My student number: s144006\n\n");
                    for(;a>0;){
                            printf("%8d / %d = ", a, b);
                            a /= b;
                            printf(" %d\n", a);
                    }
            printf("\n\n---------------------\n\n");
    

    なぜ,for 文自体が字下げされるのか?

        printf("My student number: s144023\n\n");
            for(;a!=0;a/=b)
                    printf("%8d / %d = %d\n",a,b,a/b);
    

    これも同じですね.何故,for 自体が下がるのか?不思議です.

            printf("My student number: s144022\n\n");
    
                    for(;a>0;){
                            printf("%8d / %d = ",a, b);
                    a /= b;
                    printf(" %d\n", a);
            }
    
        printf("\n\n---------------------\n\n");
    

    いつも言っているTABとスペースの混在によるずれですね.

                    for( ;mae >= ato; )
                            {       printf("%8d / %d =",mae,ato);
                                    printf(" %d\n",mae / ato);
                                    mae = mae / ato;
                            }
                            printf("%8d / %d = %d\n",mae,ato,mae / ato);
    
    
    
        return(0);
    }
    

    下げる位置がめちゃくちゃです.

            return(0);
      }
    

    なぜ,最後の閉じ中括弧が中途半端な位置なのか?

  4. 前回の復習

    • 「式1」の意味

      教科書のp.39にある for 文の基本形式ですが,その内のまず「式1」 についてもう少し説明しておきます.良くあるのが,i=1 のようなも のですが,これは見てのとおり「代入」です.変数 i にこの場合数値 の1を代入しています.for ループの中で使用する変数 i の 値を初期化しているわけですが,ここで注意が必要なのは,前回多くの人が間違 えていた以下のような処理です.

          i = rand();
      
          for(i=1; i<=10; i++)
      

      上では,1行目で変数 i に乱数の値を代入していますが,その直後に for 文で i に1を代入しています.for 文で使 用する変数はこのように初期化されるので,それ以前にたとえ値を持っていた としても,変更されます.気を付けて下さい.

      そのため,for 文の仮変数として使用される i, j, k, ... などは通常の変数名として使用しません.整数を扱う変数名としては,m, n, p, q などを使用するか,きちんとした名前をつけるかしてください.

    • 「式2」について

      「式2」は真偽値を判断するためのものです.教科書に書いてあるように,式2が 真であればループ内の処理(「文」)を実行します.偽になるとループを抜けるこ とになります.無限ループになる,もしくは,実行しない場合など,この式2も 原因となっていることがありますので,注意してください.

          for(i=1; i==10; i++)
      

      上のような場合,ループは一回も回りません.また,

          for(i=1; i=10; i++)
      

      では無限ループになります.

    • 「式3」について

      式3も無限ループを引き起こす可能性のある部分ですので注意してください.例 えば,次の例は教室のCの環境では動作しますが,別の環境では無限ループにな る場合がありますので,注意してください.

          for(i=1; i<=10; i=i++)
      

    • 複合演算子と変数初期値

      複合演算子を学習しました.これは,数学とは大きく異なり以下のような処理が可能なプログラム言語特有の機能でした.

          a = a + 1;
      

      これは変数 a の値に1を加えたものを新たに a に代入するというもので,これを複合演算子を用いて以下のように記述できます.

          a += 1;
      

      このとき,変数 a に初期値を与えていない場合,a の値が不定のままで代入作業が行われるので,処理系によってはとんでもない値が混じってしまうことになります.そこで,このような複合演算子を使用するときは必ずその前に値を代入しておかなければなりません.

      ただ,そうは言っても忘れてしまうこともあるでしょう.そのようなミスを未然に防ぐために,コンパイル時にコマンドにオプションをつけることで,警告を確認することができます.以下のプログラムは変数 a を初期化していない不適切なものです.

      #include <stdio.h>
      
      main()
      {
      	int a;
      	
      	printf("%d\n", a += 1);
      	
      	return(0);
      }
      

      私の使用している環境(Vine Linux)では実行結果は以下のようになります.

      -1075861099
      

      とんでもない値ですね.コンパイル時に以下のようにしてみましょう.

      $ cc -Wuninitialized hoge.c

      すると,以下のように警告が出てくると思います.

      hoge.c: 関数 `main' 内:
      hoge.c:5: 警告: `a' might be used uninitialized in this function
      

      これにより変な動作を未然に防ぐことができます.

      教室の環境では警告の文章は少し違っていますが,意味は同じです.
  5. 多重の for

    例題4.8では2重の for 文を使用して2次元の座標のような考え方を実 現しています.ただし,あまり良い例ではありません.もっと単純な2次元処理 を考えてみましょう.変数 i j を用意して以下のよ うな処理を考えると,

        for(i=1; i<=5; i++)
            for(j=1; j<=5; j++)
    

    以下のような座標的な処理が実現できますので,その位置で何をするか決めれば いろんな処理が出来ます.

    (1,1) (1,2) (1,3) (1,4) (1,5)
    (2,1) (2,2) (2,3) (2,4) (2,5)
    (3,1) (3,2) (3,3) (3,4) (3,5)
    (4,1) (4,2) (4,3) (4,4) (4,5)
    (5,1) (5,2) (5,3) (5,4) (5,5)
    

    例えば,そこで変数 i j の値を表示させてみるとよくわかるでしょう.

    	for(i=1; i<=5; i++)
    		for(j=1; j<=5; j++)
    			printf("(%d,%d)", i, j);
    

    ちなみに教科書の例題4.8を書き直すと以下のようになります.

    #include <stdio.h>
    
    main()
    {
    	int i, j;
    	
    	for(i=-5; i<=5; i++){
    		for(j=0; j<=i*i; j++)
    			printf(" ");
    			
    		printf("*\n");
    	}
    	
    	return(0);
    }
    

    #include <stdio.h>
    
    main()
    {
    	int i, j;
    	
    	for(i=-5; i<=5; i++){
    		for(j=0; j<=25; j++)
    			if(j==i*i)
    				printf("*");
    			else
    				printf(" ");
    				
    		printf("\n");
    	}
    
    	return(0);
    }
    

  6. 実習

    実習の演習問題は当日ご案内します.

  7. 次回の予習範囲

    教科書のp.49の例題4.9を予習してきてください.ただし,前回と同様5行目でインクルード されている conio.h というヘッダファイルは教室の環境には無いので 使えません.これは12行目の clrscr() (クリアスクリーン)を使うた めのものなので,この行を削除すれば conio.h をインクルードしなく ても大丈夫です.

  8. 宿題

    授業の終わりに宿題の案内をします.ただし,問題を見ることができるのは2日以降です.

    10.184.10.130/report/

    にアクセスして問題を見てください.


目次ページに戻る