リスト構造がうまく動かないC言語のプログラムの原因と対策

このQ&Aのポイント
  • C言語でリスト構造を使用したプログラムのループがうまく動作しない原因と対策について解説します。
  • プログラムはコンパイルは通るが、2人目以降のデータを表示できない問題が発生しています。
  • 原因はリスト構造のfor文が正しくループしていないことです。対策として、ループの条件を修正する必要があります。
回答を見る
  • ベストアンサー

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

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); }

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

  • ベストアンサー
  • 0x131cc6e
  • ベストアンサー率36% (42/115)
回答No.1

>2人目以降のデータを表示させようとしても表示してくれません ということですが、とりあえずMacOS X + GCCで動かしたところ、二人目以降も表示してますね。 ただ、最後の人は絶対にヒットしないので修正する必要があります。ヒントは検索ループの継続条件。 あと、問題がもう一つ。 newperson()でmallocしているけど、プログラム中のどこにもfreeする箇所がない。 とりあえずはそれでも動作しますが、確保したメモリーはきちんと解放するようにしましょうね。

you-two
質問者

お礼

ヒントありがとうございます!! おかげで「LIST != NULL;」ってことに気づけました。あとfreeの注意にも感謝します!!

その他の回答 (2)

  • mac_res
  • ベストアンサー率36% (568/1571)
回答No.3

バグがありました。 -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- #include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct _person { char *name; int height; int age; struct _person *next; } person; char * getline(void) { static char buf[BUFSIZ]; if (fgets(buf, BUFSIZ, stdin) == NULL) { exit(0); } buf[strlen(buf) - 1] = 0; return (buf); } int main(void) { int find; char *s, *name; person *head = NULL; person *list; person **nlist; nlist = &head; while (1) { printf("知りたい人の名前は?\n"); name = getline(); find = 0; for (list = head; list != NULL; list = list->next) { if (strcoll(name, list->name) == 0) { printf("%s\t%d\t%d\n", list->name, list->height, list->age); find++; break; } } if (find == 0) { name = strdup(name); printf("見つかりません\n"); printf("データを入れますか? (y/n) "); s = getline(); if (s[0] != 'n') { list = (person *) malloc(sizeof(person)); list->next = NULL; list->name = name; printf("身長:"); list->height = atoi(getline()); printf("年齢:"); list->age = atoi(getline()); *nlist = list; nlist = &list->next; } else { free(name); } } } return (0); }

  • mac_res
  • ベストアンサー率36% (568/1571)
回答No.2

#include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct data { char *name; int height; int age; struct data *next; } person; person * newperson() { person *dummy; dummy = (person *) malloc(sizeof(person)); dummy->next = NULL; return (dummy); } char * getline(void) { static char buf[BUFSIZ]; if (fgets(buf, BUFSIZ, stdin) == NULL) { exit(0); } buf[strlen(buf) - 1] = 0; return (buf); } int main(void) { int find; char *s, *name; person *head = NULL; person *list; person **nlist; person *LIST; nlist = &head; while (1) { printf("知りたい人の名前は?\n"); name = getline(); find = 0; for (LIST = head; head != NULL && LIST != NULL; LIST = LIST->next) { if (strcoll(name, LIST->name) == 0) { printf("%s\t%d\t%d\n", LIST->name, LIST->height, LIST->age); find++; break; } } if (find == 0) { name = strdup(name); printf("見つかりません\n"); printf("データを入れますか? (y/n) "); s = getline(); if (s[0] != 'n') { list = newperson(); list->name = name; printf("身長:"); list->height = atoi(getline()); printf("年齢:"); list->age = atoi(getline()); *nlist = list; nlist = &list->next; } else { free(name); } } } return (0); }

you-two
質問者

お礼

ありがとうございます!! 該当者を検索するプログラムの訂正だけじゃなく、データの追加まで組み込んでもらって助かりました。

