質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.06%

c言語でつくった単純な自作関数をmain関数で呼び出すプログラムだが、もっとスマートにしたい。

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 314

Kanikama_h

score 40

やりたいこと

以下の内容の関数を作りmainで呼び出すことが自分の課題になっている。
・double型の行列
・最初の行列Aを表示(形は123,456,789の3x3で決まっている)
・転置行列ATの計算からの表示
・A+ATの計算
・A-ATの計算

これらの処理を動くように書いてみたがもうちょっとスマートにかけないか?? もっと別の方法で書けないか??さらにはc言語の規則的にどう書くのが正しいのか??というかぶっちゃけこの頭悪そうなコードが嫌すぎるというのがあります

が気になってしまっていろいろ調べてみたが、先人の知恵をお借りできれば新しい考えが浮かぶと思って質問しました。

今回書いたプログラム

内容は

・double型の行列
・最初の行列Aを表示(形は123,456,789の3x3で決まっている)
・転置行列ATの計算からの表示
・A+ATの計算
・A-ATの計算
のようになっている

#include <stdio.h>

// 関数初期化宣言
double tenti(double A[3][3], double AT[3][3]);
double make_gyouretu(double A[3][3],double AT[3][3]);
double add_tenti(double A[3][3],double AT[3][3]);
double deff_tenti(double A[3][3],double AT[3][3]);

// main関数
int main(void) {
    double A[3][3] = {{1.0,2.0,3.0},{4.0,5.0,6.0},{7.0,8.0,9.0}};
    double AT[3][3];

    // 関数呼び出し
    make_gyouretu(A,AT);
    tenti(A, AT);
    add_tenti(A,AT);
    deff_tenti(A,AT);

    return 0;
}

// 行列の表示
double make_gyouretu(double A[3][3],double AT[3][3])
{
    int i,j;

    printf("行列A\n");

    for (i=0; i < 3; i++) {
        for (j=0; j< 3; j++) {
            printf("%.1f ", A[i][j]);
        }
        printf("\n");
    }
}

// 転置行列
double tenti(double A[3][3],double AT[3][3])
{
    int i,j;
    for (i=0; i < 3; i++) {
        for (j=0; j< 3; j++) {
            AT[j][i] = A[i][j];
        }
        printf("\n");
    }
    printf("転置行列AT\n");
    for (i=0; i < 3; i++) {
        for (j=0; j< 3; j++) {
            printf("%.1f ", AT[i][j]);
        }
        printf("\n");
    }
    printf("\n");

}

// 和を求める
double add_tenti(double A[3][3],double AT[3][3])
{
    int i,j;
    printf("AT-A\n");
    for (i=0; i < 3; i++) {
        for (j=0; j< 3; j++) {
            printf("%.1f ", A[i][j] + AT[i][j]);
        }
        printf("\n");
    }  
    printf("\n");
}

//差を求める
double deff_tenti(double A[3][3],double AT[3][3])
{
    int i,j;
    printf("AT-A\n");
    for (i=0; i < 3; i++) {
        for (j=0; j< 3; j++) {
            printf("%.1f ", A[i][j] - AT[i][j]);
        }
        printf("\n");
    }  
    printf("\n");
}

結果

行列A
1.0 2.0 3.0
4.0 5.0 6.0
7.0 8.0 9.0



転置行列AT
1.0 4.0 7.0
2.0 5.0 8.0
3.0 6.0 9.0

AT-A
2.0 6.0 10.0
6.0 10.0 14.0
10.0 14.0 18.0

AT-A
0.0 -2.0 -4.0
2.0 0.0 -2.0
4.0 2.0 0.0

まとめ

自分の中で書き換えられると思えるのは転置行列を求めるところが一番である。
本来mainの中で書けば全然問題ないのだが、目的はあえて自作関数をスマートに書いてmainで呼び出すことなのでご了承ください。

皆さん知恵を貸していただき好きに魔改造していただきたいです。
何か至らない点があればご指摘よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • cateye

    2020/08/02 06:24 編集

    指摘が有りますが、返り値がない関数はvoidを使いましょう。
    で、ネーミングは置いといてw、行列を1つしか使ってないのに2個渡している。
    make_gyouretu(A,AT);→ make_gyouretu(A);
    double make_gyouretu(double A[3][3],double AT[3][3])→void make_gyouretu(double A[3][3])

    キャンセル

  • Daregada

    2020/08/02 07:52

    行列の計算と表示を分離してみては。

    キャンセル

  • Kanikama_h

    2020/08/02 16:22

    ありがとうございます!いろいろ知らないことばっかりで参考になります!

    キャンセル

  • miyabi-sun

    2020/08/03 15:58 編集

    関数型プログラミングとは一体……うごごごご……!

    キャンセル

回答 5

+1

僕だったら

  • print(A) : A をプリントする
  • copy(B,A) : B を A にコピーする
  • transpose(A) : Aの転置をAに求める
  • add(A,B): A + B をAに求める
  • sub(A,B): A - B をAに求める

こんだけ作る。
※ print(A)以外の関数はプリントしない。

こんだけあれば行列 A, AT, X を用意しておいて

print(A) A をプリント

copy(AT, A)
transpose(AT)
print(AT) Aの転置(AT)をプリント

copy(X,A)
add(X,AT)
print(X) A+AT をプリント

copy(X,A)
sub(X,AT)
print(X) A-AT をプリント

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

0

