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

2つの行列の行と列を入力し、積を計算するプログラムを関数を使って書きたいのですが、上手く行きません。どこをどのように直したらよいか教えてください!お願いします!!

以下が私が書いたプログラムです。



#include<stdio.h>
#define NUMBER 10

int first(int x1,int x2,int y1,int y2,int i,int j,int k)
{
int a[NUMBER][NUMBER] = {0};
int b[NUMBER][NUMBER] = {0};
int c[NUMBER][NUMBER] = {0};

do{
printf("2つの行列の行と列を入力してください\n");
scanf("%d", &x1); scanf("%d", &x2);
scanf("%d", &y1); scanf("%d", &y2);
if(x1 != y2){
printf("行列の積は計算できません\n");
}
}while(x1 != y2);

printf("行列Aの要素を入力してください\n");
for(i=0; i<x1; i++){
for(j=0; j<x2; j++)
scanf("%d", &a[i][j]);
}

printf("行列Bの要素を入力してください\n");
for(j=0; j<y1; j++){
for(k=0; k<y2; k++)
scanf("%d", &b[j][k]);
}
}


int second(int x1,int x2,int y1,int y2,int i,int j,int k)
{
int a[NUMBER][NUMBER] = {0};
int b[NUMBER][NUMBER] = {0};
int c[NUMBER][NUMBER] = {0};

for(i=0; i<x1; i++){
for(k=0; k<y2; k++){
for(j=0; j<x2; j++)
c[i][k] = c[i][k] + a[i][j]*b[j][k];
}
}

for(i=0; i<x2; i++){
for(k=0; k<y2; k++)
printf("%3d", c[i][k]);
printf("\n");
}
}


int main(void)
{
int a[NUMBER][NUMBER] = {0};
int b[NUMBER][NUMBER] = {0};
int c[NUMBER][NUMBER] = {0};

printf("行列の積を計算します\n %d\n", first(x1,x2,y1,y2,i,j,k));

printf("行列Aと行Bの積は\n %3d",second(x1,x2,y1,y2,i,j,k));
}

A 回答 (7件)

>初期化してみましたが上手く行きませんでした・


int a[NUMBER][NUMBER] = {0};
int b[NUMBER][NUMBER] = {0};
int c[NUMBER][NUMBER] = {0};

の部分を関数の外に出してください。
それぞれの配列でのやりとりをしていないので、
同じ配列をいじるというプログラムになっていますが、
現状は、別々に確保されています。
    • good
    • 0
この回答へのお礼

ありがとうございます。
関数の外に出して定義しました。

お礼日時:2005/06/19 22:58

No5 bf109e さんに補足です。



No5 bf109e さんのご回答の、first()、second() のそれぞれの引数を、以下の3つのうちのいずれかに変更してみてください。
# a だけでなく、b も同様です。

int a[][]
→int a[NUMBER][NUMBER]
 int a[][NUMBER]
 int (*a)[][NUMBER]

一番目は、配列をそのまま渡すイメージでわかりやすいと思います。

二番目は、配列をそのまま渡すイメージではありますが、前の要素数が空っぽになっています。
要するに書いても意味がないってことです。

その理由が三番目です。
これは「配列を指すポインタ」の定義になります。
配列はその先頭要素を指すポインタに読み替えられるのはご存知でしょうか。
配列の配列でも同様の読替えが起こります。

参考URL の No5 (私のアドバイスですけど。。。) にも書いていますので、そちらもご参照ください。
# 少々長いのはご勘弁ください。。。

これでいかがでしょうか。

参考URL:http://oshiete1.goo.ne.jp/kotaeru.php3?q=1440162
    • good
    • 0
この回答へのお礼

ありがとうございます。
配列のところでつまづいたままなのできちんと勉強しなおしたいと思います。

お礼日時:2005/06/19 22:58

#include<stdio.h>


#define NUMBER 10

void first(int a[][], int b[][])
{
/*行列a,bの要素を入力*/
second(a, b, x1, x2, y1, y2);
}

void second(int a[][], int b[][], int x1, int x2, int y1, int y2)
{
int c[NUMBER][NUMBER] = {0};
/*a,bの積を計算,表示*/
}

int main(void)
{
int a[NUMBER][NUMBER] = {0};
int b[NUMBER][NUMBER] = {0};
printf("行列の積を計算します\n");
first(a,b);
return 0;
}
大まかな形はこんなもんでどうでしょう。
    • good
    • 0
この回答へのお礼

ありがとうございます^^
大まかに参考にさせてもらいましたが、やっぱり上手くいきませんでした・・。

お礼日時:2005/06/16 21:09

#1さんの様に、


式中にc[i][j]を埋め込まないで、一時変数を使うというのは、
ループの中で、[i][j]によるアドレスの計算をいちいちさせないという効果があります。
コンパイラによっては自分で最適化してくれるかもしれませんが、書いても損にはなりません。(むしろ推奨です)
ただ、使う前に初期化しないといけないのは同じです。
    • good
    • 0
この回答へのお礼

ありがとうございます^^
式中にc[i][j]を埋め込まないで一時変数をおくといいのですね。初期化ということはどこかでw=0と書くということで良いのでしょうか?
参考になりました^^

お礼日時:2005/06/16 21:08

#2さんに賛成。


よく考えたら、同じでした。
ごめんなさい。
    • good
    • 0

c[i][k]がちゃんと0で初期化されていないのが原因だと思います。


適当なタイミング
for(j=0; j<x2; j++)の前で
c[i][k]=0をしてやればいいような気がします
    • good
    • 0
この回答へのお礼

ありがとうございます!
指定していただいた場所で初期化してみましたが上手く行きませんでした・・でも初期化のことは今後の参考にさせていただきます^^

お礼日時:2005/06/16 21:06

for(j=0; j<x2; j++)


c[i][k] = c[i][k] + a[i][j]*b[j][k];
}

ここで、足し過ぎてませんか?
変数をもうひとつ用意して、

w=w + a[i][j]*b[j][k];

c[i][k] = w;

では、いかがでしょう。
    • good
    • 0
この回答へのお礼

ありがとうございます!
参考にさせていただきました^^

お礼日時:2005/06/16 21:05

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