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

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

詳細はこちら
C

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

1393閲覧

座標の値の重複を削除したいです C言語

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2021/01/14 11:17

編集2021/01/14 12:43

前提・実現したいこと

C言語で2つのdatファイルを読み込み、結合して新しいファイルに出力するプログラムを作ってます。2つのdatファイルには、節点のx座標、y座標、z座標があり、それぞれのファイルから値を二次元配列に保存するところまではできたのですが、新しいファイルに出力する際に、重複をなくして出力しないといけないのですが、重複をなくしてすっきりと表示できません。
二次元配列には 接点1のx座標は[0][0]、y座標は[0][1]、z座標は[0][2]、接点2のx座標は[1][0]、y座標は[1][1]、z座標は[1][2]、のように保存してあります。

今回が最初の質問なので伝わりにくかったらごめんなさい。お願いします。
コードもきれいとは言えないので改善点もあればお願いします。

発生している問題・エラーメッセージ

for文とif文を使ったのですが、重複を取り除いた後の座標の数がとても多くなってしまいました。
きれいに取り除けず、取り除いた値が重複してしまいます。

該当のソースコード

C

1#include <stdio.h> 2 3int main(){ 4int point1[1024][16]; 5int point2[1024][16]; 6double epoint1[1024][2]; 7double epoint2[1024][2]; 8double ecomb2[1024][2]; 9 10/* ファイル読み込みなどは割愛 */ 11 12 13//読み取って配列に保存 14for(int i = 1; i < point1[0][0]+1; i++){ 15 //point1[0][1]、point2[0][1]はヘッダー部分に記された接点の数 16 //すでに配列に保存済み。 17 for(int j = 0; j < 3; j++){ 18 fscanf(readf_in1,"%lf", //lfは倍精度実数で読み取る 19 &(epoint1[i][j]), 20 &(epoint1[i][j+1]), 21 &(epoint1[i][j+2]) 22 ); 23 } 24 } 25 for(int i = 1; i < point2[0][0]+1; i++){//配列に保存 26 for(int j = 0; j < 3; j++){ 27 fscanf(readf_in2,"%lf", //lfは倍精度実数で読み取る 28 &(epoint2[i][j]), 29 &(epoint2[i][j+1]), 30 &(epoint2[i][j+2]) 31 ); 32 } 33 } 34 35/* -- ここからわかりません -- */ 36 int k = 0; 37 for(int i = 0; i < point2[0][0]; i++){ 38 for(int j =0; j < point1[0][0]; j++){ 39 if(epoint1[i][0] == epoint2[j][0] && epoint1[i][1] == epoint2[j][1] && 40epoint1[i][3] == epoint2[j][3] ){ 41 printf("match\n");//確認用 42 } 43 else{ 44 k = k + 1; 45 ecomb2[k][0] = epoint2[j][0]; 46 ecomb2[k][1] = epoint2[j][1]; 47 ecomb2[k][2] = epoint2[j][2]; 48 } 49 } 50 } 51/* -- -- */ 52 //確認用 53 for(int i = 0; i < k; i++){ 54 fprintf(writef_in,"%24.13E%24.13E%24.13E\n", 55 ecomb2[i][0], ecomb2[i][1], ecomb2[i][2] 56 ); 57}

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

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

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

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

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

kazuma-s

2021/01/14 14:38

2つのファイルそれぞれには重複はないのですか?
退会済みユーザー

退会済みユーザー

2021/01/14 14:54

重複はないです。
guest

回答2

0

ベストアンサー

出力したものだけを憶えておいて、
入力の値がそこにあるかどうかをチェックすればよいでしょう。

C

1#include <stdio.h> 2#include <stdlib.h> // exit 3 4int find_add(double e[1024][3], int n, const double *p) 5{ 6 if (n >= 1024) { puts("too many data"); exit(1); } 7 for (int i = 0; i < 3; i++) e[n][i] = p[i]; 8 for (int i = 0; i < n; i++) 9 if (e[i][0] == p[0] && e[i][1] == p[1] && e[i][2] == p[2]) return 0; 10 return 1; 11} 12 13int main(void) 14{ 15 FILE *f1 = fopen("f1.txt", "r"); 16 if (!f1) return 1; 17 FILE *f2 = fopen("f2.txt", "r"); 18 if (!f2) return 2; 19 FILE *f3 = fopen("f3.txt", "w"); 20 if (!f3) return 3; 21 int point1[1][1] = { 4 }, point2[1][1] = { 3 }; 22 double epoint[1024][3], p[3]; 23 int n = 0; 24 while (fscanf(f1, "%lf%lf%lf", p, p+1, p+2) == 3) 25 if (find_add(epoint, n, p)) { 26 fprintf(f3, "%24.13E%24.13E%24.13E\n", p[0], p[1], p[2]); 27 n++; 28 } 29 while (fscanf(f2, "%lf%lf%lf", p, p+1, p+2) == 3) 30 if (find_add(epoint, n, p)) { 31 fprintf(f3, "%24.13E%24.13E%24.13E\n", p[0], p[1], p[2]); 32 n++; 33 } 34 fclose(f1), fclose(f2), fclose(f3); 35}

