0001. 行列の積の計算と表示(C言語)

戻る

gyoretsu.cのソースコード】


/*
 * 行列の積の計算と表示をするプログラム
 * gyoretsu.c
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* strlen()  */
#include <ctype.h>  /* isdigit() */
#include <time.h>   /* time()    */

#define BUF_SIZE 256





/*
 * 自作のbool型の定義
 */
typedef enum {
    false, /* 0 */
    true   /* 1 */
} bool;





/*
 * ユーザー定義関数の関数原型宣言
 */
void print_title(void);
void input(void);
bool is_valid_number(char buf[]);
void subst_rand(void);
void calc(void);
void print_result(void);
bool retry(void);





/*
 * グローバル変数
 */
int I, J, K, i, j, k;
int a[5][5], b[5][5], c[5][5];





/*
 * メイン関数
 */
int main(void)
{
    /* 乱数の種の発生 */
    srand((unsigned int)time(NULL));
    
    while (1) {
        /* 標題・説明の表示 */
        print_title();
        
        /* 行数および列数の入力 */
        input();
        
        /* 擬似乱数の代入 */
        subst_rand();
        
        /* 計算 */
        calc();
        
        /* 結果の表示 */
        print_result();
        
        /* 操作を続けるかどうかの選択 */
        if (!retry())
            break;
    }
    return EXIT_SUCCESS;
}



/*
 * 標題および説明を表示する関数
 */
void print_title(void)
{
    printf("【行列の積の計算と表示】\n\n");
    printf("行列の積\n");
    printf("A(I行K列)×B(K行J列) = C(I行J列)\n");
    printf("の計算をします。\n");
    printf("(ただし、I、J、Kは1~5の整数)\n\n");
}



/*
 * 行数および列数を入力する関数
 * is_valid_number()関数を使用する。
 */
void input(void)
{
    char buf[BUF_SIZE], zz;
    
    printf("I、J、Kを順に入力してください。\n");
    printf("(ただし、I、J、Kは1~5の整数)\n\n");
    
    while (1) {
        printf("エンターキーを押してください・・・");
        fgets(buf, sizeof buf, stdin);
        sscanf(buf, "%c", &zz);
        if (zz != '\n')
            continue;
        else
            break;
    }
    printf("\n");
    
    while (1) {
        printf("I = ? ");
        fgets(buf, sizeof buf, stdin);
        buf[strlen(buf) - 1] = '\0';
        sscanf(buf, "%d%c", &I, &zz);
        if (!is_valid_number(buf)) {
            printf("半角整数値を入力してください\n");
            continue;
        } else if ((I < 1) || (I > 5)) {
            printf("1から5の整数を入力してください: ");
            continue;
        } else
            break;
    }
    while (1) {
        printf("J = ? ");
        fgets(buf, sizeof buf, stdin);
        buf[strlen(buf) - 1] = '\0';
        sscanf(buf, "%d%c", &J, &zz);
        if (!is_valid_number(buf)) {
            printf("半角整数値を入力してください\n");
            continue;
        } else if ((J < 1) || (J > 5)) {
            printf("1から5の整数を入力してください: ");
            continue;
        } else
            break;
    }
    while (1) {
        printf("K = ? ");
        fgets(buf, sizeof buf, stdin);
        buf[strlen(buf) - 1] = '\0';
        sscanf(buf, "%d%c", &K, &zz);
        if (!is_valid_number(buf)) {
            printf("半角整数値を入力してください\n");
            continue;
        } else if ((K < 1) || (K > 5)) {
            printf("1から5の整数を入力してください: ");
            continue;
        } else
            break;
    }
}



/*
 * 文字列が正しい形式の整数値かどうかを判定する関数
 */
bool is_valid_number(char buf[])
{
    int i = 0;
    
    /* 最初は符号(省略可) */
    if (buf[i] == '+' || buf[i] == '-')
        i++;
    /* 次に数字(省略不可) */
    if (!isdigit(buf[i]))
        return 0;
    i++;
    /* 次に数字列(省略可) */
    while (isdigit(buf[i]))
        i++;
    
    return buf[i] == '\0';
}



/*
 * 行列の成分に擬似乱数を代入する関数
 */
void subst_rand(void)
{
    char buf[BUF_SIZE], zz;
    
    printf("行列A、Bの成分に、擬似乱数を自動で代入します。\n");
    
    while (1) {
        printf("エンターキーを押してください・・・");
        fgets(buf, sizeof buf, stdin);
        sscanf(buf, "%c", &zz);
        if (zz != '\n')
            continue;
        else
            break;
    }
    printf("\n");
    
    printf("行列A(%d行%d列)", I, K);
    for (i = 0; i < I; i++) {
        printf("\n\t");
        for (k = 0; k < K; k++) {
            a[i][k] = rand() % 20 - 10;
            printf("%4d", a[i][k]);
        }
    }
    printf("\n");
    printf("行列B(%d行%d列)", K, J);
    for (k = 0; k < K; k++) {
        printf("\n\t");
        for (j = 0; j < J; j++) {
            b[k][j] = rand() % 20 - 10;
            printf("%4d", b[k][j]);
        }
    }
    printf("\n");
}