コメントと命名を見て気になった部分を書きました。

  • 関数の名前が実際の処理と矛盾している
    make_gyouretuというよりもprint_gyouretu
    add_tentiだと転置行列を元の行列と足すと感じられるので、add_gyouretuの方が良い。(あるいは和を表示するだけなのでprint_add_gyouretuとか)
  • スペルミス
    ex:defではなくdiff(different)。そもそも引き算は英語でsubtractionなのでsub_gyouretuの方が良い。
  • 戻り値ない。
  • 和なのにAT-Aと表示している。
  • コメントが実際の処理と違って困惑する。//差を求めると書くと、定義が関数なのでなんらかの計算して値を返してくれるのかなと期待する。実際には //差を表示する でしょう。
  • 行列は英語でmatrixなのでそう書いた方がかっこいい。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/08/02 16:08

    たくさんの方の中から最初に返信してくださったのでベストアンサーにしました。スペルミスや名前の付け方など教えてくれてありがとうございます。

    キャンセル

0

関数名等いじってないですが・・・いくらか見やすいかと?

#include <stdio.h>

typedef double Matrix[3][3];
// 関数プロトタイプ宣言
void print(const char *msg, Matrix mat);
void tenti(Matrix A, Matrix AT);
void add_tenti(Matrix A, Matrix AT);
void deff_tenti(Matrix A, Matrix AT);
// main関数
int main(void)
{
    Matrix A = {{1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}, {7.0, 8.0, 9.0}};
    Matrix AT;

    // 関数呼び出し
    print("行列A",A);
    tenti(A, AT);
    add_tenti(A, AT);
    deff_tenti(A, AT);

    return 0;
}

// 行列の表示
void print(const char *msg, Matrix mat)
{
    putchar('\n');
    puts(msg);

    for(int i = 0; i < 3; i++) {
        for(int j = 0; j < 3; j++) {
            printf("%.1f ", mat[i][j]);
        }
        putchar('\n');
    }
}
// 転置行列
void tenti(Matrix A, Matrix AT)
{
    for(int i = 0; i < 3; i++) {
        for(int j = 0; j < 3; j++) {
            AT[j][i] = A[i][j];
        }
    }
    print("転置行列AT", AT);
}
// 和を求める
void add_tenti(Matrix A, Matrix AT)
{
    Matrix tmp;
    for(int i = 0; i < 3; i++) {
        for(int j = 0; j < 3; j++) {
            tmp[i][j] = A[i][j] + AT[i][j];
        }
    }
    print("AT+A", tmp);
}
// 差を求める
void deff_tenti(Matrix A, Matrix AT)
{
    Matrix tmp;
    for(int i = 0; i < 3; i++) {
        for(int j = 0; j < 3; j++) {
            tmp[i][j] = A[i][j] - AT[i][j];
        }
    }
    print("AT-A", tmp);
}


結果↓

行列A
1.0 2.0 3.0 
4.0 5.0 6.0 
7.0 8.0 9.0 

転置行列AT
1.0 4.0 7.0 
2.0 5.0 8.0 
3.0 6.0 9.0 

AT+A
2.0 6.0 10.0 
6.0 10.0 14.0 
10.0 14.0 18.0 

AT-A
0.0 -2.0 -4.0 
2.0 0.0 -2.0 
4.0 2.0 0.0 

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/08/02 08:17

    AT+A→A+AT
    AT-A→A-AT

    キャンセル

  • 2020/08/02 16:14

    自分のコードと比べたらかなりスマートです!!ありがとうございます!!

    キャンセル

0

  1. 行列をグローバルに宣言してヘッダーに移動する。
    行列を関数の引数に渡さない。
  2. 関数宣言を全部ヘッダーに移動する。
  3. 行列のサイズ(3)を #define MATRIX_SIZE 3などにする
  4. for文内で変数宣言
for(int i=0; i<MATRIX_SIZE; i++)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/08/02 11:44

    > 行列をグローバルに宣言してヘッダーに移動する。
    > 行列を関数の引数に渡さない。
    これは「スマート」じゃないと思う。

    キャンセル

  • 2020/08/02 16:12

    さまざまな意見ありがたいです。行列サイズを固定するやり方は参考になりました。

    キャンセル

0

魔改造?

#include <stdio.h>

void mat_print(const char *name, double A[3][3]);
void mat_trans(double A[3][3], double AT[3][3]);
void mat_add(double A[3][3], double B[3][3], double Sum[3][3]);
void mat_sub(double A[3][3], double B[3][3], double Dif[3][3]);

int main(void)
{
    double A[3][3] = {
        { 1.0, 2.0, 3.0 },
        { 4.0, 5.0, 6.0 },
        { 7.0, 8.0, 9.0 }
    };
    double B[3][3], C[3][3];

    mat_print("行列A", A);
    mat_trans(A, B);  mat_print("転置行列AT", B);
    mat_add(A, B, C); mat_print("A + AT", C);
    mat_sub(A, B, C); mat_print("A - AT", C);
    return 0;
}

// 行列の表示
void mat_print(const char *name, double A[3][3])
{
    printf("%s\n", name);
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++)
            printf("%6.1f ", A[i][j]);
        putchar('\n');
    }
}

// 転置行列
void mat_trans(double A[3][3], double AT[3][3])
{
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            AT[i][j] = A[j][i];
}

// 和を求める
void mat_add(double A[3][3], double B[3][3], double Sum[3][3])
{
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            Sum[i][j] = A[i][j] + B[i][j];
}

//差を求める
void mat_sub(double A[3][3], double B[3][3], double Dif[3][3])
{
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            Dif[i][j] = A[i][j] - B[i][j];
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/08/02 16:11

    魔改造ありがとうございます!!!参考にします!!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.06%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • トップ
  • Cに関する質問
  • c言語でつくった単純な自作関数をmain関数で呼び出すプログラムだが、もっとスマートにしたい。