• 締切済み

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

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より大きい(あるいは小さい場合)どうすればよいのかを図とか描きながら学習してみては。