情報科学演習
2017.01.11

Back to index page



  1. 本日の作業内容

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

    コンパイルエラーと解答用紙を使わなかったのと2件,採点対象外がありました.残念です.今後は注意しましょう.

    コンパイルエラー: program3

    解答用紙不使用: b1449

    インデントの不備,という,今回のようなシンプルなプログラムではありえないと予想していたものが何故か出てきました.

    インデントの不備: b1637

    さて,以下は問題のあるプログラムの一部です.参考にしてください.

            int a = (rand () % 21);
    

    外側のカッコはいらないですね.

            int random=rand()%21, ary[21]={11,1,17,19,23,29,31,37,41,43,53,59,61,67,71,73,79,83,89,97};
    

    配列の入力間違いで答えが変わってしまったパターンです.コピペでいいのに,わざわざ入力して損しましたね.

            i=rand()% 21 + 1; 
    

    これでは配列の要素に無い21番目を呼び出してしまいます.

            printf("Random number: %d\n",num=rand()%20);
    

    逆に,これでは最後の要素は出てきませんね.素数は21種類です.また,配列の添字は0から始まります.

            int ary[21] = {11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 };
            
            printf("My student number: s164029\n\n");
            
            printf("Random number: %d\n",ary);      
            printf("Corresponding prime number: %d\n",ary[rand()%21]);
    

    乱数の printf のところで配列の名前 ary を呼び出しているので,変なことになります.また,その後の printf のところで乱数を発生させてはダメです.

    今回,まず乱数を発生させてそれに対応する配列要素を表示する,という手順にしたのですが,それがわかっていなかった人が結構いました.残念です.correspondというのは対応する,相応する,という動詞ですね.例えば乱数で3が出たら添字で3番めの19が対応しますよ,という問題だったんですが.

            printf("Random number: %d\n ",a);
    
                    if(ary[i]=a){
                            printf("Corresponding prime number: %d\n",i);
                    }
    

    ???????????

            printf("Random number: %d\n",a);
            printf("Corresponding prime number: %d\n", ary[rand()%a]);
    

    ???????????

            printf("Corresponding prime number: %d\n",ary[21]);
    

    なぜ存在しない21番目の要素を指定する?

            printf("Random number:%d\n",rand()%21);
            printf("Corresponding prime number: %d\n\n", ary[rand()%21]);   
    

    対応関係がわかっていない例ですね.

  3. 宿題の結果について

    宿題の方は,相変わらずインデント(字下げ)のおかしいものがたくさん提出されています.そろそろきちんと対応してもらいたいものです.

    インデントの不備: b1605 b1606 b1634 b1648 b1651 b1664 b1669 b1677 b1678 b1107 b1415 b1418 b1450 b1484

    解答用紙の不使用: b1288 b1568

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

            for(k=1;k<=6;k++){
            
                    printf("%d ",coin[k]);
                    
                    }
    

    配列の添字が0から始まることがまだ理解できていないようです.このような場合には6番目の要素は無いので不定の値(変な数)が表示されることもあります.

            for(i=0;i<=5;i++){
                    for(j=1;j<=100;j++){
                            num=rand()%2;
                            count[i]+=num;
                    }
            }
    

    上の例は何人かありました.これは100枚のコインを6回投げる,という作業になっています.なので,各回の表の枚数を表示するだけになるので,

    
    0  1  2  3  4
    53 43 60 47 45 
    
    0: *****************************************************
    1: *******************************************
    2: ************************************************************
    3: ***********************************************
    4: *********************************************
    
    

    実行すると,上のようになってしまいます.やってみたら違いがわかるはずなのですけどね.

            int i,j, a[6]={0},b;
    

    こんなものや,

            int i,j,k,l,m,b[6]={0},a[2]={0};
    

    こんなものが時々見られました.配列の要素の個数分だけ初期値は必要ですので,動作が保証されません.注意しましょう.

    例えば, ary[10][10] のような配列の要素を全部0で初期化しようとすると,100個の0を書かないといけません.なので,初期化にもなるべく for 文などの反復処理を使いましょう.

            for(i=1; i<=100; i++){
                    count=0;
                    
                    for(j=1; j<=6; j++)
                            count += rand() % 2;
                            
                    coin[count]++;
            }
    

    上のような間違いや,

            for(j=1;j<=100;j++){
                    sum=0;
                    for(i=0;i<=5;i++){
                            num=rand()%2;
                            sum+=num;
                    }
                    coin[sum]++;
            }
    

    のような間違いがかなりたくさん見られました.これらの動作としては6枚のコインを投げていることになりますので,対称型の2項分布にならず,

    
     0  1  2  3  4  5 
     3 12 23 27 23 11 
    
     0: ***
     1: ************
     2: ***********************
     3: ***************************
     4: ***********************
     5: ***********
    
    

    このような実行結果になります.表が5枚の場合が多く出てくるので,気づいて欲しいところです.

            printf(" %2d %2d %2d %2d %2d %2d \n",k[0],k[1],k[2],k[3],k[4],k[5]);
    

    これも何人かいました.絶対にやっちゃダメな書き方です. for 文というものがあるので,使いましょう.

            int ary[6] = {0,1,2,3,4,5};
    

    ??????????

  4. 前回の復習

    配列を扱いました.配列は添字(インデックス)を使って中の値を参照するもので すが,その添字は記号を利用した数式でも構いません.そのため,for 文などと組み合わせて,たくさんの値を一度に代入したり,計算した りすることが可能です.これが配列の便利なところなので,今後も反復処 理と組み合わせて利用する実習課題を行っています.

    まず,配列の宣言ですが,

    	int ary[4];
    

    のように行います.ここで,配列 ary の次に数字の4がありますが,このように定義の文の中ではこれは要素の個数を表します.

    一方,プログラム中では添字として使われる数値は0から始まりますので,要素の個数が4個であれば,割り当てられているのは下図のように0から3までです.まずは,ここに注意してください.そして,添字として扱う場合には, ary[3] のようになると,これは配列の添字3の要素(4個目の値)を指すことにも注意してください.

    さて,上述のように定義すると,次の図のように整数値を入れるための入れ物(配列)が用意されます.

    また,以下のように定義すると,下図のように値が入った配列が用意されます.

    	int ary[4] = {5, 11, 2, 3};
    

    それから初期化について改めて注意しておきます.初期化がきちんと出来ているかどうかは以下のようにオプションをつけてコンパイルすることでわかります.

    $ cc -O -Wuninitialized hoge.c

    なお,初期化が必要なものは以下のように最初に値を利用するもので,代入であれば問題ありません.

    初期化が必要な例

    	int i;
    	
    	while(i>0)
    		hoge;
    

    	int i, a;
    	
    	for(i=0; i<=4; i++)
    		a += i;
    

    初期化が不要な例

    	int i, j, count;
    	
    	for(i=0; i<=4; i++);{
    		count = 0;
    		
    		for(j=0; j<=4: j++)
    			count++;
    	}
    

  5. 2次元配列

    2次元の配列は上の図で示したような入れ物が2重になっているもので,例えば以下のように表すことも出来ます.

    	int ary[3][4] = {{5, 11, 2, 3}, {4, 15, 6, 9}, {12, 13, 1, 7}};
    

    教科書p.54の図5.3にあるように2次元の配列を用意すると,マトリックス状にデー タを格納できます.これを利用して,表計算のようなことも出来ます.例えば, 次のような配列があるとします.

        ary[3][3] = {{11, 12, 13}, {21, 22, 23}, {31, 32, 33}}
    

    要素は例えば,ary[0][1] は12ですし,ary[2][0] は31です.

    このとき,ふたつ目のインデックス(添字)が1に関する和を取ると,12+22+32の 足し算となります.これがデータを行と列に並べた場合の列に関する和となりま す.

    111213
    212223一つ目の添字が1のものはこの行ary[1][j]
    313233
    2つ目の添字が1のものはこの列
    ary[i][1]

    また,マトリックス的なものでは無い多次元配列の使い方としては,前回説明し た温度測定の場合でもあります.1次元の配列だと,1日の温度のデータが格納で きるだけですが,次元を上げていくと次のようにも使えます.

    次元補足
    2 temp[11][0]
    temp[16][14]
    11日午前0時の気温
    16日午後2時の気温
    3 temp[1][11][0]
    temp[2][1][15]
    1月11日午前0時の気温
    2月1日午後3時の気温
    4 temp[15][2][1][16]
    temp[17][1][11][0]
    2015年2月1日午後4時の気温
    2017年1月11日午前0時の気温

    このように添字を使用すれば,後から値を読み出すときに変数を使用して簡単に 出来ます.

    	    year = 17;
    	    month = 1;
    	    date = 11;
    	    hour = 0;
    
    	    printf("%d\n", temp[year][month][date][hour]);
    

  6. 実習

    実習の演習問題(予習用)はこちらです.

  7. 次回の予習範囲

    教科書のp.66-70を予習してきてください.また,次回の授業では最初に文字列配列に関する小テストを実施しますので,文字列について予習をしっかりしてきてください.

  8. 宿題

    授業の終わりに宿題の案内をします.ただし,問題を見ることができるのは11日18時以降です.レポート提出システムから閲覧してください.


目次ページに戻る