🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

Q&A

解決済

3回答

818閲覧

c言語 重心を求めたい! 助けてください!

0126tami

総合スコア60

C

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

0グッド

0クリップ

投稿2019/11/13 12:50

編集2019/11/17 10:34

zyusin関数が全く機能していないみたいです。
どうか助けてください。

ちなみにzyusin関数は全て自分で作っています泣

8 10 //8かける10のテキストファイル
0 0 0 0 0 1 1 1
0 0 0 0 1 1 1 0
2 0 0 0 1 1 1 0
2 2 0 0 0 1 1 0
2 2 0 0 0 0 0 0
2 2 2 0 0 0 0 0
2 2 2 0 0 0 0 0
0 2 2 0 0 0 0 0
0 2 2 2 0 0 0 0
0 0 2 2 0 0 0 0

1つの画像を値として考えたものをテキストファイルに保存してあります

このようにラベリング処理されたものがあるとします。
それをラベルごとの座標の重心を求めたいです。

例えば 1の場合(5、0)(6、0)(7、0)(4、1)(5、1)(6、1)(4、2)(5、2)(6、2)(5、3)(6、3)で

(5+6+7+4+5+6+4+5+6+5+6)/11=5 小数点はなし
(0+0+0+1+1+1+2+2+2+3+3)/11=1 小数点はなし

(5、1)

このような計算をするzyusin関数を作りたいです。

