プログラミング入門 情報科学演習
2017.01.23

Back to index page



  1. 本日の作業内容

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

    コンパイルエラーとコアダンプと2つ出てきてしまいました.残念です.

    コンパイルエラー: b1449

    コアダンプ: b1679

    上記は採点の対象外です.そして,まだまだインデントの不備が見られました.気をつけましょう.

    インデントの不備: b1604 b1605 b1653 b1668 b1569

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

            char str[10] = {"Sanfrecce"};
    

    教科書のp.67にも文字列配列の宣言が例として出ていますし,テストの問題にも配列の定義の仕方は書いてあったのに,なんでこんなことをするんですかね?

            for(i=0; i<=a; i++){
                    printf("%c",str[i]);
            }
    

    結構多かった間違いですね. for 文の式2で繰り返しを変数 a まで行っているので,一文字余分に表示されます.

            for(i=0; i<=num; i++)
                    printf("%c",str[i-1]);
    

    こちらもかなり多かった間違いで, printf で文字列の i-1 番目を表示させるということは,最初変数 i が0のときには -1 番目を表示させようとしますので,ゴミが出ます.これなんかは,

    $ ./a.out | less

    のようにlessに処理を渡すと見つけることができますので,先週何度も言いましたが,文字列を扱うときには必ずlessで確認しましょう.

  3. 宿題の結果について

    宿題の方では,無限ループが出てきました.こういうのが提出されるというのは迷惑なので注意してください.

    無限ループ: b1604

    そして,なぜか解答用紙の不使用がたくさん出てきました.不思議です.

    解答用紙の不使用: b1620 b1628 b1637 b1675

    残念ながら上記の方々は採点の対象外です.

    そして,相変わらず変数の初期化をしないまま比較演算などを行う悪いプログラムがたくさん見られました.何度も言いますが,教室の環境はたまたま初期化されていない変数に勝手に0が入っているだけで,世の中はそうは行きませんので,使用する前に必ず初期化を行いましょう.以下の方々のプログラムは1回もループが実行されない可能性があります.

    初期化の未実施: b1605 b1610 b1614 b1617 b1629 b1635 b1639 b1641 b1642 b1663 b1669 b1671 b1680 b1269 b1448 b1539 b1548 b1553

    そして,インデントの不備も相変わらず見られました.だいぶ減りましたので,もうちょっとですかね.気をつけましょう.

    インデントの不備: b1622 b1638 b1655 b1659 b1505

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

            while(1){
                    
                    int a=rand()%3,b=rand()%3;
                    
                    printf("You:%s\n\n",hand[a]);
            
                    printf("Computer:%s\n\n",hand[b]);
                    
                    printf("%s",hand[a-b]);
                    
                    }
    

    while 文の式が常に真なので無限ループですね.

            for(i=0;i<=1;i++){
                    You=rand()%3;
                    Computer=rand()%3;
                    printf("You: %s\n",hand[You]);
                    printf("Computer: %s\n",hand[Computer]);
                    printf("%s\n\n",result[(You-Computer+3)%3]);
            }
    

    必ず2回で終わるじゃんけん.変です.

            int num, num2, num3;
            
            printf("\nMy student number: s164005\n\n");
            
            while(num3<=0){
    

    while 文の式で変数 num3 の値を見ていますが,その前に初期化されていないので,値は不定です.なので, while ループは実行されないことが大半です.

                    printf("%s\n\n",result[(fc3==-1||fc3==2)?2:(fc3==-2||fc3==1)?1:0
    

    なんでこんな複雑なことを考えるんでしょうか?

            char hand[3]
            [6]={"Gu","Choki","Pa"};
                    char result[3]
            [20]={"Aiko","Winner is computer!","Winner is you!"};
    

    どうして,配列の添字の途中で改行するんでしょうか?

                    switch(judge){
                            case 0: printf("%s\n",result[0]);
                                    break;
                            case 1: printf("%s\n", result[1]);
                                    break;
                            default: printf("%s\n", result[2]);
                                    break;
                    }
    

    条件分岐は使用しないように問題文に書いてあったはずですが?

            for(i=0;i<1;i++){
                    for(;i<1;){
                            a=rand()%  3;
                            b=rand()%  3;
                            c=b+3-a;
                            d=c%3;
                            printf("\nYou: %s\n",hand[b]);
                            printf("Computer: %s\n",hand[a]);
                            printf("%s",result[d]);
                            printf("\n\n");
                            if(d==0){
                                    i++;
                            }
                    }
            }       
    

    なんのことやら?な複雑な処理ですが,アイコになったら終わるという間違った処理になっています.

            while((v<2)&&(i<6)&&(l<2)){
                    a = rand() % 3;
                    printf("You: %s\n",hand[a]);
                    b = rand() % 3;
                    printf("Computer:  %s\n",hand[d]);
                    c=(((b+1)%3)==a);
                    d=(c+(a!=b));
                    i++;
                    v+=c;
                    l+=(d==1);
                    printf("%s\n",result[v]);
            }
    

    自分でややこしくしているだけですね.お疲れ様でした.

            you=rand()%3+3;
            comp=rand()%3;
            kekka=(you-comp)%3;
            
            printf("You : %s\n",hand[you-3]);
            printf("Computer : %s\n",hand[comp]);
            printf("%s\n",result[kekka]);
            
            while(kekka==0){
                    you=rand()%3+3;
                    comp=rand()%3;
                    kekka=(you-comp)%3;
                    
                    printf("\nYou : %s\n",hand[you-3]);
                    printf("Computer : %s\n",hand[comp]);
                    printf("%s\n",result[kekka]);
            }
    

    変数 kekka を初期化しておきさえすれば前半の部分は不要です.

  4. 前回の復習

    文字列配列の要素数と添字

    整数型の配列のときと異なる要素の考え方について理解の足らない人が多く見られました.もう一度よく確認してください.

    • 文字列の考え方

      文字列(複数の文字の組合せ)はそれ自体が配列です.ですので,整数型で定義していた変数ならば,

      	int a = 100;
      

      のように定義していたのですが,数値としての100は値が一つなのに対して,文字列としての100であれば3つの文字の列として扱われるので,それだけで配列となり,以下のように定義しないといけなくなります.

      	char a[4] = "100";
      

    • NULL文字

      文字列は複数の値を持つということで,どこが文字列の終わりなのかを示す記号であるNULL文字が必ず必要となります.そのため,要素の個数は文字数+1となります.

      	char a[4] = {'1', '0', '0', '\0'};
      

      のような定義方法であれば,要素が4つというのがよくわかりますが,これは面倒なので,以下のような定義が便利なのですが,その際にはヌル文字まで含めた要素の個数に注意してください.

      	char a[4] = "100";
      

    • 添字

      上のような要素として1,0,0の3つを持つ文字列配列の要素を for 文を使用して順に表示する場合,以下のような添字なので対応に注意が必要です.

      添字 0 1 2 3
      '1' '0' '0' '\0'

      上記のような添字との対応なので,for 文で順に表示する際には,変数 i は0から2までと要素のサイズよりも2つ小さい i = 2 までになります.

      配列のサイズよりも1つだけ小さい i まで反復処理を行なう例が前回も多く見られました.その間違いに気づくためにも,処理を less に渡すことを忘れないでください.

      $ ./a.out | less
    • %s の意味

      教科書のp.21で %s はすでに紹介されていたのですが,文字列を扱うようになると頻繁に使用するようになります.前回のテキストでも説明しておきましたが,文字1つずつは %c ですが,文字列単位で出力するときには %s が便利です.

      	char a[3] = "ab";
      	char b[3][3] = {"ab", "bc", "ca"};
      	
      	printf("%s\n", a);
      	printf("%s\n", b[0]);
      	
      	for(i=0; i<=2; i++)
      		printf("%s\n", b[i]);
      
      

      のように使用できます.文字列単位で扱えるということは,文字順を示す添字が不要なので,配列の添字が省略できることに注意してください.

  5. 実習

    実習の演習問題は当日ご案内します.

  6. 宿題

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


目次ページに戻る