- •Создание динамических структур данных
- •Встроенный динамический класс Collection
- •Создание собственных динамических классов
- •Обертывание коллекции vba
- •Несколько слов об api, Win32, dll
- •Вызов функций и оператор Declare
- •Две кодировки ansi и Unicode
- •Два языка: c и vb. Различия при вызове функций
- •Соответствие между простыми типами данных
- •Структуры языка c и тип, определенный пользователем, в языке vba
- •Об описателях языка c и объектах Windows
- •Void функции языка c
- •Вызов аргументов по ссылке ByRef и по значению ByVal
- •Строковые аргументы при вызове функций Win32 api
- •Примеры работы с Win32 api функциями
- •Работа с окнами
- •Характеристики окружения
- •Вызов функций Win32 api, работающих в Unicode кодировке
- •Обработка ошибок, возникающих при вызове функций Win32 api
- •Функции api и вызов Callback функций
- •Функции высших порядков и конструкция AddressOf
- •Функции перечисления Win32 api
- •Функция EnumWindows
- •Еще один пример работы с функцией EnumWindows
- •Функции Win32 api для работы с таймером
- •Функция SetTimer
- •Функция обратного вызова TimerProc
- •Функция KillTimer
- •Пример создания, работы и удаления таймера
- •Классы как обертка вызовов функций Win32 api
- •Построение класса "ВашТаймер"
- •Использование класса ВашТаймер
- •Операторы
- •Операторы и строки
- •Оператор комментария
- •Присваивание
- •Оператор Let
- •Оператор lSet
- •Оператор rSet
- •Оператор Set
- •Управляющие операторы
- •Условный оператор If Then Else End If
- •Оператор выбора Select Case
- •Цикл For Next
- •Цикл Do...Loop
- •Цикл While...Wend
- •Цикл For Each...Next
- •Работа с каталогами, папками и файлами
- •Изменение текущего диска: оператор ChDrive
- •Изменение текущего каталога (папки): оператор ChDir
- •Создание каталога (папки): оператор MkDir
- •Переименование каталогов (папок) и файлов: оператор Name
- •Удаление каталога (папки): оператор RmDir
- •Установка атрибутов файла: оператор SetAttr
- •Копирование файлов: оператор FileCopy
- •Удаление файлов: оператор Kill
- •Прочие операторы
- •Операции с одним объектом. Оператор With
- •Операции
- •Работа с числовыми данными
- •Математические функции
- •Работа со строками
- •Сравнение строк
- •Сравнение с образцом
- •Основные операции над строками
- •Новые функции для работы со строками
- •Функция InStrRev - поиск последнего вхождения подстроки
- •Функция Replace - замена всех вхождений подстроки
- •Удаление подстроки
- •Разбор строки. Функции Split, Join и Filter
- •Преобразование строки в массив. Функция Split
- •Сборка элементов массива в строку. Функция Join
- •Фильтрация элементов массива. Функция Filter
- •Несколько модификаций встроенных функций
- •Замена, основанная на шаблоне. Функция WildReplace
- •Замена разных символов строки. Функция CharSetReplace
- •Фильтрация, основанная на шаблоне. Функция WildFilter
- •Разбор строки, допускающей разные разделители ее элементов. Функция WildSplit
- •Работа с датами и временем
- •Присваивание значений
- •Встроенные функции для работы с датами
- •Определение текущей даты или времени.
- •Вычисления над датами
- •Функция Timer и хронометраж вычислений
- •Некоторые встроенные функции
- •Функции проверки типов данных
- •Преобразование типов данных
- •Форматирование данных. Функции группы Format
- •Функция Format.
- •Другие функции форматирования
- •Описание и создание процедур
- •Классификация процедур
- •Синтаксис процедур и функций
- •Функции с побочным эффектом
- •Создание процедуры
- •Создание процедур обработки событий
- •Вызовы процедур и функций Вызовы процедур Sub
- •Вызовы функций
- •Использование именованных аргументов
- •Аргументы, являющиеся массивами
- •Конструкция ParamArray
- •Задача о медиане
- •Пользовательские функции, принимающие сложный объект Range
- •Рекурсивные процедуры
- •Деревья поиска
- •Класс TreeNode
- •Класс BinTree
- •Работа со словарем
- •Отладка
- •Написание надежных программ
- •Искусство отладки
- •Средства отладки
- •Панель отладки и команды меню
- •Окна наблюдения
- •Окно локальных переменных - Locals
- •Окно проверки - Immediate
- •Окно контрольных выражений - Watch
Окно проверки - Immediate
В этом окне появляется вся отладочная информация, поступающая в результате выполнения методов Print и Assert объекта Debug. В этом основное назначение этого окна. Об объекте Debug мы еще поговорим особо, а сейчас рассмотрим другие возможности, которые предоставляет окно проверки. Еще одно назначение этого окна состоит в том, что оно представляет блокнот или калькулятор, в котором можно производить какие-либо дополнительные вычисления. Во-первых, в этом окне можно выполнять любые операторы, допустимые в контексте процедуры, выполнение которой было приостановлено. Отсюда, в частности, следует, что в окне можно изменять значения доступных переменных. Во-вторых, в этом окне можно выполнять запросы на вычисление выражений. Запрос начинается со знака "?", после которого печатается запрашиваемое выражение. После нажатия Enter в окне появляется значение выражения. В предыдущих лекциях мы неоднократно пользовались запросами для вычисления значений различных функций. Окно позволяет изменять и значения глобальных переменных модуля. Взгляните, как выглядит окно проверки, в котором выполняются некоторые вычисления в состоянии прерывания процедуры. В частности, в этом окне дважды присваивалось новое значение глобальной переменной и выдавался запрос на получение ее значения. Здесь же был вызван на исполнение метод PostfixOrder объекта root. В этом же окне появились результаты его работы, напечатанные оператором Debug.
увеличить изображение Рис. 10.8. Вычисления в окне проверки
Окно контрольных выражений - Watch
Привычное назначение окна Watch в той или иной среде программирования состоит в том, что оно является окном наблюдений и позволяет следить за состоянием некоторых переменных и выражений программы. Теперь, во многом, эта функция перешла к окну Locals. Тем не менее, и окно Watch используется для этой же цели. В отличие от окна Locals, выражения, появляющиеся в этом окне, не связаны с контекстом выполняемой процедуры. Программист сам формирует список наблюдаемых переменных и выражений, при этом всегда можно точно указать область определения наблюдаемой переменной.
Наблюдение за состоянием выражений перестало быть главной функцией окна Watch. Выражения, хранящиеся в этом окне, являются контрольными выражениями (может быть, точнее было бы - контролируемыми выражениями). Контрольными могут быть любые арифметические, логические или строковые выражения. Для заданных контрольных выражений отладчик позволяет следить за:
-
Значением контрольного выражения. В этом случае контрольное выражение - это обычное наблюдаемое выражение.
-
Моментом изменения значения контрольного выражения. В этом теперь основное назначение контрольных выражений. Всякий раз, когда контрольное выражение меняет свое значение, выполнение приостанавливается на операторе, следующим за оператором, изменившим контрольное выражение. Вот пример, когда такое использование контрольных выражений крайне полезно. В сложных системах обмен информацией между модулями может осуществляться через общий пул данных - общие глобальные переменные. В этом случае бывает трудно понять, какая из процедур меняет неподходящим образом значение общедоступной глобальной переменной. Без контрольного выражения поймать такую ошибку крайне трудно.
-
Моментом, когда контрольное выражение, принимает значение True. Это вариация предыдущего случая и можно указать много ситуаций, когда обнаружение такого факта, приостанавливающего вычисления весьма полезно при отладке.
Следует только понимать, что злоупотреблять контрольными выражениями не следует, поскольку они замедляют процесс вычислений, поскольку перевычисляются на каждом шаге. Кроме того, по этой же причине следует аккуратно задавать контекст, в котором следует вычислять эти выражения.
Помимо окна Watch, в котором появляются контрольные выражения, есть еще окно для добавления нового контрольного выражения, напомним, это окно может быть вызвано соответствующей инструментальной кнопкой панели Debug или, чаще всего, командой Add Watch из контекстного меню, появляющегося при нажатии правой кнопки в окне кода. Вот как выглядит это окно:
Рис. 10.9. Окно добавления контрольного выражения
В поле "Expression" вводится новое контрольное выражение. В нашем примере - это переменная info, в общем случае это может быть любое выражение. В этом окне задается контекст, в котором выражение будет регулярно вычисляться по завершении каждого оператора. Контекст определяет процедуру, модуль и проект. В нашем примере мы указали все процедуры модуля BinTree текущего проекта. Как уже говорилось, чем шире контекст, тем больше проводится дополнительных вычислений по ходу отладки. Кроме контекста задается один из трех возможных типов контрольного выражения. Выбранный нами тип "Break When Value Changes" позволяет прервать вычисления всякий раз, когда в заданном контексте изменится значение контрольной переменной rusword. Добавленное контрольное выражение появляется в окне "Контрольные значения" (Watch).
Просмотреть значение и добавить новое контрольное выражение можно в окне быстрого просмотра Quick Watch. Для этого достаточно выделить выражение и нажать упоминавшуюся ранее инструментальную кнопку панели Debug, выполнить команду меню или нажать комбинацию горячих клавиш - Shift +F9. Вот как выглядит это окно
Рис. 10.10. Окно быстрого просмотра контрольного выражения
Щелкнув по кнопке Add в этом окне, мы добавили переменную MyDict в окно Watch. Сравнивая окно Watch с окном Locals, отметим, что к трем колонкам Expression, Value и Type добавился еще один столбец Context, в котором задается контекст контрольного выражения. Взгляните, как выглядят эти окна после того, как мы добавили три контрольных выражения:
увеличить изображение Рис. 10.11. Окна отладчика после добавления контрольных выражений
Еще один вид информации о текущем состоянии вычисления представлен стеком вызовов процедур. Имя каждой вызванной процедуры помещается на вершину этого стека в момент ее вызова и убирается из него сразу после завершения этого вызова. Просмотреть стек вызовов можно, нажав клавиши Ctrl+L или выбрав инструментальную кнопку или команду "Call Stack…" в меню View. Чаще всего, в окно "Стек вызова" попадают из окна Locals, щелкнув в нем имеющуюся для этой цели кнопку "…".
Продолжим работу с нашим примером. Мы остановились в момент выполнения оператора, запускающего обход дерева. В ходе отладки мы ввели некоторые контрольные выражения. Продолжим теперь выполнение нашей программы. Очередное прерывание в ее работе наступило вследствие того, что изменилось значение контрольного выражения, переменная info получила новое значение в процессе работы процедуры поиска SearchAndInsert. Взгляните на соответствующее состояние окон отладчика в этот момент:
увеличить изображение Рис. 10.12. Окна отладчика в момент прерывания
Заметьте, полученной информации достаточно, чтобы понять в какой процедуре произошло изменение значения переменной info. Но эта процедура рекурсивна и вызывалась неоднократно. Поэтому хотелось бы знать, на каком шаге ее вызова произошло изменение контрольной переменной. Для этого и служит стек вызовов, окно которого и было открыто щелчком соответствующей кнопки в окне Locals.
Рис. 10.13. Окно стека вызовов
Три вызова функции SearchAndInsert были выполнены, прежде чем изменилось значение контрольной переменной. К сожалению, в окне стека вызовов не указаны параметры соответствующих вызовов. Но получить информацию об их значениях и о состоянии локальных переменных вызовов можно. Для этого нужно выделить интересующий вызов в стеке и щелкнуть по кнопке "Show". В результате в окне Locals ,будут отображены значения локальных переменных в момент выделенного вызова.