情報科学演習
2017.01.16

Back to index page



  1. 本日の作業内容

  2. 小テストについて

    文字列配列に関する小テストを実施します.テストの時の席配置で柱の部分を避けて座ってください.

  3. 宿題の結果について

    減っては来ましたが,まだインデント(字下げ)に問題のあるものが提出されています.注意しましょう.また,解答用紙を使用しない人もなかなか無くなりません.残念です.

    インデントの不備: b1609 b1611 b1635 b1637 b1644 b1287 b1418

    解答用紙不使用: b1567

    今回の宿題では数値を表示させるときの桁数指定を忘れている,もしくは,適切でないという人が結構たくさんいました.見た目が違ってくるので気づくはずなんですが,なぜ対応しないのでしょうか.今後は注意してください.今回の例で言えば,最低点は0点で最高点は100点ですので,3桁分の幅が必要でした. %3d を使う必要がありましたね.

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

            for(i=0;i<5;i++){
                    for(j=i+1;j<5;j++){
                            if(score[i][1]<score[j][1]){
                                    point=score[i][1];
                                    num=score[i][0];
                                    score[i][1]=score[j][1];
                                    score[i][0]=score[j][0];
                                    score[j][1]=point;
                                    score[j][0]=num;
                            }
                    }
                    printf("%4d %4d \n",score[i][0],score[i][1]);
            }
    

    今回の提出で最も多かった不適切な処理がこのパターンでした.変数 i が4まで繰り返されますから,変数 j が5に設定される処理があります.式2で j<5 がありますから実行はされませんが,余分に1回ループを回すことになります.無駄な処理を無くすのが良いプログラムです.

            for(j=0;j<=3;j++){
                    for(i=0;i<=3;i++){
                            if(score[i][1] < score[i+1][1]){
    

    このやり方でもできますが,もしデータ数が多くなったら繰り返しの処理の回数が膨大になります.データ数が n だとすると,解答例の方法は反復回数が Σ k k が1から n - 1 までなので, n ( n - 1) / 2 ですが,この方法だと ( n - 1)2 となりますのでちょっと問題です.

            for( i = 0; i < 5; i++ ){
                    for( j = i+1; j < 4; j++ ){
    

    変数の範囲を間違えているので,正しく並べ替えが行われません.

                    num=rand()%100+1;
    

    乱数の発生範囲を間違えています.これでは0点は出てきません.

            for(i=0;i<5;i++){
                    j=0;
                    Score[i][j]=1001+i;
                    for(j=1;j<2;j++){
                            Num=rand()%101;
                            Score[i][j]=Num;
                    }
            }
    

    for 文で使う変数 j の変な初期化は必要ないですね.

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

    配列の添字が0から始まることを理解できていません.このプログラムではコアダンプを生じるので,本人は気づいているはずなのになんで提出するんですかね?

  4. 初期化

    C言語の変数の初期値に関しては統一の規定が無いために,教室環境のように自動的に0を入れてくれるものや,広く普及しているGCC(GNU C Compiler)のように不定のままのものなど,多様な仕様が存在しています.

    そのため,みなさんは初期値を入れる(初期化する)こと無しに変数を使うという悪い癖が身についてしまっている可能性があります.これについては,Yahoo知恵袋などでも紹介されていますので,良く読んでおいて,以後は注意してください.

    http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1421060754 http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1449816014

    初期化を忘れることを防ぐためには何度も書いていますが,以下のようにオプションを利用してください.

    $ cc -O -Wuninitialized hoge.c

    実際に採点する環境はGCCを使用しているので,初期化が行われていないのに複合演算子を使用した場合,間違った答えが出てきます.自分で気づかないうちに減点されるので,うっかりミスは致命的です.
  5. 前回の復習

    配列以前に,変数の値の入れ換えができない人が見られました.値の入れ換えは数値や文字の並べ変えを理解する際の基本ですので,これができないと実際のプログラミング課題に困難が生じます.復習や質問をしっかり行って理解を深めて下さい.

  6. 文字列配列

    C言語では文字列(abc shimane のような文字の組)は配列 となります.それぞれの文字は配列の要素として利用可能です.文字列に関して は以下のような注意が必要です.

    • ヌル文字

      文字列の最後には文字列の終わりを意味するヌル文字 \0 があります. これは目には見えませんが,必ず付いているものです.ですので,配列の要素の 個数は文字数+1にしておく必要があります.

      実際にNULL文字が存在するのかは以下のようなプログラムで確認することが出来 ます.

      #include <stdio.h>
      
      main()
      {
      	int i;
      	char str[4]="abc";
      	
      	for(i=0; i<=4; i++)
      		printf("%c", str[i]);
      	
      	printf("\n");
      	
      	return(0);
      }
      

      このプログラムでは,for 文で実際には存在しない配列 str の4文字目までを出力することになっています.しかし,そこにはNULL文字が入っているのですが,NULL文字自体は通常の端末では目に見えません.そこで,標準出力(画面)への出力結果を整形して表示するページャと呼ばれるソフトにその表示処理を預けてみると,確認できます.

      $ ./a.out | less

      通常の実行コマンドの後に縦棒 | に続けて標準のページャソフトである less を指定することで,UNIXのパイプという機能を使用して出力を渡すことができます.結果はどうでしたでしょうか?

      なお,less を終了するには,キーボードから q を入力してください.文字列配列を使用したプログラムの実行は,このように必ず処理を less に渡すようにしてください.これでうっかりミスが防止できます.

    • 文字としての数字

      見た目には区別しにくいですが,char 型で定義すると数字も文字にな り,四則演算はできなくなります.注意してください.次の配列は数値です.

          int ary[2] = {1, 2};
      
          printf("%d\n", ary[0]+ary[1]);
      
      

      しかし,次のものは文字なので,計算には使用できません.

      
          char str[3] = {'1', '2', '\0'};
      
          printf("%d\n", str[0]+str[1]);
      
      

    • static 宣言

      教科書のp.59からは初期化のところで,auto (省略可)と static の宣言の話が出てきます.この授業の範囲では auto で構 いませんので,特別に宣言することは不要です.

    • %s %c

      教科書では配列の要素としての文字列を printf を用いて出力する際 に %s を使用しています.教科書のp.21にあるように,%s は「文字列」を表示させるものです.一方,文字列の中の「一文字」を出力する 際には %c を使用します.この違いに注意してください.本日の実習 では,%s %c の両方を使用します.

      #include <stdio.h>
      
      main()
      {
      	int i;
      	char str[4]="abc";
      	
      	for(i=0; i<=3; i++)
      		printf("%c", str[i]);
      	
      	printf("\n");
      	
      	printf("%s\n", str);
      	
      	return(0);
      }
      

      これも以前に書きましたが,二重引用符 " " で囲まれたものは文字列です.ですので,目に見えないヌル文字が最後についています.一方,引用符 ' ' で囲まれたら1文字です.ですので,その場合にはヌル文字はついていません.

  7. 実習

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

  8. 次回の予習範囲

    次回も文字列です.文字列を集めた配列が2次元配列になることにも注意して予習してください.

  9. 宿題

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


目次ページに戻る