6-2 演習

問題1 整数の順番

1次元配列に1から10の整数を入れてください。
そして配列の[最後]~[0]の順番でprintしてください。

問題2 文字の順番

1次元配列にアルファベットのaからzの文字を入れてください。
そして配列の[最後]~[0]の順番でprintしてください。

問題3 最大最小

以下の実数を配列に入れてください。
そして配列の中から最大値、最小値を探して「最大値=xx 最小値=xx」とprintしてください。

15.0, 30.5, 3.14, 9.82, 7.2, 1.3, 80.5, 11.5, 2.53, 5.52

問題4 選択ソート

1次元配列に以下の10個の整数を入れます。
そして、選択ソートを使用して昇順(小さい数値から大きい数値へ)に並べ替えを行って、配列の内容をprintしてください。

10, 7, 30, 8, 2, 15, 5, 18, 27, 12

以下に選択ソートのアルゴリズム(処理の方法)を示します。
一言でいうと、最小値を見つけて前に持っていくことを繰り返すことで昇順に並べ替えます。
この例では配列 su[0]~[4] に5個の数値を入れて、ソートしています。

問題5 選択ソート

問題4を降順(大きい数値から小さい数値へ)に並べ替えを行って、配列の内容をprintしてください。
ヒント、最小値と最大値の考え方を変えたらどうなるでしょう。

問題6 選択ソート応用

2次元配列に以下の情報をセットし、平均点の高い人から順に以下のようにprintしてください。
平均点は少数以下は切り捨てます。
尚、ソートアルゴリズムは選択ソートを使用してください。

print内容
順位 受験番号 数学 英語 理科 平均点
 1    202       96    97    75    89
受験番号数学英語理科
205755165
101606570
300758060
216809185
106586271
112907592
220554861
180514559
130405260
202969775

解答1

#include <stdio.h>

int main()
{
    int ar[] = {1,2,3,4,5,6,7,8,9,10};

    for (int i=9; i>=0; i--)
        printf("%d\n", ar[i]);
}
実行結果
10
9
8
7
6
5
4
3
2
1

for文はマイナスもできますよ。

解答2

#include <stdio.h>

int main()
{
    char ar[] = {'a','b','c','d','e','f','g','h','i','j',
                 'k','l','m','n','o','p','q','r','s','t',
                 'u','v','w','x','y','z'};

    for (int i=25; i>=0; i--)
        printf("%c\n", ar[i]);
}
実行結果
z
y
x
省略
c
b
a

文字(1文字)は '' で囲みます。

解答3

#include <stdio.h>

int main()
{
    double val[10] = {15.0, 30.5, 3.14, 9.82, 7.2, 1.3, 80.5, 11.5, 2.53, 5.52};
    double dmin; /* 最小値 */
    double dmax; /* 最大値 */

    /* 仮の最大値、最小値をセット */
    dmin = val[0];
    dmax = val[0];

    for (int i=0; i<10; i++) {
        if (dmin > val[i]) {
            /* 小さい値を見つけた */
            dmin = val[i];
        }
        if (dmax < val[i]) {
            /* 大きい値を見つけた */
            dmax = val[i];
        }
    }
    printf("最大値=%5.2f 最小値=%5.2f\n", dmax, dmin);
}
実行結果
最大値=80.50 最小値= 1.30

仮の最大値をセットしておいて、その値よりも大きな値をみつけたら、その値を最大値にします。
最小値も同様です。
自分で宣言した配列サイズより多く、アクセスしないように気を付けましょう。

解答4

#include <stdio.h>

int main()
{
    int ary[10] = {10, 7, 30, 8, 2, 15, 5, 18, 27, 12};
    int imin; /* 最小値 */
    int idx;  /* 最小値のインデックス */
    int iw;   /* ワーク変数 */

    for (int i=0; i<=8; i++) {
        /* 仮の最小値 */
        imin = ary[i];
        /* 最小値のインデックス */
        /* -1 は小さい値が無かったことを表す */
        idx = -1;

        for (int k=i+1; k<=9; k++) {
            if (imin > ary[k]) {
                /* 更に小さい値を見つけた */
                imin = ary[k];
                idx = k;
            }
        }

        /* 最小値が見つかったら交換をする */
        if (idx>0) {
            iw = ary[i];
            ary[i] = ary[idx];
            ary[idx] = iw;
        }
    }

    /* 結果プリント */
    for (int i=0; i<10; i++)
        printf("ary[%d] = %d\n", i, ary[i]);
}
実行結果
ary[0] = 2
ary[1] = 5
ary[2] = 7
ary[3] = 8
ary[4] = 10
ary[5] = 12
ary[6] = 15
ary[7] = 18
ary[8] = 27
ary[9] = 30

for文が i=8 までしか回らな所に注意してください。
データの交換方法もよく見てください。
ワーク変数とは一時的に使用する変数のことです。

解答5

#include <stdio.h>

