1

ここでadd_to_front 関数を使用して sequence_insert_at を実装しようとしています

以前のすべて

typedef struct sequence *Sequence;

別のcファイルから貼り付けられます。

void sequence_insert_at(Sequence s, int pos, int item)
{
    struct node* temp = s->lst;
    for(; pos > 0; --pos)
    {
        temp = temp->rest;
    }
    add_to_front(&temp, item);
    ++s->length;
    if(!temp->rest)
    {
        s->end = temp;
    }
    //s->lst = temp;
}

実行時エラーが発生し続ける理由がわかりません。s->lst のクローンを作成してクローンをトラバースすると、s のノードへのポインターは変更されませんが、temp を変更すると、ノードはすべてまだリンクされているため、s->lst に変更が反映されます。これを修正する方法についてのアイデアはありますか? トラバーサル後の一時の1つ前に別のノードを作成し、それを->rest = tempに設定しようとしましたが、それも失敗しました。

4

1 に答える 1

2

次の間違いを見つけることはできますが、メイン関数を実行するのはこれまでだけです

new_sequence作成するものは何も初期化しませんSequencelstでアクセスすると初期化されませんsequence_insert_at

struct node* temp = s->lst;

ここでどのように見えるべきか

Sequence new_sequence()
{
    Sequence s = malloc(sizeof(struct sequence));
    if(!s)
    {
        printf("Out of memory. Can't allocate s\n");
        exit(EXIT_FAILURE);
    }
    s->lst = malloc(sizeof(struct node));
    if(! s->lst) {
        printf("Out of memory. Can't allocate lst\n");
    }
    s->lst->rest = NULL;
    s->length = 0;
    return s;
}

s->lst->restに設定する必要がありますNULL。これは、リストに要素がなく、end廃止されないことを示しています。

struct sequence
{
    struct node* lst;
    int length;
};

シーケンス内の内部データへのポインタではなく、シーケンス自体を関数に渡す必要があります。

add_to_front(&temp, item);

関数sequence_insert_atは、任意の位置を処理できるものである必要があります。そのため、位置をadd_to_front()使用して呼び出す方が簡単であり、穴の作業を 1 つの関数で実行できます。ここと半分ではありません。0add_to_front()

void sequence_insert_at(Sequence s, int pos, int item)
{
    if(s && pos <= s->length) {
        print_sequence(s);
        struct node *newnode = malloc(sizeof(struct node));
        if (newnode == NULL) {
            printf("ERROR! add_to_front ran out of memory!\n");
            exit(EXIT_FAILURE);
        }
        newnode->first = item;

        struct node* temp = s->lst;
        struct node* prv = NULL;
        for(int i = 0; i < pos; i++) {
            printf("skip %d\n", temp->first);
            prv = temp;
            temp = temp->rest;
        }
        newnode->rest = temp;
        if(pos == 0) {
            printf("insert as first\n");
            s->lst = newnode;
        } else {
            printf("insert before %d\n", temp->first);
            prv->rest = newnode;
        }

        ++s->length;
    }
}

add_to_front必要なステートメントは 1 つだけです

void add_to_front(Sequence s, int item) {
    sequence_insert_at(s, 0, item);
}

リストの後ろに挿入するのと同じように

void add_to_back(Sequence s, int item) {
    sequence_insert_at(s, s->length, item);
}

main 関数を使用した小さなテスト

void print_sequence(Sequence s)
{
    struct node* temp = s->lst;
    for(int i = 0; i < s->length; temp = temp->rest) {
        printf("%d ", temp->first);
        i++;
    }
    printf("\n");
}

int main()
{
    Sequence derp = new_sequence();
    sequence_insert_at(derp, 0, 14);
    add_to_front(derp, 16);
    sequence_insert_at(derp, 0, 17);
    sequence_insert_at(derp, 2, 15);
    add_to_back(derp, 13);
    print_sequence(derp);
    delete_sequence(derp);
    return 0;
}

出力は次のとおりです。

17 16 15 14 13

他の機能を調べて修正する必要があります。

最後に、あなたが選択した変数名は、誤解を招くものではないにしても、少し紛らわしいことに注意してください。私はこのように名前を付けます

typedef struct node {
  int data; /* the data that a node holds */
  struct node* next; /* the pointer to the next node */
} Node_t;

typedef struct sequence {
    struct node* head; /* head or first element of the sequence/list */
    int length; /* length is ok but size is better */
} Sequence_t;
于 2013-03-07T20:41:25.010 に答える