前提・実現したいこと
C言語で2つのdatファイル(in.dat1,in.dat2)を読み込み、結合して新しいファイル(in.dat)に出力するプログラムを作ってます。それぞれのファイルには、決まったフォーマットで、節点数、要素数が書き込まれてあり、それらを合わせていつのファイルにしたいです。
節点のx座標、y座標、z座標に重複があった場合に重複をなくして出力し、節点番号(下にファイルのフォーマットがあります。)を更新して出力しなければならないのですが、どのようなコードで書けばいいのかわかりません。
ファイルのフォーマットとそれぞれのファイルの内容も載せておきます。
質問2回目です。質問等が伝わりにくかったらごめんなさい。お願いします。
該当のソースコード
C
1#include <stdio.h> 2#include <stdlib.h> //exit関数を用いるために必要 3 4int main() 5{ 6 //readfは読み込むファイル,writefは書き込むファイル 7 FILE *readf_in1, *readf_in2, *writef_in; 8 9 char in1[] = "in.dat1"; 10 char in2[] = "in.dat2"; 11 12 int point1[1024][16];//配列の数は適当です。 13 int point2[1024][16]; 14 float fpoint1[1024][4]; 15 float fpoint2[1024][4]; 16 double epoint1[1024][3]; 17 double epoint2[1024][3]; 18 double ecomb2[1024][3]; 19 20 //読み込むファイルをopen 21 readf_in1 = fopen(in1,"r"); 22 if(readf_in1 == NULL){//エラー処理 23 printf("error in.dat1\n"); 24 exit(1); //強制終了 25 } 26 else{ 27 printf("read in.dat1\n"); 28 } 29 //読み込むファイルをopen 30 readf_in2 = fopen(in2,"r"); 31 if(readf_in2 == NULL){//エラー処理 32 fclose(readf_in1); 33 printf("error in.dat2\n"); 34 exit(1); //強制終了 35 } 36 else{ 37 printf("read in.dat2\n"); 38 } 39 40 //書き込むファイルをopen 41 writef_in = fopen("in.dat", "w"); 42 if(writef_in == NULL){//エラー処理 43 fclose(readf_in1); 44 fclose(readf_in2); 45 printf("error in.dat\n"); 46 exit(1); //強制終了 47 } 48 else{ 49 printf("write in.dat\n"); 50 } 51 52 for(int i = 0; i < 4; i++) {//配列に保存 53 fscanf(readf_in1,"%d", &(point1[0][i])); 54 } 55 for(int i = 0; i < 4; i++) {//配列に保存 56 fscanf(readf_in2,"%d", &(point2[0][i])); 57 } 58 for(int i = 0; i < 1; i++) {//配列に保存 59 fscanf(readf_in1,"%E", &(fpoint1[0][i])); 60 } 61 for(int i = 0; i < 1; i++) {//配列に保存 62 fscanf(readf_in2,"%E", &(fpoint2[0][i])); 63 } 64 for(int i = 1; i < point1[0][1]+1; i++){//配列に保存 65 for(int j = 0; j < 4; j++){ 66 fscanf(readf_in1,"%d", 67 &(point1[i][j]), 68 &(point1[i][j+1]), 69 &(point1[i][j+2]), 70 &(point1[i][j+3]) 71 ); 72 } 73 } 74 for(int i = 1; i < point2[0][1]+1; i++){//配列に保存 75 for(int j = 0; j < 4; j++){ 76 fscanf(readf_in2,"%d", 77 &(point2[i][j]), 78 &(point2[i][j+1]), 79 &(point2[i][j+2]), 80 &(point2[i][j+3]) 81 ); 82 } 83 } 84 for(int i = 1; i < point1[0][0]+1; i++){//配列に保存 85 for(int j = 0; j < 3; j++){ 86 fscanf(readf_in1,"%lf", //lfは倍精度実数で読み取る 87 &(epoint1[i][j]), 88 &(epoint1[i][j+1]), 89 &(epoint1[i][j+2]) 90 ); 91 } 92 } 93 for(int i = 1; i < point2[0][0]+1; i++){//配列に保存 94 for(int j = 0; j < 3; j++){ 95 fscanf(readf_in2,"%lf", //lfは倍精度実数で読み取る 96 &(epoint2[i][j]), 97 &(epoint2[i][j+1]), 98 &(epoint2[i][j+2]) 99 ); 100 } 101 } 102 103/* -- ここからわかりません -- */ 104 int k = 0; 105 for(int i = 0; i < point2[0][0]; i++){ 106 for(int j =0; j < point1[0][0]; j++){ 107 if(epoint1[i][0] == epoint2[j][0] && epoint1[i][1] == epoint2[j][1] && epoint1[i][3] == epoint2[j][3] ){ 108 printf("match\n"); 109 } 110 else{ 111 k = k + 1; 112 ecomb2[k][0] = epoint2[j][0]; 113 ecomb2[k][1] = epoint2[j][1]; 114 ecomb2[k][2] = epoint2[j][2]; 115 } 116 } 117 } 118 119 fprintf(writef_in,"%8d\n", k);//確認用 120 for(int i = 0; i < k; i++){ 121 fprintf(writef_in,"%24.13E%24.13E%24.13E\n", 122 ecomb2[i][0], ecomb2[i][1], ecomb2[i][2] 123 ); 124 } 125/* -- ここまでわかりません -- */ 126 127 //ファイルをclose 128 fclose(readf_in1); 129 fclose(readf_in2); 130 fclose(writef_in); 131}
ファイルのフォーマット
dat
1 節点数 要素数 0 0 1.000E+03 2 要素1を形成する節点番号4つ 要素2を形成する節点番号4つ 3 要素3を形成する節点番号4つ 要素4を形成する節点番号4つ 4 要素5を形成する節点番号4つ 要素6を形成する節点番号4つ 5 . 6 . 7 . 8 要素23を形成する節点番号4つ 要素24を形成する節点番号4つ 9 節点1のx座標 節点1のy座標 節点1のz座標 10 節点2のx座標 節点2のy座標 節点2のz座標 11 節点3のx座標 節点3のy座標 節点3のz座標 12 . 13 . 14 . 15 節点18のx座標 節点18のy座標 節点18のz座標
in.dat1(入力ファイル)
dat
1 6 3 0 0 1.000E+03 2 1 2 3 4 5 6 1 2 3 3 4 5 6 4 11 11 11 5 12 12 12 6 13 13 13 7 14 14 14 8 15 15 15 9 16 16 16
in.dat2(入力ファイル)
dat
1 9 5 0 0 1.000E+03 2 1 2 3 4 5 6 7 8 3 9 1 2 3 4 5 6 7 4 8 9 1 2 5 21 21 21 6 13 13 13 7 15 15 15 8 22 22 22 9 23 23 23 10 24 24 24 11 16 16 16 12 25 25 25 13 26 26 26
in.dat(出力ファイル)
dat
1 12 8 0 0 1.000E+03 2 1 2 3 4 5 6 1 2 3 3 4 5 6 7 3 5 8 4 9 6 10 11 12 7 3 5 5 8 9 6 10 11 12 7 3 6 11 11 11 7 12 12 12 8 13 13 13 9 14 14 14 10 15 15 15 11 16 16 16 12 21 21 21 13 22 22 22 14 23 23 23 15 24 24 24 16 25 25 25 17 26 26 26
重複の定義がよくわかりません。
重複をなくすべきなのは、「節点全体で重複があった場合」「1つの要素の中で構成する節点の座標に重複があった場合」いずれでしょうか?
また、座標値が浮動小数点数ですが、重複の定義はどうなりますか?許容誤差などは考えず、完全一致で考えていいのですか?
恐らく前の質問の問題の発展形なのかと思いますが、
[座標の値の重複を削除したいです C言語]
https://teratail.com/questions/315989
そこでいただいた回答での指摘事項などが反映されていない(消化できていない?)ように見えますが、そんなことはありませんでしょうか。
重複の定義は座標点での重複です。
誤差は考えずに完全一致でいいです。
前回質問した部分を反映したコードは重複を見つけて削除するだけだったので、新しいコードに追加するのは良くないと思い前のコードのままにしておきました。
コードの不備は直しておきます。
> in.dat2は文字数の関係で載せられませんでした。
節点数や要素数を小さくした例で、期待する結果も含めて、3つのファイルを提示してください。
コンパイラは何ですか? どんなコンパイラでもコンパイルエラーになるはずですが。
ファイルを3つ提示しました。
コンパイラはCです。
>@質問者さん
私宛のコメントではありませんでしたが、返信させていただきます。
> コンパイラはCです。
ここで問われているコンパイラとは、CとかC++とかJavaとかプログラミング言語の話ではなく、gcc とか clangとかVisual Studio(C++)とか、
Cコンパイラの種類、製品、バージョンを指します。kazuma-sさんの「どんなコンパイラでもコンパイルエラーになるはずですが。」との指摘通り、
C言語のコードに不備がある為、コンパイルエラーになっています。
ここから>>>>
$ gcc --version
gcc (GCC) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gcc -Wall t8.c
t8.c: 関数 ‘main’ 内:
t8.c:45:12: エラー: ‘readf_sin1’ undeclared (first use in this function); did you mean ‘readf_in1’?
45 | fclose(readf_sin1);
| ^~~~~~~~~~
| readf_in1
t8.c:45:12: 備考: 未宣言の識別子は出現した各関数内で一回のみ報告されます
t8.c:46:12: エラー: ‘readf_sin2’ undeclared (first use in this function); did you mean ‘readf_in2’?
46 | fclose(readf_sin2);
| ^~~~~~~~~~
| readf_in2
t8.c:68:24: 警告: 書式への引数が多すぎます [-Wformat-extra-args]
68 | fscanf(readf_in1,"%d",
| ^~~~
t8.c:78:24: 警告: 書式への引数が多すぎます [-Wformat-extra-args]
78 | fscanf(readf_in2,"%d",
| ^~~~
t8.c:88:24: 警告: 書式への引数が多すぎます [-Wformat-extra-args]
88 | fscanf(readf_in1,"%lf", //lfは倍精度実数で読み取る
| ^~~~~
t8.c:97:24: 警告: 書式への引数が多すぎます [-Wformat-extra-args]
97 | fscanf(readf_in2,"%lf", //lfは倍精度実数で読み取る
| ^~~~~
t8.c:7:45: 警告: 使用されない変数 ‘writef_sin’ です [-Wunused-variable]
7 | FILE *readf_in1, *readf_in2, *writef_in, *writef_sin;
| ^~~~~~~~~~
<<<ここまで
このような不完全なコードでは、実際に実行して確認してみようという回答者さんらにとって使えませんし、質問者さんがどこまでコードを理解されているかも推し量ることができません。
ごめんなさい。理解不足でした。
コードは修正しておきました。
gcc (MinGW.org GCC-6.3.0-1) 6.3.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
見たところ、in.dataはin.data2と全く同じですね。
目的とするin.dataを書いていただかないと、回答できません。
すいません。すぐに直します。
重複がどうとかこうとかいう以前の問題です。
in.data1 だけを読み込んで、それを in.data として書き出すだけのプログラムが書けますか?
それはできました。
なぜ質問を消すんですか?
コメントとの整合性が取れません。
元に戻してください。
そして、コードについて注釈を追加してください。
回答1件
あなたの回答
tips
プレビュー