情報科学演習
2017.11.13

Back to index page



  1. 本日の作業内容

  2. 小テスト

    授業の最初に小テストを実施します.例によって,窓際の柱のある部分の席は使用しないで下さい.

    なお,授業でも少しお話ししましたが,教科書の for 文の例題があまり良くないので,以下に基本的な例を2つ示しておきます.参考にしてください.

    main()
    {
    	int i;
    
    	for(i=1; i<=10; i++)
    		printf("%d\n", i);
    	
    	return(0);
    }
    

    上の例は1から10までの整数を1行に1つずつ表示するもの.次の例は,1行に全部表示するものです.

    main()
    {
    	int i;
    
    	for(i=1; i<=10; i++)
    		printf("%d ", i);
    	
    	printf("\n");
    	
    	return(0);
    }
    

  3. 前回の宿題の結果について

    今回もコンパイルエラーの答案が出てきてしまいました.エラーになるプログラムは採点しませんので,提出しないでください.また,解答用紙を使用しないものも出てきました.こちらも採点しませんので,今後は注意してください.

    コンパイルエラー: b1716
    解答用紙不使用: b1780

    また,解答用紙に番号と名前を記入しないものや実行結果の末尾にハイフンによるラインを出力しないものも出ております.こちらも注意してください.

    番号と名前無し: b1734
    ハイフンライン無し: b1728 b1751 b1737

    さて,インデント(字下げ)の不備も相変わらずです.少し減ってきたと安心していたら,今回はまたたくさん出てきました.インデントがわからない場合には必ず質問して確認してください.

    インデントの不備: b1715 b1718 b1722 b1733 b1736 b1738 b1740 b1741 b1749 b1751 b1752 b1754 b1763 b1767 b1774 b1440

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

            int a = rand() % 2 + 0;
            int b = rand() % 2 + 0;
    

    ときどき上のような例が見られるのですが,最後の + 0 は意味無いですね.でも,これがあると内部的にはレジスターを1つ用意しないといけなくなります.無駄ですね.

            {
            if(a == 0 && b == 0)
                    printf("0");
            else
                    printf("1");
            }
    

    if 全体を中括弧でくくることに意味は無いですね.

            if(a == 0 && b == 0)
                    printf("OR -> 0, XOR -> 0\n");
            if(a == 0 && b == 1)
                    printf("OR -> 1, XOR -> 1\n");
            if(a == 1 && b == 0)
                    printf("OR -> 1, XOR -> 1\n");
            if(a == 1 && b == 1)
                    printf("OR -> 1, XOR -> 0\n");
    

    if の羅列です.どれかに収まる場合には else を使うのが流儀です.

            if (c==0){
                    printf("%d+%d\n",a,b);
                    printf("OR->0, XOR->0\n");
            }
            else if (c==1){
                    printf("%d+%d\n",a,b);
                    printf("OR->1, XOR->1\n");
            }
            else{
                    printf("%d+%d\n",a,b);
                    printf("OR->1, XOR->0\n");
            }
    

    上側の printf 文は選択処理に関係ないので,毎回入れる必要は無いですね.無駄にプログラムが長くなります.

            if(a = b)
                    printf("XOR -> 0\n\n");
            else
                    printf("XOR -> 1\n\n");
    

    こういう間違いもよくあるということは最初にも説明しましたが,やっぱり出てきますね. if 文の条件式が必ず真になってしまいます.

  4. 前回の復習

    switch 文を学習しました.switch 文では if else 文の else と同様に default を必ず付けましょう.

  5. for

    1. for 文の基本

      for 文は教科書p.39の図4.2の下にあるような形式で使用します.式1から式3までは初期値,実行条件(この式の値が「真」であれば処理を実行),増分を表します.これらは必要に応じて処理のために使用するので,必ずしも書かなくてはいけないものではありません.ここが空欄であれば,教科書p.40にあるような無限ループになります.

      今後万一無限ループを作ってしまってプログラムが終わらない場合には,「コントロールキーとCのキー」を同時に押して処理を停止してください.Ctrl+Cと覚えておいてください.

      教科書に出ているCtrl+ZはWindowsにおける強制終了です.

    2. 仮変数

      for 文の式1から式3までの設定では変数 i がよく使用されます.これは整数(Integer)の頭文字を取ったものです.for 文ではこのように i を使用しますので,他の場所で i を使用する場合には注意が必要です.ただし,複数の for 文が一つのプログラム中にあってもこの変数(仮変数)は i のままで構いません.ですので,変数 i が重複して何度も出てくるようなプログラム,例えば,

      	for(i=0; i<=5; i++)
      		printf("hoge\n");
      	
      	for(i=10; i>=0; i--)
      		printf("hoge\n");
      	
      	for(i=0; i<=100; i++)
      		printf("hoge\n");
      

      でもエラーにはなりませんし,まずいプログラムでもありません.これで真っ当な書き方です.

      次回以降で扱う多重のループの場合には変数は使い分ける必要があります.その 際にはアルファベットの順番で i, j, k, l, m, ... などがよく使用 されます。

    3. 複合演算子

      教科書p.38で紹介されている複合演算子は非常に重要です.以後,頻繁に使用さ れる予定です.変数の値を変更する際に利用されますので,よく理解しておいて ください.本日の実習でも使用します.また,略号の方がよく使用されますので, そちらも注意してください.

      • 複合演算子の基本

        変数自身の値を変えることが出来るので,教科書の和の例のように積算を取るこ とが可能です.例えば,

        	a = 1;
        	
        	if(hoge)
        		a = 3;
        	
        	if(hoge)
        		a = 5;
        		
        		…
        

        のように条件が満たされる度に変数 a の値を2ずつ増やしたいときには,

        	a = 1;
        	
        	for(i=0; i<=10; i++)
        		if(hoge)
        			a += 2;
        

        のようにすれば良いということになります.

    4. インクリメント演算子

      教科書のp.39に出てくるインクリメント演算子(とデクリメント演算子)も非常に 重要です.変数の値を1増やす,もしくは,1減らすという処理ですので,こちら も頻繁に使用します.

      応用例としては「カウンタ」があります.例えば,さいころを複数回振る作業で, 1の目が何回出てきたかを数えるような処理のときに変数の値を1ずつ増やせるこ の演算子は効果的です.

      ときどき for 文の式3を以下のように書く人がいるのですが,これは環境によっては無限ループになるので,絶対に止めてください.

      	for(i=0; i<=5; i=i++)
      
    5. break

      教科書では無限ループから抜け出すのに,if 文と break の 組合せの例が出ていますが,この授業では基本的に break は使用しま せん.教科書p.39の for 文の説明にある「式2」を工夫することによっ て,面白い for 文の抜け出し方が実現できますので,それを練習する ことにします.

    6. 複合演算子と初期化

      教科書のp.38にある複合演算子はこれから非常に重要なものになります.

      	a += 1;
      

      このような複合演算子は変数自身の値を変えて行くことができるので,繰り返しの中で順に値が変わっていく場合に重宝します.ただし,注意しないと行けないのは,初期化を行わないと正しく動作しない場合があることです.

      上の変数 a は値を1増やす処理となっていますが,元の値がそもそもなければ変なことになります.ですので,インクリメント演算子(複合演算子の特殊型)や複合演算子を使用する場合には,必ず変数の初期化を行ってください.

      ところが,困ったことに教室のCコンパイラは初期化されていない変数の値を勝手に0にする仕様となっています.便利なのは便利ですが,これに慣れてしまうと他のコンパイラを使用した場合に不定の値が入ってしまい,予想外の結果となりかねません.C言語は使用するコンピュータやOSによって動作が微妙に違っていますので,必ず初期化するようにしてください.

      初期化できているかどうか,不安な場合には以下のオプションをつけてコンパイルするとわかります.

      $ cc -Wuninitialized hoge.c

  6. 実習

    実習の演習問題はこちらです.

  7. 次回の予習範囲

    次回は出張の関係で11月22日(水)に補講の形で行います.ご注意ください.

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

    また,例題4.8のやり方に固執すると今後のプログラミングに支障が出ますので,よりこの授業に合ったやり方を以下に紹介します.こちらについても理解をお願いします.

    #include <stdio.h>
    
    main()
    {
    	int i, j;
    	
    	for(i=-5; i<=5; i++){
    		for(j=0; j<=i*i-1; 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);
    }
    

    最後の方法がわかると期末試験等で楽にプログラミングできるはずです.

  8. 宿題

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


目次ページに戻る