• ベストアンサー

自己参照型構造体のFree関数について

/////////////////////////////////////// // 自己参照型構造体 /////////////////////////////////////// // 以下のソースで、free関数がうまく使えません。 // アドバイスを下さい。 // よろしくお願いします。 #include<iostream> using namespace std; struct data { int num; data *next; }; typedef struct data dat; int main() { dat da; dat *p1,*p2,*p3; p1=&da;p2=&da; for(int i=0;i<10;i++) { p1->next=(dat *)malloc(sizeof(dat));; p1->num=i+1; p1=p1->next; } int sum=0; for(int i=0;i<10;i++) { sum+=p2->num; p2=p2->next; } for(int i=0;i<10;i++) { p3=p2->next; free(p2); p2=p3; } cout << sum; getchar();return 0;

質問者が選んだベストアンサー

  • ベストアンサー
  • mitoneko
  • ベストアンサー率58% (469/798)
回答No.5

 #4補足宛  気がつかれたようですね=^・。・^=。もとのソースがおかしかったのは、そこです。  10件目からの解放にどうしてもこだわられてるようですが。1件目から解放しても問題ないですよ。解放する前に、nextのアドレスさえ保管してしまえばよいわけです。mallocで確保した順番とfreeで解放する順番は対応している必要は「ありません。」ようするに、確保した物が最終的に一度だけ解放されればそれでよいのです。  1件目から解放するとすると、#4補足に書かれたループは、少し簡単になります。 p1=dat.next; for(int m=0;m<10;m++) { p2=p1->next; // p1を解放する前にnextを保存 free(p1); p1=p2; }  こんな感じでしょうか。  後は、スタイルの問題ですけど、このソース、全体としては、リストの初期化・リストの処理・リストの解放の3つの部分からなっています。  これを各々、関数に分けると、全体の見通しがすっきりします。特にいろいろな処理に使い回しているp1・p2・p3が関数の中に封じ込められますので、この効果が大きいでしょうか。  この程度の長さであれば、まぁ、なんとかなりますけど、もう少し、変数・処理が長くなると収拾つかなくなりますから、この例を書き直してみてどうなるか、ご自分で試してみられると良いでしょう。関数に分けるときには、datをグローバル変数にせずに、引数で渡すようにしてくださいね。

noname#6117
質問者

お礼

長々とお付き合いくださり、ありがとうございました。 お礼申し上げます。

noname#6117
質問者

補足

つまるところ、 p1=&da; としたのは、 もともとそこは、 malloc確保ではなかったので、エラーになっていたということみたいですが、、、 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (5)

  • terra5
  • ベストアンサー率34% (574/1662)
回答No.6