f1.txt

text

144.444 44.444 44.444 233.333 33.333 33.333 322.222 22.222 22.222 411.111 11.111 11.111

f2.txt

text

155.555 55.555 55.555 233.333 33.333 33.333 366.666 66.666 66.666

実行後の f3.txt

text

1 4.4444000000000E+01 4.4444000000000E+01 4.4444000000000E+01 2 3.3333000000000E+01 3.3333000000000E+01 3.3333000000000E+01 3 2.2222000000000E+01 2.2222000000000E+01 2.2222000000000E+01 4 1.1111000000000E+01 1.1111000000000E+01 1.1111000000000E+01 5 5.5555000000000E+01 5.5555000000000E+01 5.5555000000000E+01 6 6.6666000000000E+01 6.6666000000000E+01 6.6666000000000E+01

追記
それぞれのファイルに重複がないのなら、
1つめのファイルの内容を全部覚えておいて、
2つめのファイルの値がそこにあるかどうかをチェックすればよいでしょう。

C

1#include <stdio.h> 2 3int main(void) 4{ 5 FILE *f1 = fopen("f1.txt", "r"); 6 if (!f1) return 1; 7 FILE *f2 = fopen("f2.txt", "r"); 8 if (!f2) return 2; 9 FILE *f3 = fopen("f3.txt", "w"); 10 if (!f3) return 3; 11 int point1[1][1] = { 4 }, point2[1][1] = { 3 }; 12 double ep[1024][3], p[3]; 13 int n = 0, i; 14 for (; n < 1024 && fscanf(f1, "%lf%lf%lf", ep[n], ep[n]+1, ep[n]+2) == 3; n++) 15 fprintf(f3, "%24.13E%24.13E%24.13E\n", ep[n][0], ep[n][1], ep[n][2]); 16 if (n == 1024) { puts("too many data"); return 4; } 17 18 while (fscanf(f2, "%lf%lf%lf", p, p+1, p+2) == 3) { 19 for (i = 0; i < n; i++) 20 if (ep[i][0] == p[0] && ep[i][1] == p[1] && ep[i][2] == p[2]) break; 21 if (i == n) 22 fprintf(f3, "%24.13E%24.13E%24.13E\n", p[0], p[1], p[2]); 23 } 24 fclose(f1), fclose(f2), fclose(f3); 25}

投稿2021/01/14 15:05

編集2021/01/14 15:23
kazuma-s

総合スコア8224

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

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

退会済みユーザー

退会済みユーザー

2021/01/14 22:38

ありがとうございます。 とてもすっきりしました! ぜひ機会があればまたお願いします。
退会済みユーザー

退会済みユーザー

2021/01/14 23:26

よければ回答してください。 二つ目のコードのpは一つ目と同じくdouble 型で宣言するだけで良いのでしょうか。
guest

0

質問は、

/* -- ここからわかりません -- */

ここの二重ループのことでしょうか?
という以前にその前のコードに不明点があります。
まず、point1[0][0], point1[0][0]が何かが分からない。きっと、/* ファイル読み込みなどは割愛 */にあるかも思いますが、質問文だけでは不明。

for(int i = 1; i < point1[0][0]+1; i++){//配列に保存

iが 1から始まってますが、Cの場合、普通は、0からです。その一方、for(int i = 0; i < point2[0][0]; i++){ とこちらと範囲が違ってます。もう一つの epoint2[][]に入力している方も同様。
と思ったら、for(int i = 0; i < point2[0][0]; i++){のループは、iが、point2[0][0]にも関わらず、epoint1[i]で参照、組合せが違ってませんか?

また、データの読み込みですが、

fscanf(readf_in1,"%lf", //lfは倍精度実数で読み取る

で、一度に、1つのデータしか読み込まない設定なのに、引数が 3つとなっています。後半の 2つには値が入らない、、、と思ったら、 for()ループの都合で、結果 OKか? 配列のサイズも x, y, z の 3つ分で良いのに、epoint1[1024][16] で 16個分は余分ですね。

と、全体的に、見直すべきところは多いように思えます。

投稿2021/01/14 12:17

pepperleaf

総合スコア6385

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

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

退会済みユーザー

退会済みユーザー

2021/01/14 12:35

回答ありがとうございます。質問も含めて見直します。 もう少し、コードのほうを載せたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問