2015-02-26 2 views
0

В настоящее время я создал набор ADT, который использует связанные функции списка для реализации данного интерфейса.Ошибки с set_add и set_contains

Утилита тестирования, которую мы испытываем для тестирования набора ADT, дает мне ошибки в set_add и set_contains.

// Push function, pushes element on head of set 
void Push(set_t **set, void *elem) { 
     // Allocates memory for a newNode 
     set_t *newNode = (set_t *) malloc(sizeof(set_t)); 
     // sets element to elem which is in input 
     newNode->elem = elem; 
     // Previous head to next 
     newNode->next = *set; 
     // Newnode as head 
     *set = newNode; 
} 

void AppendNode(set_t **headRef, void *elem) { 
     set_t *current = *headRef; 
     set_t *newNode; 

     newNode = malloc(sizeof(set_t)); 
     newNode->elem = elem; 
     newNode->next = NULL; 

     if (current == NULL) { 
       *headRef = newNode; 
     } 
     else { 
       while (current->next != NULL) { 
         current = current->next; 
       } 
       current->next = newNode; 
     } 
} 

/* 
* Adds the given element to the given set. 
*/ 
void set_add(set_t *set, void *elem) { 
     if (set_contains(set, elem) == 1) { 
       return; 
     } 
     else { 
       AppendNode(&set, elem); 
     } 
} 

/* 
* Returns 1 if the given element is contained in 
* the given set, 0 otherwise. 
*/ 
int set_contains(set_t *set, void *elem) { 
     set_t *current = set; 

     while (current != NULL) { 
       if (current->elem == elem) { 
         return 1; 
       } 
       current = current->next; 
     } 

     return 0; 
} 

Это не имеет значения, если я использую Нажмите, чтобы нажать на голове или использовать AppendNode добавить на конце хвоста.

Вот мой набор структура:

struct set { 
    void *elem; 
    set_t *next; 
    cmpfunc_t cmpfunc; 
} 

ли кто-то увидеть что-то, что очень выключен?

ответ

0

Ваши функции Push и AppendNode выглядят нормально. Ошибка: set_add, где вы обновляете set по адресу set_add. Это изменение не будет отражено в функции, которая вызывает set_add.

Вы должны изменить функцию:

void set_add(set_t **set, void *elem) { 
    if (set_contains(*set, elem) == 0) { 
     AppendNode(set, elem); 
    } 
} 

Функция set_contains не требует параметра указатель на указатель, потому что он только проверяет набор, но не меняет его.

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

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

интерфейс, определенный в, скажем, set.h, который объявляет set_t как непрозрачный тип:

typedef struct set set_t; 

set_t *set_create(void); 
void set_destroy(set_t *set); 
void set_add(set_t *set, void *elem); 
int set_contains(const set_t *set, void *elem); 

Реализация в set.c определяет содержимое структура. Он также определяет тип для узлов, который является приватным до set.c. И, конечно же, она выполняет функции:

#include <set.h> 

typedef struct setnode setnode_t; 

struct set { 
    setnode_t *head; 
}; 

struct setnode { 
    void *elem; 
    setnode_t *next; 
}; 

set_t *set_create(void) 
{ 
    set_t *set = malloc(sizeof(*set)); 

    if (set) set->head = NULL; 
    return set; 
} 

void set_destroy(set_t *set) 
{ 
    setnode_t *curr = set->head; 

    while (curr) { 
     setnode_t *next = curr->next; 
     free(curr); 
     curr = next; 
    } 

    free(set); 
} 

int set_contains(const set_t *set, void *elem) 
{ 
    setnode_t *curr = set->head; 

    while (curr != NULL) { 
     if (curr->elem == elem) return 1; 
     curr = curr->next; 
    } 

    return 0; 
} 

void set_add(set_t *set, void *elem) 
{ 
    if (set_contains(set, elem) == 0) { 
     setnode_t *node = malloc(sizeof(*node)); 

     node->elem = elem; 
     node->next = set->head; 
     set->head = node; 
    } 
} 

Клиентский код может затем использовать набор как так:

#include <set.h> 

int main() 
{ 
    set_t *set = set_create(); 

    for (size_t i = 3; i < 17; i++, i++) { 
     set_add(set, (void *) i); 
    } 

    for (size_t i = 0; i < 20; i++) { 
     printf("%4zu %d\n", i, set_contains(set, (void *) i)); 
    } 

    set_destroy(set); 

    return 0; 
} 
+0

Спасибо за комментарий. Set_add и set_contains заданы из set.h, которые я не могу изменить, поэтому я не могу использовать ссылки в качестве аргументов в них. Но после публикации этого вопроса я посмотрел пример, где cmpfunc использовался для set_contains. if (current-> cmpfunc (elem, current-> elem == 0) {return 1;} Cmpfunc определяется как «typedef int (* cmpfunc_t) (void *, void *) ;. – IndentationFaulter

+0

Итак, ваш интерфейс, и вы должны обеспечить реализацию, правильно? В этом случае вы можете переименовать свой 'set_t' в' setnode_t' и сделать его приватным для реализации. Ваш 'set_t' мог бы быть structrue, содержащий головной узел; 'typedef struct {setnode_t * head;} ​​set_t;' Структура передается в функции с помощью указателя, так что отражается отражение в голове. (И интерфейс к 'set_contains' должен быть сделан' const set_t * '.) –

+0

Конечно, связанный список не очень эффективная реализация набора.Но вы можете использовать подход interface-struct для двоичных деревьев и других структур данных. Фактически, это позволяет вам маскировать реализацию от пользователя. –

 Смежные вопросы

  • Нет связанных вопросов^_^