Последний стек In-First Out в bash? - PullRequest
0 голосов
/ 28 апреля 2020

Как сделать последний стек In-First Out с помощью сценариев оболочки ... Я могу сделать это на C ++

int main()  
{  
    stack<int> stack ;  

    stack = stack_push(stack);  
    stack = stack_pop(stack);  
    stack = stack_push(stack);  
    stack_peek(stack);  
    stack_search(stack, 2);  
    stack_search(stack, 6);  
    return 0; 
} 

1 Ответ

4 голосов
/ 28 апреля 2020

Вы можете легко реализовать стек, используя массив.

Обратите внимание, что bash не является объектно-ориентированным, поэтому нет способа написать mystack.doSomething(), как это было бы в C ++. Вместо этого вы должны передать имя стека в качестве параметра функции: doSomething myStack. Если вам нужен только один стек, вы можете жестко закодировать имя стека внутри функций, что упрощает процесс.

Один глобальный стек

#! /bin/bash
stack=()
push() { stack+=("$@"); }
peek() { printf %s\\n "${stack[-1]}"; }
pop() { peek; unset 'stack[-1]'; }

Использование интерактивного примера. $ - это приглашение:

$ push a b
$ push c
$ peek
c
$ pop
c
$ pop
b
$ pop
a
$ pop # stack is empty, results in error
-bash: unset: [-1]: bad array subscript

Несколько стеков

#! /bin/bash
push() { local -n "stack=$1"; shift; stack+=("$@"); }
peek() { local -n "stack=$1"; printf %s\\n "${stack[-1]}"; }
pop() { peek "$1"; unset "$1[-1]"; }

Интерактивный пример использования. $ - это приглашение:

$ push stack1 a
$ push stack2 b
$ peek stack1
a
$ peek stack2
b

Другие операции

Помните, что стеки - это обычные массивы. Такие функции, как size или search могут быть реализованы путем прямого доступа к массиву. Например, для размера stack записать ${#stack[@]}.

Альтернативный подход: несколько стеков в одном ассоциативном массиве

До сих пор каждый стек использовал свой собственный массив. Вы должны удостовериться, чтобы избежать конфликтов имен с остальной частью вашего сценария. Поскольку переменная для каждого стека использует имя стека (первый аргумент после push / peek / pop), в стеках могут быть только имена, принятые bash (например, stack1, но не stack 2, 3rdStack, . или ""). В качестве альтернативы вы можете хранить все стеки в одном ассоциативном массиве (также известном как карта). Однако вы потеряете прямой доступ к массиву, поэтому реализация дополнительных методов может оказаться более сложной:

#! /bin/bash
declare -A stacks=()
size() { local j="${stacks[.$1]}"; printf %d\\n "${j/-*/0}"; }
lastindex() { local i="$(size "$1")"; echo "$((i - 1))"; }
push() { local j="$(size "$1")"; stacks["$j.$1"]="$2"; stacks[".$1"]="$((j+1))"; }
peek() { local i="$(lastindex "$1")"; printf %s\\n "${stacks[$i.$1]}"; }
pop() { local i="$(lastindex "$1")"; peek "$1"; unset "stacks[$i.$1]"; stacks[".$1"]="$i"; }

Это только базовая c реализация. Вы можете использовать только sh один элемент за раз, то есть вы должны написать push stackname a; push stackname b вместо push stackname a b. peek или pop в пустом стеке ничего не делают, кроме вывода пустой строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...