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

// Схема массива: [0] - N, число стеков в массиве
//                [1] - размер первого стека, [2] - указатель на верхушку первого стека
//                ... повторить [1] и [2] N раз
//                [1 + 2N] - начало первого стека, [1 + 2N + [1]] - конец первого стека
//                ... повторить N раз

void init_array_params(int *this_array){
    // Ввод числа стеков
    int N;
    printf("\nType number of stacks: ");
    if ((scanf("%d", &N) == 0) || (N < 3)){
        printf("\nError.*\n ");
        exit(-1);
    }
    // Создание временного массива, в котором будут храниться начальные размеры будущих стеков
    int *sizes;
    sizes = (int*)malloc(sizeof(int)*N);
    // Ввод начальных размеров стеков
    for (int i = 0; i < N; i++) {
        int tmp;
        printf("Type size of stack number %d: ", i);
        if ((scanf("%d", &tmp) == 0) || ( tmp < 2)) {
            printf("\nError. Try again.\n ");
            i--;
            continue;
        }
        sizes[i] = tmp;
    }
    // Вычисление длины будущего массива
    int size = 1 + N * 2;               // +длина "заголовка" массива
    for (int i = 0; i < N; i++){
        size += sizes[i];               // +длина каждого из стеков
    }
    *this_array = malloc(sizeof(int)*size);
    // Заполнение заголовка
    this_array[0] = N;
    int last_pointer = 1 + N * 2;
    for (int i = 0; i < N; i++){
       this_array[1+i*2] = sizes[i];
       this_array[2+i*2] = last_pointer;
       last_pointer += sizes[i];
    }
    free(sizes);
}

void print_array(int this_array[]){
    printf("\n----------------");
    printf("\nNumber of stacks: %d", this_array[0]);
    printf("\nLength of header: %d", 1+this_array[0]*2);
    printf("\n----------------");
    for (int i = 1; i/2 < this_array[0]; i += 2){
        printf("\nStack #%d\n",    i/2);
        printf("\nSize: %d",     this_array[i]);
        printf("\nPointer: %d",  this_array[i+1]);
        printf("\n----------------");
    }
}

int push(int stack_number, int value, int *this_array){
    if ((stack_number < 0) || (this_array[0] <= stack_number))
        return -1;
    // Изменение указателя на верхушку стека
    this_array[2+stack_number*2]++;
    int pointer = this_array[2+stack_number*2];
    // Установка значения по указателю
    this_array[pointer] = value;
    printf("\nValue %d was pushed to stack #%d\n", value, stack_number);
    return 1;
}

int pop(int stack_number, int *this_array){
    if ((stack_number < 0) || (this_array[0] <= stack_number))
        return -1;
    // Извлечение значения
    int pointer = this_array[2+stack_number*2];
    int value = this_array[pointer];
    // Изменение указателя на верхушку стека
    this_array[2+stack_number*2]--;
    printf("\nPoped value: %d\n", value);
    return value;
}

int main() {
    int *array = NULL;
    init_array_params(&array);
    int menu_pointer = -1;
    while (menu_pointer != 0){
        print_array(&array);
        printf("\n\n1. Push to stack...");
        printf("\n2. Pop from stack...");
        printf("\n\n0. Exit");
        printf("\n----------------\n");
        scanf("%d", &menu_pointer);
        if (menu_pointer == 1){
            int stack_number = -1, value;
            printf("\nType stack number(0,1,2...): ");
            scanf("%d", &stack_number);
            printf("\nType value to push: ");
            scanf("%d", &value);
            push(stack_number, value, &array);
        }
        if (menu_pointer == 2){
            int stack_number, value;
            printf("\nType stack number: ");
            scanf("%d", &stack_number);
            value = pop(stack_number, &array);
            printf("\n----------------\n");
            printf("\nPoped value: %d\n", value);
            char a;
            scanf("%c", &a);
        }
    }
    return 0;
}
return 0;
}