• ベストアンサー

セグメンテーション違反が出てしまいます・・・.

#include<stdio.h> typedef struct tag{ int num; char name[10]; struct tag *next; }DATA; void add(void); DATA *head,*wp,*back; int main(void) { FILE *rfp,*wfp; char buf[256]; DATA *p; head=NULL; //ファイルを読み込み--------------------------- rfp=fopen("sample.txt", "r"); while(fgets(buf,256,rfp)!=NULL){ p=(DATA *)malloc(sizeof(DATA)); sscanf(buf,"%d %s", &(p->num),p->name); if(head==NULL){ head=p; head->next=NULL; back=p; } else{ back->next=p; back=p; } p->next=NULL; } fclose(rfp); //読み込み終了--------------------------------- } void add(void){ DATA *newp; newp=(DATA *)malloc(sizeof(DATA)); scanf("%d", &newp->num); scanf("%s", &newp->name); newp->next=NULL; for(wp=head; wp!=NULL; wp=wp->next){ if(head=NULL)head=newp; else if(newp->num < wp->num){ head->next = newp; } } } sample.txtからデータを読み込みそれを構造体のリスト構造にしてその構造体にデータを追加したいのですが、最後のhead->next=newpのところでセグメンテーション違反が出てしまいます。なぜでしょうか? 恐らくプログラムの内容はあまりないと思いますので概要だけ汲み取ってくれたら嬉しいです。因みにadd関数は途中です。

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

  • ベストアンサー
  • salsberry
  • ベストアンサー率69% (495/711)
回答No.3

if(head=NULL)head=newp; ここで必ずheadがNULLになってしまった直後に、else if以下を実行しています。

wachi888
質問者

お礼

ド素人ですいません・・・。まさにその通りでした。的確な回答ありがとうございます。

その他の回答 (3)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

うん, #2 の通り add は呼び出されていないね. 全然関係ないけど ・malloc を使うなら stdlib.h を #include してくれ. ・typedef するところで struct tag って, 「tag」という名前は意味をなさないのでやめてほしい. せめて typedef struct DATA { ... } DATA; とか.

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

>最後のhead->next=newpのところでセグメンテーション違反 そうでしょうか? せっかく作ったadd関数をどこからも呼び出していません。

回答No.1

流れは追ってません。 パッとみてすぐ怖くなったので、回答。 whileの中で、mallocしてますが、なぜ? 確保した領域は、どこで開放(free())するのでしょう? もう少しフローを固めてから、流してみては如何。

wachi888
質問者

お礼

malloc後に解放するのを忘れてました。色々とあやふやなまま作っているのでおっしゃる通りもう少し考えて作りたいと思います。ありがとうございます。

