訓練校の授業で出されたコーディング課題のまとめ。

C言語の授業が始まり、本日で12日目が終了しました。先日の記事でお伝えした日程枠は間違いで、基礎の授業は当初の個人予想よりも実は長めに確保されていたようです。

進捗としては、昨日でポインタが終わり、今日からストリーム、構造体に突入。

基本的には「かんたんC言語」という入門書を使用し、そこに書かれた内容の順序に沿って進めているスタイルなのですが、要所、要所で先生から確認テストが出題されています。

出題用のプリントが配布され、それを見ながら20分程度で解き、答え合わせ、といった流れで、これまでに数回行われてきました。

折角解いた問題ですし、尚且つ、訓練校の授業では一体どんなコードを書いているのか?といった情報の需要があるかどうかはわかりませんが、個人的な備忘録としての意味でもブログにコードを掲載してみようかと思います。

ただ前提としてIDEのVidualStadioを利用してスクリプトを動かしているだけなので、何か立派な成果物といえるようなものはまだ作れてません。

もっとも現段階では、基礎コースという名目なので、これから学習の応用を図り、PLCを使った成果物を制作していくようです。

9×9表を作成する

基礎の基礎たる、変数、演算子、制御、繰り返し構文が終わった時点で出題されたのがこれ。

#include <stdio.h>

int main(void) {
    int x;
    int y;

    for (x=1; x<10; x++) {
        for (y=1; y<10; y++) {
            printf("%3d ", x*y);
        }
        printf("\n");
    }
    return 0;
}

二重ループ構文ですね。

変換指定子に3を付与することで桁合わせが可能になるのですが、問題は、授業がまだ6章までしか進んでいないにも関わらず、
桁合わせの説明が11章に記載されていたので多くの方が当惑してしまったということ。

比較的簡単に解けました。

ということで次。

ユーザーが入力した3つの値から最小値を求める関数を作る。

#include <stdio.h>

int min(int a, int b, int c) {

    int min;

    if (a < b && a < c) {
        min = a;
    }   else if (b < a && b < c) {
        min = b;
    } else {
        min = c;
    }
    return min;
}

int main(void) {
    int a, b, c, num_min;

    printf("整数A:"); scanf("%d", &a);
    printf("整数B:"); scanf("%d", &b);
    printf("整数C:"); scanf("%d", &c);

    num_min = min(a, b, c);

  printf("最小値は%dです\n", num_min);
    return 0;
}

scanf関数からアドレスで値を渡しているのでポインタの概念が入ってくるのですが、この時点ではまだポインタを学んでいないので、そこは補足で説明がありました。

出された課題の中で唯一これだけは時間内に解くことができず、とても悔しい思いをしました。

制御構文は分かったのですが、自分の関数への理解の甘さを痛感しました。

ただ悔しい思いをすると頭に定着するので、結果はどうあれ課題と対峙する意義は大きいなと改めて思いました。

配列の値から偶数と奇数を選り分け、それぞれの要素数を表示

#include <stdio.h>

int main(void) {
int data[] = { 10, 27, 81, 46, 29, 3, 35, 136, 58, 77 };
int i, even, odd;

even = odd = 0;

for (i = 0; i<10; i++) {
    if (data[i] % 2 == 0) {
        even++;
    } else {
        odd++;
    }
}

printf("偶数の数は%d個です\n", even);
printf("奇数の数は%d個です\n", odd);

return 0;
}

配列、制御、繰り返し構文、インクリメントなどを複合させた例題。

これも、自分としてはまぁなんとか解けたのですが、おいそれとはいかず、多少時間がかかってしまいました。

「分かってるつもり」がこういうところで浮き彫りになりますね。

ポインタを使ってユーザーが入力した値を昇順ソートする

#include <stdio.h>

void swap(int *nx, int *ny) {
  int tmp;
  tmp = *nx;
  *nx = *ny;
  *ny = tmp;
}

