
Методичка по Visual Studio 2008
.pdf
Продолжение отладки
Если в сеансе отладки вы ушли с выполняющегося кода, то найти дорогу назад часто бывает очень трудно. Выполнявшаяся строка поте- рялась в одном из многих открытых окон с кодом. К счастью, для того чтобы вернуться назад, вы можете использовать команду Показать следующий оператор (значок с желтой стрелкой) в панели инстру- ментов Отладка (рис. 24). Это вернет вас на ту строку, которая вы- полнялась в момент останова отладчика.
Рис. 24. Вызов команды Показать следующий оператор
Продолжить отладку после точки останова можно повторным на- жатием на кнопку F5 (Начать отладку).
31
Окончание сеанса отладки
Можно заканчивать сеанс отладки несколькими способами. Один из самых часто используемых методов – это прекратить выполнение приложения. Это можно сделать нажатием кнопки Закрыть (или х) окна консольного приложения. При завершении приложения произой- дет также и завершение сеанса отладки. Завершить сеанс отладки можно также, выбрав в меню Отладка команду Завершить все.
Отладка в случае аварийного завершения программы
Бывает так, что в процессе тестирования программы на некоторых наборах входных данных (необязательно на всех) вдруг происходит некое событие, после которого программа не может продолжать рабо- ту и аварийно (преждевременно) завершается. Это говорит о том, что в коде программы содержится логическая ошибка – ошибка времени выполнения. Для эффективного поиска и быстрого исправления ошиб- ки в таких случаях особенно полезно использовать отладчик.
Рассмотрим пример простой программы, осуществляющей заполне- ние массива целых чисел (пример 4). На рис. 25 показан момент выпол- нения этой программы, когда отладчик идентифицирует обращение к
элементу массива по некорректному адресу и выдает соответствующее диагностическое сообщение. В подобных ситуациях следует прерывать
выполнение программы и внимательно изучать состояние всех объектов программы, которые привели к аварийной ситуации. В рассматриваемом случае ошибка связана с тем, что переменная i (счетчик цикла) может принимать значения, не превышающие 32767 – максимального предста- вимого целого числа в типе short. Чтобы исправить эту ошибку, дос- таточно расширить диапазон возможных значений счетчика цикла (на- пример, для переменной i объявить тип int).
Пример 4. Программа с ошибкой времени выполнения
void main()
{
int a[50000];
for(short i = 0; i < 50000; i++) a[i] = i;
}
32

