Стеки: для каждой пары скобок напечатать номера их позиций в тексте - C (СИ)
Формулировка задачи:
В строке записан текст что сбалансированный за круглыми скобками:
<текст>::=<пусто>|<елемент><текст>
<елемент>::=<буква>|(<текст>)
Надо для каждой пары скобок открывающиеся и закрывающиеся напечатать номера их позиций в тексте, упорядочив пары номеров по возрастанию номеров позиций скобок видкриваються.Наприклад, для текста А + (45-F (X)*(B-C)) нужно напечатать 3 17;8 10;12 16.
Решение задачи: «Стеки: для каждой пары скобок напечатать номера их позиций в тексте»
textual
Листинг программы
#include <stdio.h> #include <stdlib.h> //#include <assert.h> typedef struct pair_t { int first; // Позиция скобки '(' int second; // Позиция скобки ')' } TPair; typedef struct node_t { TPair data; // Позиции скобок struct node_t* next; // Указатель не следующий узел } TNode; //----------------------------------------------------------------------------- // Функция добавления новой группы скобок в стек TNode* Push(TNode** stack, const TPair data) { // Проверка не передан ли NULL //assert(stack); // Создаём новый узел TNode* node = (TNode*) malloc(sizeof(TNode)); // Копируем данные в новый узел node->data = data; // Добавляем элемент на вершину стека node->next = *stack; *stack = node; return *stack; } //----------------------------------------------------------------------------- // Функция добавления новой группы скобок. При добавление элементы сразу сортируются. // Правило сортировки задаётся передаваемой функцией TNode* PushWithSort(TNode** stack, const TPair data, int (*func)(const TPair*, const TPair*)) { // Проверка не передан ли NULL //assert(stack); //assert(func); // Временный узел, в конце функции удаляется. // Нужен для упрощения алгоритма поиска TNode* head = (TNode*) malloc(sizeof(TNode)); head->next = *stack; // Курсор который и будет пробегаться по списку TNode* cur = head; // Ищем нужное место for (; cur->next && (func(&data, &cur->next->data) > 0); cur = cur->next) { ; } // Добавляем указанную позицию наше значение Push(&cur->next, data); *stack = head->next; // Удаляем временный вершинный узел free(head); return *stack; } //----------------------------------------------------------------------------- // Функция извлечения значения из стека TPair Pop(TNode** stack) { // Проверка не передан ли NULL или пустой стек //assert(stack); //assert(*stack); // Временно сохраняем указатель на верхний узел TNode* node = *stack; // Спускаемся к следующему элементу *stack = node->next; // Сохраняем значение удаляемого узла TPair data = node->data; // Удаляем узел free(node); return data; } //----------------------------------------------------------------------------- // Функция удаления всех элементов стека void Clear(TNode** stack) { // Проверка не передан ли NULL //assert(stack); // Пока есть элемент в стеке while (*stack) { // Извлекаем элемент из стека Pop(stack); } } //----------------------------------------------------------------------------- // Функция сравнения двух значений типа TPair. Функция используется // в качестве параметра функцией PushWithSort. int CompareFirst(const TPair* a, const TPair* b) { return (a->first - b->first); } //----------------------------------------------------------------------------- // Функция выводит в стандартный поток вывода все элементы стека void Print(const TNode* stack) { // Перебираем все элементы стека и выводим их for (; stack; stack = stack->next) { printf("%d %d; ", stack->data.first, stack->data.second); } printf("\n"); } //----------------------------------------------------------------------------- // Функция находит в выражении все открывающиеся и закрывающиеся скобки и // выводит их координаты по порядку (по пере их появления) void PrintsPosBreckets(const char* str) { //assert(str); // Временный стек хранящий текущие позиции скобок TNode* temp = NULL; // Результирующий список, хранящий позиции скобок в отсортированном виде TNode* result = NULL; // Вспомогательная переменная TPair data; // Позиция в выражении int pos = 0; // Перебираем все элементы выражения for (; *str; ++str) { pos++; // Проверяем, не является ли скобкой switch (*str) { case '(': // Сохраняем позицию открывающейся скобки, и добавляем // позицию во временный стек data.first = pos; data.second = -1; Push(&temp, data); break; case ')': // Извлекаем из временного стека позицию последней открывающейся // скобки, добавляем позицию закрывающейся, и добавляем эти две // координаты в результирующий список. Используем для добавления // функцию добавления с сортировкой, т.е. при добавлении элемент // будет добавляться не на вершину стека, а туда, где не будет выполнять // функция CompareFirst data = Pop(&temp); data.second = pos; PushWithSort(&result, data, CompareFirst); break; } } // Печатаем результирующий список Print(result); // Удаляем все элементы списка Clear(&result); } //----------------------------------------------------------------------------- int main() { const char CExpression[] = "(A+(45-F(X)*(B-C)))*Z"; printf("%s\n", CExpression); PrintsPosBreckets(CExpression); //system("pause"); return 0; }
Объяснение кода листинга программы
- Структура данных
pair_t
представляет собой пару значений типа int, обозначающих позиции скобок '(' и ')'. - Структура данных
node_t
представляет собой узел стека, содержащий пару значений типа TPair и указатель на следующий узел. - Функция Push добавляет новую группу скобок в стек. Проверяет не NULL указатель на стек, создает новый узел, копирует данные в новый узел, добавляет элемент на вершину стека и возвращает указатель на вершину стека.
- Функция PushWithSort добавляет новую группу скобок в стек, используя переданную функцию сравнения для определения места добавления. Проверяет не NULL указатель на стек и функцию сравнения, создает временный узел, добавляет элемент на вершину стека, удаляет временный узел.
- Функция Pop извлекает значение из стека, проверяет не пустой ли стек, сохраняет указатель на верхний узел, спускается к следующему элементу, сохраняет значение удаляемого узла, удаляет узел и возвращает извлеченное значение.
- Функция Clear удаляет все элементы стека.
- Функция CompareFirst сравнивает два значения типа TPair по первому значению.
- Функция Print выводит все элементы стека в стандартный поток вывода.
- Функция PrintsPosBreckets находит в выражении все открывающиеся и закрывающиеся скобки и выводит их координаты по порядку. Использует стек для хранения текущих позиций скобок и добавляет позиции в отсортированный результирующий список.
- В main() определяется константное выражение
CExpression
. Выводится это выражение, затем вызывается функция PrintsPosBreckets.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д