2012-04-11 24 views
0

中のリストは私が最初のものは先頭のセグメンテーションフォールトがへの最初のものを利用することになっている含まれている二番目の要素を追加し、私は2つの機能を使用してリンクリストに入力し、直接数字をソートするために試してみました仕事をしなさい。ここでセグメンテーションフォールトは、C

#include <stdio.h> 
#include <stdlib.h> 
typedef struct cellule 
{ 
    int val; 
    struct cellule *suivant; 
} cellule; 
typedef struct cellule* liste; 

liste insert_tete(liste L,int n) 
{ 

    liste p; 

    p=malloc(sizeof(cellule)); 
    p->val=n; 
    p->suivant=L; 
    return p; 
}//ok :) 
liste insert_croissant(liste L,int n) 
{ 
    if(!L) 
    { 
     L=insert_tete(L,n); 
     return L; 
    } 

    liste p,q; 
    for(q=L,p=L; (p!=NULL)&&(n> (p->val)) ; q=p,p=p->suivant); // 

    p=insert_tete(p,n); 
    q->suivant=p; 
    return L; 
} 
+3

は、読みやすくするために、あなたのコードを再フォーマットしてください。 –

+4

'insert_croissant()'がおいしい! – FatalError

+3

がありそうする理由はありません、それは実際にあなたがキャストせずに( '' を含めるのを忘れているという事実を隠すことができますCのmalloc関数の戻り値をキャストしないでください、nonexistant関数は 'int'を返すことが暗示されます、それは失敗するが、キャストはそれを隠す)。 Cは 'void *'を他のポインタ型に暗黙的に強制することに問題はありません。 –

答えて

0

コードには、特定のケースでリストが破損する可能性があるという問題があります。リストを適切に終端されていない状態にすることは簡単です(そして、リストからノードを失う可能性もあります)。その状況は、他のコードがどのようにリストを操作するかによって問題を引き起こす可能性があります。

空ではない新しい値を新しいノードに追加しようとすると、新しい値が最初のノードの値以下であれば、リストは2つのノードを持つ循環リストになります。リストの先頭にあったノードの後のノードはすべて失われます。

この場合、insert_tete(p,n)が呼び出されたときにpqの両方がそのノードを指しているため、これが発生します。 insert_tete(p,n)が返された後、p-suivantqはリストの先頭にあるノードを指します。したがって、

q->suivant = p; 

が実行されると、リストは循環し、「余分な」ノードが失われます。あなたの他の操作は、リストに作用する方法に応じて

、(特に場合は/あなたは要素を削除する方法)あなたは(セグメンテーション違反を引き起こす可能性がある)suivantフィールドに残ってダングリングポインタで自分自身を見つける、またはで終わる可能性無限ループ。

+0

ありがとう、私はコードが完全に機能している:) – orangepixel

1
liste insert_croissant(liste L,int n) 
{ 
    if(!L) 
    { 
     L=insert_tete(L,n); 
     return L; 
    } 

我々はLがここに正当なセグメンテーションフォルトを取得するための唯一の方法はpは、以下のポインタの一つはdoesnの非0のポインタであるということであるNULL

liste p,q; 
    for(q=L,p=L; (p!=NULL)&&(n> (p->val)) ; q=p,p=p->suivant); // 

ではないことを知っています適切に割り当てられたstruct celluleを指していますが、アクセスできないメモリがあります。次に、p->val(またはp->suivant)にアクセスしようとすると、segfaultが発生します。そのような状況に入るために

(私の限られた経験では)最も一般的な方法は、決して0

2

への最初のポインタを初期化するために忘れている私は、これはそれを修正します信じていないが、少なくとも1つはそこにありますあなたのコードのバグ。

は、Lが初期化される場合を考えるが、N < L->ヴァル:ポインタへのポインタを使用して

// p = L, q = L; 
// Let L = [val|->... 
p=insert_tete(p,n); 
// p = [n|->[val|->... 
q->suivant=p; 
// q = L 
// Therefore [val|->[n|->L 
// And you've just made your linked list circular. 
+0

あなたはそうです。 insert_tete()はp-> suivant = pを設定します。さらに、pを指すポインターは更新されないので、qサブチェーンはpチェーンから切り離されます。 – wildplasser

+0

余分な答えは申し訳ありません - 私は実際にコメントする特権を持つために十分なアクティブされていません... – Michael

+0

いいえ、それは優れています。私は10分間それを勉強した後でそれを見つけることができませんでした。問題は、周囲に浮かぶエイリアスが多すぎることです。 (私は登録されていないので投票できません)**親に投票してください!** – wildplasser

0

簡易版。注:空のリストには特別なケースはありません。

struct cellule { 
    int val; 
    struct cellule *suivant; 
    }; 

struct cellule *insert_croissant(struct cellule **LL, int val) 
{ 

    struct cellule *p,**pp; 

    for(pp=LL ; *pp && (*pp)->val < val ; pp = &(*pp)->suivant) {;} 
     /* When we arrive here, pp points to whatever pointer happens 
     ** to point to our current node. 
     ** - If the list was empty, *pp==NULL 
     ** - if the place to insert happens to be the tail of the list, *p is also NULL   
     ** - in all cases, *pp should be placed after the new node, and the new node's pointer should be assigned to *pp 
     */ 
    p = malloc(sizeof *p); 
    p->val = val; 
    p->suivant = *pp; 
    *pp = p; 

    return *LL; 

} 
+0

これははるかに優れています。その場合、頭に挿入する既存の関数を使うのは良い考えではありません、ありがとう! – orangepixel

関連する問題