メイン部分 *****新たに変えました** ラベル数に応じて返す値を増やしたりしたいのですがそこができません Zahyou zyusin(Img img){ Zahyou zahyou; int sx,sy; int x,y,label1x=0,label1y=0,label2x=0,label2y=0,label3x=0,label3y=0,label4x=0,label4y=0; int label1=0,label2=0,label3=0,label4=0; img.sx=sx; img.sy=sy; for(y=0;y<sy;y++){ for(x=0;x<sx;x++){ if(img.d[0][y][x]==1){ label1++; label1x=label1x+x; label1y=label1y+y; }else if(img.d[0][y][x]==2){ label2++; label2x=label2x+x; label2y=label2y+y; }else if(img.d[0][y][x]==3){ label3++; label3x=label3x+x; label3y=label3y+y; }else if(img.d[0][y][x]==4){ label4++; label4x=label4x+x; label4y=label4y+y; } } } label1x=label1x/label1; label1y=label1y/label1; label2x=label2x/label2; label2y=label2y/label2; label3x=label3x/label3; label3y=label3y/label3; label4x=label4x/label4; label4y=label4y/label4; Zahyou.px=label1x; Zahyou.py=label1y; return zahyou; } ******新たに追加しました***** void fputz(FILE *fp, Zahyou zahyou){ int i; for(i=0;i<4;i++){ //4はラベルの数だけ分にしたい今回の例だと2 fprintf(fp,"%d %d",zahyou.px,zahyou.py); } fprintf(fp,"\n"); }
 格納される部分 #define MAX 255 #define MX 20 #define MY 20 #define R 0 #define G 1 #define B 2 #define MC 3 typedef struct zahyou{ int px,py; } Zahyou; typedef struct img { int sx, sy; int d[MC][MY][MX]; } Img; typedef struct param { int low[MC], up[MC]; int n, t; } Param; Img fgetimg(FILE *); Param fgetparam(FILE *); void fputimg(FILE *, Img); void fputimg_uni(FILE *, Img, int); void fputz(FILE *, Zahyou);

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

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

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

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

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

guest

回答3

0

ベストアンサー

しかしやはりzyusin関数でラベルの数によって返す値が何個になるのか決める思考がどういう風にしたらいいか想像できません。泣

配列にすれば良いです。
typedef struct zahyou{
int px,py;
} Zahyou;
でpx,pyを配列にします。
px[0]はラベル1用
px[1]はラベル2用
・・・以下同様・・・
にすれば、可能になります。
まず、「格納される部分」の定義に以下を加えます。
(最大100のラベルまで対応することにします)

C

1//重心の座標定義 2#define ML (100) //ラベル番号の最大値 3typedef struct zahyou{ 4 int px[ML]; //重心のx座標の配列(他の変数も同様とする) 5 //px[0]:ラベル1用 6 //px[n]:ラベルn+1用 7 //px[99]:ラベル100用 8 int py[ML]; //重心のy座標 9 int count[ML]; //ラベルの数 10 int sumx[ML]; //xの合計 11 int sumy[ML]; //yの合計 12} Zahyou; 13 14//関数の定義 15Zahyou zyusin(Img img); 16void fputz(FILE *fp, Zahyou za); 17

次に本体ですが、以下のようになります。

C

1 //*ここの部分を見てください!!!! 2 printf("zyusin.\n"); 3 Zahyou za; 4 za = zyusin(img); //重心座標計算 5 fputz(stdout,za); //重心座標印字 6

重心座標計算と重心座標印字は以下のようにします。

C

1//*****ここから見てください***** 2Zahyou zyusin(Img img) 3{ 4 Zahyou za; 5 int i; 6 int x; 7 int y; 8 int label; 9 //重心の座標配列を初期化する 10 for (i = 0;i < ML;i++){ 11 za.px[i] = 0; 12 za.py[i] = 0; 13 za.count[i] = 0; 14 za.sumx[i] = 0; 15 za.sumy[i] = 0; 16 } 17 //読み込んだテキストのyの最大値まで繰り返す 18 for (y = 0; y < img.sy; y++) { 19 //読み込んだテキストのxの最大値まで繰り返す 20 for (x = 0; x < img.sx; x++) { 21 label = img.d[0][y][x]; //ラベルを取り出す 22 //ラベルが正常範囲ならそのラベル対応の要素へ加算する 23 if ( label > 0 && label <= ML ) { 24 za.sumx[label-1] += x; 25 za.sumy[label-1] += y; 26 za.count[label-1] += 1; 27 } 28 } 29 } 30 //重心の座標を求める 31 for (i = 0;i < ML;i++){ 32 //ラベルが存在すれば平均を計算する 33 if (za.count[i] > 0){ 34 za.px[i] = za.sumx[i] / za.count[i]; 35 za.py[i] = za.sumy[i] / za.count[i]; 36 } 37 } 38 return za; 39} 40 41void fputz(FILE *fp, Zahyou za) 42{ 43 int i; 44 //重心座標印字 45 for (i = 0; i < ML; i++){ 46 //存在するラベル番号のみ印字する 47 if (za.count[i] > 0){ 48 fprintf(fp,"labelNo=%d x=%d y=%d\n",i+1,za.px[i],za.py[i]); 49 } 50 } 51}

追伸:変数の定義、及び処理の内容についてコメントを付けるようにしてください。
そのほうが、第三者がみたとき、わかりやすいです。
又、コメントがないと、あなたも後からみてわからなくなります。

投稿2019/11/16 04:17

tatsu99

総合スコア5493

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

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

0126tami

2019/11/17 10:15

とてもわかりやすいコードありがとうございました。 おかげで先生にもらったプログラムでもわからないところも理解できそうです。本当に感謝してます。神様です。 ありがとうございました泣泣泣 他にもコメントくださった方にも本当に感謝してます!
guest

0

何をやっているのか、最終的にどうなれば良いのか、理解してませんが、今アップされてるコードの字面だけで気づいたことを3点記します。ご参考まで。

まず、↓これはコンパイル通りません。

C

1Zahyou zyusin(Img img) 2{ 3 Zahyou zahyou; // 変数名は小文字で始まる zahyou 4 // 途中省略 5 Zahyou.px = label1x; // エラー 6 Zahyou.py = label1y; // エラー 7

大文字で始まる Zahyou は型名です。ここに必要なのは(小文字で始まる)変数名 zahyou です。

2つ目。次はエラーにならないとしても、明らかな誤り。

C

1Zahyou zyusin(Img img) 2{ 3 int sx, sy; // sx, sy の値は不定 4 // 途中省略 5 img.sx = sx; img.sy = sy; // 不定値を書き込んだらダメでしょう 6

ここは、zyusin() 関数に渡された img 構造体の値を使って計算を始めるところだと思うので、普通 sx = img.sx; とすべきではないか。

3つ目。
func_bin() 〜 fgetimg() が return する bimg 〜 img が不審。
bimg 〜 img は main() のローカル変数にあります。もし main() でない他の関数が return しようとしているなら、それは無理です、やろうとしてもコンパイルエラーになります。
たまたま同名の別の変数だ、というなら良いですが。

投稿2019/11/15 06:38

rubato6809

総合スコア1382

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

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

rubato6809

2019/11/15 06:47

他にも奇妙な点があるけど。 定義しただけで使わない変数、代入したけど使わない変数がいくつかありますね。 特に奇妙なのは label2? 〜 label4? 変数。何のために計算したのかな?
0126tami

2019/11/17 09:51

1つ目と2つ目の指摘、簡単なミスなのに気づかなかったです。ありがとうございました!3つ目については今回考えていないのでプログラム自体をだいぶ省略させてもらってます。 そしてlabel2~4についてですが、本当はラベルの数によって値を返すのをlabel1のx、yの値,label2のx,yの値という風に返したいのですが元々8*10の結果のラベルの数によって何個値を返すという命令のプログラムの作り方がわからなかったので曖昧な感じに書いています。 わかりにくくてすみません!
guest

0

zyusin関数が全く機能していない

パラメータで受け取っている img を使わず, ローカルに生成した(空っぽの?) limg を使っています.

zyusin関数で最後に返したいのはラベリングしたものの重心の座標なので

void なら「返せない」と思います.
先生が言っているのは(もちろん想像ですが)「zyusin 関数では計算のみを行い, 表示は zyusin 関数を呼び出した側で( zyusin 関数が返した値を使って)行う」ということではないでしょうか.

他にも, ご提示のファイルは "1" と "2" の2つしか島がありませんが, これが 3つ 4つと多くなったり, 逆に1つや無しの場合は zyusin 関数はどう動作するのでしょうか.

投稿2019/11/13 17:09

編集2019/11/13 17:27
jimbe

総合スコア13202

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

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

0126tami

2019/11/14 04:13

回答ありがとうございます! 指摘していただいた箇所直しました それからreturnで座標を返そうと思っても xとyとふたつ返さないといけない値がある場合はどう対処したらよいでしょうか そして島が2つ以上になった場合についてはそういうプログラムを最終的には作りたいと思っていますが、全ての場合を考えたプログラムを作る能力が私に足りておらず、この場でヒントを見つけれたらいいなと考えていました。
tatsu99

2019/11/14 09:31

>指摘していただいた箇所直しました どこを直したのでしょうか。 Img limg; このlimgは内容が不定です。その不定なものに対して、if (limg.d[0][y][x] == 1) などのように 値が1かどうかを判定するのは、意味がありません。 あなたが、しているのは、int a;と確保した変数に対して if ( a== 1)と行っているのと同じことです。(aの内容は不定なので0かも知れないし、100かも知れないし、5000かも知れない) >xとyとふたつ返さないといけない値がある場合はどう対処したらよいでしょうか xとyを2つ含む、構造体の変数を確保し、それで、return します。 return img;としているところと考え方は同じです。
jimbe

2019/11/15 11:34 編集

> 指摘していただいた箇所直しました ご質問は修正できますので, (出来ましたらどう直されたのか分かるようにコメントを入れて)最新のコードを追記して頂けると, こちらにも進捗が見えて助かります.
0126tami

2019/11/15 04:22

構造体を追加してみました! しかしやはりzyusin関数でラベルの数によって返す値が何個になるのか決める思考がどういう風にしたらいいか想像できません。泣
jimbe

2019/11/15 11:39 編集

> ラベルの数によって返す値が何個になるのか ラベリングの結果のファイルを見て, 気づきませんでしょうか. 島が2つの場合, 1 の島と 2 の島が出来ています. もし島が4つだったら, おそらく 3 の島と 4 の島も出来ているでしょう. つまり, ラベリングの結果のファイルの中に出てくる最大の数字が, ラベルの件数ではないでしょうか. もし, ラベルの数字が連続しない場合(1,2,5,6で4つの島を表す等)があるとするなら, 「島を表す数字(=0以外)が幾つあるか」を数えることになります.
0126tami

2019/11/17 09:47

私の質問の仕方がわるかったです。すみません ラベリングの結果を見て何個の値を返せばいいのかはわかるのですがどのような例を使った時でも使えるようなプログラムを作る思考が考え付かないという風に言いたかったです。わかりにくくてすみません
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問