Стеки: для каждой пары скобок напечатать номера их позиций в тексте - 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;
}

Объяснение кода листинга программы

  1. Структура данных pair_t представляет собой пару значений типа int, обозначающих позиции скобок '(' и ')'.
  2. Структура данных node_t представляет собой узел стека, содержащий пару значений типа TPair и указатель на следующий узел.
  3. Функция Push добавляет новую группу скобок в стек. Проверяет не NULL указатель на стек, создает новый узел, копирует данные в новый узел, добавляет элемент на вершину стека и возвращает указатель на вершину стека.
  4. Функция PushWithSort добавляет новую группу скобок в стек, используя переданную функцию сравнения для определения места добавления. Проверяет не NULL указатель на стек и функцию сравнения, создает временный узел, добавляет элемент на вершину стека, удаляет временный узел.
  5. Функция Pop извлекает значение из стека, проверяет не пустой ли стек, сохраняет указатель на верхний узел, спускается к следующему элементу, сохраняет значение удаляемого узла, удаляет узел и возвращает извлеченное значение.
  6. Функция Clear удаляет все элементы стека.
  7. Функция CompareFirst сравнивает два значения типа TPair по первому значению.
  8. Функция Print выводит все элементы стека в стандартный поток вывода.
  9. Функция PrintsPosBreckets находит в выражении все открывающиеся и закрывающиеся скобки и выводит их координаты по порядку. Использует стек для хранения текущих позиций скобок и добавляет позиции в отсортированный результирующий список.
  10. В main() определяется константное выражение CExpression. Выводится это выражение, затем вызывается функция PrintsPosBreckets.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

14   голосов , оценка 3.929 из 5
Похожие ответы