作り直すのがベストとは思いますが、一応現状の問題と対策を。 >私は、10件目のmallocから、freeしていけばいいと >思っていますが、 この考え方は(適切では無いが)間違いではありません。 ですが、10件目のnextは11件目ですよね? freeするのは9~1件目です。 意味的には p3 = p2->previous が正解になりますが、 previousはありません(^^; previousを作る手もありますが、この場合本末転倒に近いので、 nextだけで実現する手を考えるのが普通です。 作った時と同じような手順をとりますが、 freeしてしまった後にはnextは参照できませんので、 一時保存する必要があります。

noname#6117
質問者

お礼

長々とお付き合いくださり、ありがとうございました。 お礼申し上げます。

noname#6117
質問者

補足

即席ですが、 こういうものが作れるようになりました。 皆様のおかげです。 /* #include<iostream> using namespace std; struct data { int age; char name[12]; data *next; }; typedef struct data dat; dat *nextpoint(dat *p); void freedata(dat *p2,int cnt); void display(dat *p3,int cnt); int main() { dat da; dat *p1; p1=&da; int select=0; int cnt=0; while(1) { printf("1:input 2:end 3:display -->"); scanf("%d",&select); switch(select) { case 1: printf("Name->"); scanf("%s",p1->name); printf("Age ->"); scanf("%d",&p1->age); p1=nextpoint(p1); cnt++; break; case 2: freedata(&da,cnt); return 0; break; case 3: display(&da,cnt); break; } } getchar();getchar();return 0; } dat *nextpoint(dat *p) { p->next=(dat *)malloc(sizeof(dat)); return p->next; } void freedata(dat *p2,int cnt) { dat *p3; p2=p2->next; for(int i=0;i<cnt;i++) { p3=p2->next; free(p2); p2=p3; } } void display(dat *p3,int cnt) { for(int i=0;i<cnt;i++) { printf("name:%s age:%d\n",p3->name,p3->age); p3=p3->next; } } */

全文を見る
すると、全ての回答が全文表示されます。
回答No.4

 C++で書き直すなら、malloc & freeではなく、new & deleteですよね?この2つはメモリ管理の仕方が違いますから、混ぜると危険です。また、C++なら、structと書いてもこれはデフォルトのアクセスレベルがpublicになるだけでclass宣言と変わりませんから、解放はクラスのデストラクタか、メソッドで行えばよいでしょう。 > このソースをどうしたいのかわかりません。 > 使い方がよくわからないです。  『チェーンの使い方』と言うことでしょうか?  たとえば、『malloc(sizeof(MyStruct) * 10)』とすると、MyStructが必要とする領域の10倍を、一度に連続して確保しようとします。このとき、連続した空き領域がないと確保できず、nullが返ります。チェーンだと、1個ずつ確保するので、MyStruct分の空き領域が、連続していなくても10個分あれば、確保できます。  これはメモリのフラグメンテーションが関係する話なので、このように考えるといいかも。 ○:空き ●:使用中 |:わかりやすくする為の区切り すべて空き:○○○○○○○○○○ 3個確保:●●●|○○○○○○○ 3個確保:●●●|●●●|○○○○ 3個解放:○○○|●●●|○○○○ ここで空きは7個あるが、7個確保しようとしても、連続した空きは3個と4個なので確保できない。しかし、1個を7回確保することは出来る。 > 初心者ですので、よろしくお願いします。  初心者だろうが、仕事なら自分の仕事に責任持ちましょうよ。学生なら、将来の自分にたいして、自分で責任を持ちましょうよ。初心者であっても、初心者だからこそ、丸投げ(ソースください)はよくありません。“もらう癖”でなく、“理解する癖”をつけるべきです。

noname#6117
質問者

お礼

長々とお付き合いくださり、ありがとうございました。 お礼申し上げます。

noname#6117
質問者

補足

一応、考えてみました。 最後のFreeのところだけ、 for(int m=0;m<10;m++) { p1=&da; for(int i=0;i<10-m;i++) { p1=p1->next; } free(p1); } こんな感じですが、 これでよろしいでしょうか? >>丸投げ(ソースください)はよくありません。 はい、確かにそのとおりです。 行き詰まりのときは、丸投げします。 反省しています。 > 初心者ですので、よろしくお願いします。 なんか、これを書けば何とかしてもらえるという甘えです。 申し訳ありません。 皆様、ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
  • mitoneko
  • ベストアンサー率58% (469/798)
回答No.3

 #2の返事に対して、一つ質問しておきます。 >私は、10件目のmallocから、freeしていけばいいと >思っていますが、  の関係です。  問題のstruct dataですが、今、ある要素があるとき、次の要素のアドレスを知ることは可能です。p1->nextですね。よって、先頭のdata構造体のアドレスが判れば、次の要素のアドレスを知ることはできます。(そして、すべての要素のアドレスが順番に取得できます。)  では、ある要素のアドレスp1があるとき、前の要素のアドレスを求めることはできますか?  10件目から、さかのぼって領域を開放していくためには、これが求められる必要があります。3つめのループで、10件目のp3から、9件目のp2をしることができないと、9件目の削除ができませんから。

noname#6117
質問者

お礼

長々とお付き合いくださり、ありがとうございました。 お礼申し上げます。

noname#6117
質問者

補足

回答ありがとうございます。 for(;;)を2回使用しました。 p1を先頭アドレスに指定しました。 10回ほどp1=p1->nextして、ラストのアドレスを指定し、 それをfreeしました。 もう一度、先頭アドレスを指定しました。 9回ほどp1=p1->nextして、アドレスを指定しました。 freeしました。 間違っていないと思うのですが、 これでいいのでしょうか?

全文を見る
すると、全ての回答が全文表示されます。
  • mitoneko
  • ベストアンサー率58% (469/798)
回答No.2

 根本的には・・・全面的に、書き直したいです(^_^;)  これでは、回答にもアドバイスにもなりませんし、freeがうまくいかない理由だけ書いておきます。(どう修正するか、私が考えるとプログラムの原型が無くなってしまいます(^_^;))  これ、リンクリストですよね。  一つめのループでリストの確保と、初期化。  二つめのループで、そのリストの処理。  ここまではいいです。  ここまで終わった時点で、p1は、リストの最後の要素を、p2もリストの最後の要素を差しているはずです。  とすると、3つめのループのリストのメモリー解放なんですが、この時点で、  p3=p2->next;  としているp2は、やっぱり、リストの最後の要素ですよね?  ループの一回目のfreeは、最後の要素の解放。では、最後の要素の次の要素と指定されたp3にはいったい何が?  かくして、ループの2回目は、もう何をやっているのかわかりません。最後の要素のnextの初期化はされていないのと思うので、動作は未定義です。  では、p3を最初に初期化しておいて(p2の使い方と同じようにです。)やるとすると・・・最初の要素が dat da;  で定義されてますので、単純にすると、free関数は使えません。(freeでは、mallocで確保したメモリーしか解放できませんから。)これに注意しておけば、後は単純です。  とこれで、後は、問題の所を直せばokと思います。が・・・アドバイスをと言われると、基本的には、やっぱり、プログラムの構造をなおしたくなります。どう直すかは、#1さんがあげられてますから、私は、ふれないことにします。

noname#6117
質問者

お礼

長々とお付き合いくださり、ありがとうございました。 お礼申し上げます。

noname#6117
質問者

補足

回答ありがとうございます。 malloc と free の 処理の仕方が全然違うのでしたら、 原型なくなってもいいので、 プログラムの構造を変更した サンプルソースを教えてください。 お願いいたします。 私は、10件目のmallocから、freeしていけばいいと 思っていますが、 p1=p1->next の時点で何だかわからなくなりました。 それから、入門書も関数処理が書いてありましたが、 よくわかりません。文字列の処理でしたが、 複雑でしたので、よくわかりませんでした。 int ならわかると思い、mallocで領域確保したはいいですが、freeが使えません。

全文を見る
すると、全ての回答が全文表示されます。
  • toysmith
  • ベストアンサー率37% (570/1525)
回答No.1

このソースをどうしたいですか? 1.関数分割せずに1関数で全て処理したい。 2.適度に関数分割しても良いが、再起は使いたくない。 3.メイン、構造体確保関数、構造体開放関数にわける。再起しても良い。 おすすめは3なんですけど… あと、べたべたにCで書いてる割にはiostreamだったり、coutだったりするんですが、完全にC++で仕様から考え直すって言う選択肢もあります。

noname#6117
質問者

お礼

長々とお付き合いくださり、ありがとうございました。 お礼申し上げます。

noname#6117
質問者

補足

回答ありがとうございます。 3番目のようにしたいですが、 いきなり処理を分けてしまうと、よくわからなくなります。再起というのは、意味がよくわからないです。 free関数の使い方がよくわかっていません。 すみません。 C++に直したいです。 このソースをどうしたいのかわかりません。 使い方がよくわからないです。 データの件数が不定のときに、使うのかな程度にしか 理解していません。 すみません、最後の二行についてもよくわからないです。 stdio.h , printf("",); の方がよいということでしょうか? 初心者ですので、よろしくお願いします。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • ポインタ・構造体・並び替え

    http://www9.plala.or.jp/sgwr-t/c/Q/ens15-3.html ↑のページの問2のプログラムを #include <stdio.h> typedef struct data{ int number; int subject[4]; int sum; }data_t; int get_sum(data_t); int main(void) { data_t st[5]={{1001,85,74,63,90}, {1002,78,65,70,62}, {1003,89,92,88,76}, {1004,32,48,66,25}, {1005,92,76,81,98}, }; data_t *p; data_t q; int i,j; for(i=0;i<5;i++) { p=&st[i]; p->sum=get_sum(st[i]); } for(i=0;i<3;i++) { for(j=0;j<3-i;j++) { if((p+j)->sum<(p+j+1)->sum) { q=*(p+j); *(p+j)=*(p+j+1); *(p+j+1)=q; } } } for ( i = 0; i < 5; i++ ) { printf( "%4d ", ( p+i )->number ); for ( j = 0; j < 4; j++ ) printf("%4d ", ( p+i )->subject[j] ); printf( " %4d\n", ( p+i )->sum ); } return 0; } int get_sum(data_t data) { data_t *p=&data; int i,sum=0; for(i=0;i<4;i++) { sum+=p->subject[i]; } return sum; } と、作ってみたのですが、最高点の1005が一番上に来るけど、それ以外が正しく表示されません。 どこを直せばいいでしょうか? よろしくお願いします。

  • 構造体へのポインタ

    すみません、構造体へのポインタの配列の扱いに困っています。 下記ソースの struct list *hashtable[HASHSIZE]; の箇所をmain部に入れた場合の 他の関数内での使用の仕方が全くわかりません。 どのように修正すれば良いのでしょうか。 申し訳ありませんが教えてください。 --------------------- #include <stdio.h> #include <stdlib.h> #include <string.h> #define HASHSIZE 40 #define MAX_KW_LEN 256 #define NUM_KW 23 #define TRUE 1 #define FALSE 0 struct list {  char keyword[MAX_KW_LEN];  struct list *next;   /* 次の list へのポインタ */ }; struct list *hashtable[HASHSIZE]; /* ハッシュテーブル */ /* キーワード ( Cの予約語 ) */ static char kw[NUM_KW][MAX_KW_LEN] = {   "auto", "break", "double",   "enum", "char", "continue", "extern", "float", "for", "int",   "long", "register", "short", "signed", "static",   "struct", "typedef", "union", "unsigned", "return",   "void", "volatile", "while" }; int Hash(char *key); void InitHTable(void); int FindKeyWord(char *key); void ListKeyWord(void); void FreeKeyWord(void); int main(void); int Hash(char *key) {  int hashval = 0;  while (*key != '\0')   hashval += *key++;  return (hashval % HASHSIZE); } void InitHTable(void) {  int i;  struct list *p, *q;  int hashval;  for (i = 0; i < NUM_KW; i++) {   printf("%d\n",i);   if ((FindKeyWord(kw[i])) == FALSE) { /* 登録されていなかったら */             /* メモリを割り付ける */    if ((p = (struct list *)malloc(sizeof(struct list))) == NULL) {     fprintf(stderr, "メモリ不足です。\n");     exit(2);    }    strcpy((*p).keyword, kw[i]);    hashval = Hash(kw[i]);    /* ハッシュ値を求めて */        if (hashtable[hashval] == NULL) { /* 未登録なら */     hashtable[hashval] = p;  /* p の指すアドレスを登録 */     p->next = NULL;    /* リストの末尾に NULL を追加 */    }    else {        /* 既に登録していたら */     q = hashtable[hashval];     while (q->next != NULL) {  /* データがなくなるまで */      q = q->next;    /* リストをたどる */     }     q->next = p;     /* リストの末尾に p の指すアドレスを登録 */     p->next = NULL;    /* その末尾に NULL を追加 */    }   }  } } int FindKeyWord(char *key) {  struct list *p;  for (p = hashtable[Hash(key)]; p != NULL; p = p->next)   if (!strcmp(key, (*p).keyword))  /* 登録済みなら */    return (TRUE);     /* TRUE を返す */   return (FALSE);      /* 未登録ならFALSE を返す */ } void ListKeyWord(void) {  int i;  struct list *p;  for (i = 0; i < HASHSIZE; i++)   for (p = hashtable[i]; p != NULL; p = p->next) /* p が NULL でなければ */               /* ハッシュ値とキーワードを表示 */    printf("予約語:%s ハッシュ値:%d:\n", (*p).keyword, Hash((*p).keyword)); } /* malloc( ) で割り付けたメモリを解放 */ void FreeKeyWord(void) {  int i;  struct list *p, *q;  for (i = 0; i < HASHSIZE; i++)   for (p = hashtable[i]; p != NULL; ) { /* p が NULL でなければ */    q = p->next;      /* p->next を保存 */    free(p);       /* メモリを解放 */    p = q;        /* p->next を p に代入 */   } } int main(void) {  char word[MAX_KW_LEN];  int i;  InitHTable( );  ListKeyWord( );  for (i = 0; i < 4; i++) {   printf("Cの予約語を入力して下さい ");   fgets(word, 128, stdin);   if ((FindKeyWord(word)) == TRUE)    printf("%s は登録済みです。\n", word);   else    printf("%s は未登録です。\n", word);  }  FreeKeyWord( ); }

  • C言語の構造体についてなんですが。

    struct LIST {     struct Num* number;     struct LIST* next;/* 次の要素へのポインタ */ }*root; struct Num{     int a;     struct Num* next; /* 次の要素へのポインタ */ }*numroot; と構造体を定義したときに、 main(){     struct LIST *p;     for(p = root; p != NULL; p = p->next) ; } とすれば、pの先頭からNULLまでを参照していくことは分かるんですが、pのnumberの先頭からNULLまでの参照方法(プログラムのfor文の記述方法)がイマイチわかりません。つまり、構造体の構造体をどのように参照するかということです。 これを実現したい理由は、構造体内での数の格納を配列(固定長)ではなく可変長で格納したいからです。 分かる方は解答をお願いします。

  • リスト構造のプログラミング

    #include<stdio.h> #include<stdlib.h> typedef struct number{ float x; struct number *next; }Num; void append_list(Num **, float); int main(void) { Num *start,*p; float i,d; start=NULL; for(i=0.0;i<10.0;i++){ append_list(&start,i); } p=start; while(p!=NULL){ printf("%f\n",p->x); p=p->next; } p=start; while(p !=NULL){ Num *q; q=p; p=p->next; free(q); } return 0; } void append_list(Num **s, float n) { Num *end, *new; if(*s==NULL){ *s=(Num *)malloc(sizeof(Num)*1); (*s)->x=n; (*s)->next=NULL; return; }end=(*s); while(end->next !=NULL){ end=end->next; } new=(Num *)malloc(sizeof(Num)*1); new->x=n; new->next=NULL; end->next=new; } 0~9までの数値を順番に追加してリスト構造のデータ構造で 保存するプログラミングを作ったのですが、これにキーボード から入力した1つの実数(0~9)を数値の順序を乱さないよう にその数値を持つ要素を追加するにはどうすればよいのでしょうか?

  • 構造体の構造体 引数

    構造体の中の構造体の関数の引き渡し方法がわかりません。 下記ソースで試したのですが、うまくいきませんでした。 助言お願いいたします。 //repo.c #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #define NUM 20 #define MAX 15 struct seiseki{ float shu[3]; }; struct seito{ char name[NUM]; int age; struct seiseki kekka; }; void input(struct seito *p); void s_input(struct seiseki *p); void ss_input(struct seiseki *data); int main(){ int i; struct seito data[2]; for(i=0;i<2;i++){ printf("------------------------------\n"); printf("%d人目",i+1); input(&data[i]); } printf("%f\n",data[0].kekka.shu[0]); printf("%f\n",data[0].kekka.shu[1]); printf("%f\n",data[0].kekka.shu[2]); //data[1]に格納できない。 printf("%f\n",data[1].kekka.shu[0]); printf("%f\n",data[1].kekka.shu[1]); printf("%f\n",data[1].kekka.shu[2]); return 0; } void input(struct seito *p){ printf("名前->"); scanf("%s",p->name); printf("年齢->"); scanf("%d",p->age); s_input(&(p->kekka)); } void s_input(struct seiseki *data){ printf("国語->"); ss_input(data); printf("算数->"); ss_input(data); printf("英語->"); ss_input(data); } //下記関数で成績をchar型で受け取り、数値化したい。 void ss_input(struct seiseki *data){ char p[100]; int i=0; static int o=0; scanf("%s",p); while( p[i] != '\0'){ if(isdigit(p[i])==0){ printf("再入力してください"); scanf("%s",p); } i++; } data->shu[o]=atof(p); printf("%f\n",data->shu[o]); o++; }

  • 構造体のアクセスについて

    タイトル通りではないかもしれないですが、 以下のソースで、「x()」を使わずに、「xx()」を使用するにはどうすればよいでしょうか? 説明不足ですが、どういえば言いのか判らないので、 うまく表現できないです。 要するに、「x()」の一階層上の「xx()」でアクセスがしたいのです???... #include<iostream> using namespace std; class data { public: struct list { int m; int n; list operator +(list &dat); list operator -(list &dat); int x(){return m;} } li; int xx() { data::list cd; return cd.m; } }; data::list data::list::operator +(data::list &dat) { list tmp; tmp.m=tmp.n=dat.m+dat.n; return tmp; } data::list data::list::operator -(data::list &dat) { list tmp; tmp.m=tmp.n=dat.m-dat.n; return tmp; } int main() { data dat1,dat2; dat1.li.m=10; dat1.li.n=79; dat2.li=dat1.li+dat1.li; cout << dat2.xx(); cout << dat2.li.x(); while(1){}return 0; } 大変申し訳ありませんが、よろしくお願いします。 また、何か上手な記述がありましたら、ご教授ください。

  • 自己参照型構造体とソート

    現在C言語の自己参照型について勉強をして入るのですが mallocで確保した領域でソートを行うにはどのようにすれば 良いのでしょうか。 (qsort関数は使わず、独自の関数で行う) *図 -database |number |name |next----batabase _____________|number _____________|name _____________|next------と続く ソースコード #include <stdio.h> struct database{ int number; char f_name; struct *next; }; int data_sort(){ /* ここのやり方がWebを見ても理解が出来ない状態です。 */ } int main(){ struct database *d1,*d2; d1 = (struct database *)malloc(sizeof(struct database*)) d2 = NULL; while(cnt < 10){ scanf("%d",&d1->number); scanf("%s",d1->name); d1->next = d2; d2 = d1; cnt++; } data_sort(); }

  • 構造体の中の構造体

    typedef struct number{ int x; struct number *next; }Num; 初心者な質問で申し訳ないんですが、構造体の中に構造体があるのはどう解釈していいんでしょうか? typedef struct number{ int x; int y; }Num; の場合はNum a,b;がint a.x,a.y,b.x,b.yとなるのは分かるんですが・・・

  • 構造体の構造体の構造体をまとめて初期化したい

    gnuplotをCで吐くためのプログラムを作成していますが、 構造体の構造体の構造体をまとめて初期化することができません。 以下がコードそのコードです。 #define MAX_PLOT_DATA_NUM 8 #define MAX_GRAPH_SET_NUM 35 //child -------------------------------------------------- typedef struct { char *fileName; int column[2]; char *caption; } Col; //child -------------------------------------------------- typedef struct { char *category; char *subCategory; char *xLabel, *yLabel; char *saveFileName; Col col[MAX_PLOT_DATA_NUM]; } GraphSet; //child -------------------------------------------------- typedef struct { char *lineFormat; int lineWidth; } Common; //mother ------------------------------------------------- typedef struct { GraphSet gs[MAX_GRAPH_SET_NUM]; Common common; } PlotFormats; int main(){ PlotFormats pF = { {"Motor angle","right","Time [s]","Angle [rad]","ang_R", {"motor.dat",1,2,"ang #1 "}, {"motor.dat",1,3,"ang #2 "}, {"motor.dat",1,4,"ang #3 "}, {"motor.dat",1,5,"ang #4 "}, {"motor.dat",1,6,"ang #5 "}, {"motor.dat",1,7,"ang #6 "}, }, //ここから下のコメントアウトしてる部分をはずすとコンパイルが通らなくなります。 //{"Motor angle","left","Time [s]","Angle [rad]","ang_L", // {"motor.dat",1,12,"ang #1 "}, // {"motor.dat",1,13,"ang #2 "}, // {"motor.dat",1,14,"ang #3 "}, // {"motor.dat",1,15,"ang #4 "}, // {"motor.dat",1,16,"ang #5 "}, // {"motor.dat",1,17,"ang #6 "}, //}, {"w l", 5}}; return 0; } エラーは ・間接参照のレベルが 'char *' と 'int' で異なっています。(複数) ・初期化子の数が多すぎます。 と出ます。 長くなりましたが、わかる方がいましたら、よろしくお願いします。

  • C言語による構造体の値渡しについて

    以下プログラムを作成しました。 1.read_file関数によりファイルを読み込み。 2.avg_kokugo関数により、国語の平均点を出す。 という流れで組まれているのですが、 1.read_file関数実行時に、dat構造体を渡しています。 2.read_file関数内で、fscanfによる読み込みを行い、dat[i].name,&dat[i].kokugo,&dat[i].sansuに格納しているみたいに感じます。 ここで、疑問なのが、 「構造体を値渡しでdatをread_file関数に渡してる」と思っているのですが、 「read_file関数から、値渡しで渡された構造体datに、値を格納することはできるのでしょうか?」 本を参考にして勉強していたのですが、 「構造体は、値渡しの時に読み込みはできるが、更新はできない」 と書かれていたのです。(ポインタ参照渡しの時は可能。) なぜ今回、read_file関数から、構造体datに値の格納ができるのでしょうか? 更新と新規格納は意味が異なるからなのでしょうか? ご教授よろしくお願いします。 <ソース> #include <stdio.h> //グローバル #define FNAME "test.txt" struct score{ char name[20]; int kokugo; int sansu; }; int read_file(struct score dat[],int n); float avg_kokugo(struct score dat[],int n); int main(void){ struct score dat[3]; int ret; float kokugo; float sansu; ret= read_file(dat,3); if(ret <0){ return 0; } kokugo = avg_kokugo(dat,3); printf("国語の平均 %.1f\n",kokugo); return 0; } int read_file(struct score dat[],int n){ FILE *fp; //ファイルポインタ int i; fp=fopen(FNAME,"r"); if(fp==NULL){ printf("ファイルをオープンできませんでした。\n"); return -1; //-1によるプログラム強制終了 } //データ読み込み i=0; //datに保存していく。 while((fscanf(fp,"%s%d%d",dat[i].name,&dat[i].kokugo,&dat[i].sansu)) != EOF){ i=i+1; //ファイル件数読み込み } fclose(fp); return 0; } float avg_kokugo(struct score dat[],int n){ int sum; //合計 float answer; int i; sum=0; for(i=0;i<n;i++){ sum = sum + dat[i].kokugo; } //平均点を求める answer =(float)sum / (float)n; return answer; }