1時間ごとに更新!Amazon.co.jpで今売れている本トップ100   掲示板ランキング



掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板1

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧

No.6106

コンパイルできてもセグメーテンション違反に...
投稿者---きらり(2006/07/10 20:17:29)


始めまして、c言語を勉強し初めて半年くらいになるものです。
リストを使ったプログラムをつくっていて、成績管理プログラムをつくっています。
”arrange_num”でomakeに入っているものを大きいもの順に並べようとしています。”print_r”の関数にまでは入るのですが、”arrange_num”にはいるとセグメーテンションになってしまいます。なにがおかしいのか教えて頂けませんでしょうか。
おかしい関数だけ、添付したのですが、他にいるものがあればおしえてください。

質問は初めてで、質問の仕方も不慣れなので、何か不備がありましたら、教えて頂けると幸いです。

Kyoka *arrange_num(Kyoka *head,Kyoka *new){

  Kyoka *new2;
  Kyoka *p,*q; 
  
  new2= (Kyoka *)malloc(sizeof(Kyoka)); /* 新規にメモリ確保 */
  new2->num = new->num;
  strcpy(new2->num , new->num);
  new2->eng = new->eng;
  new2->math = new->math;
  new2->jpn = new->jpn;
  new2->rika = new->rika;
  new2->syakai = new->syakai;
  new2->omake = new->omake;
  
  new2->next_ptr = NULL ;      /* newの中身をnew2にコピー */
  
  if(head == NULL){   /* 整列後のリストが空なら */
    head = new2;            /* new2 を先頭に */
    head->next_ptr = NULL;
  } else  {    /* 整列後のリストが既にあるなら */
    if(head->omake < new-> omake){      /* 先頭に追加するケース */
      new2->next_ptr = p;      
      head = new2;
    }      
    /* p:整列後のリストの要素へのポインタ */
    /* q:pの次の要素へのポインタ */
    
    p = head;            /* pを先頭にセット */
    while(1){
      q = p->next_ptr;    

    /* qをpの次の要素にセット */
      if(q == NULL){            /* 探したけど pが最後まで来てしまった時 */
    p->next_ptr = new2;  /* new2を最後にする */
    break;
      }else if(new2->omake <= p->omake && new2->omake >=q->omake){
    /* 上のいずれでもないから p q それぞれを1個づつ進めてループの先頭に戻る */
    new2->next_ptr=p->next_ptr;
    p->next_ptr=new2;
    break;
      }
      p=q;
    }
  }
  return  head; 
}

void print_r(Kyoka *head){    /*表示関数 順位順*/
  
  Kyoka *cur,*pri_ptr=NULL,*x;
  int i=1,j=1,p;
  
  if(head == NULL){
    printf("エラー\n");
  }
  printf("narabi\n");
  for(x=head;x!=NULL;x=x->next_ptr){  
    pri_ptr = arrange_num(pri_ptr,x);
  }
  printf("print_r\n");
  cur=pri_ptr;
  while(cur!=NULL){        
    printf("%-3d %-3d %-10s %3d \n",i,cur->num,cur->name,cur->omake);
    p=cur->omake;
    cur=cur->next_ptr;
    j++;
    if(cur->omake!=p)
      i=j;
  }
  delete(pri_ptr);
} 



計算機環境は
gcc (GCC) 4.0.2
Linux で Red Hatです。
長々とすみません。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:コンパイルできてもセグメーテンション違反に... 6107 rvr_driver 2006/07/10 21:25:34
<子記事> Re:コンパイルできてもセグメーテンション違反に... 6108 ruby 2006/07/10 22:33:29
<子記事> Re:コンパイルできてもセグメーテンション違反に... 6109 shu 2006/07/10 22:49:14
<子記事> Re:コンパイルできてもセグメーテンション違反に... 6110 きらり 2006/07/10 23:51:32


No.6107

Re:コンパイルできてもセグメーテンション違反に...
投稿者---rvr_driver(2006/07/10 21:25:34)


Kyokaの定義は何ですか?
ぱっと見た感じではここが怪しい。