/*
 * 計算をする関数
 */
void calc(void)
{
    char buf[BUF_SIZE], zz;
    
    printf("行列の積 A×B = C を計算します。\n");
    
    while (1) {
        printf("エンターキーを押してください・・・");
        fgets(buf, sizeof buf, stdin);
        sscanf(buf, "%c", &zz);
        if (zz != '\n')
            continue;
        else
            break;
    }
    printf("\n");
    
    for (i = 0; i < I; i++)
        for (j = 0; j < J; j++) {
            c[i][j] = 0;
            for (k = 0; k < K; k++)
                c[i][j] += a[i][k] * b[k][j];
        }
}



/*
 * 計算結果を表示する関数
 */
void print_result(void)
{
    printf("\n");
    printf("行列C(%d行%d列)", I, J);
    for (i = 0; i < I; i++) {
        printf("\n\t");
        for (j = 0; j < J; j++)
            printf("%5d", c[i][j]);
    }
    printf("\n");
}



/*
 * 操作を続けるかどうかを選択する関数
 * true: 繰り返す、false: 終了する。
 */
bool retry(void)
{
    bool ret;
    char buf[BUF_SIZE], ch, zz;
    
    while (1) {
        printf("\n続けますか?(y/n) ");
        
        fgets(buf, sizeof buf, stdin);
        sscanf(buf, "%c%c", &ch, &zz);
        
        if (((ch == 'y') || (ch == 'Y')) && (zz == '\n')) {
            printf("\n+++++\n\n");
            ret = true;
            break;
        } else if (((ch == 'n') || (ch == 'N')) && (zz == '\n')) {
            ret = false;
            break;
        }
        printf("無効な入力です。\n");
        printf("yまたはnを入力してください。\n");
    }
    
    return ret;
}


gyoretsuの実行結果】赤字はユーザによる入力を表す。

C:\Users\skonishi\Documents>gyoretsu
【行列の積の計算と表示】

行列の積
A(I行K列)×B(K行J列) = C(I行J列)
の計算をします。
(ただし、I、J、Kは1~5の整数)

I、J、Kを順に入力してください。
(ただし、I、J、Kは1~5の整数)

エンターキーを押してください・・・[エンター]キー

I = ? 3
J = ? 4
K = ? 5
行列A、Bの成分に、擬似乱数を自動で代入します。
エンターキーを押してください・・・[エンター]キー

行列A(3行5列)
          -4   7   5   0   2
           1   9  -6  -9   2
           8   1 -10  -4   8
行列B(5行4列)
           1  -9 -10  -1
          -5 -10   4   7
           3   3  -7  -4
          -1   1   3   7
           9   9  -2   8
行列の積 A×B = C を計算します。
エンターキーを押してください・・・[エンター]キー


行列C(3行4列)
           -6   -1   29   49
          -35 -108   37   39
           49  -44  -34   75

続けますか?(y/n) y

+++++

【行列の積の計算と表示】

行列の積
A(I行K列)×B(K行J列) = C(I行J列)
の計算をします。
(ただし、I、J、Kは1~5の整数)

I、J、Kを順に入力してください。
(ただし、I、J、Kは1~5の整数)

エンターキーを押してください・・・[エンター]キー

I = ? 1
J = ? 1
K = ? 5
行列A、Bの成分に、擬似乱数を自動で代入します。
エンターキーを押してください・・・[エンター]キー

行列A(1行5列)
          -6   1 -10  -2  -3
行列B(5行1列)
          -4
           3
          -3
           6
           1
行列の積 A×B = C を計算します。
エンターキーを押してください・・・[エンター]キー


行列C(1行1列)
           42

続けますか?(y/n) y

+++++

【行列の積の計算と表示】

行列の積
A(I行K列)×B(K行J列) = C(I行J列)
の計算をします。
(ただし、I、J、Kは1~5の整数)

I、J、Kを順に入力してください。
(ただし、I、J、Kは1~5の整数)

エンターキーを押してください・・・[エンター]キー

I = ? 5
J = ? 5
K = ? 1
行列A、Bの成分に、擬似乱数を自動で代入します。
エンターキーを押してください・・・[エンター]キー

行列A(5行1列)
           2
          -4
           7
           8
         -10
行列B(1行5列)
           4 -10   7  -2  -3
行列の積 A×B = C を計算します。
エンターキーを押してください・・・[エンター]キー


行列C(5行5列)
            8  -20   14   -4   -6
          -16   40  -28    8   12
           28  -70   49  -14  -21
           32  -80   56  -16  -24
          -40  100  -70   20   30

続けますか?(y/n) n

戻る