プログラムのトレースについての質問

このQ&Aのポイント
  • プログラムのトレースの参考書を読んでいますが、自己参照構造体の利用例についてわからない箇所があります。
  • 特に、「作成した構造体wkdtpを既存のチェーンにはめ込んでいく」部分でつまづいています。
  • forループの始めでip=startを代入しているのですが、startの中身が構造体dmyであるため、ループが実行されずに抜けてしまいます。理解が間違っているのか、何か他の原因があるのか、詳しい解説をお願いします。
回答を見る
  • ベストアンサー

プログラムのトレース

プログラムのトレース  参考書のプログラムを読んでいて、どうしてもわからないところがあります。  自己参照構造体の利用例というところなのですが、次のプログラムです。 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct person { char name[30]; int age; struct person *next; } Person; int main(void) { Person dmy = {"", 0, NULL}; Person *start = &dmy; Person *wkdtp; Person *ip; char name[30], age_ss[10]; while(1){ /* キーボードからデータを入力する */ printf("名前="); gets(name); if(strcmp(name, "") == 0) break; printf("年齢="); gets(age_ss); /* 構造体1個分のメモリを確保する */ wkdtp = (Person *)malloc(sizeof(Person)); if(wkdtp == NULL){ printf("メモリ確保できません。\n"); exit(1); } /* 確保した構造体に名前と年齢を設定する */ strcpy(wkdtp->name, name); wkdtp->age = atoi(age_ss); /* 作成した構造体wkdtpを既存のチェーンにはめ込んでいく */ for(ip=start; ip->next != NULL; ip = ip->next){ if(wkdtp->age < ip->next->age){ wkdtp->next = ip->next; ip->next = wkdtp; break; } } /* 最高齢だったらチェーンの最後につなぐ */ if(ip->next == NULL){ ip->next = wkdtp; wkdtp->next = NULL; } } /* チェーンをたどって構造体の内容を表示する */ for(ip = start->next; ip != NULL; ip = ip->next){ printf("%s %d\n", ip->name, ip->age); } return 0; } /* 作成した構造体wkdtpを既存のチェーンにはめ込んでいく */ の次のforループの始めで、つまづいてしまうのです。 ip=start で、startをipに代入していますが、このstartの中身って、構造体dmyすなわち、{"", 0, NULL}なのではないですか? forループの継続条件が、ip->nextがNULLでないことですから、その時点でforループの中の文を実行せずにループから抜けてしまうのではないでしょうか。「これはきっと何かの間違いだ」と思い、リストを打ち込んで、コンパイル・リンク・実行してみたら、参考書の通り、 名前=田中一郎←入力する 年齢=20 名前=伊藤二郎 年齢=40 名前=鈴木三郎 年齢=10 名前=内田四郎 年齢=30 名前=[enter]←[enter]だけ押下で入力終了 鈴木三郎 10←年齢順になっている 田中一郎 20 内田四郎 30 伊藤二郎 40 と、うまく作動しました。済みません、すごく初歩的な質問をしていると思うのですが、私の理解のどこが間違っているのでしょうか、どなたか解説をお願いします。

  • utu-ne
  • お礼率96% (674/702)

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

  • ベストアンサー
  • asuncion
  • ベストアンサー率33% (2126/6286)
回答No.2

>その時点でforループの中の文を実行せずにループから抜けてしまうのではないでしょうか。 最初のデータを入力するときは、確かにそのforループをすっ飛ばします。 すっ飛ばした後、 ip->next = wkdtp; wkdtp->next = NULL; を実行するので、nextポインタには適切な値が入るはずです。 まあ、コードをつぶさに検討したわけではないので、 書いたことが間違っているおそれはありますけれど。

utu-ne
質問者

お礼

 ありがとうございます。少し分かった気になりました。もう少し考えてみます。

その他の回答 (1)

  • t_nojiri
  • ベストアンサー率28% (595/2071)
回答No.1

>構造体dmyすなわち、{"", 0, NULL} は、 /* 構造体1個分のメモリを確保する */ /* 確保した構造体に名前と年齢を設定する */ /* 作成した構造体wkdtpを既存のチェーンにはめ込んでいく */ /* 最高齢だったらチェーンの最後につなぐ */ 処(ソースコードは省略)で書き換わってるでしょ?

utu-ne
質問者

補足

 済みません、まだ分かりません。ip=startのstartは、最初の{"",0,NULL}の先頭アドレスが保持されているのではないでしょうか。どこで書き換わったのでしょう、自分でももう少し考えますが、もしよろしければ、ご教示願います。