int main()
{
    int ary[10] = {10, 7, 30, 8, 2, 15, 5, 18, 27, 12};
    int imax; /* 最大値 */
    int idx;  /* 最大値のインデックス */
    int iw;   /* ワーク変数 */

    for (int i=0; i<=8; i++) {
        /* 仮の最大値 */
        imax = ary[i];
        /* 最大値のインデックス */
        /* -1 は大きい値が無かったことを表す */
        idx = -1;

        for (int k=i+1; k<=9; k++) {
            if (imax < ary[k]) {
                /* 更に大きい値を見つけた */
                imax = ary[k];
                idx = k;
            }
        }

        /* 最大値が見つかったら交換をする */
        if (idx>0) {
            iw = ary[i];
            ary[i] = ary[idx];
            ary[idx] = iw;
        }
    }

    /* 結果プリント */
    for (int i=0; i<10; i++)
        printf("ary[%d] = %d\n", i, ary[i]);
}
実行結果
ary[0] = 30
ary[1] = 27
ary[2] = 18
ary[3] = 15
ary[4] = 12
ary[5] = 10
ary[6] = 8
ary[7] = 7
ary[8] = 5
ary[9] = 2

うまく動作しないときには、デバッグライトを行います。
デバッグライトとは正しく動いているか確認するためにprintすることです。
例えば、この例で値の交換処理が正しく動作しているかどうかを確認したいとします。

  /* 最大値が見つかったら交換をする */
printf("idx = %d \n",idx);
 if (idx>0) {
      iw = ary[i];
printf("i=%d iw=%d\n", i, iw);
       ary[i] = ary[idx];
printf("ary[%d] = ary[%d] %d \n", i, idx, ary[idx] );
       ary[idx] = iw;
printf("ary[%d] = %d \n", idx, iw);
  }

この赤字のようにprintすれば、動作がよく分かるでしょう?
これをデバッグライトといいます。
ぜひ使用してみてください。

解答6

#include <stdio.h>

int main()
{
    int seiseki[][5] = {
        //受験番号,数学,英語,理科,平均点
        {205, 75, 51, 65, 0},
        {101, 60, 65, 70, 0},
        {300, 75, 80, 60, 0},
        {216, 80, 91, 85, 0},
        {106, 58, 62, 71, 0},
        {112, 90, 75, 92, 0},
        {220, 55, 48, 61, 0},
        {180, 51, 45, 59, 0},
        {130, 40, 52, 50, 0},
        {202, 96, 97, 75, 0}
    };
    int ken = 10;   //seiseki データ件数
    int iw;         // ワーク変数
    int imax;       // 最大値
    int idx;        // 最大値のインデックス

    /*-----------------------------------------*/
    /* 平均点を求めて seiseki[][4]にセットする */
    /*-----------------------------------------*/
    for (int i=0; i<ken; i++) {
        iw = 0; //合計点
        for (int k=1; k<=3; k++) iw += seiseki[i][k];
        seiseki[i][4] = iw / 3; // 切り捨て
    }

    /* デバッグ用 平均点表示 */
    printf("ソート前\n");
    for (int i=0; i<ken; i++) {
        for (int k=0; k<5; k++) {
            printf("%d ", seiseki[i][k]);
        }
        printf("\n");
    }

    /*-----------------------------------------*/
    /* ソートする                              */
    /*-----------------------------------------*/

    for (int i=0; i<=(ken-2); i++) {
        // 仮の最大値
        imax = seiseki[i][4]; //平均点
        // 最大値のインデックス
        // -1 は大きい値が無かったことを表す
        idx = -1;

        for (int k=i+1; k<=(ken-1); k++) {
            if (imax < seiseki[k][4]) {
                // 更に大きい値を見つけた
                imax = seiseki[k][4];
                idx = k;
            }
        }

        // 最大値が見つかったら交換をする
        if (idx>0) {
            for (int n=0; n<=4; n++) {
                iw = seiseki[i][n];
                seiseki[i][n] = seiseki[idx][n];
                seiseki[idx][n] = iw;
            }
        }
    }

    // 結果プリント
    printf("順位 受験番号 数学   英語   理科   平均点\n");
    for (int i=0; i<ken; i++) {
        printf("%4d ", i+1);
        for (int k=0; k<5; k++) {
            printf("%6d ", seiseki[i][k]);
        }
        printf("\n");
    }

    return 0;

}
実行結果
ソート前
205 75 51 65 63
101 60 65 70 65
300 75 80 60 71
216 80 91 85 85
106 58 62 71 63
112 90 75 92 85
220 55 48 61 54
180 51 45 59 51
130 40 52 50 47
202 96 97 75 89
順位 受験番号 数学   英語   理科   平均点
   1    202     96     97     75     89
   2    216     80     91     85     85
   3    112     90     75     92     85
   4    300     75     80     60     71
   5    101     60     65     70     65
   6    106     58     62     71     63
   7    205     75     51     65     63
   8    220     55     48     61     54
   9    180     51     45     59     51
  10    130     40     52     50     47

平均点を別の配列にセットするやり方もありますが、同じ配列内にセットした方が便利だと思います。
整数の割り算を行って、整数にセットすると切り捨てされます。
データの件数などは、for文の中などに直接数値を書かずに変数にした方が良いです。
理由はデータの件数が変更になった時に、修正する場所が沢山あると間違えるからです。
処理のアルゴリズムは問題5と同じですよね。
実際に正解が出るまで、ぜひ実行してみてください。

コメント

タイトルとURLをコピーしました