new2->num = new->num;
strcpy(new2->num , new->num);

ここは何をしようとしてますか?
Kyokaのメンバであるnumの型は?



この投稿にコメントする

削除パスワード

No.6108

Re:コンパイルできてもセグメーテンション違反に...
投稿者---ruby(2006/07/10 22:33:29)


他に気になるところとしては…
>  new2= (Kyoka *)malloc(sizeof(Kyoka)); /* 新規にメモリ確保 */

new2がNULLの場合の処理を加える方がよいです。

>  if(head == NULL){
>    printf("エラー\n");
>  }

このif文が真の場合、
>  cur=pri_ptr;

pri_ptrはNULLのままです。その状態で
>  delete(pri_ptr);

delete関数の中身はわかりませんが、適切なエラー処理か何かを
行なっておかないとまずいかもしれません。


この投稿にコメントする

削除パスワード

No.6109

Re:コンパイルできてもセグメーテンション違反に...
投稿者---shu(2006/07/10 22:49:14)


//
//	サンプルプログラム
//

//	サンプル構造体
struct list {
    //	データ省略
    int omake;
    struct list *next;
}
typedef struct list LIST;

//
void print_list(LIST *head);	//	表示
LIST *list_sort(LIST *head);	//	並べ替え
void free_list(LIST *head);		//	解放

//////////////
int main(void)
{
    LIST *head = NULL;
    
    //	リスト生成
    //	head = ...	省略
    
    //	普通に表示
    print_list(head);
    
    //	並べ替え
    list_sort(head);
    
    //	並べ替え後の表示
    print_list(head);
    
    //	list_sort()でheadをreturnすれば
    //	こんな風にも書ける
    print_list(list_sort(head));
    
    //	リスト解放
    free_list(head);
    
    return 0;
}


print_r()のなかで、arrange_num()が呼び出されてたり、
arrange_num()のなかで、malloc()してたりしている。
表示は表示、並べ替えは並べ替え、1関数1機能。
はっきり分けたほうがいい。



この投稿にコメントする

削除パスワード

No.6110

Re:コンパイルできてもセグメーテンション違反に...
投稿者---きらり(2006/07/10 23:51:32)


みなさま早いお答えありがとうございます。

>rvr_driverさま
Kyokaは構造体で
typedef struct list{
 int num;
 char name[10];
 int eng;
 /* 以下 int型で定義 */ 
 struct list *next_ptr;
}Kyoka;

となっているのですが、
strcpy(new2->num , new->num);


strcpy(new2->name , new->name);

の間違えです。こんな単純ミスにきがつかなくてすみません。

学校でしかプログラミングができないので明日変えて実行してみます。


>rubyさま
>delete関数の中身はわかりませんが、適切なエラー処理か何かを
行なっておかないとまずいかもしれません。

deleteはリストの解体のための関数です。コメントがぬけていまいした。
リストの解体だけでも、pri_ptrがNULLはまずいのでしょうか?

>shuさま
>arrange_num()のなかで、malloc()してたりしている。

malloc()はどういう場所に入れればよいのでしょうか?
サンプルプログラムありがとうございます。これを元に修正をしてみます。

質問ばっかりすみません。


この投稿にコメントする

削除パスワード

No.6112

Re:コンパイルできてもセグメーテンション違反に...
投稿者---ruby(2006/07/11 08:32:59)


>deleteはリストの解体のための関数です。コメントがぬけていまいした。
>リストの解体だけでも、pri_ptrがNULLはまずいのでしょうか?

delete関数の中身を見せてくだされば、
どこに手を入れればよいかor現状のままでよいかがわかるかもしれません。



この投稿にコメントする

削除パスワード

No.6118

コンパイルできてもセグメーテンション違反に...
投稿者---きらり(2006/07/11 18:15:19)


>delete関数の中身を見せてくだされば、
>どこに手を入れればよいかor現状のままでよいかがわかるかもしれません。

