Блок задач

1. Разгон

Сложность 1

Задача «Стек»

Реализовать на языке C модуль для работы со стеком элементов.

Строго заданный интерфейс:

#include <stddef.h>  // size_t

static const size_t INVALID = ~((size_t)0);

void * stack_create(size_t itemSize);
void stack_destroy(void * stack, void(*destroy)( void * ));

void * stack_init(void * stack, size_t itemSize, void(*destroy)(void*));
void stack_clear(void * stack, void(*destroy)( void * ));

size_t stack_count(const void * stack);
void * stack_push(void * stack);
void stack_pop(void * stack, void(*destroy)( void * ));
void * stack_peek(const void * stack);

size_t stack_first(const void * stack);
size_t stack_next(const void * stack, size_t item_id);
size_t stack_stop(const void * stack);
void * stack_current(const void * stack, size_t item_id);
  • INVALID -- код ошибки для невалидных ситуаций.
  • stack_create -- Создать новый пустой стек. Размер элемента -- itemSize байт.
  • stack_destroy -- Удалить существующий стек. Если указана функция destroy, то вызвать её для каждого удаляемого элемента.
  • stack_init -- Инициализировать стек новыми параметрами. Если stack содержит элементы, то сначала удалить все элементы, потом инициализировать стек с учетом новых параметров. Размер элемента -- itemSize байт. Если указана функция destroy, то вызвать её для каждого удаляемого элемента.
  • stack_clear -- Удалить все элементы из стека. Если указана функция destroy, то вызвать её для каждого удаляемого элемента.
  • stack_count -- Количество элементов в стеке. В случае, если stack равен NULL, возвращает INVALID константу.
  • stack_push -- Добавить элемент на вершину стека. В случае успеха, функция возвращает указатель на добавленный элемент, иначе -- NULL.
  • stack_pop -- Удалить элемент с вершины стека. Если указана функция destroy, то вызвать её для удаляемого элемента.
  • stack_peek -- Подсмотреть элемент с вершины стека, не удаляя его. В случае успеха, функция возвращает указатель на верхний элемент, иначе -- NULL.
  • stack_first -- Идентификатор для элемента с вершины стека. Идентификатор может стать невалидным при модификации стека.
  • stack_next -- По идентификатору текущего элемента получить идентификатор следующего элемента стека.
  • stack_stop -- Идентификатор, получаемый при попытке обратиться к элементу за пределами стека.
  • stack_current -- Получить указатель на элемент стека по его идентификатору.
//Пример использования
#include <string.h>
#include <assert.h>
#include <math.h>

#include "stack.h"

typedef struct {
    int array[8];
    float d_variable;
} Value;

int main(int argc, char* argv[])
{
    //Создаем стек с элементами типа Value;
    void* stack = stack_create(sizeof(Value));

    assert(0 == stack_count(stack));
    assert(stack_stop(stack) == stack_first(stack));

    //Создаем объект для стека
    Value value = { {1, 2, 3, 4, 5, 6, 7, 8}, 0.f };

    //Добавляем новый элемент в стек
    Value* insertedValue = (Value*)stack_push(stack);

    //Инициализируем добавленный элемент
    *insertedValue = value;

    Value* item = (Value*)stack_peek(stack);

    for (size_t i = 0; 8 > i; ++i) {
        assert(item->array[i] == value.array[i]);
    }

    assert(fabsf(item->d_variable - value.d_variable) < 1e-10f);
    assert(stack_next(stack, stack_first(stack)) == stack_stop(stack));

    stack_destroy(stack, NULL);

    return 0;
}