C - простой связанный список удаляет первый элемент, содержащий 'k' - PullRequest
1 голос
/ 07 мая 2020

Я хочу удалить элемент из простого связанного списка, содержащего «k». Я могу получить «k» в name = popIfK(&kopf);. Теперь в функции popIfK(...) я должен указать на элемент до элемента после. Как мне решить эту проблему?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct V_LISTE
{
    char vorname;
    struct V_LISTE *nachfolger;
};
struct V_LISTE *insert(struct V_LISTE *list, char key)
{
    struct V_LISTE *newElement;
    newElement = (struct V_LISTE *) malloc(sizeof(struct V_LISTE));
    newElement->vorname = key;
    newElement->nachfolger = list;
    list = newElement;
    return list;
}


char popIfK(struct V_LISTE **kopf)
{
    char *returnVal;
    struct V_LISTE *kElement;
    kElement = (*kopf)->nachfolger;
    while (kElement->vorname != 'k')
    {
        kElement = kElement->nachfolger;
    }
    returnVal = &kElement->vorname;
    // Nun muss das Element davor auf das danach zeigen 
    // und Speicher von dem Element mit k muss freigegeben werden
    free(*kopf);
    *kopf = kElement;
    return *returnVal;
}

void ausgabe(struct V_LISTE *list)
{
    while (list != NULL)
    {
        printf("%c", list->vorname);
        list = list->nachfolger;
    }
    printf("\n");
} 

int main()
{
    struct V_LISTE *kopf;
    kopf = (struct V_LISTE *) malloc(sizeof(struct V_LISTE));

    kopf->vorname = 'n';
    kopf->nachfolger = NULL;

    kopf = insert(kopf, 'n');
    kopf = insert(kopf, 'a');
    kopf = insert(kopf, 'k');
    kopf = insert(kopf, ' ');
    kopf = insert(kopf, 'o');
    kopf = insert(kopf, 'l');
    kopf = insert(kopf, 'i');
    kopf = insert(kopf, 'T');

    ausgabe(kopf);
    printf("Nun müsste ein 'k' kommen:\n");
    name = popIfK(&kopf);
    printf("%c\n", name);
    printf("Nun müsste \"Tilo ann\" kommen:\n");
    ausgabe(kopf);
}

Итак, моя проблема заключается в следующем: ausgabe(kopf) дает результат: Tilo kann

После используя функцию name = popIfK(&kopf); со вторым вызовом ausgabe(kopf), я ожидаю вывода: Tilo ann

Но в качестве вывода я получаю: kann

Итак, как я могу решить эту проблему?

Ответы [ 3 ]

0 голосов
/ 07 мая 2020
while (kElement->vorname != 'k')
{
    kElement = kElement->nachfolger;
}

В этом поиске вы также должны сохранить другую переменную, которая следует за kElement. попробуйте что-нибудь вроде этого

{
    follower=kElement;
    kElement=kElement -> nachfolger;
}

таким образом после l oop вы можете изменить follower.

0 голосов
/ 07 мая 2020

Для начала используйте английские sh слова для именования идентификаторов. В противном случае другим программистам будет сложно читать ваш код.

Определение вашей функции, по крайней мере, из-за последнего оператора в этом фрагменте кода

char popIfK(struct V_LISTE **kopf)
{
    char *returnVal;
    struct V_LISTE *kElement;
    kElement = (*kopf)->nachfolger;
    //...

может вызывать неопределенное поведение при вызове функции для пустого списка. Он также вызывает неопределенное поведение, когда список не содержит узла со значением 'k'. Или он даже не будет работать, если это первый узел, содержащий значение 'k'.

Учтите, что вы должны решить, что возвращать из функции, если в списке нет узла со значением 'k'.

Один из подходов - вернуть например символ '\0'.

Если я правильно понял, вам нужно следующее

char popIfK( struct V_LISTE **kopf )
{
    char returnVal = '\0';

    while ( *kopf != NULL && ( *kopf )->vorname != 'k' )
    {
        kopf = &( *kopf )->nachfolger;
    }

    if ( *kopf != NULL )
    {
         returnVal = ( *kopf )->vorname;

         struct V_LISTE *kElement = *kopf;

         *kopf = ( *kopf )->nachfolger;

         free( kElement );
    }

    return returnVal;
}

На мой взгляд, функция не имеет большого смысла. Вы можете написать более общую функцию, которая удаляет из списка узел с заданным символьным значением.

Такая функция может выглядеть следующим образом:

int remove( struct V_LISTE **kopf, char vorname )
{
    while ( *kopf != NULL && ( *kopf )->vorname != vorname )
    {
        kopf = &( *kopf )->nachfolger;
    }

    int success = *kopf != NULL;

    if ( success )
    {
         struct V_LISTE *kElement = *kopf;

         *kopf = ( *kopf )->nachfolger;

         free( kElement );
    }

    return success;
}
0 голосов
/ 07 мая 2020

Вам нужен второй указатель, который следует за одним узлом за kElement. Таким образом, когда вы найдете узел, который хотите удалить, вы можете сделать что-то вроде prev->nachfolger = kElement->nachfolger.

...