delete関数は
void delete(Kyoka *head_ptr){
  
  Kyoka *cur_ptr, *del_ptr; 
  
  cur_ptr=head_ptr;          /* データの削除*/
  do{ 
    del_ptr = cur_ptr;
    cur_ptr = cur_ptr->next_ptr;
    free(del_ptr);
  } while(cur_ptr != NULL);
}

です。先頭がNULLのことまで考えていなくて、どうしてよいかわかっておりません。

num の所を name に変えてみたのですが、表示までをしたらセグメーテンションになりましたが、
while(1){ 
/*前回と同じなので以下略*/

  if(cur==NULL) /*最後になったので終わる*/
    break;
  if(cur->omake!=p)
    i=j;
}

としたらなおりました。

今は関数を小さく 表示は表示、並べ替えは並べ替え、1関数1機能。
をめざしております。

みなさんに思ったこと以上のことを教えていただき、勉強になっております。ありがとうございす。


この投稿にコメントする

削除パスワード

No.6119

Re:コンパイルできてもセグメーテンション違反に...
投稿者---rvr_driver(2006/07/11 21:56:14)


>今は関数を小さく 表示は表示、並べ替えは並べ替え、1関数1機能。
>をめざしております。

がんばってください。
なぜこのように関数を小さく、1関数1機能にするのか理由も
理解されているのなら言うことはないです。
もし、人から言われたから単にやるというのならあまり意味がないです。

もし余裕があるのなら、このあたりを読んでみるといいかも。
「UNIXという考え方―その設計思想と哲学」
http://www.amazon.co.jp/gp/product/4274064069/249-2398410-8171547?v=glance&n=465392




この投稿にコメントする

削除パスワード

No.6122

Re:コンパイルできてもセグメーテンション違反に...
投稿者---きらり(2006/07/11 23:29:46)


>なぜこのように関数を小さく、1関数1機能にするのか理由も
>理解されているのなら言うことはないです。
>もし、人から言われたから単にやるというのならあまり意味がないです。

