プログラミング入門I
2022.01.24

Back to index page



  1. 本日の作業内容

  2. 前回の宿題について

    今回も残念ながらコンパイルエラーが出ました.提出前に自分で確認して欲しいと,これも何度もここで書いているのですが,効果がないようです.エラーの原因は本当に些細なことなので,よく見直してもらえれば,エラーメッセージも参考に解決できるものが大半です.気をつけましょう.

    コンパイルエラー: b2153

    そして,今回の課題では処理の中に複合演算子(自己代入)の += を使うものがありましたが,その際には変数の初期化が必須です.初期化が無いために不定の値になってしまい結果が変になるケースが以下のようにありましたので,こちらも注意しましょう.

    変数の初期化なし: C007 b2117

    解答用紙に関係する不備もあいかわらずです.こちらも気をつけましょう.

    番号間違い: b2118 b2121
    名前間違い: b2121

    インデントの不備もなかなか直りません.困ったものです.

    インデントの不備: b1734 b1825 b2027 b2048 b2067 b2103 b2118 b2121 b2136 b2158

    それと,しばらく前からまだ学習していない配列を使用してプログラムを書いている人が結構います.もちろん配列を使うこと自体は問題ありませんし,自分で学習して使いこなせるようになればそれはそれで大変良いことです.しかし,配列は反復処理と組み合わせて処理を楽にするものですので,無駄に配列を使用して余分な作業が出るようなものは歓迎しません.

    当然ですが,乱数のように教科書に無いことをあらかじめ説明したもの以外は,学習した範囲内で書ける処理しか,課題として用意しません.素直に考えてください.
    以下は例によって問題のあるプログラムの例です.参考にしてください.

        int Eng, Math, Phys, Total, i, Top, max = 0;
    

    変数名は小文字で始めるように,何度も何度も何度も何度も何度も何度も......

        int eng, math, phys, total, i, max_stu, max_sco;
        
        for (i = 1; i < 6; i++)
        {
            eng = rand() % 100 + 1;
            math = rand() % 100 + 1;
            phys = rand() % 100 + 1;
            total = eng + math + phys;
    
            printf("%3d%5d%5d%5d%6d\n", i, eng, math, phys, total);
    
            if (total > max_sco)
            {
                max_sco = total;
                max_stu = i;
            }
        }
    

    変数 max_sco の値が無いのに,if() の式で使っているので,判定がおかしいことになります.

    一部のコンパイラでは変数を初期化しなかったときに,勝手に0を代入します.親切な設計というよりもおせっかいな,というより,余計な処理です.別の環境に移して実行すると期待しない結果になりますので,必ず変数の初期化を忘れないでください.

        for(i=1; i<=5; i++)
        {
            printf("%d", i);
            
            sum = 0;
            max = 0;     
            
            for(j=1; j<=3; j++)
            {
                score = rand() % 100 + 1;
                printf("%5d", score);
                
                sum += score;
                
                            if(sum>max)
                            {
                                    max = sum;
                            } 
                
            }
            
            printf(" %5d\n",sum);
    
            total += sum;
    
            if(total

    変数 max をそこで初期化すると,if() のところで,毎回 max に sum の値が代入されてしまい,結果がおかしくなります.自分で実行して分かったはずですが?

            if(total > max)
            {
                max = total;
                time ++;
            }
    

    変数名がなぜ time なのかも謎ですが,このように if() のところで演算子 ++ を使うと単純に値が増えていって,何番が最大値だったかがわからなくなります.

        printf("\nTop scorer: No.%d\n", i );     
        printf("Total score: %d\n", max );
    

    何番がトップだったかではなく,最終的に変数 i の値がいつくになっているかを出力しています.そりゃ6に決まっていますよね?

        printf("\nTop scorer: No%d\n", top);
    

    こんな風になっている人が結構いました.英語では単語を短縮するとピリオドで短縮していることを表します.なので, No. のピリオドは必須です.どうして気付かないのでしょうかね.

                num = rand()%99 + 1;
    

    これでは100点が出ません.

        for(i=1;i<=5;i++)
        {
            printf("%3d",i);
    
            for(j=1;j<=3;j++)
            {
                num = rand() % 100 + 1;
                printf("%5d",num);
                sum += num; 
            }
    
            printf("%5d\n",sum);
    
            if(max<=sum)
            {
                max =sum;
                No = i;
            }
        } 
    

    変数 sum が for() 文の中で初期化されていないので,総得点はひたすら加算され続けます.そうすると,下のような結果になっちゃいますね.

    No. Eng  Math Phys Total
    ------------------------
      1   42   36    332846
      2   37   78   3632997
      3   74   30   4633147
      4   21   81   6533314
      5   13   25   7333425
    

            if(sum>max1)
            {
                max1 = sum;
            }
    
            if(sum=max1)
            {
                max2 = i;
            }
    

    なぜ if() が2つあるのか不明ですが,2つ目の if() 文の式はよくやる等号1個の間違いなので,処理が変です.

            for(Y=1; Y<=3; Y++)
            {
                point = rand()%100+1;
                if(point<=9)
                {
                    printf("    %d",point);
                }
                if(point>=10 && point<=99)
                {
                    printf("   %d",point);
                }
                if(point==100)
                {
                    printf("  %d", point);
                }
                total+=point;
                if(max<total)
                {
                    max=total;
                    topscorer=X;
                }
            }
    

    上のような処理を書いている人が結構いました.教科書のp.27からp.28で書式指定子について学習したはずですね.解答例を参考にしてください.

            total1 = total2;
            total2 = total3;
            total3 = total4;
            total4 = total5;
            total5 = eng + math + phys;
            printf("\n");
        }
    
        printf("\nTop scorer: ");
    
        for(i = 1; 5 >= i; i++)
        {
            if(topscore == total1)
            {
                printf("No.%d ",i);
            }
    
            total1 = total2;
            total2 = total3;
            total3 = total4;
            total4 = total5;
        }
    

    これはもう何をやっているのかわかりません.なぜこんなにたくさんの変数が必要なんでしょうか.

    今週は久しぶりに絶対やっちゃダメ!なプログラムが出てきました.それも2つも.こんな面倒な事を私がやらせることは決してありません.処理が長くなったらそれは何かおかしいと思って考え直してください.

    とにかく if() で場合分け,という発想を捨てましょう.規則性を見つけることが大事です.
        for(int i = 1; i <= 5; i++){    
            int scoEng = rand()%100+1;
            int scoMath = rand()%100+1;
            int scoPhys = rand()%100+1;
            sco = scoEng + scoMath + scoPhys;
            printf("  %d",i);
            if(scoEng < 10){ 
               printf("    %d",scoEng);
               }
            else if(scoEng == 100){
               printf("  %d",scoEng);
               }
               else{
               printf("   %d",scoEng);
               };
            if(scoMath < 10){
               printf("    %d",scoMath);
            }
            else if(scoMath == 100){
               printf("  %d",scoMath);
               }
                else{
               printf("   %d",scoMath);
                };
            if (scoPhys < 10)
            {
               printf("    %d",scoPhys);
            }
            else if(scoPhys == 100){
               printf("  %d",scoPhys);
               }
                else{
               printf("   %d",scoPhys);
                };
            if(sco < 10){
               printf("     %d\n",sco);
            }
            else if(sco < 100){
               printf("    %d\n",sco);
            }    
            else if(sco > 100){
               printf("   %d\n",sco);
            };
            
            if(sco > scoMax){
                scoMax = sco;
                num = i;
            };
        };
    

        int a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, v, w, x, y, z;
        a = rand() % 100 + 1, b = rand() % 100 + 1, c = rand() % 100 + 1,
        d = rand() % 100 + 1, e = rand() % 100 + 1, f = rand() % 100 + 1,
        g = rand() % 100 + 1, h = rand() % 100 + 1, i = rand() % 100 + 1,
        j = rand() % 100 + 1, k = rand() % 100 + 1, l = rand() % 100 + 1,
        m = rand() % 100 + 1, n = rand() % 100 + 1, o = rand() % 100 + 1;
        v = a + b + c;
        w = d + e + f;
        x = g + h + i;
        y = j + k + l;
        z = m + n + o;
    
        printf("No. Eng  Math  Phys Total\n");
        printf("-------------------------\n");
    
        printf("  1  %3d  %3d   %3d   %3d\n", a, b, c, v);
        printf("  2  %3d  %3d   %3d   %3d\n", d, e, f, w);
        printf("  3  %3d  %3d   %3d   %3d\n", g, h, i, x);
        printf("  4  %3d  %3d   %3d   %3d\n", j, k, l, y);
        printf("  5  %3d  %3d   %3d   %3d\n\n", m, n, o, z);
    
        if(v>w && v>x && v>y && v>z)
        {
            printf("Top scorer: No.1\n");
            printf("Total score: %d\n", v);
        }
        else if(w>v && w>x && w>y && w>z)
        {
            printf("Top scorer: No.2\n");
            printf("Total score: %d\n", w);
        }
        else if(x>v && x>w && x>y && x>z)
        {
            printf("Top scorer: No.3\n");
            printf("Total score: %d\n", x);
        }
        else if(y>v && y>w && y>x && y>z)
        {
            printf("Top scorer: No.4\n");
            printf("Total score: %d\n", y);
        }
        else if(z>v && z>w && z>x && z>y)
        {
            printf("Top scorer: No.5\n");
            printf("Total score: %d\n", z);
        }
    

  3. 前回の復習

    本格的な多重のループの問題に挑戦しましたが,基本は手順(アルゴリズム)を考えることです.どういう順番に何をすると目的が達成されるのかを一つ一つ考えてください.そのためには,メモなど紙に書いて考えること,変数の値がどのように変わっていくのか,自分で手作業で確認していくことが重要でした.忘れないようにしましょう.

  4. まとめ

    2重の for 文の基本は以下のようなものでした.

    • 外側の for 文が縦に行を進めていく

    • 内側の for 文は各行を左から右へ進む

    • 反復処理の部分と単発の処理の部分を切り分ける

    • 適切な場所に改行を入れて行を整理する

    • 内側の反復処理により和などを求める場合には,和を格納する変数の初期化は反復処理の直前に置く

  5. 実習

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

  6. 宿題

    授業は今回が最後ですが,宿題は出しますので,最後のチャレンジをよろしくお願いします.締切りは1月31日です.


目次ページに戻る