• ベストアンサー

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

mitonekoの回答

  • 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が使えません。

関連する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; }