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

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

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

関数型プログラミング

関数型プログラミングとは、関数を用いて演算子を構築し、算出し、コンピュータプログラムを構成する枠組みです。

Q&A

解決済

5回答

3062閲覧

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

oinari03

総合スコア59

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

関数型プログラミング

関数型プログラミングとは、関数を用いて演算子を構築し、算出し、コンピュータプログラムを構成する枠組みです。

0グッド

0クリップ

投稿2020/08/01 18:24

編集2020/08/01 18:30

やりたいこと

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

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

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

今回書いたプログラム

内容は

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

c

1#include <stdio.h> 2 3// 関数初期化宣言 4double tenti(double A[3][3], double AT[3][3]); 5double make_gyouretu(double A[3][3],double AT[3][3]); 6double add_tenti(double A[3][3],double AT[3][3]); 7double deff_tenti(double A[3][3],double AT[3][3]); 8 9// main関数 10int main(void) { 11 double A[3][3] = {{1.0,2.0,3.0},{4.0,5.0,6.0},{7.0,8.0,9.0}}; 12 double AT[3][3]; 13 14 // 関数呼び出し 15 make_gyouretu(A,AT); 16 tenti(A, AT); 17 add_tenti(A,AT); 18 deff_tenti(A,AT); 19 20 return 0; 21} 22 23// 行列の表示 24double make_gyouretu(double A[3][3],double AT[3][3]) 25{ 26 int i,j; 27 28 printf("行列A\n"); 29 30 for (i=0; i < 3; i++) { 31 for (j=0; j< 3; j++) { 32 printf("%.1f ", A[i][j]); 33 } 34 printf("\n"); 35 } 36} 37 38// 転置行列 39double tenti(double A[3][3],double AT[3][3]) 40{ 41 int i,j; 42 for (i=0; i < 3; i++) { 43 for (j=0; j< 3; j++) { 44 AT[j][i] = A[i][j]; 45 } 46 printf("\n"); 47 } 48 printf("転置行列AT\n"); 49 for (i=0; i < 3; i++) { 50 for (j=0; j< 3; j++) { 51 printf("%.1f ", AT[i][j]); 52 } 53 printf("\n"); 54 } 55 printf("\n"); 56 57} 58 59// 和を求める 60double add_tenti(double A[3][3],double AT[3][3]) 61{ 62 int i,j; 63 printf("AT-A\n"); 64 for (i=0; i < 3; i++) { 65 for (j=0; j< 3; j++) { 66 printf("%.1f ", A[i][j] + AT[i][j]); 67 } 68 printf("\n"); 69 } 70 printf("\n"); 71} 72 73//差を求める 74double deff_tenti(double A[3][3],double AT[3][3]) 75{ 76 int i,j; 77 printf("AT-A\n"); 78 for (i=0; i < 3; i++) { 79 for (j=0; j< 3; j++) { 80 printf("%.1f ", A[i][j] - AT[i][j]); 81 } 82 printf("\n"); 83 } 84 printf("\n"); 85}

結果

行列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で呼び出すことなのでご了承ください。

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cateye

2020/08/01 21:29 編集

指摘が有りますが、返り値がない関数は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/01 22:52

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

2020/08/02 07:22

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

2020/08/03 06:59 編集

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

回答5

0

僕だったら

  • 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 をプリント

投稿2020/08/02 04:03

episteme

総合スコア16612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

魔改造?

C

1#include <stdio.h> 2 3void mat_print(const char *name, double A[3][3]); 4void mat_trans(double A[3][3], double AT[3][3]); 5void mat_add(double A[3][3], double B[3][3], double Sum[3][3]); 6void mat_sub(double A[3][3], double B[3][3], double Dif[3][3]); 7 8int main(void) 9{ 10 double A[3][3] = { 11 { 1.0, 2.0, 3.0 }, 12 { 4.0, 5.0, 6.0 }, 13 { 7.0, 8.0, 9.0 } 14 }; 15 double B[3][3], C[3][3]; 16 17 mat_print("行列A", A); 18 mat_trans(A, B); mat_print("転置行列AT", B); 19 mat_add(A, B, C); mat_print("A + AT", C); 20 mat_sub(A, B, C); mat_print("A - AT", C); 21 return 0; 22} 23 24// 行列の表示 25void mat_print(const char *name, double A[3][3]) 26{ 27 printf("%s\n", name); 28 for (int i = 0; i < 3; i++) { 29 for (int j = 0; j < 3; j++) 30 printf("%6.1f ", A[i][j]); 31 putchar('\n'); 32 } 33} 34 35// 転置行列 36void mat_trans(double A[3][3], double AT[3][3]) 37{ 38 for (int i = 0; i < 3; i++) 39 for (int j = 0; j < 3; j++) 40 AT[i][j] = A[j][i]; 41} 42 43// 和を求める 44void mat_add(double A[3][3], double B[3][3], double Sum[3][3]) 45{ 46 for (int i = 0; i < 3; i++) 47 for (int j = 0; j < 3; j++) 48 Sum[i][j] = A[i][j] + B[i][j]; 49} 50 51//差を求める 52void mat_sub(double A[3][3], double B[3][3], double Dif[3][3]) 53{ 54 for (int i = 0; i < 3; i++) 55 for (int j = 0; j < 3; j++) 56 Dif[i][j] = A[i][j] - B[i][j]; 57}

