• 締切済み

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

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が辞書順にするもので、たぶん問題はここの最後です。お願いします><

みんなの回答

回答No.3

今日は土曜日、一杯飲みながら解答を作ってみました m(_ _)m  失礼ですが、何故そのように難しく考えるのでしょう? UNIXユーザは、先にデータファイルを作成し、取り込むようにすると作業が簡単になると同時に、エディタで後からデータファイルを書き換えできることから保守管理が容易な次のような使い方をします。 1.データファイル(data_file)を作る。   シェル・プロンプトから echo コマンドでリダイレクトする。   echo alice 80 73, bob 90 80, carol 72 95, dave 82 65, charlie 0 0 | tr , "\n">data_file 2.データファイルの内容を確認する。   cat data_file 3.データファイルを取り込んで名前等を出力する。   ./ufo<data_file 4.データファイルの修正はエディタを使う。   先のデータファイルをテンプレート・ファイルとして別ファイル名で更新する(過去のファイルを残すようにする)。 /* ufo.c program *  execution: ./ufo<data_file *  compile:  gcc ufo.c -o ufo */ #include <stdio.h>    /* for scanf() */ #include <string.h>    /* for strcmp() */ #define MEMBER 50  /* number of students */ struct set1 {  char name[20];  int eng;  int math; }students[MEMBER]; int n; void printlst(void); void data_scan(void); /* ソースは見易い topdown を心掛ける */ int main(void) {  data_scan(); // データ取り込み  printlst();  // 内容の出力  return 0; } void data_scan(void) {  n = 0;  scanf("%s %d %d", students[n].name, &students[n].eng, &students[n].math);  while(!feof(stdin)) {   n += 1;   scanf("%s %d %d", students[n].name, &students[n].eng, &students[n].math);  }  if (strcmp(students[n].name, "") == 0) // 末尾補正   n -= 1; } void printlst(void) {  int i;  for (i = 0; i <= n; i++) {   printf("name: %s\n", students[i].name);   printf("eng : %d\n", students[i].eng);   printf("math: %d\n", students[i].math);   printf("\n");  } }

  • zuntac
  • ベストアンサー率36% (45/124)
回答No.2

最後の辞書順に追加する部分を書いてみました。 同じ名前でも登録する方法になっています。 バグがある(かも)しれませんが参考になれば幸いです。 p = root; prev_p = NULL; do { if (strcmp(p->name, newp->name) >=0) { if (prev_p == NULL) root = newp; else prev_p->next = newp; newp->next = p; break; } else if (p->next == NULL) { p->next = newp; newp->next = NULL; break; } prev_p = p; p=p->next; } while(p != NULL);

  • osamuy
  • ベストアンサー率42% (1231/2878)
回答No.1

>newp->next=NULL; として、elseで >newp->next->next; ――としているから、NULLポインタ参照でエラーになってます。 リンクリスト形式のポインタ操作は古典的なプログラミングネタなので、教科書とか参考サイトとか調べてみては。 >void insertが辞書順にするもの strcmpで1回比較するだけでは足りないかと。aliceより小さければ問題ないけど、bobより大きい(あるいは小さい場合)どうすればよいのかを図とか描きながら学習してみては。