void sort_3(int *n1, int *n2, int *n3) {
  if (*n1 > *n2)
    swap(n1, n2);
  if (*n2 > *n3)
    swap(n2, n3);
  if (*n1 > *n2)
    swap(n1, n2);
}

int main(void) {
    int x, y, z;

    printf("整数を入力して下さい\n");
    printf("整数X : "); scanf("%d", &x);
    printf("整数Y : "); scanf("%d", &y);
    printf("整数Z : "); scanf("%d", &z);

    sort_3(&x, &y, &z);

    printf("昇順に並べ替えた結果です\n");
    printf("整数-小 : %d\n", x);
    printf("整数-中 : %d\n", y);
    printf("整数-大 : %d\n", z);

    return 0;
}

これは辛うじて時間内に解けたのですが…、○というより△という感じでしょうか。

上掲は先生の解答例なのですが、僕はアルゴリズムが良く分からず、無駄にif文でゴリゴリ書いてしまいました。

以下が自分で書いたコード。

#include <stdio.h>

void sort_3(int *x, int *y, int *z) {

if (*x > *y && *x > *z) {
    if (*z > *y) {
        int tmp = *y;
        *y = *z;
        *z = tmp;
    }
}
if (*y > *x && *y > *z) {
    int tmp = *x;
    *x = *y;
    *y = tmp;
    if (*z > *y) {
        int tmp = *y;
        *y = *z;
        *z = tmp;
    }
}
if (*z > *x && *z > *y){
    int tmp = *x;
    *x = *z;
    *z = tmp;
    if (*z > *y) {
        int tmp = *y;
        *y = *z;
        *z = tmp;
    }
    return;
}
}

int main(void) {
int x, y, z;

printf("整数を入力して下さい\n");
printf("整数X : "); scanf("%d", &x);
printf("整数Y : "); scanf("%d", &y);
printf("整数Z : "); scanf("%d", &z);

sort_3(&x, &y, &z);

printf("昇順に並べ替えた結果です\n");
printf("整数-小 : %d\n", z);
printf("整数-中 : %d\n", y);
printf("整数-大 : %d\n", x);

return 0;
}

まず、入れ替え用の関数を用意するという発想が時間内で出てこなかったですね。

ちなみにクラス内にCOBOL書きの元SEの方がおられて、わからないところはしばしば知見を仰いでいるのですが、

要素数が多い場合はループを回せば良いよ、という話を聞いて、その通り書いたら動いたので感動してしまいました。

以下は要素数が5個だった場合。

#include <stdio.h>

void swap(int *nx, int *ny) {
int tmp;
tmp = *nx;
*nx = *ny;
*ny = tmp;
}

void sort_5(int *n1, int *n2, int *n3, int *n4, int *n5) {
int i = 0;
for (i; i < 4; i++) {
    if (*n1 > *n2)
        swap(n1, n2);
    if (*n2 > *n3)
        swap(n2, n3);
    if (*n3 > *n4)
        swap(n3, n4);
    if (*n4 > *n5)
        swap(n4, n5);
}
printf("%d回ループさせました。\n", i);
//ループさせる回数は要素数-1回で良いっぽい。
}
int main(void) {
int a, b, c, d, e;

printf("整数を入力して下さい\n");
printf("整数A : "); scanf("%d", &a);
printf("整数B : "); scanf("%d", &b);
printf("整数C : "); scanf("%d", &c);
printf("整数D : "); scanf("%d", &d);
printf("整数E : "); scanf("%d", &e);

sort_5(&a, &b, &c, &d, &e);

printf("昇順に並べ替えた結果です\n");
printf("整数-最小 : %d\n", a);
printf("整数-小 : %d\n", b);
printf("整数-中 : %d\n", c);
printf("整数-大 : %d\n", d);
printf("整数-最大 : %d\n", e);

return 0;
}

あえてサンプルなので何回ループさせたかを明示させてます。要素数-1で良いと思うのですが、もし違かったらご指摘頂けると幸いです。

C言語の授業も残り数回。

その後はマイコンプログラミングに入っていく予定です。