プログラミング入門I
2018.12.10

Back to index page



  1. 本日の作業内容

  2. 確認テストの結果について

    確認テストですが,残念ながらコンパイルエラーがありました.採点できませんでした.

    コンパイルエラー: b1822 b1861 b1566

    警告はたくさん出ておりました.主として, %f を使っているのに,そこに入る値が整数型である問題でした.

    警告: b1810 b1820 b1826 b1836 b1841 b1849 b1852 b1858 b1861 b1864 b1202 b1449 b1751

    またしても,解答用紙の改ざんがありました.勝手に変更しないでください.

    解答用紙改ざん: b1810 b1862

    インデントの不備もいくつかありました.

    インデントの不備: b1805 b1839 b1842 b1737 b1763

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

    	int a = rand() % 899 + 100;
    	int b = rand() % 899 + 100;
    

    まだ,乱数わかってない人いたし...

    	if(a < b)
    	{
    		a = tmp;
    		b = a;
    		tmp = b;
    	}
    

    代入の基本がこちらはわかっていないようです.右辺の値を左辺の変数に代入するのが基本中の基本です.普段行っている,

    	a = 1;
    

    というものと同じなのですが,変数同士になると何故か間違える人がいます.

            if(a < b)
    	{
            	c = a;
            	a = b;
            	b = c;
            	
            	printf("Random numbers: %d %d\n",a,b);
            }        
            else
            {
            	printf("Random numbers: %d %d\n",a,b);
            }        
    

    見かけ上はわからないですがインデントがひどいのは置いといて,入れ替え操作を行っても, if - else を使うのなら意味無いです.

    	if(m > n)
    	{
    		printf("m - n = %d\n",m - n);
    	}
    	if(m < n)
    	{
    		printf("m + n = %d\n",m + n);
    	}
    	if(m == n)
    	{
    		printf("m * n = %d\n",m * n);
    	}
    

    if - else の基本とあえて明記していたのに.

    	float b;
    	printf("Numbers: ");
    	
    	printf("%d",a=rand()%90+10);
    	b += a;
    

    問題の後の脚注に,「初期化を忘れずに」と,書いておいたのに,残念ながらしていませんね.初期化については,授業で別途説明しますが,教室の環境がまずいので,これは本当に要注意です.テストの際には,オプションをつけて,

    $ cc -O -Wunitialized hoge.c

    と,する癖をつけてください.

    	printf("Average: %.1f\n",(a+a+a+a+a)/5);
    

    今回の警告の多くは上のようなものについてでした. printf の中で, %f を使って浮動小数点数で表示させようとしているのに,後ろの方が整数型の演算を行っているので,型があっていません.

    	int m = rand()%5+11;
    	int n = rand()%5+11;
    	int c = m-n;
    	int d = m+n;
    	int e = m*n;
    

    間違いでは無いのですが,変数 c, d, e は一度しか使用しないので,不要です.

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

    残念ながら今回も警告が出るプログラムがありました.他は少しずつ良くなっているようにも思いますが,解答用紙に名前を書いてから解答を始める習慣をつけておきましょう.無駄な減点を回避してください.

    警告: b1854
    解答用紙に名前と番号なし: b1816 b1820 b1759
    ハイフンライン無し: b1839 b1848
    インデント不備: b1814 b1843

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

            int dice = rand() % 6 + 1 ;
            int dice2 = rand() % 5 + 2 ;
            
            switch(dice)
            {
                    case 1:
                    case 2:
                    case 3:
                            printf("Dice: 1\n");
                            break;
                    default:
                            printf("Dice: %d\n", dice2);
                            break;
            }
    

    理屈としてはあっていますが,こういうややこしい処理は歓迎しません.

            if (a == 2)
            {
                    printf("2");
            }
            
            else if (a == 3)
            {
                    printf("3");
            }
                    
            else if (a == 4)
            {
                    printf("4");
            }
            
            else if (a == 5)
            {
                    printf("5");
            }
            
            else if (a == 6)
            {
                    printf("6");
            }
            else  
            {
                    printf("1");
            }
    

    予想通りの面倒なプログラム.簡単に文字数少なく,というのがプログラミングのミソです.

            switch(num)
            {
                    case 1:
                            printf("2");
                            break;
                    case 2:
                            printf("3");
                            break;
                    case 3:
                            printf("4");
                            break;
                    case 4:
                            printf("5");
                            break;
                    case 5:
                            printf("6");
                            break;
                    default:
                            printf("1");
                            break;
            }                       
    

    今回 switch 文も多く出ていました.で,これは同じ switch 文でもダメな方.もっと簡潔に書きましょう.

            if(num == 0 || num == 7 || num == 8 || num == 9)
            {
                    num = 1;
            }
            
            printf("\nDice: %d\n\n--------------------\n", num);
    

    論理演算子もこんなにたくさん使わなくても良いでしょうに.もうひと工夫.

            int a,b;
            a =rand()%10;
            b = a-3;
    

    間違ってはいませんが,変数 b は要りませんよね.

  4. 前回の復習

    if 文は, if だけで書く場合と, else をつける場合の2通りをこれまで学習してきました.そして,その2つは意味が違うということも説明しておきました.最後にもう一回確認しましょう.

    • else を使用しない場合

      特定の条件に合致した場合のみ処理を行い,そうでない場合には処理を行わない場合が該当します.例題で紹介したように,乱数が偶数ならば何かの処理を行う,というような場合です.

    • else を使用する場合

      ある条件に合致した場合にはAの処理を行い,そうでない場合にはBの処理を行う,というように,条件に応じて処理が分かれるものの,必ずどれかの処理を行う場合には else をつけてください.処理条件が3つ以上になる場合には else if で分岐を増やしていくことも可能です.

  5. for

    1. for 文の基本

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

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

    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.34で紹介されていた複合演算子(代入演算子)は非常に重要です.以後,頻繁に使用さ れる予定です.変数の値を変更する際に利用されますので,よく理解しておいて ください.本日の実習でも使用します.また,略号の方がよく使用されますので, そちらも注意してください.

      • 複合演算子の基本

        変数自身の値を変えることが出来るので,積算を取るこ とが可能です.例えば,

        	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.35に出ていたインクリメント演算子(とデクリメント演算子)も非常に 重要です.変数の値を1増やす,もしくは,1減らすという処理ですので,こちら も頻繁に使用します.

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

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

      	for(i=0; i<=5; i=i++)
      
    5. 複合演算子と初期化

      先程も書きましたが,複合演算子はこれから非常に重要なものになります.

      	a += 1;
      

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

      上の変数 a は値を1増やす処理となっていますが,元の値がそもそもなければ変なことになります.ですので,インクリメント演算子(複合演算子の特殊型)や複合演算子を使用する場合には,必ず変数の初期化を行ってください.教科書のp.59のリスト3_8では,総和を入れるための変数 total の値が0に初期化されています.これが大事です.

      	total = 0;
      

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

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

      $ cc -O -Wuninitialized hoge.c

    6. for 文基本形

      教科書には例題が少ないので,まずは,基本中の基本として以下のようなものを載せておきます.参考にしてください.

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

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

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

      10個の乱数を表示し終わった後に改行文字 \n を出力するための printf があることに注意してください.

  6. 実習

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

  7. 次回の予習範囲

    次回も引き続き for 文です.演習問題で予習しておいてください.

  8. 宿題

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

  9. メンター学習室お休みについて

    すみませんが,今週はメンター学習室は学生さんが出張のためお休みです.自力で予復習をおねがいします.


目次ページに戻る