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

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

詳細はこちら
C

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

Q&A

解決済

2回答

3274閲覧

C言語で構造体のデータをバイナリファイルに保存・読み込む方法

darakuzanmai

総合スコア1

C

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

0グッド

0クリップ

投稿2021/01/22 05:41

前提・実現したいこと

円の中心位置と半径を3セット入力し、半径の大きい順にソートしたものをバイナリに保存するプログラムと、保存されたバイナリを読み込んで中心位置が原点から近い順にソートして表示するプログラムを作りたいです。

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

ファイルを読み込んで表示するときに、①で入力した値とは違うものが表示されてしまいます。
テキストファイルに保存したとき(fprintf,fscanfを使ったとき)は問題が起こらなかったので、fwriteやfreadの引数が間違っているのかなと思います。

該当のソースコード

①ファイルを保存するプログラム

C

1#include <stdio.h> 2#include <math.h> 3struct circle 4{ 5 double x; 6 double y; 7 double rad; 8}; 9void swap(double *px,double *py) 10{ 11 double tmp=*px; 12 *px=*py; 13 *py=tmp; 14} 15int main(void) 16{ 17 int i,j; 18 double num[3]={1,2,3}; 19 struct circle n[3]; 20 char str[50]; 21 FILE *fp; 22 23 puts("3つの円の座標と半径を入力"); 24 for(i=0;i<3;i++) 25 { 26 printf("円%.0f\n",num[i]); 27 printf("座標x="); scanf("%lf",&n[i].x); 28 printf("座標y="); scanf("%lf",&n[i].y); 29 printf("半径r="); scanf("%lf",&n[i].rad); 30 } 31 puts("半径の大きい順にソート\n"); 32 for(i=0;i<3;i++) 33 { 34 for(j=i+1;j<3;j++) 35 { 36 if(n[i].rad<n[j].rad) 37 { 38 swap(&num[i],&num[j]); 39 swap(&n[i].x,&n[j].x); 40 swap(&n[i].y,&n[j].y); 41 swap(&n[i].rad,&n[j].rad); 42 } 43 } 44 } 45 for(i=0;i<3;i++) 46 printf("円%.0f:(%.2f,%.2f),r=%.2f\n",num[i],n[i].x,n[i].y,n[i].rad); 47 48 //ファイルに出力 49 printf("ファイル名を入力:"); scanf("%s",str); 50 fp=fopen(str,"wb"); 51 if(fp==NULL) 52 printf("ファイル%sをオープンできませんでした。\n",str); 53 else 54 { 55 printf("半径および中心位置を保存しました。\n"); 56 fwrite(n,sizeof(n),3,fp); 57 fclose(fp); 58 } 59 return 0; 60} 61

②ファイルを読み込んで表示するプログラム

C

1#include <stdio.h> 2#include <math.h> 3struct circle 4{ 5 double x; 6 double y; 7 double rad; 8 double len; 9}; 10void len_p(double x,double y,double *len) 11{ 12 *len=sqrt(pow(x,2)+pow(y,2)); 13} 14void swap(double *px,double *py) 15{ 16 double tmp=*px; 17 *px=*py; 18 *py=tmp; 19} 20int main(void) 21{ 22 int i,j; 23 struct circle n[3]; 24 char str[50]; 25 FILE *fp; 26 27 printf("ファイル名を入力:"); scanf("%s",str); 28 if((fp=fopen(str,"rb"))==NULL) 29 printf("ファイル%sをオープンできませんでした。\n",str); 30 else 31 { 32 fread(n,sizeof(n),3,fp); 33 for(i=0;i<3;i++) 34 { 35 printf("(%.2f,%.2f),r=%.2f\n",n[i].x,n[i].y,n[i].rad); 36 len_p(n[i].x,n[i].y,&n[i].len); 37 } 38 puts("中心位置が原点から近い順にソート"); 39 for(i=0;i<3;i++) 40 { 41 for(j=i+1;j<3;j++) 42 { 43 if(n[i].len>n[j].len) 44 { 45 swap(&n[i].x,&n[j].x); 46 swap(&n[i].y,&n[j].y); 47 swap(&n[i].rad,&n[j].rad); 48 swap(&n[i].len,&n[j].len); 49 } 50 } 51 } 52 for(i=0;i<3;i++) 53 printf("(%.2f,%.2f),r=%.2f,距離%.2f\n",n[i].x,n[i].y,n[i].rad,n[i].len); 54 fclose(fp); 55 } 56 return 0; 57} 58

補足情報(FW/ツールのバージョンなど)

開発環境はwindows10のMinGWです。

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

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

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

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

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