そう言われてみると、人に言われているからという理由で関数を小さくしている気がします(^^;
理由...私は長いと見にくいしわかりづらいので、関数にするようにしています。
ですが、未熟なので色々な機能を一度に扱うようになるとどれが一つの機能かわからなくなり、煩雑になり上のようになってしまします。
ただ、上のサンプルプログラムをもとにすこし小さくなりました。
ただarrange_numは一つも手を出せないのですがもう少し小さくできるでしょうか?

>もし余裕があるのなら、このあたりを読んでみるといいかも。
>「UNIXという考え方―その設計思想と哲学」

お勧めありがとうございます。夏休みによませていただきます。
色々な本がたくさんあるので薦めて頂いてうれしいです。



この投稿にコメントする

削除パスワード

No.6129

Re:コンパイルできてもセグメーテンション違反に...
投稿者---rvr_driver(2006/07/12 21:22:25)


>理由...私は長いと見にくいしわかりづらいので、関数にするようにしています。
>ですが、未熟なので色々な機能を一度に扱うようになるとどれが一つの機能かわからなくなり、煩雑になり上のようになってしまします。

考え方はいいと思います。
まだ利点はありますが、話がずれてしまうので止めておきます。

>ただ、上のサンプルプログラムをもとにすこし小さくなりました。
>ただarrange_numは一つも手を出せないのですがもう少し小さくできるでしょうか?

できます。なぜ一つも手を出せないのですか?
・arrange_numを機能分割できない。
・機能分割はできても関数にすることができない。
など想像できますが、きらりさんの質問の答えはshuさんのサンプルプログラムにあります。
上記の考えを持っていらっしゃるのであれば、あとはきらりさんでいろいろ考えてみてください。

考えた結果を報告していただければ、識者の方からアドバイスしてもらえると思います。


この投稿にコメントする

削除パスワード

No.6131

Re:コンパイルできてもセグメーテンション違反に...
投稿者---きらり(2006/07/13 00:53:10)


>do〜whileを使って実装しているのがまずいと思います。
>引数head_ptrがNULLの場合、cur_ptrもNULLとなり、
>do〜whileループの中でcur_ptr->next_ptrを得ようとしたときに落ちるでしょう。

よくわかりました。
whileでループさせて、whileのトップにif文で(cur_ptr==NULL)の条件式でループを抜けるようにしました。
そもそも、上ででdelete関数のことについて触れられたというのは、
print_r関数ではループでdelete関数に入るときはNULLになっているということを仰られていたのにようやく気づきました。
運がよかったのかshuのサンプルプログラムのように早くからdeleteは実行前(動く前)にprint_rからだしたので気づきませんでした。

>できます。なぜ一つも手を出せないのですか?
>・arrange_numを機能分割できない。
>・機能分割はできても関数にすることができない。
>など想像できますが、きらりさんの質問の答えはshuさんのサンプルプログラムにあります

私はshuさんのコメントからなんとなくarrange_numは機能分割できる気がしてたのですが機能分割がよくできませんでしたが、なんとかつくってみました。

void make(Kyoka *new2,Kyoka *new){

  new2->num = new->num;
  strcpy(new2->name , new->name);
  new2->eng = new->eng;
/*以下略*/
 new2->next_ptr = NULL ; 
}

Kyoka *arrange_num(Kyoka *head,Kyoka *new){

  Kyoka *new2;

 if((new2= (Kyoka *)malloc(sizeof(Kyoka)))==NULL){
    printf("エラー\n"); 
    return head;
  }

  make(new2,new);

 /*以下略*/

return head;
}

という感じになりました。

>new2がNULLの場合の処理を加える方がよいです。

とあったのでnew2がNULLの場合をつくったのですが、そもそもnew2にNULLが入ることはないきがしましたがきっと何か別の意図があるのだろうと思いますし、
私がやってることは違う自信はあるのですが、ここでギブです。

return head;が二つもあるのはおかしいですよね。。。



この投稿にコメントする

削除パスワード

No.6133

Re:コンパイルできてもセグメーテンション違反に...
投稿者---ruby(2006/07/13 08:28:57)


>>new2がNULLの場合の処理を加える方がよいです。
>
>とあったのでnew2がNULLの場合をつくったのですが、そもそもnew2にNULLが入ることはないきがしましたがきっと何か別の意図があるのだろうと思いますし、

malloc系の関数を使って動的メモリー確保を行なう際、
何らかのエラーによって確保ができなかった場合(NULLが返ってくる)に
備えるのは必須です。

実際にNULLが返ってくることがどのくらいの頻度で生じるかは
よくわかりませんが、安定して動作するプログラムを書くための
お約束であるとお考えください。


この投稿にコメントする

削除パスワード

No.6134

Re:コンパイルできてもセグメーテンション違反に...
投稿者---shu(2006/07/13 09:58:51)


>whileでループさせて、whileのトップにif文で(cur_ptr==NULL)の条件式でループを抜けるようにしました。

必要無い。
whileの条件が、(cur_ptr != NULL)なので、
(cur_ptr==NULL)という条件では、whileループに入らないから。

//	
//	サンプルプログラム2
//	

//	リストの表示
void print_list(LIST *head)
{
    LIST *p;
    
    for (p = head; p != NULL; p = p->next) {
        printf(/*省略*/);
    }
}

//	リストの並べ替え(未完成版)
LIST *list_sort_test(LIST *head)
{
    LIST *p, *q;
    
    for (p = head; p->next != NULL; p = p->next) {
        for (q = p->next; q != NULL; q = q->next) {
            //	比較する二つの値を表示
            printf("%d VS %d\n", p->omake, q->omake);
        }
    }
    return head;
}

//	リストの解放
void free_list(LIST *head)
{
    LIST *p, *q;
    
    for (p = head; p != NULL; p = q) {
        q = p->next;	//	free()の前に、退避。
        free(p);
    }
}


>私はshuさんのコメントからなんとなくarrange_numは機能分割できる気がしてたのですが機能分割がよくできませんでしたが、なんとかつくってみました。

arrange_numを機能分割するのではなく、
arrange_numにarrange_numという機能を持たせる。
arrange_numとは、どういう機能なのか?


この投稿にコメントする

削除パスワード

No.6143

コンパイルできてもセグメーテンション違反に...
投稿者---きらり(2006/07/13 18:48:16)


>必要無い。
>whileの条件が、(cur_ptr != NULL)なので、
>(cur_ptr==NULL)という条件では、whileループに入らないから。

そうですよね。たしかにそうでした。
ありがとうございます。

>arrange_numを機能分割するのではなく、
>arrange_numにarrange_numという機能を持たせる。
>arrange_numとは、どういう機能なのか?

やっと、意味がわかりました。arrange_numは並び変えなので並び変えだけにすればよっかったのですね。
本当に何度も何度も同じことを言っていただいてたのになかなか理解できずにすみませんでした。

>malloc系の関数を使って動的メモリー確保を行なう際、
>何らかのエラーによって確保ができなかった場合(NULLが返ってくる)に
>備えるのは必須です。

そうだったのですか、今度からはmalloc系の関数を使うときは忘れず使うようにします。

なかなか理解せず、的外れのことばかりする私を見捨てず、長々と教えて頂ありがとうございました。
そもそも最初の質問からずれて、関数化のことに移ってしまいましたね(^^;

また、C言語でわからないことがあった時また質問させていただく時がありましたら、またよろしくお願いします。
ただし、今回のような単純ミスはしないよう頑張ります。

では、rvr_driverさま、rubyさま、shuさま、本当にありがとうございました。


この投稿にコメントする

削除パスワード

No.6152

Re:コンパイルできてもセグメーテンション違反に...
投稿者---shu(2006/07/14 12:40:48)


>やっと、意味がわかりました。arrange_numは並び変えなので並び変えだけにすればよっかったのですね。
>本当に何度も何度も同じことを言っていただいてたのになかなか理解できずにすみませんでした。

もう一回、shuの最初の返信のサンプルプログラム以外の部分を読んでもらえればありがたい。


この投稿にコメントする

削除パスワード

No.6123

Re:コンパイルできてもセグメーテンション違反に...
投稿者---ruby(2006/07/12 00:56:29)


>void delete(Kyoka *head_ptr){
>  
>  Kyoka *cur_ptr, *del_ptr; 
>  
>  cur_ptr=head_ptr;          /* データの削除*/
>  do{ 
>    del_ptr = cur_ptr;
>    cur_ptr = cur_ptr->next_ptr;
>    free(del_ptr);
>  } while(cur_ptr != NULL);
>}




この投稿にコメントする

削除パスワード

No.6124

Re:コンパイルできてもセグメーテンション違反に...
投稿者---ruby(2006/07/12 00:57:25)


>void delete(Kyoka *head_ptr){
>  
>  Kyoka *cur_ptr, *del_ptr; 
>  
>  cur_ptr=head_ptr;          /* データの削除*/
>  do{ 
>    del_ptr = cur_ptr;
>    cur_ptr = cur_ptr->next_ptr;
>    free(del_ptr);
>  } while(cur_ptr != NULL);
>}

do〜whileを使って実装しているのがまずいと思います。
引数head_ptrがNULLの場合、cur_ptrもNULLとなり、
do〜whileループの中でcur_ptr->next_ptrを得ようとしたときに落ちるでしょう。


この投稿にコメントする

削除パスワード

No.6125

Re:コンパイルできてもセグメーテンション違反に...
投稿者---ruby(2006/07/12 00:59:10)


No.6123は投稿ミスです。申し訳ありません。
なお、「セグメーテンション」ではなく「セグメンテーション」です。


この投稿にコメントする

削除パスワード

No.6132

Re:コンパイルできてもセグメーテンション違反に...
投稿者---きらり(2006/07/13 01:07:06)


>なお、「セグメーテンション」ではなく「セグメンテーション」です。

ありがとうございます。タイトルにしてるというのがなおいっそう痛いですね・・・


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧





掲示板提供:(有)リアル・インテグリティ