Как мне создать «отменить» в C ++? - PullRequest
6 голосов
/ 30 апреля 2010

Мне нужно создать функцию, которая отменяет предыдущее задание / добавление / изменение. Как мне это сделать в Borland C ++?

(Программа сохраняет строки текста в текстовом файле с использованием «списка». Он сохраняется и стирается, если я не использую созданную мной функцию сохранения.)

Кстати, я имел в виду создание функции отмены в простом консольном приложении.

Ответы [ 6 ]

16 голосов
/ 30 апреля 2010

Я дам еще один ответ, но я думаю, что охват пока недостаточен.

Сюжет далеко не тривиален, и поиск в Google возвращает множество результатов. Во многих приложениях реализована операция отмены, и существует множество вариантов.

Здесь есть 2 модели дизайна, которые могут помочь нам:

  • Command: это ограничение действия
  • Memento: состоит в сохранении состояния (обычно подразумевает некоторую форму сериализации)

Шаблон Command интенсивно используется в графических средах, потому что обычно есть различные способы выполнить действие. Представьте себе сохранить в Microsoft Word, например:

  • Вы можете нажать на сохранить значок
  • Вы можете зайти в меню Файл и нажать Сохранить
  • вы используете ярлык, обычно CTRL + S

И, конечно, save , вероятно, реализован в терминах save as .

Преимущество шаблона Command здесь двоякое:

  • вы можете создать стек объектов
  • вы можете попросить каждый объект реализовать undo операцию

Теперь существуют различные проблемы, которые относятся к undo:

  • некоторые операции не могут быть отменены (например, рассмотрим rm в Linux или пустое мусорное ведро действие в Windows)
  • некоторые операции трудно отменить, или они могут не быть естественными (вам нужно сохранить какое-то состояние, объект обычно уничтожается, но здесь вам нужно будет фактически сохранить его в команде для действия отмены)
  • обычно мы рассматриваем отмену / повтор как стек, некоторые программы (в основном, графические) предлагают отменить элементы без фактического удаления того, что было сделано впоследствии, этого гораздо труднее достичь, особенно когда новые действия были построены на вершина отмены ...

Поскольку существуют различные проблемы, существуют различные стратегии:

  • Для простой команды вы можете рассмотреть возможность отмены (например, добавление символа можно отменить, удалив его)
  • Для более сложной Команды вы можете рассмотреть возможность отмены восстановления как восстановления предыдущего состояния (вот где Memento срабатывает)
  • Если у вас много сложных команд, что может означать много Memento с, которые занимают место, вы можете использовать подход, который заключается в запоминании только одной Снимок каждые 10 или 20 команд, и затем повторяет команды с последнего снимка до отмененной команды

На самом деле, вы, вероятно, можете смешивать Command и Memento на досуге, в зависимости от особенностей вашей системы и, следовательно, от сложности любого из них.

Я бы только рассмотрел возможность отмены последнего выполненного действия, для начала (с использованием стека действий). Функциональность отмены любых действий, которые пользователь желает, намного сложнее.

13 голосов
/ 30 апреля 2010

Чтобы реализовать Undo, вам нужно создать «стек действий» в вашем приложении. Однако есть два основных подхода:

  1. Зная вашу базовую линию (последний раз, когда файл был сохранен или с момента создания файла), запомните каждое отдельное изменение, чтобы, когда что-то нужно было отменить, вы просто выбрасываете «самый верхний» "пункт и восстановить текущий вид с базовой линии плюс все изменения. Нажатие «Повторить» затем просто помещает этот элемент обратно в стек. Это дает дополнительное преимущество, заключающееся в возможности тривиального удаления элементов в любом месте стека, не путая другие параметры отмены / возврата, хотя потребуется особая осторожность, чтобы убедиться, что применение «более высоких» состояний соответствует назначению пользователя.

  2. Для каждого действия сохраните изменения, внесенные в предыдущее состояние, а также изменения, которые потребуются для восстановления этого предыдущего состояния, если вы хотите отменить. Теперь, когда пользователь нажимает «Отменить», просто выполните действия «Отменить». При нажатии «Повторить» повторно примените внесенные изменения. В некоторых случаях шаги «Отменить» будут «вот как это выглядело раньше», но это может привести к хаосу, если вы хотите разрешить пользователям удалять элементы, которые не находятся на вершине стека, а затем необходимо удалить что-то выше это.

Правильный выбор зависит от множества факторов, в том числе от того, сколько данных вы можете / будете носить с собой. Вариант № 1 в некотором смысле проще, но он может стать очень медленным, чтобы отменить что-либо, если стек действий большой.

5 голосов
/ 30 апреля 2010
4 голосов
/ 30 апреля 2010

Также см. Образец памятного подарка.Иногда разум, который должен войти в команду, чтобы отменить операцию, довольно сложен.Рисование объектов в программе рисования, например.Может быть проще просто сохранить память, а затем восстановить ее, чтобы выполнить отмену.

2 голосов
/ 30 апреля 2010

Вы можете хранить снимки состояния. Состояние - это набор данных, которые действие может изменить. Когда вы нажимаете «Отменить», текущее состояние заменяется предыдущим. На самом деле это не тривиальная задача, особенно если состояние сложное.

0 голосов
/ 07 июня 2012

Я недавно экспериментировал на эту тему. Если вам не нужна двоичная совместимость, проверьте https://github.com/d-led/undoredo-cpp

...