guest

回答2

0

自己解決

ファイルに保存するデータがx,y,radの3つなのに対し、②の構造体がx,y,rad,lenと4つになっていたのがエラーの原因かも知れないと思ったので修正してみました。
また、回答からsizeof(n)の部分をsizeof(*n)に直しました。
回答者さんありがとうございます。問題なく動作するようになりましたが、まだココがおかしいという点がありましたら指摘してください。

↓以下コード

C

1#include <stdio.h> 2#include <math.h> 3struct circle 4{ 5 double x; 6 double y; 7 double rad; 8}; 9void swap(double *px,double *py) 10{ 11 double tmp=*px; 12 *px=*py; 13 *py=tmp; 14} 15int main(void) 16{ 17 int i,j; 18 double num[3]={1,2,3}; 19 struct circle n[3]; 20 char str[50]; 21 FILE *fp; 22 23 puts("3つの円の座標と半径を入力"); 24 for(i=0;i<3;i++) 25 { 26 printf("円%.0f\n",num[i]); 27 printf("座標x="); scanf("%lf",&n[i].x); 28 printf("座標y="); scanf("%lf",&n[i].y); 29 printf("半径r="); scanf("%lf",&n[i].rad); 30 } 31 puts("半径の大きい順にソート\n"); 32 for(i=0;i<3;i++) 33 { 34 for(j=i+1;j<3;j++) 35 { 36 if(n[i].rad<n[j].rad) 37 { 38 swap(&num[i],&num[j]); 39 swap(&n[i].x,&n[j].x); 40 swap(&n[i].y,&n[j].y); 41 swap(&n[i].rad,&n[j].rad); 42 } 43 } 44 } 45 for(i=0;i<3;i++) 46 printf("円%.0f:(%.2f,%.2f),r=%.2f\n",num[i],n[i].x,n[i].y,n[i].rad); 47 48 //ファイルに出力 49 printf("ファイル名を入力:"); scanf("%s",str); 50 fp=fopen(str,"wb"); 51 if(fp==NULL) 52 printf("ファイル%sをオープンできませんでした。\n",str); 53 else 54 { 55 printf("半径および中心位置を保存しました。\n"); 56 fwrite(n,sizeof(*n),3,fp); 57 fclose(fp); 58 } 59 return 0; 60}

C

1#include <stdio.h> 2#include <math.h> 3struct circle 4{ 5 double x; 6 double y; 7 double rad; 8}; 9void len_p(double x,double y,double *len) 10{ 11 *len=sqrt(pow(x,2)+pow(y,2)); 12} 13void swap(double *px,double *py) 14{ 15 double tmp=*px; 16 *px=*py; 17 *py=tmp; 18} 19int main(void) 20{ 21 int i,j; 22 struct circle n[3]; 23 double len[3]; 24 char str[50]; 25 FILE *fp; 26 27 printf("ファイル名を入力:"); scanf("%s",str); 28 if((fp=fopen(str,"rb"))==NULL) 29 printf("ファイル%sをオープンできませんでした。\n",str); 30 else 31 { 32 fread(n,sizeof(*n),3,fp); 33 for(i=0;i<3;i++) 34 { 35 printf("(%.2f,%.2f),r=%.2f\n",n[i].x,n[i].y,n[i].rad); 36 len_p(n[i].x,n[i].y,&len[i]); 37 } 38 puts("中心位置が原点から近い順にソート"); 39 for(i=0;i<3;i++) 40 { 41 for(j=i+1;j<3;j++) 42 { 43 if(len[i]>len[j]) 44 { 45 swap(&n[i].x,&n[j].x); 46 swap(&n[i].y,&n[j].y); 47 swap(&n[i].rad,&n[j].rad); 48 swap(&len[i],&len[j]); 49 } 50 } 51 } 52 for(i=0;i<3;i++) 53 printf("(%.2f,%.2f),r=%.2f,距離%.2f\n",n[i].x,n[i].y,n[i].rad,len[i]); 54 fclose(fp); 55 } 56 return 0; 57}

投稿2021/01/22 06:27

darakuzanmai

総合スコア1

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

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

0

fwrite(n,sizeof(n),3,fp);

sizeof(n)ってポインタのサイズですよ。
sizeof(*n)でいこう


ああちがうわ。sizeof(n) は配列全体のサイズになりますね
それだと、書き込みはともかく、読み出しのときにアクセス違反となりますな。

投稿2021/01/22 05:46

編集2021/01/22 06:16
y_waiwai

総合スコア88040

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

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

darakuzanmai

2021/01/22 06:14

回答ありがとうございます!早速直してみます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問