删除链表中的元素,直到我找到单词

时间:2016-01-10 14:28:58

标签: c variables linked-list

我在删除列表中的元素时遇到问题

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

#define MAX 30

typedef struct elem{

    char name[MAX];
    int statistic;
    int price;

    struct elem *next;
    struct elem *prev;

} shop; 

我创建了一个函数,在列表中搜索一个在main中定义的单词,然后如果找到它,它会一直删除1 st 元素,直到它找到该单词,然后删除所选单词,然后将其作为第一:

void delete_from_list(shop *first, char word[MAX], int* check)
{
    shop *tmp= first;
    while (tmp!=NULL && strcmp(tmp->name, word) != 0)
    {
        tmp = tmp->next;
    }

    if (tmp != NULL && strcmp(tmp->name, word)==0)
    {
        printf("FOUND!");
    }
    else
    {
        *check=1;
    }
    if (check==0)
    {
        while (strcmp(first->name, tmp->name)!=0)
        {
            first=first->next;
            free(first->prev);
            first->prev=NULL;
        }
        first=first->next;
        free(first->prev);
        first->prev=NULL;
    }
}

void print_list(shop *first)
{
    first=first->next;

    if(first->name==NULL)
        printf("There is nothing!!!\n");

    while(first->next!=NULL){

        printf("%20s",first->name);
        printf("%20d \t\t",first->statistic);
        printf("%d\n",first->price);

        first=first->next;
    }

}

我打印清单然后说话。

main()
{
    int check = 0;

    print_list(first);
    scanf("%s", word);

    delete_from_list(first, word, &check);

    if (check!=1)
    {
        print_list(first);
    }
    else
    {
        check=0;
    }
}

问题是链表没有变化,所以我应该添加指针,但我不知道如何。

2 个答案:

答案 0 :(得分:1)

您必须通过引用传递指针first

此功能也有错误。找到的元素之后的下一个元素可以等于NULL。在这种情况下这些陈述

    first=first->next;
    free(first->prev);
         ^^^^^^^^^^^
    first->prev=NULL;
    ^^^^^^^^^^^

导致未定义的行为。

该功能可以按以下方式编写

void delete_from_list( shop **first, const char *word, int *check )
{
    shop *tmp = *first;

    while ( tmp!=NULL && strcmp( tmp->name, word ) != 0 )
    {
        tmp = tmp->next;
    }

    if ( tmp != NULL)
    {
        printf("FOUND!");
    }
    else
    {
        *check = 1;
    }

    if ( check == 0 )
    {
        tmp = tmp->next;
        while ( *first != tmp )
        {
            shop *current = *first;
            *first = ( *first )->next;
            free( current );
        }
        if ( *first ) ( *first )->prev = NULL;
    }
}

这个函数依赖于在main中设置的check的值,这是一个糟糕的设计。如果函数本身设置变量check会更好。在这种情况下,您可以将功能拆分为两个功能。第一个将搜索目标元素,第二个将删除满足条件的所有元素(如果需要)。

我会按以下方式定义函数

int delete_from_list( shop **first, const char *word )
{
    shop *tmp   = *first;
    int deleted = 0;

    while ( tmp!=NULL && strcmp( tmp->name, word ) != 0 )
    {
        tmp = tmp->next;
    }

    if ( tmp != NULL)
    {
        deleted = 1;

        tmp = tmp->next;
        while ( *first != tmp )
        {
            shop *current = *first;
            *first = ( *first )->next;
            free( current );
        }
        if ( *first ) ( *first )->prev = NULL;
    }

    return deleted;
}

函数print_list也是错误的。通常,参数firstfirst->next可以等于NULL。在这种情况下,这些语句

first=first->next;
if(first->name==NULL)
while(first->next!=NULL){

导致未定义的行为。

这个函数的逻辑本身是错误的。

答案 1 :(得分:1)

首先,您必须采用函数delete_from_list的参数列表, 这样它就能删除第一个元素。使用shop **first代替 shop *first。找到name word的元素。只要第一个元素不是找到的元素,就删除列表的第一个元素。

void delete_from_list(shop **first, char word[MAX], int* check)
                        // ^^ pointer to pointer of first element
{
    // search for elemnt with name word 
    shop *found = *first;
    while ( found != NULL && strcmp(found->name, word) != 0 )
        found = found ->next;

    if ( found != NULL )
    {
        // found is element with name word
        printf("FOUND!");

        // Delete the first element of your list as long as first elment is not found element
        shop *temp = *first;
        while ( temp != found )
        {
           shop *next = temp->next;       
           free( temp );
           temp = next;
        } 

        *first = found;        // write back the new first element of your list 
        (*first)->prev = NULL; // predecessor of first element is NULL
    }
    else
        *check=1;
}