アプリ版:「スタンプのみでお礼する」機能のリリースについて

二次元配列を関数の引数として渡し、
その配列を戻り値として呼び出し元の変数に返したいです。
具体的にはルンゲクッタ法で微分する関数の引数を行列で扱いたいです。
for (i=0;i<N;i++){
for (j=0;j<N;j++){
y[i][j]=rand();
}
}
  K1=h*ff(t,y);
K2=h*ff(t+h/2,y+K1/2);
K3=h*ff(t+h/2,y+K2/2);
K4=h*ff(t+h,y+K3);
Ka=(K1+2*K2+2*K3+K4)/6;

double ff(int t,double y[][]){
ここで
return y[][];
のような形で二次元配列を戻り値として変数に返したいのです。
}

C言語初心者なのでいまいちよくわかりません、
宜しくお願いいたします。

A 回答 (4件)

>Ka=(K1+2*K2+2*K3+K4)/6;


>の文の後に元の配列y[][]にKa[][]を加える操作 y+Ka; をします。
>また、K2=h*ff(t+h/2,y+K1/2);

C言語では「配列同士」や「配列と数値」の演算は直接できませんので、K2=h*ff(t+h/2,y+K1/2) という式は書けないのですが、このあたりはご理解されているでしょうか?
ご理解されているという前提で続けますと、配列を渡してその中身を変えることなく結果を配列で返したいときは、構造体のメンバにする方法があります。

#define N 10
typedef struct
{
double K[N][N];
} hairetu;

hairetu ff(hairetu arr)
{
/* arr.K[][] に対して演算する */

return arr;
}

int main()
{
hairetu y, Ka;
int i, j;

for (i=0;i<N;i++){
for (j=0;j<N;j++){
y.K[i][j]=rand();
}
}

Ka = ff(y); /* y.K[][]の内容は変わらない。ffの演算結果をKa.K[][]に代入できる */
・・・・・
}
    • good
    • 0
この回答へのお礼

ありがとうございました。
以前違う言語で書いたものがそのままになっていて分かりにくいところがありすみませんでした。

お礼日時:2005/02/04 18:41

#1の方の指摘の通り、普通の変数は関数の中で値を変えても呼び出し元の変数は変わりませんが、


配列の場合はアドレスを渡すことになるので、特別な方法を使わない限り、関数の中で配列の中身を変更すると結果として呼び出し元の配列の中身も変わります。
ですから、特別な事情がない限り配列を返す必要はあまりありません。

普通の変数では
void ff(int a)
{
a = 3;
}
int main()
{
int a;
a = 0;
ff(a);
printf("%d\n", a); /* 0と表示される 3とは表示されない */
return 0;
}

配列では
void ff(int a[][4])
{
a[0][0] = 3;
}
int main()
{
int a[2][4];
a[0][0] = 0;
ff(a);
printf("%d\n", a[0][0]); /* 3と表示される 0とは表示されない */
return 0;
}

この回答への補足

回答ありがとうございます。

下の補足にも書かせていただきましたが、
書き忘れていましたが、
質問文のプログラム例の
Ka=(K1+2*K2+2*K3+K4)/6;
の文の後に元の配列y[][]にKa[][]を加える操作
y+Ka;
をします。
また、
K2=h*ff(t+h/2,y+K1/2);
K3=h*ff(t+h/2,y+K2/2);
K4=h*ff(t+h,y+K3);
のように
求めていくK1,K2,K3をそれぞれ関数の引数としてまた計算させたいのです。
その場合でも戻り値にしなくてもできるのでしょうか?
宜しくお願いいたします。

補足日時:2005/02/03 13:57
    • good
    • 0

void ff(int t,double** ppY,int x,int y)


{
}

double ppy[10][9];
ff(8,(double**)ppy,10,9);

という感じではどうでしょうか?
引数で渡している二次元配列を処理して同じ二次元配列を返すだけでしたらあえてreturun ppy;のようにしなくてもいいかと思います。またx,yはppY[x][y]の最大インデックスを示しています。そうしないと変なメモリにアクセスしかねませんから。

この回答への補足

回答ありがとうございます。

このようにポインタを使うことで戻り値としても使えるのですね。
そのようにした場合、
K1=h*ff(t,(double**)ppy,10,9);
K2=h*ff(t+h/2,(double**)ppy+K1/2,10,9);

というようにしていけばいいのでしょうか?
すみませんが、宜しくお願いいたします。

補足日時:2005/02/03 14:03
    • good
    • 0

戻り値として返すのは何か特別な目的があるのですか。



そうでなければ、戻り値を使わなくても引数にした配列に自動的に答えが戻ってきます。
配列はアドレス渡しですので、呼び出し側と関数側で同一配列を共用することになります。

この回答への補足

回答ありがとうございます。

すみません。
書き忘れていましたが、質問文のプログラム例の
Ka=(K1+2*K2+2*K3+K4)/6;
の文の後に元の配列y[][]にKa[][]を加える操作
y+Ka;
をします。
そうするとy[][]の値が変化していってしまうと不便だなと思ったのですが、いかがでしょうか。
宜しくお願いいたします。

補足日時:2005/02/03 13:55
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!