関連するQ&A

  • あと少しの所なので教えてください><

    C言語で名前と成績を並べるプログラムを書いてみたのですがコンパイラは通るもののうまくいきません><教えて下さい><長いですがそんなに難しくないのでお願いします>< #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct student{ char name[20]; int eng; int math; struct student *next; }lst; lst *root=NULL; void attach(char *n,int e,int m) { lst *newp,*p; newp=(lst *)malloc(sizeof(lst)); if(newp==NULL){ fprintf(stderr,"エラーです\n"); exit(1); } strncpy(newp -> name,n,20); newp -> eng =e; newp -> math=m; newp -> next=NULL; if(root==NULL){ root=newp; } else{ for(p=root;(p ->next)!=NULL;p=p -> next); p -> next=newp; } } void delete(char *n) { lst *p,*tmp; if(root!=NULL){ if(strncmp(root ->name,n,20)==0){ tmp=root -> next; free(root); root=tmp; } else { for(p=root;(p -> next)!=NULL;p= p -> next){ if(strncmp(p->next->name,n,20)==0){ tmp= p->next->next; free(p -> next); p -> next = tmp; break; } } } } } void printlst() { lst *p; if(root==NULL){ printf("リストは空です\n"); } else { p=root; do { printf("名前: %s\n",p->name); printf("英語: %d\n",p->eng); printf("数学: %d\n",p->math); printf("\n"); p=p->next; }while(p!=NULL); } } void insert(char *n,int e,int m) { lst *newp,*p; newp=(lst *)malloc(sizeof(lst)); if(newp==NULL){ fprintf(stderr,"エラー:メモリーの確保に失敗しました。\n"); exit(1); } strncpy(newp->name,n,20); newp->eng=e; newp->math=m; newp->next=NULL; if(strcmp(n,root->name)<=0){ newp->next=root; root=newp; } else { //ここです。 p=newp->next->next; newp->next->next=newp->next; newp=p; } } int main() { root=NULL; attach("alice",80,73); attach("bob",90,80); attach("carol",72,95); attach("dave",82,65); attach("charlie",0,0); delete("bob"); delete("alice"); printlst(); insert("charlie",0,0); } という感じなんですがvoid insertのところで先頭のcarolを入れると大丈夫なんですが2番目以降に入るはずのdaveやcharlieを入れるとBus errorとでてしまうので2番目以降に入れるためのプログラム void insertの//ココです。の所の書き方が間違っているんだと思います。どなたか教えてください><お願いします。 補足 void attachがメンバを書き込むもの。 delateが消去。 void insertが辞書順にするもので、たぶん問題はここの最後です。お願いします><

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

    #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)を数値の順序を乱さないよう にその数値を持つ要素を追加するにはどうすればよいのでしょうか?

  • あと少しの所なので教えてください><

    C言語について質問です。↓のような生徒の名前とテストの点数を表示させるプログラムをつくってほぼできているのですが。。生徒の名前を辞書順、(abc順)にするところで悩んでいます、教えてください。 長くなってますがそんなに難しくはないのでお願いします。 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct student{ char name[20]; int eng; int math; struct student *next; }lst; lst *root=NULL; void attach(char *n,int e,int m) { lst *newp,*p; newp=(lst *)malloc(sizeof(lst)); if(newp==NULL){ fprintf(stderr,"エラーです\n"); exit(1); } strncpy(newp -> name,n,20); newp -> eng =e; newp -> math=m; newp -> next=NULL; if(root==NULL){ root=newp; } else{ for(p=root;(p ->next)!=NULL;p=p -> next); p -> next=newp; } } void delete(char *n) { lst *p,*tmp; if(root!=NULL){ if(strncmp(root ->name,n,20)==0){ tmp=root -> next; free(root); root=tmp; } else { for(p=root;(p -> next)!=NULL;p= p -> next){ if(strncmp(p->next->name,n,20)==0){ tmp= p->next->next; free(p -> next); p -> next = tmp; break; } } } } } void printlst() { lst *p; if(root==NULL){ printf("リストは空です\n"); } else { p=root; do { printf("名前: %s\n",p->name); printf("英語: %d\n",p->eng); printf("数学: %d\n",p->math); printf("\n"); p=p->next; }while(p!=NULL); } } int lexorder(char s1[],char s2[]) { int i; for(i=0;;i++){ if(s1[i]<s2[i]) return(-1); if(s1[i]>s2[i]) return(1); if(s1[i]=='\0'&&s2[i]=='\0') return(0); } } void insert(char *n,int e,int m) { lst *newp,*p; newp=(lst *)malloc(sizeof(lst)); if(newp==NULL){ fprintf(stderr,"エラー:メモリーの確保に失敗しました。\n"); exit(1); } strncpy(newp->name,n,20); newp->eng=e; newp->math=m; newp->next=NULL; if(root==NULL||lexorder(n,root->name<=0)){ newp->next=root; root=newp; }else { //ここです } } int main() { root=NULL; attach("alice",80,73); attach("bob",90,80); attach("carol",72,95); attach("dave",82,65); attach("charlie",0,0); delete("bob"); delete("alice"); printlst(); } int lexorderは並びをかえるためのものでたぶんできていてvoid insertも先頭に入れるプログラムはできたのですが2番目以降に入れるプログラムを//ここです。の所がうまく書けません><教えて下さい><お願いします。

  • C言語の自己参照型プログラムについて

    #include <stdio.h> #include <string.h> #include <stdlib.h> struct list { int key; /* キー */ char name[20]; /* 名前 */ struct list *next; /* 次のデータへのポインタ */ }; struct list *add_list(int key, char *name, struct list *head); void show_list(struct list *p); void free_list(struct list *p); int main(void) { struct list *head; /* 先頭ポインタ */ char name[20]; int key = 0; head = NULL; /* 先頭ポインタにNULLを設定 */ printf("キーと名前(MAX:19文字)を入力(終了:CTRL+Z)\n"); while (scanf("%d %s", &key, name) != EOF) { /* リストにデータを登録 */ head = add_list(key, name, head); } /* リストの表示 */ show_list(head); /* リストの開放 */ free_list(head); return 0; } /*** リストにデータを登録 ***/ struct list *add_list(int key, char *name, struct list *head) { struct list *p; /* 記憶領域の確保 */ if ((p = (struct list *) malloc(sizeof(struct list))) == NULL) { printf("malloc error\n"); exit(EXIT_FAILURE); } /* リストにデータを登録 */ p->key = key; strcpy(p->name, name); /* ポインタのつなぎ換え */ p->next = head; /* 今までの先頭ポインタを次ポインタに */ head = p; /* 新たな領域を先頭ポインタに */ return head; } /*** リストの表示 ***/ void show_list(struct list *p) { while (p != NULL) { /* 次ポインタがNULLまで処理 */ printf("%3d %s\n", p->key, p->name); p = p->next; } } /*** リストの開放 ***/ void free_list(struct list *p) { struct list *p2; while (p != NULL) { /* 次ポインタがNULLまで処理 */ p2 = p->next; free(p); p = p2; } } これを実行すると、 新しく入力された順にリストが表示されます。 そうではなく、キーの昇順に表示したいです。 どなたかそのように実行できるようにプログラムを書き換えてくれませんか? 図々しいですがよろしくお願いいたします。m(_ _)m

  • 連結リストによるデータ管理プログラムの解説

    ★から★までのプログラムが、各行ごとにどのような動きをしているのか簡潔な言葉で説明を書いていただきたいのです。必要がないと判断した行はとばして下さって構いません。 (例) printf("hello!"); …hello!と表示 if(a==0){ …aが0なら #include <stdio.h> #include <stdlib.h> struct CELL{ struct CELL *next; char data; }; /* Head CELL CELL CELL +-------+ +-------+ +-------+ +-------+ | ? | *----> | 5 | *----> | 6 | *----> | 8 | / | +-------+ +-------+ +-------+ +-------+ */ main(void){★ struct CELL head; struct CELL *p, *wp; char a; head.next=NULL; printf("?\n"); scanf("%c %*c",&a); while(a!='0'){ printf("mode?\n"); scanf("%c",&mode); if(mode=="a"){ p=&head; while(p->next!=NULL){ p=p->next; } wp=(struct CELL *)malloc(sizeof(struct CELL)); if(wp==NULL){ printf("cannot allocate enough memory.\n"); return 0; } p->next=wp; p->next->data=a; p->next->next=NULL; printf("?\n"); scanf("%c %*c",&a); } if(mode=="p"){ printf("\n\nNow...\n"); p=&head; while(p->next!=NULL){ printf("%c --> \n",p->next->data); p=p->next; } printf("NULL\n"); if(mode=="d"){ p=&head; while(p->next->data==a){ p=p->next; } if(p==NULL) break; wp=p->next->next; while(p->next->data==a) p=wp;★ } } return 0; }

  • ポインターの繋ぎ換え

    動的に確保した領域にデータを入れ、 入れたデータをソートするプログラムを作っているのですが、 ソートする際に(入力3データ)→[head=p->next]→(入力2データ)→[head=p->next]→(入力1データ)→[head=p->next]と最後まで見た場合に再度先頭に戻る方法が分からないのでご教授お願いします。 ■イメージ head=NULL p 動的な領域の確保(p) (入力1)|no.1|Name1|struct sample *next| p->next = head /* NULLを入れる */ head = p; /* 入力したデータを入れる */ 動的な領域の確保(p) (入力2)|no.2|Name2|struct sample *next| p->next = head /* 前回の[入力1]のデータを入れる */ head = p; /* 入力2で入れたデータを入れる */ 動的な領域の確保(p) (入力3)|no.3|Name3|struct sample *next| p->next = head /* 前回の[入力2]のデータを入れる */ head = p; /* 入力3で入れたデータを入れる */ *現状* (入力3)-(入力2)-(入力1)-NULL ↑最後に入力したデータ (降順にソート後) |no.3|Name3|struct sample *next| 動的な領域の確保 |no.2|Name2|struct sample *next| 動的な領域の確保 |no.1|Name1|struct sample *next| 環境:WinXP-SP3 コンパイラ:VisualC++ExpressEdition2008 使用関数:malloc 以上、宜しくお願いします。

  • 双方向リストのプログラミングのチェック

    指定したファイルを読み込み、一行ずつ構造体に保存し、表示させる。その後、キーボードから指定した行を削除し、処理後の結果を表示させる・・・といったプログラミングを作成しています。 通常の表示の部分はできましたが、後は指定した行の削除の部分ができません。 あらかじめHPで調べてあるので、削除するときは、その削除したい行をまたいで、前後のリストを繋げるといった概念的なのは大体理解できました。 自分なりに考えたり調べて、下のように打ちました。 ですが、キーボードから入力した値をどう関数に対応させていくのか、 delete_head,delete_tailの関数の部分に出る、head,tailは使えない的なエラーの対処の仕方がわからなく、詰まってます。 アドバイス、他にも直す場所等ありましたらお願いします。 #include<stdio.h> #include<stdlib.h> #define LINE 1000 typedef struct num{ char line[LINE]; struct num *next; struct num *prev; }Num; void normal(Num **,Num **,char *); void reverse(Num *,Num *,char *); void delete_head(void); void delete_tail(void); void delete(Num *target); int main(int argc,char *argv[]) { FILE *fp; char line[LINE]; int i=0,j; Num *head,*tail,*p; head=NULL; tail=NULL; fp=fopen("test.txt","r"); if(fp==NULL){ fprintf(stdout,"File not found.\n"); exit(1); } while(fgets(line,LINE,fp)!=NULL) { normal(&head,&tail,line); } p=head; while(p!=tail){ printf("%s\n",p->line); p=p->next; } printf("%s\n",p->line); p=tail; while(p!=head){ printf("%s\n",p->line); p=p->prev; } printf("%s\n",p->line); printf("input number\n"); scanf("%d",&j); p=head; for(i=0;i<=j;i++);{ p=p->next; } if(p==head){ delete_head(void); } else if(p==tail){ delete_tail(void); } else{ delete(p->prev); } p=head; while(p!=tail){ printf("%s\n",p->line); p=p->next; } printf("%s\n",p->line); fclose(fp); return 0; } void normal(Num **s,Num **e,char *g){ Num *tmp; int i; if(*s==NULL){ *s=(Num *)malloc(sizeof(Num)*1); (*e)=(*s); for(i=0;((g[i]!='\0')&&(g[i]!='\n'));i++){ (*s)->line[i]=g[i];} (*s)->next=*e; (*s)->prev=*s; } else{ tmp=(Num *)malloc(sizeof(Num)*1); for(i=0;((g[i]!='\0')&&(g[i]!='\n'));i++){ tmp->line[i]=g[i];} tmp->prev=(*e); (*e)->next=tmp; tmp->next=(*e); (*e)=tmp; } return ; } void reverse(Num *kan1,Num *kan2,char *g){ Num *tmp; int i; tmp=(Num *)malloc(sizeof(Num)*1); for(i=0;((g[i]!='\0')&&(g[i]!='\n'));i++){ tmp->line[i]=g[i];} tmp->prev=kan1; kan1->next=tmp; tmp->next=kan2; kan2->prev=tmp; return ; } void delete_head(void){ Num *second=head->next; if(secound==NULL){ free(head); head=NULL; tail=NULL; } else{ second->prev=NULL; free(head); head=second; } } void delete_tail(void){ Num *second_last=head->prev; if(second_last==NULL){ free(tail); head=NULL; tail=NULL; } else{ second_last->next=NULL; free(tail); tail=second_last; } } void delete(Num *target){ Num *after_target; Num *before_target; after_target=target->next; before_target=target->prev; after_target->prev=target->prev; before_target->next=target->next; free(target); }

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

    双方向リストをバブルソートを用いてソートしたいです。 下記がプログラム(一部)ですが、ソートした後にリスト表示すると 無限ループに陥ります。 どこがいけないのでしょうか。 #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; } } }

  • fclose()でセグメンテーション違反

    C言語でのファイル読み込みで、ファイルを開いてデータを読み込んで表示することはできたのですが、最後のfclose(fp)でセグメンテーション違反になります。一番最後のwhileループをコメントアウトしたところセグメンテーション違反にはならなかったので、ここに何か問題があると思うのですが、どこが悪いのかが分かりません... #include<stdio.h> #include<stdlib.h> main(void){ FILE *fp; int i=0 , j=0 ,cnt = 0 , c=0; char *name="data.txt"; float *buf1,*buf2; if((fp = fopen(name,"r")) == NULL){ printf("error\n"); return 0; } else{ while((c = getc(fp)) != EOF) { if(c == '\n') cnt++; } printf(">>%d<<\n",cnt+1); rewind(fp); buf1 = (float *)malloc( (int)(cnt/2) +1); buf2 = (float *)malloc( (int)(cnt/2) +1); /*ここからがおかしい?*/ while(1){ if( fscanf( fp ,"%f %f",&buf1[i],&buf2[i])==EOF )break; printf("%f %f\n",buf1[i],buf2[i]); i++; } fclose(fp); } return 0; } なぜセグメンテーション違反になっているのでしょうか?

  • ポインタを使った連結リストへの挿入

    siteiで指定されているポインタの直後に要素xを挿入する関数insertをポインタの連結リストを用いて作成したのですが、実行するとセグメンテーション違反がでて上手く動きません。何処に問題があるのでしょうか?topの初期値が不定になるのが問題と思い、topをNULLで初期化して実行してみたのですが、結果は変わりませんでした。 宜しければ回答または問題点を指摘していただけますでしょうか?宜しくお願いします。 typedef struct{ int data; struct DATA *next; }DATA; DATA top; int insert(int x,DATA *sitei) { DATA *p,*buf; p=&top; while( p!=NULL && p!=sitei) p=p->next; buf=malloc(sizeof(DATA)); buf->next=p->next; p->next=buf; buf2->data=x; return 0; }