情報科学演習
2017.11.22

Back to index page



  1. 本日の作業内容


  2. 端末の基本的な操作について

    前回の小テストの最中に何人かの学生さんから日本語入力ができないという質問を受けました.日本語入力のためのかな漢字変換機能がオフになっているのが原因でしたが,なぜそうなるのかはよくわかりません.ただ,以下の方法で回復するので,今後はそれで試してください.


    図1 画面上部のタスクバーの右端の様子

    上の図1は画面の上部に表示されているタスクバーの右端の部分ですが,そこの一番左に文字入力の文字種選択のアイコンが見えます.現在は _A となっていますが,そこをクリックして日本語を選択し,さらにもう一度クリックしてひらがなを選択することで日本語入力が可能となります.その操作は文字入力が可能なソフトを起動している時に行ってください.

    もう一つ前回の授業で気になったことですが,PCの電源ボタンは薄く点灯しているのに電源ボタンを押しても起動しないPCが何台かあったことです.これはそれ以前に使用していた学生が作業終了後にシャットダウンしないでスリープモードにしてしまったためのようです.授業の終了時に毎回電源を落として退室するように指示していますが,その際には電源ボタンを押すのではなく,図1の右端の下三角記号(▼)をクリックして表示される電源操作一覧の中から電源オフを選択するようにしてください.電源ボタンをいきなり押してしまうと,シャットダウンではなくスリープになるようで,しかもそのスリープからの復帰方法がよくわからないので,結局は電源ボタン長押しの強制シャットダウンになってしまいます.今後は注意してください.

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

    小テストは宿題と異なりタイムプレッシャーがかかるのでミスが多くなるのですが,それでもコンパイルエラーと無限ループについては自分で確認することができるはずなので,提出しないようにしてください.無限ループは特に面倒なので,決して出さないようにしてください.

    コンパイルエラー: b1706 b1711 b1755 b1772 b1677
    無限ループ: b1751
    解答用紙の変な使用: b1754 b1760

    上記は残念ながら採点の対象外としました.以下は減点ですね.

    学生番号間違い: b1733
    ハイフンライン無し: b1777 b1512 b1621
    インデント(字下げ)の不備: b1714 b1715 b1719 b1733 b1735 b1736 b1740 b1747 b1749 b1769 b1773 b1777 b1780 b1449 b461 b1468 b1512 b1623 b1675

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

            for(i=10;i<='a'; i++){
    

    なぜ,式2に文字が?アルファベット小文字の a の値は教科書の末尾にあるASCII表からもわかるように97ですが,それが何か?

        for(i=10; i<=a;)
    

    for 文の式3が無いので変数 i の値が増えません.よって,無限ループになります.

    以下は乱数の問題です.

            int a=rand()%89+10;
    

    いつになっても89とか899とか出てくるのですが,いい加減理解して欲しいです.結構多くの人に見られました.2桁の正の整数を発生することにおいて必要条件は満足していますが,99は決して出てこないので十分条件を満足していません.

            int a = rand() % 99 + 1;
    
            int i,a = rand() % 100 + 10;
    
            int a= rand() % 90 + 1;
    

    上記3つは2桁の条件を満足していません.

  4. 宿題の結果について

    相変わらず提出の不備が続いています.注意しましょう.まずは,間違ってかどうかはわかりませんが,前回の小テストの答案を出した人もいました.

    小テストのプログラムを提出: b1601

    当然採点対象外ですので,今後はきちんとしましょう.また,減点となる対象ですが,以下のようにいくつか出ています.

    解答用紙に番号と名前を入力していない: b1702 b1713 b1556
    学生番号が間違っている: b1736
    末尾にハイフンによるラインが無い: b1679

    そして,前回から for 文が始まったために, for 文と if 文の組み合わせでインデントが変になった人が多数出てきました.こちらもわからなければ質問してください.

    インデントの不備: b1703 b1708 b1711 b1713 b1716 b1723 b1724 b1733 b1736 b1740 b1742 b1743 b1744 b1746 b1749 b1751 b1752 b1753 b1754 b1757 b1762 b1766 b1767 b1769 b1771 b1772 b1773 b1774 b1777 b1440 b1461

    そして,授業中にも注意しました変数の初期化ですが,以下のようにかなりの数の人が初期化を怠ったために正しい答えが出ないプログラムを作っていました.教室の環境では,初期化をしていない変数の初期値がたまたま0になっているだけで,他の環境では違いますので,今後とも注意してください.

    初期化していない変数の使用による間違い: b1707 b1719 b1743 b1765 b1774 b1782 b1449 b1623 program1

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

            int a,i,Max,Second;
    

    変数名は原則小文字で始めてください.

            int a , b , c , d , e , i;
    

    無駄に多い変数の定義ですね.後で使わないものは削除しておきましょう.

            b==0;
            c==0;
    

    何人かいたのですが,上のは代入ではなくて真偽値のための等価演算子ですね.

            for(i=1 ; i<=10 ; i++){
            int num = rand() % 900 + 100;
    

    インデントもおかしいですが,それよりも for 文の中で int の宣言をしているのが問題です.同じ変数の型の宣言を10回繰り返して行っていますが,これも環境によっては警告が出ますので,やめましょう.

                    a = rand() % 899 + 100;
    

    まだいました.いいかげん,89とか899とかの数字は忘れてください.

            for(i=0;i<10;i++){
                    num = rand() % 900 + 100;
                    printf("%d ",num);
                    if(num>=max1)
                            max1 = num;
                    else if(max2<=num){
                            max2 = num;
                    }
            }
    

    今回多かった間違いのパターンです.最初の if の部分で最大値の置き換えだけを行っているので,2番目に大きい数の保存ができていません.そのため,乱数の順番によっては間違った答えが出ます.

            for(i=1; i<=10; i++){
                    a = rand() % 900 + 100;
                    printf("%d ", a);
                    if(a<b && a>c)
                            c = a;
                    if(a>b)
                            b = a;
                    }
    

    上と同様で,2番目に大きな値を更新出来ていません.

            int a ,b ,c ,d ,e ,f ,g ,h ,i ,j;
            
            a = rand() % 900 + 100 ;
            b = rand() % 900 + 100 ;
            c = rand() % 900 + 100 ;
            d = rand() % 900 + 100 ;
            e = rand() % 900 + 100 ;
            f = rand() % 900 + 100 ;
            g = rand() % 900 + 100 ;
            h = rand() % 900 + 100 ;
            i = rand() % 900 + 100 ;
            j = rand() % 900 + 100 ;
    

    こういう発想を捨ててください.

            int a,i,max,second;
            
            a = rand() % 900+100 ;
            max = 0;
            second = 0;
    

    動作的に問題は発生しませんが, for 文に入る前に乱数を発生させて変数 a に代入していますが,これは全く意味が無いですね.

  5. 前回の復習

    • 「式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++)
      

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

      式2について,「終了条件」のように間違って理解している人が時々見られます.式2は終了条件ではなく実行条件です.

    • 「式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);
      }
      

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

      -1075861099
      

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

      $ cc -Wuninitialized hoge.c

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

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

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

      教室の環境では警告の文章は少し違っていますが,意味は同じです.
  6. 多重の 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);
    }
    

  7. 実習

    実習の演習問題予習分はこちら.他は当日ご案内します.

  8. 次回の予習範囲

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

  9. 宿題

    今回は開講日が変則的になり,メンター学習室を開設できませんので,宿題は無しとします.各自予習と復習をしっかり行ってください.


目次ページに戻る