関連するQ&A

  • リスト構造のソートで悩んでます。。。

    リスト構造のソートで悩んでます。プログラムの内容はファイルからデータをリスト構造の構造体に読み込み、名前順にソートし結果を表示する。というものです。データの追加や削除はできるのですがソートとなると頭が混乱してしまいお手上げ状態になってしまいました。。。。。 読み込み用のデータとプログラムソースを以下に記載するのでどなたか良きアドバイスをお願いしますm(_ _)m ○データ Sakuragi 16 Rukawa 16 Miyagi 17 Akagi 18 Mitsui 18 ○ソース #include <stdio.h> #include <stdlib.h> #include <string.h> #define MENBER 5 typedef struct data{ char name[BUFSIZ]; int age; struct data *next; }LIST; LIST *newLIST(void); LIST *sort(LIST *); int main(int argc,char *argv[]){ FILE *fp; LIST *p; LIST *np; LIST *npb; LIST *head; char namae[BUFSIZ]; int toshi,i; if((fp=fopen(argv[1],"r"))==NULL){ printf("no file\n"); exit(1); } head = newLIST(); npb =head; for(i=0;i<MENBER;i++){ np = newLIST(); fscanf(fp,"%s %d",namae,&toshi); strcpy(np->name,namae); np->age = toshi; npb->next =np; npb = np; } sort(head); for(p=head->next;p != NULL;p=p->next){ printf("%s\t%d\n",p->name,p->age); } for(p=head->next;p != NULL;p=np){ np = p->next; free(p); } fclose(fp); return(0); } LIST *newLIST(){ LIST *p; p = (LIST *)malloc(sizeof(LIST)); p->next = NULL; return(p); } LIST *sort(LIST *head){ }

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

    リストの削除のプログラムを実行して行ってみると、リストの削除処理中にプログラムが終わって変更後処理がうまく表示されません。どこが間違っているかが分からないしだいです。返答のほどよろしくお願いいたします。 #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; } }

  • アルゴリズム 線形リスト

    最近リストについて習い始めました。入力したデータと同順に並ぶリストを作成しようと思い、コードを打ったのですが…動作中止の表示がでてしまいました。どこが間違っているのか、ずっと悪戦苦闘して組んでいるのですが、全く出口が見えてきません。何が間違えているのか、はたまた根本的に違うのか、ご指導して頂けると有難いです。 以下、コードです。 #include <stdio.h> #include <stdlib.h> #include <string.h> struct hito{ char name[20]; int age; struct hito *next; }; void main(void){ struct hito *p, *head, *dummy; char new_name[20]; int new_age; dummy = (struct hito *)malloc(sizeof(struct hito)); head = dummy; dummy->next = p; dummy = p; while (scanf("%s %d" , new_name, &new_age) != EOF) { p = (struct hito *)malloc(sizeof(struct hito)); strcpy(p->name, new_name); p->age = new_age; p->next = head; head = p; } while(p != NULL) { printf("\t%-20s %3d\n" , p->name, p->age); p = p->next; } }

  • freeでメモリが開放できません。。。

    以下のプログラムは、下記の入力データを構造体に格納し、平均身長と平均体重を求めて画面に出力するプログラムです。feeによるメモリの開放が動いていないようで、結果まで出力してくれるのですが、その直後エラー終了してしまいます。なにが悪いのか全く分かりません!!どなたかアドバイスをお願いしますm(__)m データファイル Sakuragi 189 83 みたいなデータが5組あります。 ソースプログラム #include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct person{ char name[20]; int height; int weight; struct person *next; }LIST; LIST *ave(LIST *head); LIST *newLIST(void); int main(int argc,char *argv[]){ char namae[20]; int n=0,shinchou,taijuu; FILE *fp; LIST *head; LIST *p; LIST *np; LIST *npb; LIST *AVE; head = newLIST(); npb = head; if((fp=fopen(argv[1],"r"))==NULL){ printf("no file\n"); exit(1); } while(n != 5){ np = newLIST(); fscanf(fp,"%s %d %d",namae,&shinchou,&taijuu); strcpy(p->name,namae); np->height= shinchou; np->weight= taijuu; npb->next=np; npb=np; n++; } fclose(fp); AVE = ave(head); printf("%d\t%d\n",AVE->height,AVE->weight); for(p=head;p != NULL;p= p->next){ free(p); } return(0); } LIST *newLIST(){ LIST *p; p=(LIST*)malloc(sizeof(LIST)); p->next = NULL; return(p); } LIST *ave(LIST *head){ LIST *p,*pp; int h=0,w=0; for(p=head->next;p != NULL;p=p->next){ h += p->height; w += p->weight; } h = h/5; w = w/5; pp->height = h; pp->weight = w; return(pp); }

  • list構造。。。

    リストの末尾にデータを追加すると、最後に追加したデータで今までのリストのデータが上書きされてしまいます。。 以下に、ソースを掲載させていただきます。 void SetNode(List* node_first, List* node_second, int *data) { node_first->move = data; node_first->next = node_second; return ; } /*末尾に挿入*/ void Insert_Tail(List **head, int* data) { List *ptr = *head; if(ptr == NULL){ *head = (List*)calloc(1,sizeof(List)); SetNode(*head, NULL, data); return ; }else{ while(ptr->next != NULL){ ptr = ptr->next; } ptr->next = (List*)calloc(1,sizeof(List)); SetNode(ptr->next, NULL, data); } return ; } void show_list(List *list) { List *ptr = list; while(ptr != NULL){ printf("%d\n",*(ptr->move)); ptr = ptr->next; } return ; } int main(int argc, char** argv) { /*宣言*/ Node* root; /**/ List* top; /* 手順のリスト */ int judge; top = NULL; do{ printf("num:"); scanf("%d",&judge); switch(judge){ case 1: /*データを末尾に追加*/ printf("mem:"); scanf("%d",mem); root->board = mem; Insert_Tail(&top, root->board); break; case 2: /*リストを頭から表示*/ show_list(top); break; default: break; } }while(judge != 0); return 0; } 自分は最後のリストまでたどって、callocしたつもりなのですが、どうもそうではないようで、困っています。 どうか、御指導の程、お願いします。

  • プログラミング構造体について。

    include<stdio.h> #include<stdlib.h> #include<string.h> struct person{ char name[10]; int gender; int age; }; void printPersonList(struct person *person_p, int size); void outputPersonList(struct person *person_p, int size); double getAverageOfAge(struct person *person_p, int size); int countMales(struct person *person_p, int size); int countFemales(struct person *person_p, int size); int main(void){ struct person *person_p; int i, count, gender, age, maleCount, femaleCount; char name[20]; double average; printf("登録する人数を入力してください。\n"); scanf("%d", &count); person_p = (struct person*)malloc(sizeof(struct person)* count); for(i=0; i < count; i++){ printf("名前・性別(男性:0, 女性:1)・年齢をスペース区切りで入力してください。\n"); scanf("%s %d %d", name, &gender, &age); strcpy((person_p + i) -> name, name); (person_p + i) -> gender = gender; (person_p + i) -> age = age; } printPersonList(person_p, count); outputPersonList(person_p, count); average = getAverageOfAge(person_p, count); printf("平均年齢:%f\n", average); maleCount = countMales(person_p, count); femaleCount = countFemales(person_p, count); printf("男性:%d名, 女性:%d名\n", maleCount, femaleCount); free(person_p); return 1; } void printPersonList(struct person *person_p, int size){ int i; printf("登録リスト\n"); printf(" name | gender | age\n"); printf("----------+--------+-----\n"); for(i=0; i < size; i++){ printf("%10s | %1d | %2d\n", (person_p + i) -> name, (person_p + i) -> gender, (person_p + i) -> age); } } void outputPersonList(struct person *person_p, int size){ FILE *output; int i; if((output = fopen("meibo.c", "w")) == NULL){ printf("meibo.cを開けませんでした。\n"); return; } for(i=0; i < size; i++){ fprintf(output, "%s, %d, %d\n", (person_p + i) -> name, (person_p + i) -> gender, (person_p + i) -> age); } fclose(output); } 残り3つの関数をすべて定義する(それぞれ10行程度) getAverageOfAge, countMales, countFemales どう定義すればいいのか教えてください。お願いします。

  • リスト再質問

    前にリストについて質問した者です #include <stdio.h> #include <stdlib.h> typedef struct _node{ char name[100]; int koku; int suu; int eig; int gou; struct _node *next; }Node; int main(void) { Node *a[5]; Node *head; Node *crnt,*p,*t,dummy; int data, swap; int i; head=(Node*)malloc(sizeof (Node)); head=NULL; crnt=NULL; head=(Node*)malloc(sizeof (Node)); printf("名前:"); scanf("%s",head->name); printf("国語 数学 英語 : "); scanf("%d %d %d",&head->koku,&head->suu,&head->eig); head->gou=(head->koku+head->suu+head->eig); a[0]=head; a[0]->next=NULL; for(i=1;i<5;i++) { a[i]=(Node*)malloc(sizeof (Node)); printf("名前:"); scanf("%s",a[i]->name); printf("国語 数学 英語 : "); scanf("%d %d %d",&a[i]->koku,&a[i]->suu,&a[i]->eig); a[i]->gou=(a[i]->koku+a[i]->suu+a[i]->eig); a[i]->next=NULL; } printf("%s ",head->name); printf("%d %d %d %d\n",head->koku,head->suu,head->eig,head->gou); a[0]=head; a[0]=a[0]->next; for(i=1;i<5;i++) { printf("%s ",a[i]->name); printf("%d %d %d %d\n",a[i]->koku,a[i]->suu,a[i]->eig,a[i]->gou); a[i]=a[i]->next; } return 0; } とプログラム出来たのですが 今は入力した順に名前と点数、合計が表示するように なってます。しかしこれを合計の値で順位をつけ 一番合計点が高い人から 名前、点数、合計を表示したいのです。入力がすべて終了したらソートするようにしたいのですが わかりません どうすればいいのでしょうか?

  • 双方向リストのバブルソートについて

    双方向リストをバブルソートを用いてソートしたいです。 下記がプログラム(一部)ですが、ソートした後にリスト表示すると 無限ループに陥ります。 どこがいけないのでしょうか。 #include <stdio.h> #include <stdlib.h> struct cell{ int data; struct cell *next, *prev; }; void insert_head(struct cell **head, int num){ struct cell *p, *p1; p = *head; p1 = make_cell(); *head = p1; p1->data = num; p1->next = p; if(p1->next != (struct cell *)NULL){ p1->next = p; p->prev = p1; } } void print_list(struct cell *head){ struct cell *p; p = head; printf("data = \n"); while(p != (struct cell *)NULL){ printf("%d\n", p->data); p = p->next; } } void sort_list(struct cell **head){ struct cell *p, *p2; int i, n; n = 0; p = *head; while(p->next != (struct cell *)NULL){ p = p->next; n++; } for(i = 0, p = *head; i < n-2; i++){ if(p->data > p->next->data){ if(p == *head){ *head = p->next; }else{ p->prev->next = p->next; } p2 = p->next; p->next = p->next->next; p->next->next = p; p->next->next->prev = p; p->next->prev = p->prev; p->prev = p2; }else p = p->next; } } int main(void){ struct cell *head = (struct cell *)NULL; int n; while(1){ printf("1:Insert head 2:Insert tail 3:Delete 4:List 5:Sort 6:Exit\n"); scanf("%d", &n); switch(n){ case 1: printf("num = "); scanf("%d", &n); insert_head(&head, n); break; case 2: printf("num = "); scanf("%d", &n); insert_tail(&head, n); break; case 3: printf("num = "); scanf("%d", &n); delete_cell(&head, n); break; case 4: print_list(head); break; case 5: sort_list(&head); break; case 6: return 0; break; } } }

  • 構造体について

    5件のデータをRECORDに追加したいのですが、 RECORD inputdata(void)の宣言文エラーなどのコンパイルエラー。それと、inputdataを用いてどうやって5件のデータを入れたらいいかがわかりません。教えてください。 #define SIZE 5 #include <stdio.h> typedef struct{ int yy; int mm; int dd; }YMD; typedef struct{ char name[20]; YMD birthday; int age; }RECORD; RECORD inputdata(void); void main(void) { int i; for(i = 0;i < SIZE;i++){ inputdata(); } RECORD inputdata(void) { RECORD person; printf("名前>"); scanf("%s", person.name); printf("誕生日入力\n"); printf("年>"); scanf("%d", person.birthday.yy); printf("月>"); scanf("%d", person.birthday.mm); printf("日>"); scanf("%d", person.birthday.dd); return person; }

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

    データ構造を線形リストとして、情報を管理するプログラムのソートについてです。 以下のプログラムはデータを入れ替えて、その後アドレスを入れ替えるようにしてソートを行っていますが、そうではなく線形リストなのでつなぎ替えるようにしてソートを行うプログラムを作成したいのですがわからないのでご教授をお願い致します。ソートは逐次決定で行ってます。 構造体の宣言として、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(“ソート完了”); }

専門家に質問してみよう