投稿2020/08/02 03:54

編集2020/08/02 04:00
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oinari03

2020/08/02 07:11

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

0

  1. 行列をグローバルに宣言してヘッダーに移動する。

行列を関数の引数に渡さない。
0. 関数宣言を全部ヘッダーに移動する。
0. 行列のサイズ(3)を #define MATRIX_SIZE 3などにする
0. for文内で変数宣言

c

1for(int i=0; i<MATRIX_SIZE; i++)

投稿2020/08/01 23:21

fu7mu4

総合スコア1088

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

thkana

2020/08/02 02:44

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

2020/08/02 07:12

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

0

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

c

1#include <stdio.h> 2 3typedef double Matrix[3][3]; 4// 関数プロトタイプ宣言 5void print(const char *msg, Matrix mat); 6void tenti(Matrix A, Matrix AT); 7void add_tenti(Matrix A, Matrix AT); 8void deff_tenti(Matrix A, Matrix AT); 9// main関数 10int main(void) 11{ 12 Matrix A = {{1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}, {7.0, 8.0, 9.0}}; 13 Matrix AT; 14 15 // 関数呼び出し 16 print("行列A",A); 17 tenti(A, AT); 18 add_tenti(A, AT); 19 deff_tenti(A, AT); 20 21 return 0; 22} 23 24// 行列の表示 25void print(const char *msg, Matrix mat) 26{ 27 putchar('\n'); 28 puts(msg); 29 30 for(int i = 0; i < 3; i++) { 31 for(int j = 0; j < 3; j++) { 32 printf("%.1f ", mat[i][j]); 33 } 34 putchar('\n'); 35 } 36} 37// 転置行列 38void tenti(Matrix A, Matrix AT) 39{ 40 for(int i = 0; i < 3; i++) { 41 for(int j = 0; j < 3; j++) { 42 AT[j][i] = A[i][j]; 43 } 44 } 45 print("転置行列AT", AT); 46} 47// 和を求める 48void add_tenti(Matrix A, Matrix AT) 49{ 50 Matrix tmp; 51 for(int i = 0; i < 3; i++) { 52 for(int j = 0; j < 3; j++) { 53 tmp[i][j] = A[i][j] + AT[i][j]; 54 } 55 } 56 print("AT+A", tmp); 57} 58// 差を求める 59void deff_tenti(Matrix A, Matrix AT) 60{ 61 Matrix tmp; 62 for(int i = 0; i < 3; i++) { 63 for(int j = 0; j < 3; j++) { 64 tmp[i][j] = A[i][j] - AT[i][j]; 65 } 66 } 67 print("AT-A", tmp); 68}

結果↓

行列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/01 23:10

cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cateye

2020/08/01 23:17

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

2020/08/02 07:14

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

0

ベストアンサー

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

  • 関数の名前が実際の処理と矛盾している

make_gyouretuというよりもprint_gyouretu
add_tentiだと転置行列を元の行列と足すと感じられるので、add_gyouretuの方が良い。(あるいは和を表示するだけなのでprint_add_gyouretuとか)

  • スペルミス

ex:defではなくdiff(different)。そもそも引き算は英語でsubtractionなのでsub_gyouretuの方が良い。

  • 戻り値ない。
  • 和なのにAT-Aと表示している。
  • コメントが実際の処理と違って困惑する。//差を求めると書くと、定義が関数なのでなんらかの計算して値を返してくれるのかなと期待する。実際には //差を表示する でしょう。
  • 行列は英語でmatrixなのでそう書いた方がかっこいい。

投稿2020/08/01 19:11

Penpen7

総合スコア698

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oinari03

2020/08/02 07:08

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問