関連するQ&A

  • プログラムのトレース

    プログラムのトレース  参考書を読んでいて、どうしてもわからないところがあります。  自己参照構造体の利用というところなのですが、次のプログラムです。 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct person { char name[30]; int age; struct person *next; } Person; int main(void) { Person dmy = {"", 0, NULL}; Person *start = &dmy; Person *wkdtp; Person *ip; char name[30], age_ss[10]; while(1){ /* キーボードからデータを入力する */ printf("名前="); gets(name); if(strcmp(name, "") == 0) break; printf("年齢="); gets(age_ss); /* 構造体1個分のメモリを確保する */ wkdtp = (Person *)malloc(sizeof(Person)); if(wkdtp == NULL){ printf("メモリ確保できません。\n"); exit(1); } /* 確保した構造体に名前と年齢を設定する */ strcpy(wkdtp->name, name); wkdtp->age = atoi(age_ss); /* 作成した構造体wkdtpを既存のチェーンにはめ込んでいく */ for(ip=start; ip->next != NULL; ip = ip->next){ if(wkdtp->age < ip->next->age){ wkdtp->next = ip->next; ip->next = wkdtp; break; } } /* 最高齢だったらチェーンの最後につなぐ */ if(ip->next == NULL){ ip->next = wkdtp; wkdtp->next = NULL; } } /* チェーンをたどって構造体の内容を表示する */ for(ip = start->next; ip != NULL; ip = ip->next){ printf("%s %d\n", ip->name, ip->age); } return 0; } /* 作成した構造体wkdtpを既存のチェーンにはめ込んでいく */ の次のforループの最初のところでつまづいてしまいます。 ip=start でipにstartを代入していますが、このstartの中身って、dmyすなわち{"", 0, NULL}ではないですか。forループの継続条件が、ip->nextがNULLでないことですから、ループの開始時点でループの中の文を実行せずに抜けてしまうのではないでしょうか。「これは何かの間違いだ」と思い、打ち込んでコンパイル・リンク・実行してみると、参考書の通りに、 名前=田中一郎←入力する 年齢=20 名前=伊藤二郎 年齢=40 名前=鈴木三郎 年齢=10 名前=内田四郎 年齢=30 名前=[enter]←[enter]だけ押下で入力終了 鈴木三郎 10←年齢順になっている 田中一郎 20 内田四郎 30 伊藤二郎 40 と、動きました。済みません、すごく初歩的なことで悩んでいると思いますが、私の理解のどこが間違っているのでしょうか。どなたか解説をお願い致します。

  • C言語 家系図

    問題 構造体personを以下のように仮定する。 struct person { int age; char name[20]; struct person *father; struct person *mother; }; この構造体の表す人の名前、年齢、その人の父親の名前、およびその人の母親の名前を出力する関数 void print_person(struct person *p) を作成せよ。出力の形式は name: 本人の名前 age: 本人の年齢 father: 父親の名前 mother: 母親の名前 となるようにすること。 また、ポインタ father や mother の値が NULL のときには、名前のかわりに unknown と出力するようにせよ。 以上が問題なのですが自分でプログラムを作ってみたところ実行したら、エラーになって矯正終了されてしまいました。 以下が私の作ったプログラムです。 #include <stdio.h> struct person { int age; char name[20]; struct person *father; struct person *mother; }; void set_name(struct person *p, char name[]) { int i; i = 0; while (name[i] != 0) { p->name[i] = name[i]; i++; } p->name[i] = 0; } void print_person(struct person *p) { printf("name:%s", p->name); printf("age:%s\n",p->age); if(p->father != NULL){ printf("father:%s\n",p->father); } else{ printf("unknown"); } if(p->mother != NULL){ printf("mother:%s\n",p->mother); } else{ printf("unknown"); } } int main(void) { struct person me, dad, mom; set_name(&me, "Michael"); me.age = 16; me.father = &dad; me.mother = &mom; set_name(&dad, "David"); dad.age = 38; dad.father = NULL; dad.mother = NULL; set_name(&mom, "Susan"); mom.age = 36; mom.father = NULL; mom.mother = NULL; print_person(&me); print_person(&dad); print_person(&mom); return (0); } どこが違うのか教えていただけないでしょうか?

  • 線形リストのソートについて

    データ構造を線形リストとして、情報を管理するプログラムのソートについてです。 以下のプログラムはデータを入れ替えて、その後アドレスを入れ替えるようにしてソートを行っていますが、そうではなく線形リストなのでつなぎ替えるようにしてソートを行うプログラムを作成したいのですがわからないのでご教授をお願い致します。ソートは逐次決定で行ってます。 構造体の宣言として、nameとageとnextは氏名と年齢と次のポインタを指します。NAME_SORT、AGE_SORTはマクロです。 struct sortlist(struct PERSON *head) { int menu; struct PERSON person; /* 情報 */ struct PERSON move_person; /* 比較していく情報 */ struct PERSON work; /* 情報の一時的保存 */ struct PERSON temp; /* 作業用 */ struct PERSON temp_address; /* アドレス作業用 */ printf("ソート機能を選択:"); printf("%d:氏名\n",NAME_SORT); printf("%d:年齢\n",AGE_SORT); /* 交換処理 */ for(person = head; person -> next != NULL; person -> person -> next) { work = person; /* 交換データの探索 */ for(move_person = person -> next; move_person != NULL; move_person -> next) { switch(menu) { case NAME_SORT: if(strcmp(work -> name, move_person -> name) > 0) { work = move_person; } break; case NAME_SORT: if(work -> age > move_person -> age) { work = move_person; } break; default: printf("機能以外が選択されました"); return head; } if(work != person) { /* 情報の交換 */ temp = *person; *person = *work; *work = temp; /* アドレスの交換 */; temp_address = employee -> next; person -> next = work -> next; work -> next = temp_address; } } } } printf(“ソート完了”); }

  • リスト構造がうまく動きません!!

    C言語で以下のようなプログラムを作りました。 「main関数内で下記のデ-タを構造体に格納し、キーボードから入力された名前と該当する学生の身長と年齢を画面に表示するプログラムを作成せよ。」というものです。 このプログラムはコンパイルは通るのですが、2人目以降のデータを表示させようとしても表示してくれません。。。どうもリスト構造のfor文がうまくループしていないみたいなんですが原因が分かりません。どなたか原因の分かる方アドバイスをお願いしますm(_ _)m #include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct data{ char name[20]; int height; int age; struct data *next; }person; person *newperson(void); int main(void){ char namae[20],s[20]; int toshi,shinchou,i; person *head; person *list; person *nlist; person *LIST; head = newperson(); nlist = head; printf("データを入れてください。\n"); for(i=0;i<=4;i++){ scanf("%s",namae); scanf("%d",&shinchou); scanf("%d",&toshi); list = newperson(); strcpy(list ->name,namae); list -> height = shinchou; list -> age = toshi; nlist -> next = list; nlist = list; } printf("知りたい人の名前は?\n"); scanf("%s",s); for(LIST = head->next;LIST ->next != NULL;LIST = LIST->next){ if(strcoll(s,LIST ->name)==0){ printf("%s\t%d\t%d\n",LIST->name,LIST->height,LIST->age); break; } printf("%s\n",LIST->name); printf("%s\n",LIST->next->name); } return(0); } person *newperson(){ person *dummy; dummy = (person*)malloc(sizeof(person)); dummy -> next = NULL; return(dummy); }

  • scanfの\nの意味

    タイトルの通りです。 #include<stdio.h> struct Person{ char name[100]; char gender; int age; }; int main(void) { struct Person person1; printf("名前は:"); scanf("%s",person1.name); printf("\n年齢は:"); scanf("%d",&person1.age); printf("\n性別は:"); scanf("\n%c",&person1.gender); printf("\n{name=%s,age=%d,gender=%c}",person1.name,person1.age,person1.gender); return 0; } 上記において aaa , 11 , M と入力すると {name=aaa,age=11,gender=M} と表示されますが、 scanf("\n%c",&person1.gender); を scanf("%c",&person1.gender); に変えると {name=aaa,age=11,gender= } となってしまいます。 この理由と、/nの意味を教えてください。

  • このようなプログラムを教えて下さい

    コマンドプロンプト上の標準入力で文字列と数値を複数組入力していき、 その入力された文字列とそれに対する数値をその数値で比較し最後に大きい順で順に表示するようなプログラムを作りたいのですが、よく構造がわからないので教えて下さい。(ちなみに入力された文字列と数値は、それらを1つのクラスのフィールドとして定義するとして) たとえば人の名前と年齢を入力し大きい順に並べるとか NAME :Bob age :12 NAME :Tom age :25 NAME :Ken age :3 NAME : NAME:Tom,age:25 NAME:Bob,age:12 NAME:Ken,age:3 このように出力したいのですが もしこのようなプログラムを作成することのできる方いましたら、 教えてやってください。

    • ベストアンサー
    • Java
  • このプログラムのポインタを配列に変換したいんですけど

    C言語初心者です。助けてください。 途中までがんばったのですがどうしてもできません。問題はこの構造体の*name→name[25],*email→email[30]に変換させたいのですが、そのまま変換すると左辺値が必要や移植性のないポインタ変換などのエラーが出てしまいます。どうすればいいですか?教えてください。あと関数getlineと構造体は変えないでください。(指定した部分は除く) このプログラムは名前、メールアドレス、年齢を保存していき-1を入力した時出力されるというものです。 よろしくお願いします。 入力例 10 hakata abc@・・・ 12 yokohama dfg@・・・ -1 -1 -1 出力例 -1 -1 -1 12 yokohama dfg@・・・ 10 hakata abc@・・・ #include <stdio.h> #include<stdlib.h> struct node { char *name; char *email; int age; struct node *next; } heap[100], *hp = heap; void getline(char *s,int n) { int c; while(--n>0&&((c=getchar())!=EOF && c!='\n')) *s++=c; *s='\0'; } char* dupstr(char* strg) { char* newstr; newstr=(char*)malloc(sizeof(char)*strlen(strg)); strcpy(newstr,strg); return newstr; } struct node *new(int n ,char* a, char* b) { hp->age=n; hp->email=a; hp->name=b; hp->next=NULL; return hp++; } struct node *add(struct node *p, struct node *q) { q->next=p; p=q; return p ; } void print_list(struct node *p) { while (p != NULL) { printf("%d ", p->age); printf("%s ", p->name); printf("%s ", p->email); p=p->next; } printf("\n"); } main() { int age,p; char buf[80],a[80],b[80],*email,*name; struct node *root=NULL; while(getline!=NULL) { getline(buf,sizeof(buf)); age=atoi(buf); getline(b,sizeof(b)); getline(a,sizeof(a)); email=dupstr(b); name=dupstr(a); root=add(root,new(age,email,name)); if(age==-1) break; } print_list(root); }

  • 構造体のポインタ

    なぜかprevのほうが表示されません。 問題としては関数を作成し gyuri[23] -> sunyon[23] -> nicole[20] -> hara[20] -> jiyon[17] -> hara[20] -> nicole[20] -> sunyon[23] -> gyuri[23] -> END と表示させるのが目的です gyuri[23] -> sunyon[23] -> nicole[20] -> hara[20] -> jiyon[17] ここまではうまく表示できているのですが・・・ #include <stdio.h> void printoufuku(struct kara *p); struct kara { char name[16]; int age; struct kara *next; struct kara *prev; }; int main() { struct kara a, x, f, m, c, *start; strcpy(a.name, "gyuri"); a.age = 23; strcpy(x.name, "sunyon"); x.age = 23; strcpy(f.name, "nicole"); f.age = 20; strcpy(m.name, "hara"); m.age = 20; strcpy(c.name, "jiyon"); c.age = 17; a.next = &x; x.next = &f; f.next = &m; m.next = &c; c.next = NULL; /********************* 5 lines */ c.prev = &m; m.prev = &f; f.prev = &x; x.prev = &a; a.prev = NULL; /*********************/ start = &a; printoufuku(start); return 0; } void printoufuku(struct kara *p) { for(p->next; p != NULL;p = p->next){ printf("%s[%d] ->",p->name,p->age); } for(p->prev; p != NULL; p = p->prev){ printf("%s[%d] ->",p->name,p->age); } }

  • リストの削除について(構造体)

    リストの削除のプログラムを実行して行ってみると、リストの削除処理中にプログラムが終わって変更後処理がうまく表示されません。どこが間違っているかが分からないしだいです。返答のほどよろしくお願いいたします。 #include<stdio.h> #include<malloc.h> #include<string.h> struct list{ char name[20]; int age; struct list *next; }; void main(void) { struct list *head, *p, *n, *old; char key[20]; /*ダミーノード作成*/ head = (struct list*)malloc(sizeof(struct list)); old = head; while(p = (struct list*)malloc(sizeof(struct list)), printf("name age入力\n"), scanf("%s %d", p -> name, &p -> age) != EOF){ old -> next = p; old = p; } free(p); old -> next = NULL; p = head -> next; printf("変更前リスト\n"); while(p != NULL){ printf("name:%s age:%d\n",p -> name, p -> age); p = p -> next; } printf("削除key入力(name)\n"); gets(key); n = head; while(n != NULL){ old = n; n = n -> next; //printf("n -> name %s\n", n -> name); if(strcmp(n -> name, key) == 0){ printf("%s削除\n", key); //printf("n -> name %s old -> name %s\n", n -> name, old -> name); old -> next = n -> next; } } p = head -> next; printf("変更後リスト\n"); while(p != NULL){ printf("name:%s age:%d\n", p -> name, p -> age); p = p -> next; } }

  • 構造体のリスト削除

    かれこれ1時間くらい悩んでいて 問題として 関数delete()を作成し、プログラムを完成させよ(~yabuki/p7.c)。 関数delete()は、与えられたデータをリストから削除するものである。 ただし、データが先頭であっても動作しなければならない。 次のように出力されるはずである。 NEXT gyuri[23] -> sunyon[23] -> nicole[20] -> hara[20] -> jiyon[17] -> END PREV jiyon[17] -> hara[20] -> nicole[20] -> sunyon[23] -> gyuri[23] -> END NEXT gyuri[23] -> sunyon[23] -> nicole[20] -> hara[20] -> END PREV hara[20] -> nicole[20] -> sunyon[23] -> gyuri[23] -> END NEXT sunyon[23] -> END PREV sunyon[23] -> END list ha nakunarimasita /*******/の間に5行のプログラムを入れる。それ以外にmain()関数を 変更してはならない。 .........;の部分に構造体のメンバーを定義せよ。 というもので、Deleteしていくプログラムをつくりたいのですが NEXT gyuri[23] -> sunyon[23] -> nicole[20] -> hara[20] -> jiyon[17] -> END PREV jiyon[17] -> hara[20] -> nicole[20] -> sunyon[23] -> gyuri[23] -> END セグメントエラー となり、続きができていません。 delete関数のif(p->next != NULL){ のところだけやると 最後まで出るみたいですが、うまくいってません よろしくおねがいします。 ↓ソースです・・・ #include <stdio.h> #include <string.h> struct kara { char name[16]; int age; struct kara *next; struct kara *prev; }; struct kara * delete(struct kara *,struct kara *); struct kara * findend(struct kara *); void* printforw(struct kara *); void* printback(struct kara *); int main() { struct kara a, x, f, m, c, *start, *end, *p; char name[128]; strcpy(a.name, "gyuri"); a.age = 23; strcpy(x.name, "sunyon"); x.age = 23; strcpy(f.name, "nicole"); f.age = 20; strcpy(m.name, "hara"); m.age = 20; strcpy(c.name, "jiyon"); c.age = 17; a.next = &x; x.next = &f; f.next = &m; m.next = &c; c.next = NULL; /********************* 5 lines */ a.prev = NULL; x.prev = &a; f.prev = &x; m.prev = &f; c.prev = &m; /*********************/ start = &a; end = findend(start); printforw(start); printback(end); printf("\n"); p = &c; start = delete(start, p); if (start == NULL) { printf("list ha nakunarimasita\n"); return 0; } else { end = findend(start); printforw(start); printback(end); } printf("\n"); x.next = NULL; p = &a; start = delete(start, p); if (start == NULL) { printf("list ha nakunarimasita\n"); return 0; } else { end = findend(start); printforw(start); printback(end); } printf("\n"); p = start; start = delete(start, p); //de senntou wo kaesu if (start == NULL) { printf("list ha nakunarimasita\n"); return 0; } else { end = findend(start); printforw(start); printback(end); } return 0; } struct kara * delete (struct kara *start,struct kara *p) { /*if(p->next->next->next->next) { start = p->next->next->next->next; } */ for(p = start;p != NULL;p = p->next) { start = p->next->next->next; p = start; } /* if(p->next) { start = p->next; } if(p->prev) { start = p->prev; } if(p->next != NULL){ p->next->prev = p->prev; } } */ return p; } struct kara * findend(struct kara *start) { struct kara *pl; for(pl = start;pl != NULL; pl = pl->next){ start = pl; } return start; } void* printforw(struct kara *aa) { struct kara *pl; printf("NEXT "); for ( pl = aa; pl != NULL; pl = pl->next) { printf("%s[%d] -> ", pl->name, pl->age); } printf("END\n"); } void* printback(struct kara *cc) { struct kara *pl; printf("PREV "); //for( ; cc != NULL;cc = cc->prev){ for (pl = cc; pl != NULL; pl = pl->prev) { printf("%s[%d] ->", pl->name,pl->age); } printf("END\n"); }