Вспомогательные типы и функции задачника
Описанные на данной странице типы и функции будут доступны в программе, если
к ней подключен файл pt4.c или pt4.cpp (файл pt4.c автоматически подключается к
проекту-заготовке, на языке C,
а файл pt4.cpp к проекту-заготовке на языке C++).
Объявления типов и функций содержатся в заголовочном файле pt4.h.
При компиляции программ на языке C используется стандарт C99, при компиляции программ на языке C++ стандарт C++14.
В версии задачника 4.23 набор вспомогательных функций для языка C++ был существенно
переработан и дополнен в связи с реализацией в этой версии поддержки языка C.
Отсутствие в языке C перегрузки функций потребовало введения набора различных функций,
предназначенных для ввода исходных данных, вывода результатов и вывода отладочной информации.
Ввиду сложности стандартных функций языка C, предназначенных для преобразования данных различных типов
в их строковые представления, был разработан расширенный набор функций
для вывода отладочной информации, позволяющий выводить в разделе отладки
отформатированные данные различных типов в наиболее наглядном виде.
Все вспомогательные функции задачника, реализованные для языка C, доступны и для языка C++.
Кроме того, для языка C++ предусмотрен набор дополнительных функций и операций,
позволяющих упростить, по сравнению с языком C, действия по вводу исходных данных,
выводу результатов и выводу отладочной информации. При этом были использованы
возможности C++, отсутствующие в языке C. К числу таких возможностей относится перегрузка функций,
а также операций << и >> (последняя возможность позволяет реализовать
специальный поток ввода-вывода pt, аналогичный стандартным потокам C++).
Кроме того, для потока pt были определены итераторы ввода и вывода, а также реализованы
специальные варианты отладочного вывода, использующие параметры-итераторы
(эти возможности удобно применять при изучении стандартной библиотеки шаблонов
с помощью расширения электронного задачника PT for STL).
Большинство вспомогательных функций для языка C++, определенных в версии 4.23,
доступно и для предыдущих версий задачника,
однако у некоторых функций в версии 4.23 был изменен набор параметров или несколько изменилось поведение.
Поэтому в разделе, посвященном языку C++, сохранена страница с описанием дополнительных
типов и функций, соответствующих версии 4.22.
Базовый набор функций (языки C и C++)
Инициализация заданий, ввод-вывод данных
void Task(const char *name);
Функция инициализирует задание с именем name. Она должна вызываться в
начале программы, выполняющей это задание (до вызова функций ввода-вывода
GetPut). Если в программе, выполняющей задание, не указана функция Task,
то при запуске программы будет выведено окно с сообщением «Не вызвана
процедура Task с именем задания».
Имя задания name должно включать имя группы заданий и порядковый номер в
пределах группы (например, "Begin3" ). Регистр букв в имени группы может быть
произвольным. Если указана неверная группа, то программа выведет сообщение об
ошибке «Указана неверная тема задания»
(список всех доступных групп можно получить с помощью программных модулей PT4Demo и PT4Load). Если указан
недопустимый номер задания, то программа выведет сообщение, в котором будет
указан диапазон допустимых номеров для данной группы. Если после имени задания
в параметре name указан суффикс «?» (например, "Begin3?" ), то
программа будет работать в демонстрационном режиме.
Функция Task может также использоваться для
генерации и вывода на экран html-страницы с текстом задания или группы заданий.
Для этого необходимо указать в качестве параметра name имя конкретного задания или группы
заданий и суффикс «#», например, "Begin3#" или
"Begin#" . Дополнительные сведения о генерации html-страниц с описаниями заданий приводятся
в разделе, посвященном демонстрационному режиму задачника.
Задачник обеспечивает автоматическое тестирование программы на нескольких
наборах исходных данных при ее однократном запуске. Для отключения этой возможности достаточно
указать в параметре Name после имени задания суффикс «!» (например, "Begin3!" );
в этом случае при запуске программы она будет протестирована на единственном наборе исходных данных,
и для проверки правильности решения программу потребуется запустить несколько раз (как в предыдущих версиях
задачника).
Если функция Task вызывается в программе несколько раз, то все
последующие ее вызовы игнорируются. Исключением является ситуация, когда
функция используется для генерации html-страницы с описанием нескольких заданий или групп
заданий; в этом случае учитываются все вызовы данной функции.
Параметр name может содержать суффикс «_ru»
или «_en», позволяющий явным образом задать язык интерфейса
(русский или английский соответственно) для окна задачника и выполняемого задания.
Дополнительные суффиксы «?», «#» и «!» и суффикс настройки языка
интерфейса могут указываться в любом порядке.
В случае нескольких вызовов функции Task (для генерации
html-страницы) учитывается только суффикс настройки языка, указанный при первом вызове функции.
При отсутствии суффикса используется язык интерфейса, определенный в качестве основного для данного рабочего каталога
(в универсальном варианте задачника основной язык интерфейса можно настроить с помощью программного модуля PT4Load,
используя его контекстное меню).
void GetB(bool *a);
void GetN(int *a);
void GetD(double *a);
void GetC(char *a);
void GetS(char *a);
void GetP(PNode *a);
Функции обеспечивают ввод исходных данных в программу, выполняющую
учебное задание. Они должны вызываться после вызова функции Task; в случае их
вызова до вызова функции Task при запуске программы будет выведено сообщение
об ошибке «В начале программы не вызвана процедура Task с именем
задания».
Используемая функция ввода должна соответствовать типу очередного элемента
исходных данных; в противном случае выводится сообщение об ошибке
«Неверно указан тип при вводе исходных данных» (такое сообщение
будет выведено, например, если очередной элемент данных является символом, а для
его ввода используется функция GetN).
При попытке ввести больше исходных данных, чем это предусмотрено в
задании, выводится сообщение об ошибке «Попытка ввести лишние исходные
данные». Если исходные данные, необходимые для решения задания, введены
не полностью, то выводится сообщение «Введены не все требуемые исходные
данные».
Следует отметить, что в предыдущих версиях задачника в аналогичных функциях ввода для языка C++
в качестве параметров использовались не указатели, а ссылки. Изменение типа параметров связано с тем,
что в языке C отсутствует концепция ссылок, а выходные параметры могут оформляться только в виде указателей.
Необходимо учитывать, что, несмотря на одинаковый тип параметров функций GetC и GetS,
связанные с ними данные являются различными. Параметр функции GetC представляет собой адрес символьной переменной,
в которую записывается введенный символ, тогда как параметр функции GetS должен содержать адрес
начала символьного массива char[], в который будет записана введенная строка. В качестве размера символьного массива
достаточно указать 80, так как длины любых исходных строковых данных не превосходят 79 символов.
Тип PNode используется в задачах, связанных с динамическими структурами данных, и описывается далее
в пункте «Работа с динамическими структурами».
void PutB(bool a);
void PutN(int a);
void PutD(double a);
void PutC(char a);
void PutS(const char *a);
void PutP(PNode a);
Функции обеспечивают вывод на экран результирующих данных, найденных
программой, и их сравнение с контрольными данными (т. е. с правильным
решением). Как и функции группы Get, эти функции должны вызываться после
вызова функции Task; в противном случае при запуске программы будет выведено
сообщение об ошибке «В начале программы не вызвана процедура Task с
именем задания».
В качестве параметра функций группы Put
можно указывать не только переменные , но и выражения (в частности, константы
соответствующего типа). Используемая функция должна соответствовать типу
очередного элемента результирующих данных, в противном случае выводится
сообщение об ошибке «Неверно указан тип при выводе результатов».
Как и в случае функций группы Get, при вызовах функций группы Put
программа осуществляет контроль за соответствием количества требуемых и
выведенных результирующих данных. Если программа выведет недостаточное или
избыточное количество результирующих данных, то после проверки этих данных
появится сообщение «Выведены не все результирующие данные» или,
соответственно, «Попытка вывести лишние результирующие данные».
По поводу использования типа bool в функциях языка C см. примечание в конце описания функций группы Get.
Параметром функции PutS должен быть символьный массив, оканчивающийся нулевым символом '\0'.
Работа с динамическими структурами
Язык C
struct Node;
struct Node
{
int Data;
struct Node *Next;
struct Node *Prev;
struct Node *Left;
struct Node *Right;
struct Node *Parent;
};
typedef struct Node TNode;
typedef struct Node *PNode;
Язык C++
struct Node
{
int Data;
Node *Next;
Node *Prev;
Node *Left;
Node *Right;
Node *Parent;
static void operator delete(void *p);
};
typedef Node TNode;
typedef Node *PNode;
Типы PNode и TNode используются в заданиях групп Dynamic
и Tree. В заданиях на
стеки и очереди (Dynamic1Dynamic28) при работе со структурами типа TNode
используются только поля Data и Next; в заданиях на двусвязные списки
(Dynamic29Dynamic80) используются поля Data, Next и Prev. В большинстве заданий на
бинарные деревья (группа Tree) используются поля Data, Left и Right;
в заданиях на обработку бинарных деревьев с обратной связью
(Tree48Tree56 и Tree70Tree71) дополнительно используется поле Parent.
Все исходные и результирующие данные-указатели в заданиях имеют тип
PNode; их ввод и вывод должен осуществляться с помощью функций GetP и PutP
(или дополнительных средств ввода, предусмотренных для языка C++ и описываемых далее).
void DeleteNode(PNode p);
Данная функция обеспечивает освобождение памяти, выделенной под структуру
типа TNode (см. ее описание, приведенное выше). Функция DeleteNode используется только при
выполнении заданий групп Dynamic и Tree.
Для языка С++ вместо данной функции можно использовать стандартный оператор
освобождения памяти delete (определенный как статический член соответствующей структуры).
Вывод отладочной информации
Описываемые далее средства позволяют выводить отладочную информацию
непосредственно в окно задачника (в специальный раздел отладки).
Начиная с версии 4.22, в раздел отладки можно выводить текст, содержащий любые символы Юникода.
void ShowB(bool b);
void ShowN(int n);
void ShowD(double d);
void ShowC(char c);
void ShowS(const char *s);
void ShowLineB(bool b);
void ShowLineN(int n);
void ShowLineD(double d);
void ShowLineC(char c);
void ShowLineS(const char *s);
Отображает элемент данных указанного типа в разделе отладки окна задачника.
Варианты функций, начинающиеся с текста ShowLine, дополнительно
выполняют переход на новую экранную строку в разделе отладки после вывода указанного элемента данных.
Функция ShowB выводит текст false для ложного параметра b и текст true для истинного параметра;
после текста true добавляется пробел, чтобы любая логическая константа занимала ровно 5 экранных позиций
(по поводу использования типа bool в функциях языка C см. примечание в конце описания функций группы Get).
При выводе символа функцией ShowC он заключается в одинарные кавычки,
при выводе строки функцией ShowS строка заключается в двойные кавычки.
Как символы, так и строки должны иметь кодировку ASCII или (для русских букв) однобайтную ANSI-кодировку Windows-1251.
При выводе символов особым образом обрабатываются символы с кодами 0 и 10. Для символа с кодом 0 выводится
текст '\0', для символа с кодом 10 текст '\n'. Кроме того, символ с кодом 10 особым образом интерпретируется
при выводе строк функцией ShowS: он не приводит к переходу на новую экранную строку в разделе отладки,
а заменяется на комбинацию символов \n, например, "Строка, завершающаяся маркером конца строки\n".
Если текущая экранная строка в разделе отладки уже содержит некоторый текст, то
строка, изображающая выводимый элемент данных, снабжается начальным пробелом и приписывается к этому тексту,
за исключением случая, когда при таком приписывании размер
полученного текста превысит ширину области данных (равную 80 символам).
В последнем случае вывод строки осуществляется с начала
следующей экранной строки; если же и в этой ситуации строка с текстом выводимого элемента превысит
ширину области данных (что возможно только при выводе данных строкового типа), то эта строка
будет выведена на нескольких экранных строках, причем разрывы текста будут выполняться по
пробельным символам строки, а при отсутствии пробелов при
достижении очередного фрагмента строки длины, равной 80.
void Show(const char *cmt);
void ShowW(const wchar_t *cmt);
void ShowLine(const char *cmt);
void ShowLineW(const wchar_t *cmt);
Функции Show и ShowW выводят в раздел отладки строковый комментарий, который обычно указывается
перед выводом одного или нескольких элементов отладочных данных. В отличие от обычных строковых данных
(выводимых функцией ShowS), комментарии не заключаются в двойные кавычки. Варианты функций ShowLine и ShowLineW
дополнительно выполняют переход на новую экранную строку в разделе отладки после вывода указанного комментария.
Переход на новую экранную строку можно также выполнить, если указать
в комментарии cmt символ с кодом 10 ('\n' ). Таким образом, способ обработки этого символа
в комментариях cmt отличается от способа его обработки в строковых и символьных данных,
выводимых функциями ShowS и ShowC (которые выводят изображение этого символа \n ).
При выводе комментария в нем автоматически удаляются все завершающие пробелы
(напомним, что при выводе последующего элемента данных в раздел отладки перед ним автоматически добавляется пробел).
Если в результате удаления пробелов комментарий становится пустым, то он не выводится, и пробел между ним
и последующим элементом данных не добавляется.
Функции Show и ShowLine позволяют выводить комментарии, содержащие (подобно функциям ShowC и ShowS)
символы ASCII или русские буквы в однобайтной
ANSI-кодировке Windows-1251. Эту функцию следует использовать в редакторах интегрированных сред,
не поддерживающих кодировку UTF-8, например, в редакторе среды Dev-C++ 5.11.
Функции ShowW и ShowLineW позволяют выводить комментарии, содержащие любые символы Юникода;
для этого они должны быть представлены в виде строк wchar_t* (константы подобных строк
снабжаются префиксом L, например, L"Пример комментария" ). Если редактор интегрированной среды
поддерживает кодировку UTF-8 (а таковы редакторы большинства современных сред разработки),
то все комментарии, содержащие символы, отличные от символов ASCII, в том числе и русские буквы,
следует оформлять в виде строк типа wchar_t* и выводить с помощью функций ShowW или ShowLineW.
void HideTask(void);
Вызов данной функции обеспечивает автоматическое скрытие всех разделов окна
задачника, кроме раздела отладки. Если раздел отладки в окне задачника
не отображается (в частности, если программа запущена в
демонстрационном режиме), то вызов функции HideTask игнорируется.
Игнорируются также все повторные вызовы данной функции.
Скрыть/восстановить основные разделы окна
задачника после его отображения на экране можно также с помощью комбинации
[Ctrl]+[Space] или соответствующей команды контекстного меню раздела
отладки.
void SetPrecision(int n);
Функция предназначена для настройки формата вывода
вещественных отладочных данных. Если параметр n положителен, то он
определяет количество выводимых дробных разрядов; при этом число
выводится в формате с фиксированной точкой.
Если параметр n равен
нулю или является отрицательным, то число выводится в формате с
плавающей точкой (экспоненциальном формате); при этом
число дробных знаков полагается равным модулю параметра n; если
же параметр n равен нулю, то по умолчанию устанавливается количество
дробных знаков, равное 6.
Действие текущей настройки числового формата, определенной
функцией SetPrecision, продолжается до очередного вызова этой
функции. До первого вызова функции SetPrecision вещественные
числа выводятся в формате с фиксированной точкой и двумя дробными
знаками (что соответствует значению параметра n = 2).
Если значение параметра n больше 16 или меньше 16,
то вызов функции игнорируется.
void SetWidth(int n);
Функция предназначена для настройки ширины n области вывода отладочных данных.
Ширина n, заданная этой функцией, влияет на все последующие выводимые элементы данных
вплоть до следующего вызова этой же функции с другим параметром.
По умолчанию ширина области вывода полагается равной 0, что обеспечивает
вывод любого элемента данных в области, минимально необходимой для его отображения.
Если фактическая ширина выводимого элемента данных меньше текущего значения ширины области
вывода, то числовые данные (типа int и double) дополняются пробелами слева, а прочие данные
(типа bool, char и char*) дополняются пробелами справа. Если ширина выводимого элемента больше
текущего значения ширины области вывода, то используется область вывода минимально необходимой ширины,
достаточной для отображения выводимого элемента.
Функция SetWidth не влияет на представление комментариев (выводимых функциями Show, ShowLine, ShowW и ShowLineW),
для которых всегда используется область вывода минимально необходимой ширины.
Если значение параметра n меньше нуля или больше 100,
то вызов функции SetWidth игнорируется.
Преобразование кодировок
void RuAnsi(char *result, const wchar_t *source);
Данная функция позволяет решить проблему, связанную с несоответствием кодировок символьных
данных. Эта проблема возникает при использовании редактора кода, поддерживающего кодировку UTF-8
(в частности, редактора Visual Studio Code). Любые строковые константы, содержащие символы, отличные от символов ASCII,
должны оформляться в этом редакторе как «расширенные» строковые литералы (типа wchar_t*)
с префиксом L, например, L"Строка типа wchar_t*".
Это не препятствует их выводу в разделе отладки (для этой цели предназначена специальная функция ShowW),
однако не позволяет их использовать
при формировании выходных текстовых данных, содержащих русские буквы (так как
функции вывода, как и функции ввода, работают с однобайтными строками типа char*).
Поэтому, если требуется использовать при преобразовании или выводе данных строковые константы,
определенные в программе и содержащие русские буквы, необходимо предварительно
преобразовать эти константы (типа wchar_t*) в однобайтную ANSI-кодировку 1251 с помощью функции RuAnsi.
Исходная «расширенная» строка типа wchar_t* передается функции RuAnsi в качестве параметра source,
преобразованная строка типа char* возвращается в параметре result.
Если преобразуемые константы содержат символы Юникода, отличные от русских букв и символов,
входящих в набор ASCII, то эти символы заменяются на знаки вопроса «?».
Перед вызовом функции RuAnsi
необходимо выделить для параметра result память, достаточную для хранения преобразованной строки.
Можно, например, в качестве result использовать символьный массив размера wcslen(source) + 1.
Необходимость в использовании функции RuAnsi возникает
только при решении задач, требующих обработки символьных данных на русском языке и только в редакторах кода,
использующих кодировку UTF-8. В частности, в редакторе среды Dev-C++ 5.11, который не поддерживает
кодировку UTF-8, при работе с данными на русском языке не нужно применять ни функцию RuAnsi,
ни расширенные строки.
Заметим, что «обратная» проблема, связанная с корректным выводом в разделе отладки
символьных и строковых данных в однобайтной кодировке не возникает, поскольку функции ShowC и ShowS,
предназначенные для отладочного вывода символьных и строковых данных,
автоматически преобразуют свои параметры в кодировку UTF-8 при их выводе в раздел отладки.
Дополнительный набор функций и классов (язык C++)
Ввод-вывод данных
void GetS(std::string &a);
void PutS(std::string a);
Для языка C++ к базовому набору функций ввода-вывода добавлены
перегруженные функции для ввода и вывода строковых данных, в которых используются
тип string, отсутствующий в языке C. Следует обратить внимание на то,
что вариант функции GetS для типа string принимает не указатель, а ссылку на строковый параметр;
таким образом, вызов этого варианта, как и прежнего варианта для параметра-массива char*,
не требует применения операции &: GetS(a).
bool GetBool();
int GetInt();
double GetDouble();
char GetChar();
std::string GetString();
PNode GetNode();
Для языка С++ также добавлены функции ввода, позволяющие получить элемент исходных данных
в виде возвращаемого значения самой функции (такой подход реализован во многих современных языках программирования).
Эти функции появились в версии задачника 4.22;
их удобно использовать в ситуации, когда значение элемента исходных данных
достаточно передать в конструктор какого-либо объекта или в какую-либо функцию. Кроме того,
они позволяют совместить описание и инициализацию переменных, связанных с
исходными данными.
Поток ввода-вывода pt
Поток ввода-вывода pt может применяться вместо функций групп
GetPut.
С его использованием операторы ввода-вывода могут быть оформлены более
компактно. Например, вместо последовательности вызовов функций GetN(&n);
GetD(&d); GetS(s); достаточно указать один оператор чтения из потока:
pt >> n >> d >> s; .
Начиная с версии задачника 4.22, возможности потока вывода pt были существенно расширены.
Теперь в качестве выводимых данных для потока pt можно указывать переменные типа pair
и любого из стандартных контейнерных типов (vector, deque, list, set, multiset, map, multimap),
причем элементами контейнера могут быть данные
скалярных типов, типа pair и контейнерного типа. Компоненты типа pair
также могут иметь любой скалярный тип, тип pair и контейнерный тип.
Итератор чтения ptin_iterator<T>
Итератор записи ptout_iterator<T>
Для ввода и вывода элементов последовательностей типа T
можно использовать специализированные итераторы ptin_iterator<T> и ptout_iterator<T>
соответственно. Эти итераторы обладают теми же свойствами, что и
стандартные потоковые итераторы istream_iterator<T> и ostream_iterator<T> .
Перечислим свойства итератора чтения, совпадающие с аналогичными свойствами потоковых итераторов:
- тип T определяет тип элементов последовательности;
- чтение элемента последовательности из потока pt выполняется в начальный момент работы с итератором,
а затем при каждой операции инкремента ++;
- имеются два варианта операции ++: префиксный инкремент (++i) и постфиксный инкремент (i++);
- операция * возвращает последнее прочитанное значение, причем эту операцию можно использовать неоднократно
для получения того же самого значения;
- итератор конца последовательности создается с помощью конструктора без параметров;
- при достижении конца последовательности итератор становится равным итератору конца последовательности,
последующие вызовы операции инкремента игнорируются, а в результате вызова операции * всегда возвращается
значение последнего прочитанного элемента последовательности.
Свойства итератора записи, совпадающие с аналогичными свойствами потоковых итераторов:
- специальный конструктор для создания итератора конца последовательности не предусмотрен;
- операции * и ++ не выполняют никаких действий и просто возвращают сам итератор;
- операция присваивания вида o = выражение (где o - имя итератора записи) записывает значение
выражения в поток pt.
В отличие от стандартного потокового итератора istream_iterator, конструктор для итератора ptin_iterator
(за исключением конструктора итератора конца последовательности) имеет один параметр типа int,
определяющий размер считываемой последовательности (в элементах). В случае особого значения параметра,
равного 0, размер последовательности считывается из самого потока pt непосредственно перед считыванием
первого элемента последовательности. Если параметр конструктора является отрицательным или, в случае нулевого параметра,
если при считывании размера оказывается, что прочитанный элемент
данных не является целым числом или это число не является положительным, то итератор сразу переходит
в состояние конца последовательности (т. е. становится равным итератору ptin_iterator<T>() ).
Подобная организация итераторов чтения ptin_iterator<T> позволяет легко реализовывать
с их помощью считывание из потока ввода pt нескольких последовательностей, если заранее известен
их размер или если размер указывается непосредственно перед началом последовательности.
В качестве примера использования итераторов потока pt для ввода и вывода данных приведем
решение задачи Array7, в которой требуется ввести массив вещественных чисел указанного размера,
а затем вывести его элементы в обратном порядке (обратите внимание на подключение стандартных заголовочных файлов
<vector> и <algorithm>; для хранения массива используется контейнер vector):
#include "pt4.h"
#include <vector>
#include <algorithm>
using namespace std;
void Solve()
{
Task("Array7");
vector<double> a(ptin_iterator<double>(0), ptin_iterator<double>());
copy(a.rbegin(), a.rend(), ptout_iterator<double>());
}
Вывод отладочной информации
void ShowS(std::string s)
void ShowW(std::wstring cmt)
void Show(std::string cmt)
void Show(std::wstring cmt)
void ShowLineS(std::string s)
void ShowLineW(std::wstring cmt)
void ShowLine(std::string cmt)
void ShowLine(std::wstring cmt)
void ShowLine(void)
Для языка C++ к базовому набору функций отладочного вывода добавлены
перегруженные функции для вывода строковых данных и комментариев, в которых используются
типы string и wstring, отсутствующие в языке C. Кроме того, добавлена функция ShowLine()
без параметров, которая выполняет переход на новую строку в разделе отладки.
Следует обратить внимание на то, что все перегруженные варианты функций Show и ShowLine
с единственным строковым параметром обеспечивают вывод комментария (как и в варианте для языка C).
В частности, такие строки не заключаются в двойные кавычки, при их выводе удаляются завершающие пробелы,
а символ '\n' обеспечивает переход на новую экранную строку.
void Show([строковый тип cmt,] bool a[, int w]);
void Show([строковый тип cmt,] int a[, int w]);
void Show([строковый тип cmt,] double a[, int w]);
void Show([строковый тип cmt,] char a[, int w]);
void Show(строковый тип cmt, const char *a[, int w]);
void Show(строковый тип cmt, std::string a[, int w]);
void ShowLine([строковый тип cmt,] bool a[, int w]);
void ShowLine([строковый тип cmt,] int a[, int w]);
void ShowLine([строковый тип cmt,] double a[, int w]);
void ShowLine([строковый тип cmt,] char a[, int w]);
void ShowLine(строковый тип cmt, const char *a[, int w]);
void ShowLine(строковый тип cmt, std::string a[, int w]);
Набор перегруженных функций Show и ShowLine, позволяющий вывести в раздел отладки один элемент
данных a (логического, целого, вещественного, символьного или строкового типа), а также снабдить его
необязательным строковым комментарием cmt и задать (необязательную) ширину поля вывода w.
Если параметр w не указан, то используется ширина, ранее установленная с помощью функции SetWidth.
Комментарий cmt может иметь любой из следующих четырех строковых типов:
const char*, std::string, const wchar_t*, std::wstring.
Перегруженные варианты функции ShowLine дополнительно выполняют переход на новую строку в разделе отладки
после вывода требуемого элемента данных.
Следует обратить внимание на то, что в перегруженных вариантах для отладочного вывода строковых данных (типа const char*
и std::string) первый параметр-комментарий cmt является обязательным. Это необходимо для того, чтобы избежать конфликтов
с вариантами функции Show и ShowLine, имеющими один строковый параметр (который интерпретируется как комментарий)
или два параметра строковый и целочисленный (которые интерпретируются как комментарий и элемент данных целого типа).
Для отладочного вывода строковых данных без дополнительного комментария
можно использовать либо функции ShowS и ShowLineS, либо
варианты функций Show и ShowLine с двумя или тремя параметрами, первым из которых является пустой комментарий "".
template<typename T1, typename T2>
void Show([строковый тип cmt,] pair<T1, T2> &a)
template<typename T1, typename T2>
void ShowLine([строковый тип cmt,] pair<T1, T2> &a)
Варианты функций Show и ShowLine, позволяющие выводить в раздел отладки данные типа pair<T1, T2>;
при этом в качестве типов T1 и T2 могут использоваться типы bool, int, double, char, char* и string,
а также типы pair (глубина вложения типов pair может быть произвольной) и контейнеры vector, deque, list, set, multiset,
map, multimap с данными указанных типов.
Перед выводом первого элемента пары выводится необязательный строковый комментарий cmt
(типа const char*, std::string, const wchar_t* или std::wstring)
и открывающая круглая скобка, между элементами пары выводится запятая,
после вывода второго элемента выводится закрывающая круглая скобка.
При выводе всех данных (кроме комментариев, скобок и запятых) используется ширина поля вывода, установленная при последнем вызове функции SetWidth.
Например, элемент данных типа
pair<int, pair<int, int>> со значениями 5, 2 и 9 и комментарием «p =»
будет выведен следующим образом (если текущая ширина поля вывода равна 0 или 1):
p = ( 5 , ( 2 , 9 ) )
template<typename InIter>
void Show(InIter first, InIter last[, строковый тип cmt])
template<typename InIter>
void ShowLine(InIter first, InIter last[, строковый тип cmt])
Варианты функций Show и ShowLine, позволяющие выводить в раздел отладки элементы последовательности,
используя связанные с ней итераторы ввода first и last. Элементы последовательности могут иметь тип
bool, int, double, char, char* и string, а также pair<T1, T2>
(глубина вложения типов pair может быть произвольной); кроме того, сами элементы (или компоненты пары pair)
могут быть контейнерами vector, deque, list, set, multiset, map, multimap.
Необязательный последний параметр cmt (типа const char*, std::string, const wchar_t* или std::wstring)
позволяет задать строковый комментарий, который указывается перед выводимой последовательностью.
Вариант Show выводит элементы последовательности на одной строке, разделяя их пробелами;
после завершения вывода элементов последовательности автоматически
выполняется переход на новую строку. Вариант ShowLine выводит каждый элемент последовательности на новой строке; строковый
комментарий, если он указан, также выводится в отдельной строке.
В частности, данные варианты функций Show можно использовать для вывода элементов массива a размера n, например:
double a[5] = {1, 2, 3};
Show(a, a + 5);
В разделе отладки будет выведена следующая информация:
1> 1.00 2.00 3.00 0.00 0.00
Приведем также пример отладочного вывода двумерного вектора (обратите внимание на настройку ширины области вывода
с помощью функции SetWidth и на использование функции ShowLine):
vector<vector<int>> v(10);
for (int i = 0; i < (int)v.size(); ++i)
for (int j = 0; j < 10; ++j)
v[i].push_back((i + 1) * (j + 1));
SetWidth(3);
ShowLine(v.begin(), v.end());
Содержимое раздела отладки:
1> 1 2 3 4 5 6 7 8 9 10
2> 2 4 6 8 10 12 14 16 18 20
3> 3 6 9 12 15 18 21 24 27 30
4> 4 8 12 16 20 24 28 32 36 40
5> 5 10 15 20 25 30 35 40 45 50
6> 6 12 18 24 30 36 42 48 54 60
7> 7 14 21 28 35 42 49 56 63 70
8> 8 16 24 32 40 48 56 64 72 80
9> 9 18 27 36 45 54 63 72 81 90
10> 10 20 30 40 50 60 70 80 90 100
std::string s("Test");
ShowLine("Example 1:", s);
Show(s.begin(), s.end(), "Example 2:");
ShowLine(s.begin(), s.end(), "Example 3:");
В результате выполнения этих операторов в разделе отладки будет выведен следующий текст:
1> Example 1: "Test"
2> Example 2: 'T' 'e' 's' 't'
3> Example 3:
4> 'T'
5> 'e'
6> 's'
7> 't'
Преобразование кодировок
std::string RuAnsi(const wchar_t *source);
std::string RuAnsi(std::wstring source);
Более удобные для использования варианты ранее описанной функции RuAnsi, позволяющие получить
перекодированную строку в виде возвращаемого значения самой функции. В качестве примера применения функции RuAnsi
приведем фрагмент программы из предыдущего примечания, в котором как комментарии, так и исходная строка
содержат русские буквы (обратите внимание на то, что перекодировать текст комментариев не требуется):
std::string s(RuAnsi(L"Тест"));
ShowLine(L"Пример 1:", s);
Show(s.begin(), s.end(), L"Пример 2:");
ShowLine(s.begin(), s.end(), L"Пример 3:");
Содержимое раздела отладки:
1> Пример 1: "Тест"
2> Пример 2: 'Т' 'е' 'с' 'т'
3> Пример 3:
4> 'Т'
5> 'е'
6> 'с'
7> 'т'
void ForceUnicode(void);
Вспомогательная функция, предназначенная для программ, которые были разработаны в
одном из редакторов, поддерживающих кодировку UTF-8, а затем запущены в среде Visual Studio.
Редактор этой среды имеет ряд особенностей, которые надо учитывать, если в программах
используются строки, содержащие русский текст или символы Юникода.
В заготовках программ, создаваемых для Visual Studio, по умолчанию применяется ANSI-кодировка,
поэтому в использовании вариантов функции RuAnsi или расширенных строк нет необходимости. Однако
при добавлении в текст программы символов Юникода она преобразуется в кодировку UTF-8 (предварительно
выводится соответствующее сообщение). После такого преобразования для корректной работы с русским текстом
необходимо применять варианты функции RuAnsi и расширенные строки.
Преобразованная в кодировку UTF-8 программа сохраняется редактором Visual Studio
в файле, снабженном соответствующим маркером последовательности байтов (BOM). Это не препятствует загрузке программы в другие среды
с редакторами, поддерживающими UTF-8 (Code::Blocks, Dev-C++ 6.30, Visual Studio Code).
Однако при загрузке в среду Visual Studio программы в кодировке UTF-8, разработанной в другом редакторе
(например, Visual Studio Code) и не содержащей BOM, символы Юникода (в том числе русские буквы)
будут правильно отображаться в редакторе Visual Studio, но в разделе отладки окна задачника будут
выведены в неверной кодировке. Для решения этой проблемы следует в начале функции Solve вызвать функцию ForceUnicode.
В вариантах библиотеки pt4.cpp, не связанных со средой Visual Studio, функция ForceUnicode не выполняет
никаких действий.
Получение имени исполняемого файла
std::string GetExename();
Возвращает полное имя исполняемого файла, полученного в результате компиляции учебной программы.
Эта вспомогательная функция может использоваться при выполнении заданий из электронного задачника
по параллельному программированию на базе MPI-2, связанных с порождением новых процессов.
|