ЧАСТЬ ЧЕТВЕРТАЯ

Это ссылка на предыдущую часть (ЧАСТЬ ТРЕТЬЯ), если вы пропустили: https://medium.com/@mr_robertamoah/creating-an-interpreter-for-monty-bytecodes-using-c-programming-language -47c9bab6c4be

В третьей части статьи мы реализовали функции для выполнения push, pall и pint. В этой части мы реализуем функции для pop, swap, add и т. д.

Начиная с поп-кода операции. Этот код операции удаляет верхний узел стека (последний добавленный узел стека). Код для этой реализации можно увидеть ниже.

Для реализации будет невозможно извлечь пустой связанный список. Когда связанный список пуст, мы печатаем в stderr, освобождаем память и выходим из программы. В противном случае последний узел удаляется с помощью функции delete_stack_node. Как только мы удаляем узел, мы также должны обновить длину нашего стека. С помощью функции delete_stack_node все, что мы делаем, — это устанавливаем заголовок на следующий узел после установки временного указателя stack_t на последний узел. Затем мы удаляем (освобождаем память) последний узел, на который теперь указывает временная переменная. Чтобы проверить, работает это или нет, давайте посмотрим, чего должен достичь приведенный ниже байт-код.

Мы хотим нажать 1, 2 и 3 в этом порядке. Это сделает 3 последним, кто попадет в стек, верно? Согласно нашему коду элемент head указателя arguments будет указывать на узел с n из 3. Затем код операции pall выводит n значений всех узлов связанного списка, начиная с 3 до 1. Затем всплывающий код удалит узел с n из 3. Другой pall должен вывести 2 к 1. Еще одно всплывающее окно удаляет узел с n из 2. Следующий pall теперь печатает только 1. Последнее всплывающее окно удалит узел с n из 1. Затем последний pall ничего не печатает. . Итак, мы ожидаем увидеть на выходе следующие числа в порядке 3 2 1 2 1 1, конечно, с правильным форматированием.

Это работает нормально. Далее в списке идет код операции подкачки. Что это делает? Обмен кодом операции меняет местами два верхних элемента стека. Это, безусловно, потерпит неудачу, если в списке будет меньше двух узлов. Хороший пример использования члена stack_length нашего указателя arguments. Давайте посмотрим на код.

Я проверяю, меньше ли длина связанного списка 2. Если это так, я вывожу сообщение об ошибке в stderr, освобождаю все выделения памяти и выхожу из программы. К настоящему времени вы знакомы с этой рутиной. Если в связанном списке есть два или более узла, я пытаюсь получить два последних узла с помощью члена head указателя arguments. Обратите внимание, что «tmp1-›next» совпадает с «argument-›head-›next» и что они дают нам предпоследний узел в стеке. Как поменять? Это требует некоторой визуализации. Поэтому всегда визуализируйте узлы как имеющие элементы prev и next. следующий из tmp1 теперь должен указывать на узел после tmp2. Если это не NULL, то prev этого узла также должен быть tmp1. После этого я позволяю следующему элементу tmp2 быть tmp1, тогда как элемент prev теперь указывает на NULL. Это означает, что tmp2 теперь становится последним узлом. Чтобы сделать ссылку более полной, я установил для prev элемент tmp1 значение tmp2. Теперь, поскольку tmp2 является последним, я делаю так, чтобы элемент head arguments указывал на него. Диаграмма ниже дает наглядное представление о том, что только что произошло.

Учитывая, что у нас всего два узла. head будет указывать на tmp1. tmp1 будет иметь prev, указывающий на NULL, и next, указывающий на tmp2. tmp2 также будет иметь prev, который указывает на tmp1, и next, который в этом случае указывает на NULL, но также может указывать на другой узел, если узлов больше двух. На второй диаграмме вы видите, что head теперь указывает на tmp2. prev для tmp2 имеет значение NULL. Теперь он указывает на tmp1. Прежде чем вы это сделаете, вам нужно убедиться, что next для tmp1 будет установлено значение next для tmp2. >. Здесь NULL. Но если это не так, то эти узлы prev также следует изменить с tmp2 на tmp1. Затем prev tmp1 указывает на tmp2. Немного легче понять, что я сделал с этими диаграммами. Мы проверим наш код с помощью байт-кода ниже:

Как вы думаете, чего должны достичь приведенные выше байт-коды? Мы уже знаем о первых четырех строках. Пятая строка поменяет местами 3 и 2 узлы. Следовательно, последний код операции pall должен напечатать 2 3 1. Посмотрите на вывод ниже, когда я запускаю код. Работает отлично.

Следующий код операции, который необходимо реализовать в этой части, — это код операции добавления. Код операции add добавляет два верхних узла стека, присваивает результат предпоследнему узлу, а затем удаляет последний узел. Ниже показано, как я реализовал функцию добавления.

Я просто печатаю ошибку и выхожу из программы, когда в связанном списке меньше двух узлов. В противном случае я присваиваю сумму n элементов двух последних узлов элементу n предпоследнего узла. Затем я удаляю последний узел с помощью функции delete_stack_node. Помните, мы видели эту функцию ранее. Затем я уменьшаю длину стека на единицу, потому что мы удалили последний узел. Давайте рассмотрим приведенные ниже байт-коды, после чего мы можем запустить нашу скомпилированную программу, чтобы проверить, правильно ли работает наша функция добавления.

После первых трех строк у нас будет связанный список с тремя узлами, где последний узел имеет n элементов, равных 3. Команда pall печатает узлы от 3 до 1. Затем код операции добавления добавляет 3 к 2 и присваивает его к n элементу предпоследнего узла, который является стеком с n из 2. Теперь он будет иметь 5 вместо 2. Узел с 3, последний узел, удален. Последняя команда pall должна вывести 5 1. Запуск программы с файлом, содержащим эти коды операций, дает желаемый результат.

На этом я закончу четвертую часть статей. Попробуйте реализовать некоторые коды операций, такие как sub, div, mul и т. д., самостоятельно. Это следующие коды операций, с которыми я буду иметь дело в следующей части этой серии. Попробовать их. Затем вы можете сравнить свою реализацию с моей. Вы можете позволить реализации добавить код операции. Увидимся.

Это ссылка на следующую часть серии: https://medium.com/@mr_robertamoah/mcreating-an-interpreter-for-monty-bytecodes-using-c-programming-language-916d1837546