関連するQ&A

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

    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番目以降に入れるプログラムを//ここです。の所がうまく書けません><教えて下さい><お願いします。

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

    #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関数は途中です。

  • 検索機能

    名簿管理システムとしてメンバの追加、メンバの削除、メンバリストを名前順(アルファベット昇順)で表示、メンバリストのファイル出力 引数としてファイルパスを指定することによるメンバ初期データの読込ができるプログラムを以下のように作成しました。 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> typedef struct tagNode{ int no; char name[30]; struct tagNode *next; }Node; Node *ApndNode(Node *top, int no, char *name) { if(top == NULL){ top = (Node*)calloc(1, sizeof(Node)); top->no = no; strcpy(top->name, name); top->next = NULL; }else{ if(strcmp(top->name, name) > 0){ Node *p = (Node*)calloc(1, sizeof(Node)); p->no = no; strcpy(p->name, name); p->next = top; top = p; }else{ top->next = ApndNode(top->next, no, name); } } return top; } Node *DltNode(Node *top, int no, char *name) { if(top != NULL){ if(top->no == no && !strcmp(top->name, name)){ Node *p = top->next; free(top); top = p; }else{ top->next = DltNode(top->next, no, name); } } return top; } void PrintList(Node *top) { if(top != NULL){ printf("%-10d %s\n", top->no, top->name); PrintList(top->next); } } void PrintFile(Node *top) { FILE *fp; char file_name[256]; Node *p = top; printf("file name : "); scanf("%s", file_name); fp = fopen(file_name, "w"); if(!fp) return; while(p != NULL){ fprintf(fp, "%d %s\n", p->no, p->name); p = p->next;} fclose(fp); } void FreeList(Node *top) { while(top != NULL){ Node *p = top->next; free(top); top = p; } } int main(int argc, char *argv[]) { Node *top = NULL; int no, op; char name[30]; while ((op = getopt(argc, argv, "f:")) != -1){ switch (op){ case 'f': do{ FILE *fp = fopen(optarg, "r"); if(!fp) break; while(fscanf(fp, "%d%s", &no, name) == 2) top = ApndNode(top, no, name); fclose(fp); }while(0); } } while(1){ printf("--------command--------\n"); printf("1.Append\n2.Delete\n3.Show\n4.Save\n5.Quit\n"); printf("-----------------------\n"); printf("op : "); scanf("%d", &op); if(op == 5) break; switch(op){ case 1: printf("no : "); scanf("%d", &no); printf("name : "); scanf("%s", name); top = ApndNode(top, no, name); break; case 2: printf("no : "); scanf("%d", &no); printf("name : "); scanf("%s", name); top = DltNode(top, no, name); break; case 3: printf("=========list==========\n"); printf("<no> <name>\n"); PrintList(top); printf("=======================\n"); break; case 4: PrintFile(top); break; } } FreeList(top); 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; } } }

  • ポインタ

    #include<stdio.h> #include<stdlib.h> struct number{ int value; struct number *next; }; int main(void){ FILE *f; struct number *p; int n=0,i; f=fopen("number.txt","r"); p=malloc(sizeof(struct number)); if(p==NULL){ printf("error"); return 1; } while(fscanf(f,"%d",&(p+n)->value)!=EOF){ (p+n)->next=malloc(sizeof(struct number)); if(p+n==NULL){ printf("error"); return 1; } p+n=(p+n)->next; n++; } for(i=0;i<n;i++) printf("%d\n",(p+i)->value); free(p); fclose(f); return 0; } のp+n=(p+n)->next;の部分でバグが出てしまうのですがアロー演算子と通常の演算子を同時に使うことができないなどのような規則があるのでしょうか、それとも俺がバカなだけなのでしょうか?ご指摘お願いします。

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

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

  • リンクリストのコンパイルができない

     OS windows7 microsoft visualC++ 2010 Expless 新規作成→ win32コンソールアプリケーション→からのプロジェクト→完了 追加 →新しい項目 でコンパイルしても(addData識別子が見つかりませんでしたと表示 されます (C++がintを設定値としてサポートしていませんとエラー)がでてしまいます 多分ソース自体は何度も見直しているので問題が ないとは思うのですが設定の方が間違えているのかもしれません どなたか理由が分かる方お教えください #include <stdio.h> #include <malloc.h> #include<string.h> typedef struct _STRLIST{ int id; char name[128]; struct _STRLIST *next; } STRLIST; void enterData(STRLIST *); void listData(STRLIST *); STRLIST *getDate(STRLIST *, int); STRLIST *getLastData(STRLIST *); STRLIST *addDate(STRLIST *,STRLIST *); STRLIST *insertData(STRLIST *, int, STRLIST *); STRLIST *deleteData(STRLIST *, int); STRLIST *clearData(STRLIST *); main() { STRLIST *listtop = NULL; STRLIST inputData; int index; char cmd[20] =""; STRLIST testdata[3] = {{1, "Ichiro"},{2, "Jiro"},{3, "Saburo"}}; listtop = addData(listtop, testdata); listtop = addData(listtop, testdata+1); listtop = addData(listtop, testdata+2); printf("[Linked-List Test]\n"); printf("command=list/add/insert/delete/clear/guit\n"); while(strcmp(cmd,"guit") !=0){ printf("command:"); scanf("%s", cmd); if(strcmp(cmd,"list") == 0) { listData(listtop); } else if(strcmp(cmd, "add") ==0){ enterData(&inputData); listtop = addData(listtop, &inputData); } else if(strcmp(cmd,"insert") ==0) { printf("何番目のあとに挿入しますか:"); scanf("%d", &index); enterData(&inputData); listtop= insertData(listtop,index,&inputData); } else if (strcmp(cmd,"delete") ==0){ printf("何番目のデータを削除しますか:"); scanf("%d",&index); listtop =deleteData(listtop,index); } else if(strcmp(cmd,"clear")== 0) { listtop=clearData(listtop); } } listtop=clearData(listtop); } void enterData(STRLIST *p) { printf("追加するデータを入力してください\n"); printf("id:"); scanf("%d",&(p->id)); printf("name:"); scanf("%s", &(p->name)); } void listData(STRLIST *p) { int i= 1; printf("No. data\n---- ----\n"); while (p !=NULL){ printf("04d id=%d name=%s\n", i, p->id, p->name); p = p->next; i++; } } STRLIST *getData(STRLIST *p,int index) { int i; if(index <1) return NULL; for(i=1; i<index; i++){ p=p->next; if(p ==NULL && i<index) return NULL; } return p; } STRLIST *getLastData(STRLIST *p) { if(!p) return NULL; while (p->next !=NULL) p= p->next; return p; } STRLIST *addData(STRLIST *listtop, STRLIST *newdata) { STRLIST *newitem, *p; p=getLastData(listtop); newitem =(STRLIST *)malloc(sizeof(STRLIST)); newitem->id=newdata->id; strcpy (newitem->name, newdata->name); newitem->next =NULL; if(p == NULL) return newitem; p->next=newitem; return listtop; } STRLIST *insertData(STRLIST *listtop, int index,STRLIST *newdata) { STRLIST *p, *newitem; p =getData(listtop,index); newitem=(STRLIST *)malloc(sizeof(STRLIST)); newitem->id =newdata->id; strcpy(newitem->name, newdata->name); if(p == NULL) { newitem->next =listtop; return newitem; } newitem->next =p->next; p->next =newitem; return listtop; } STRLIST *deleteData(STRLIST *listtop, int index) { STRLIST *previtem, *delitem, *nextitem; if(index < 1 || listtop ==NULL) return listtop; if(index ==1){ delitem =getData(listtop, index); nextitem =delitem->next; free(delitem); return nextitem; } previtem =getData(listtop, index-1); delitem =previtem->next; nextitem =delitem->next; free(delitem); previtem->next =nextitem; return listtop; } STRLIST *clearData(STRLIST *p) { while(p) p = deleteData(p, 1); return p; }

  • 二分探索木

    下のプログラムはコンパイルはできたのですが、実行すると「セグメンテーション違反です」とでました。デバッガをしてみたら、 Program received signal SIGSEGV, Segmentation fault. 0x080483e8 in inorder (root=0x0) at nibun.c:12 12 inorder(root->llink); と表示されましたが解決方法が分かりません。どのように直せば、エラーを出さずに実行できるようになるか教えてください。 #include<stdio.h> #include<stdlib.h> typedef struct node *NodeP; typedef struct node { int data; NodeP llink, rlink; } Node; void inorder(NodeP root) { inorder(root->llink); printf(" %d", root->data); inorder(root->rlink); } NodeP newNode(int val) { NodeP newp = (NodeP) malloc (sizeof(Node)); newp->data = val; newp->llink = NULL; newp->rlink = NULL; return newp; } void insert(NodeP *root, int val){ NodeP curr,prev; if(*root == NULL) *root = newNode(val); else{ curr = *root; do{ prev = curr; if ( val < curr->data) curr = curr->llink; else if ( val > curr->data) curr = curr->rlink; else return; }while(curr!= NULL); if(val > prev->data){ prev->llink = newNode(val); } else{ prev->rlink = newNode(val); } } } NodeP createBSTree(void){ int i,n,val; NodeP root=NULL; printf("Number of Nodes:"); scanf("%d",&n); for (i=1;i<=n;i++){ printf("Node[%d]: ",i); scanf("%d",&val); insert(&root,val); } return root; } int main(){ NodeP root=NULL; root = createBSTree(); inorder(root); printf("\n"); return 0; }

  • リストがわかりません。

    下のプログラムはリストに昇順になるように 入力された要素を挿入するプログラムですが、うまくいきません。どうか教えてください。 #include<stdio.h> static int count; struct node_tag{ int data; struct node_tag *next; }; typedef struct node_tag node_t; node_t *insert_node( node_t *t, int d ); node_t *print_list( node_t *r ); int main( void ) { node_t root; int data; root.next = NULL; for ( ;; ) { printf( "> " ); if ( scanf( "%d", &data ) != 1 ) break; insert_node( &root, data ); print_list( &root ); } return; } node_t *insert_node( node_t *t, int d ) { node_t *new_node; new_node = (node_t *)malloc( sizeof(node_t) ); if( new_node == NULL ) return NULL; if(count == 0) { new_node -> data = d; new_node -> next = NULL; t -> next = new_node; count++; } else { for(; t -> next != NULL; t = t -> next) { if(t -> next -> data >= d) break; } if(t -> next -> data == d) return; else if(t -> next -> data > d) { new_node -> data = d; new_node -> next = t -> next; t -> next = new_node; } else if(t -> next == NULL) { new_node -> data = d; t -> next = new_node; new_node -> next = NULL; } } return new_node; } node_t *print_list( node_t *r ) { node_t *p; printf("[ "); for( p = r -> next; p != NULL; p = p -> next) { printf("%d ", p -> data); } printf("]\n"); }

  • ハッシュ法が得意な人お願いします。

    辞書検索プログラムが実行できません。どこがおかしいか教えてください。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define BUCKET_SIZE 100 typedef struct pointer { struct cell *chain; }pointer; struct cell{ char eng[20]; char jp[40]; struct cell *next; } table[BUCKET_SIZE]; int n; void read_dic(); void init_table(); int hash(char *tango); void main(); struct cell *find(char *tango); struct pointer bucket[BUCKET_SIZE]; void init_table() { int i; for (i=0;i<BUCKET_SIZE;i++){ strcpy(table[i].eng,"0"); strcpy(table[i].jp,"0"); } } void main() { int m; struct cell *p; char tango[20]; read_dic(); while(1){ printf("\n単語を入力: "); scanf("%s", tango); if (strcmp(tango, "*") == 0){ printf("検索を終了\n"); exit(0); } if((p= find(tango)) == NULL) printf("単語は見つかりませんでした\n"); else printf("訳語: %s \n", table[p].jp); } } まだ続きます。。。