0

最初の関数は先頭に要素を追加し、セグメンテーション違反を含む2番目の関数は、最初の関数を悪用してジョブを実行することになっています。

#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;
}
4

4 に答える 4

2

これで問題が解決するとは決して思いませんが、あなたのコードには少なくとも 1 つのバグがあります。

L が初期化されているが、n < L->val の場合を考えてみましょう。

// 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.
于 2012-04-11T23:02:43.267 に答える
1
liste insert_croissant(liste L,int n)
{
    if(!L)
    {
        L=insert_tete(L,n);
        return L;
    }

Lここで、そうではないことがわかりますNULL

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

ここで正当な segfault を取得する唯一の方法は、ポインタの 1 つが、適切に割り当てられたではなく、アクセスできないメモリをp指す 0 以外のポインタであることです。その後、 (または)struct celluleアクセスしようとすると、segfault が発生します。p->valp->suivant

そのような状況に陥る最も一般的な方法 (私の限られた経験では) は、最初のポインターを 0 に初期化するのを忘れることです。

于 2012-04-11T22:46:58.330 に答える
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;

}
于 2012-04-11T23:19:51.863 に答える
0

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

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

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

q->suivant = p;

が実行されると、リストは循環し、「余分な」ノードは失われます。

他の操作がリストに対してどのように動作するかによって (特に要素を削除する場合/どのように削除するか)、suivantフィールドにダングリング ポインターが残っている (セグメンテーション違反が発生する可能性がある) か、無限ループに陥る可能性があります。

于 2012-04-11T23:21:45.043 に答える