Рис. 25. Окно отладчика в момент идентификации ошибки
времени выполнения
СОЗДАНИЕ КОНСОЛЬНОГО ПРИЛОЖЕНИЯ ИЗ НЕСКОЛЬКИХ МОДУЛЕЙ
Модуль – функционально законченный фрагмент программы, оформленный в виде отдельного файла с исходным кодом (исходным текстом программы) или поименованной непрерывной его части (на- пример, пространства имен), предназначенный для использования в других программах. Модули позволяют разбивать сложные задачи на более мелкие подзадачи и обычно проектируются таким образом,
33
чтобы предоставлять программистам удобный для многократного ис- пользования интерфейс в виде связанного набора функций, классов, констант. Модули могут объединяться в пакеты и далее в библиотеки.
Модульная организация программного кода (когда программный код разбивается на несколько файлов, каждый из которых компилиру- ется отдельно от остальных) позволяет значительно уменьшить время перекомпиляции при изменениях, вносимых лишь в небольшое коли- чество исходных файлов.
Для более четкого выделения и определения интерфейса библиоте-
ки обычно применяется заголовочный файл (подключаемый файл,
иногда головной файл, англ. header file) – в языках программирова- ния C и C++ файл, содержащий, как правило, определения типов дан- ных, прототипы функций, макросы препроцессора. Заголовочный файл (или заголовочный модуль) имеет по умолчанию расширение .h. и в общем случае может содержать любые конструкции языка программи- рования. Но на практике исполняемый код библиотеки (за исключени- ем inline функций в C/C++) помещают не в заголовочный файл, а в файл исходного кода (англ. source file), который по умолчанию имеет расширение .cpp.
Таким образом, идентификаторы интерфейса библиотеки (типы и структуры данных, прототипы функций и т.д.), которые должны быть объявлены более чем в одном файле, удобно описать в заголовочном файле и затем его подключать по мере надобности, а реализацию функций библиотеки (исполняемый код) следует поместить в файл ис- ходного кода.
Рассмотрим подход с разделением интерфейса и реализации функ-
ций библиотеки на примере программы для работы с динамическим стеком (пример 5). В данной программе стек организован линейным нециклическим односвязным списком без заглавного звена.
В заголовочном файле stack.h объявлена структура данных stack и содержатся прототипы функций (inline-функция здесь описана полностью), которые определяют доступные операции над структурой stack. Файл исходного кода stack.cpp содержит только исполняе- мый код соответствующих функций. В файле main.cpp содержится подпрограмма, демонстрирующая работу со структурой stack.
Подобная организация программного кода требует, чтобы каждый исходный файл, ссылающийся на идентификаторы какой-либо библио- теки, должен содержать директиву #include для подключения соответ- ствующего заголовочного файла этой библиотеки.
34
Следует также отметить, что для большей ясности структуры про- екта в VS принято разделять заголовочные файлы и файлы исходного кода и группировать их в отдельных папках. На рис. 26 показан при-
мер размещения заголовочного файла (stack.h) и файлов исходного кода (stack.cpp и main.cpp) внутри проекта в окне Обозреватель решений.
Пример 5. Программа для работы с динамическим стеком, состоя-
щая из трех модулей
/* Файл stack.h */
#ifndef STACK_H #define STACK_H
#include <stdlib.h>
struct list
{ list *next; int elem; };
typedef list stack;
// Поместить элемент в стек void Push(stack* &p, int num);
/* inline-функция проверки стека на пустоту, тело которой может быть встроено непосредственно в месте ее вызова */
inline int isStackEmpty(stack* &p) { return p == NULL; }
//Извлечь элемент из стека int Pop(stack* &p, int &num);
//Распечатать содержимое стека void printStack(stack* &p);
#endif /* STACK_H */
/* Файл stack.cpp */
#include "stack.h" #include "stdio.h"
void Push(stack* &p, int num)
{
if (p == NULL) { p = new stack;
p->next = NULL; p->elem = num;
35
}
else {
stack *q = new stack; q->elem = num; q->next = p; p = q;
}
}
int Pop(stack* &p, int &num)
{
if (!isStackEmpty(p)) { num = p->elem;
if (p->next == NULL) { delete p;
p = NULL;
}
else {
stack *q = p; p = p->next; delete q;
}
return 0;
}
return 1;
}
void printStack(stack* &p)
{
printf_s("Содержимое стека: "); if (p != NULL) {
stack *q = p; do {
printf_s("%d ", q->elem); q = q->next;
} while (q != NULL);
}
printf_s("\n");
}
/* Файл main.cpp */
#include <stdio.h> #include <locale.h> #include "stack.h"
36
void main()
{
int n = 0, exitFlag = 0, m = 0; stack *st = NULL;
setlocale(LC_CTYPE, "Russian"); do { // Меню работы со стеком
printf_s("<1> - поместить элемент в стек\n"); printf_s("<2> - распечатать содержимое стека\n"); printf_s("<3> - извлечь элемент из стека\n"); printf_s("<4> - выход\n");
int repeatFlag = 0; do {
printf_s("Введите номер команды (от 1 до 4): "); scanf_s("%d", &n);
switch ( n ) {
case 1: printf_s("Введите число: "); scanf_s("%d", &m);
Push(st, m); break;
case 2: if (!isStackEmpty(st)) printStack(st);
else
printf_s("Стек пуст\n"); break;
case 3: if (!Pop(st, m))
printf_s("Из стека извлечен элемент:
%d\n", m);
else
printf_s("Стек пуст\n"); break;
case 4: exitFlag = 1; break;
default: printf_s("ОШИБКА: неверный номер
команды\n");
repeatFlag = 1;
}
}while (!repeatFlag && !exitFlag);
}while (!exitFlag);
}
37

Рис. 26. Пример проекта консольного приложения, состоящего
из нескольких файлов
ПОЛЕЗНЫЕ СОЧЕТАНИЯ КЛАВИШ
ВVS есть несколько предопределенных схем сочетаний клавиш, а также средства для создания и редактирования этих схем. Настроить
схему сочетаний клавиш можно с помощью команды меню Сервис ► Параметры ►Среда ► Клавиатура.
Втабл. 2 дана сводка наиболее часто используемых сочетаний кла- виш. Если не пожалеть времени на заучивание этих комбинаций, то работа в среде VS станет более плодотворным и приятным занятием.
38
|
|
Т а б л и ц а 2 |
Комбинации клавиш для работы с VS |
||
|
|
|
Сочетание клавиш |
|
Описание |
|
|
|
ВСТРОЕННАЯ СПРАВОЧНАЯ СИСТЕМА |
||
|
|
|
|
|
Отображение раздела справки в зависимости |
F1 |
|
от выбранного элемента пользовательского |
|
|
интерфейса |
|
|
|
|
|
Отображает окно Динамическая справка, |
CTRL + F1 |
|
которое содержит ссылки на разделы, свя- |
|
|
занные с выбранным элементом |
|
|
|
|
|
Отображает раздел справки, соответствую- |
SHIFT + F1 |
|
щий выбранному элементу пользовательско- |
|
|
го интерфейса |
|
|
|
|
РАБОТА С ПРОЕКТАМИ |
|
|
|
|
F7 |
|
Построить решение |
|
|
|
CTRL + ALT + F7 |
|
Перестроить решение |
|
|
|
CTRL + BREAK |
|
Отмена выполняемого построения |
|
|
|
|
|
Открывает диалоговое окно Создать файл, |
CTRL + N |
|
позволяющее выбрать новый файл для до- |
|
|
бавления в текущий проект |
|
|
|
|
|
Открывает диалоговое окно Создать про- |
CTRL + SHIFT + N |
|
ект, в котором можно создавать проекты |
|
|
и добавлять их в текущее решение |
|
|
|
|
|
Открывает диалоговое окно Открыть файл, |
CTRL + O |
|
в котором можно выбрать существующий |
|
|
файл для открытия |
|
|
|
|
|
Открывает диалоговое окно Открыть про- |
CTRL + SHIFT + O |
|
ект, в котором можно добавить в решение |
|
|
существующие проекты |
|
|
|
|
39 |
|
|
|
П р о д о л ж е н и е т а б л. 2 |
||
|
|
|
|
|
|
Сочетание клавиш |
|
|
Описание |
|
|
|
|
|
|
|
|
|
|
ОТЛАДКА |
|
|
|
|
|
|
|||
CTRL + SHIFT + F9 |
|
Удаление всех точек останова в проекте |
|||
|
|
|
|||
|
|
Завершение сеанса отладки, повторная сбор- |
|||
CTRL + SHIFT + F5 |
|
ка приложения и повторное его выполнение |
|||
|
с начала. Доступно в режимах выполнения |
||||
|
|
||||
|
|
и прерывания |
|
|
|
|
|
|
|
||
|
|
Автоматическое присоединение |
отладчика |
||
F5 |
|
и выполнение приложения. В режиме приос- |
|||
|
тановки выполнения нажатие этой клавиши |
||||
|
|
||||
|
|
приводит к продолжению |
|
||
|
|
|
|||
CTRL + F5 |
|
Выполнение кода без вызова отладчика |
|||
|
|
|
|
|
|
SHIFT + F5 |
|
Завершение |
работы |
текущего приложения |
|
|
в программе |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
F9 |
|
Добавление |
или удаление точки |
останова |
|
|
в текущей строке |
|
|
||
|
|
|
|
||
|
|
|
|
|
|
F11 |
|
Выполнение |
кода |
по одному |
оператору |
|
с заходом в вызываемые функции |
|
|||
|
|
|
|||
|
|
|
|||
F10 |
|
Выполнение следующей строки кода, но без |
|||
|
выполнения вызываемых функций |
|
|||
|
|
|
|||
|
ПОИСК И ЗАМЕНА |
|
|
||
|
|
|
|||
CTRL + F |
|
Отображение диалогового окна Найти |
|||
|
|
|
|||
CTRL + F3 |
|
Поиск следующего вхождения выделенного |
|||
|
текста в документе |
|
|
||
|
|
|
|
||
SHIFT + F3 |
|
Поиск предыдущего вхождения выделенного |
|||
|
текста |
|
|
|
|
|
|
|
|
|
|
CTRL + H |
|
Открытие диалогового окна Заменить |
|||
|
|
|
|
|
|
|
ОБЩИЕ ФУНКЦИИ |
|
|
||
|
|
|
|||
CTRL + C |
|
Копирование выделенного элемента в буфер |
|||
|
обмена системы |
|
|
||
|
|
|
|
||
|
|
|
|
|
|
|
40 |
|
|
|