WriteLn для C + + Builder (исходники), Різне, Програмування, статті

Зміст




Введення


Програмісти Delphi вже протягом довгого часу використовують функцію WriteLn як отладочного інструменту. Текст, переданий у WriteLn, прямує в консольне вікно, перетворюючи його в лог-файл реального часу. Використовуючи подібний підхід, ви можете відстежувати поведінку своєї програми в секціях коду, критичних з точки зору часу, де звичайні точки зупинки (breakpoints) не будуть працювати. На жаль, C + + Builder не включає в себе функцію WriteLn. Тим не менше, немає ніяких причин для того, щоб не реалізувати її самостійно. У цій статті я поясню вам, як це зробити. Як частина пояснення, ми розглянемо також функції AllocConsole, GetStdHandle і WriteConsole Windows API.



WriteLn по-дельфійські


Використання функції WriteLn в Delphi складається з двох кроків. Спочатку ви виділяєте консольне вікно для вашого додатки, а потім вже викликаєте WriteLn. Код виглядає приблизно таким чином:






AllocConsole();
WriteLn(`Entering Critical Section”); {Тут щось робимо}
WriteLn(`Exiting Critical Section”);

AllocConsole – це функція Win32 API, і, як і має на увазі її ім’я, вона виділяє консольне вікно для застосування. Кожна програма може мати своє власне консольне вікно – але тільки одне. Це справедливо як для GUI-додатків, так і для стандартних консольних додатків.


Після того, як додатком виділено вікно консолі, функція WriteLn виводить в нього текст. Система проста, але надзвичайно ефективна. Фактично, в деяких ситуаціях при налагодженні достатньо тільки її.



Консольний вивід у C + +


У C + + Builder є інструменти налагодження, схожі на WriteLn. Діагностичні макроси TRACE і WARN, а також функція OutputDebugString роблять, в першому наближенні, те ж саме, що і функція WriteLn. Але їх використання, тим не менш, страждає одним недоліком: їх висновок направляється в log-файл, який не оновлюється до тих пір, поки програма не затримається на точці зупинки, або поки воно не завершиться. Це обмежує використання вищезазначених інструментів в деяких ситуаціях.


Але хороші новини, крім того, що WriteLn легко реалізувати в C + + Builder, складаються також у тому, що ви можете включити в її реалізацію безпосередньо функції управління консоллю, що, в підсумку, зробить використання вашої власної функції WriteLn набагато простіше. WriteLn вимагає дескриптор вихідного буфера для консольного вікна, який ви можете отримати за допомогою функції GetStdHandle. В цілому це все буде виглядати приблизно так:






AllocConsole();
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
WriteConsole(handle, “Test”, 4, 0, 0);

Давайте розглянемо код уважніше. Виклик AllocConsole, очевидно, виділяє консольне вікно вашому додатком. У другому рядку функція GetStdHandle витягує дескриптор стандартного вихідного буфера. Ви передаєте значення STD_OUTPUT_HANDLE в цю функцію, щоб “попросити” Windows видати вам дескриптор стандартного буфера.


Як тільки ви отримали дескриптор стандартного вихідного буфера, ви можете викликати функцію WriteConsole для запису тексту в консольне вікно. Перший параметр функції WriteConsole являє собою дескриптор стандартного буфера виводу, другий параметр – текст, який відправляється в консоль, третій параметр – кількість виведених символів.



WriteLn для C + + Builder


Тепер, знаючи все необхідне, ви можете створити-таки вашу власну функцію WriteLn. Для початку, давайте оголосимо її прототип. Він дуже простий:






void WriteLn(String text);

Як бачите, функція приймає параметр типу String і нічого не повертає. Зрозуміло, значення параметра text і буде тим самим з’являються в консоль текстом. Давайте тепер поглянемо на WriteLn цілком:






void WriteLn(String text)
{
static HANDLE handle;
if(!handle) {
AllocConsole();
handle = GetStdHandle(STD_OUTPUT_HANDLE);
}
text += ”
“;
WriteConsole(handle,
text.c_str(), text.Length(), 0, 0);
}

Спочатку ви оголошуєте статичну змінну handle – вона підкаже вам, чи не було консольне вікно вже виділено вашому додатком (згадайте, що статична змінна має початкове значення, рівне нулю, і зберігає своє значення між викликами функції). Якщо значення змінної handle дорівнює нулю, то, значить, консольне вікно ще не було виділено. Таким чином, ви можете викликати функцію AllocConsole. Потім ви викликаєте GetStdHandle для отримання дескриптора стандартного вихідного буфера. Далі, ви додаєте символ перекладу нового рядка в кінець переданого у функцію тексту. Це гарантує, що кожна рядок буде починатися з нового рядка. Нарешті, ви викликаєте WriteConsole для виведення тексту в консольне вікно. Зверніть увагу, що ви передаєте довжину рядка тексту в якості третьої параметра функції WriteConsole, щоб рядок повністю була виведена в консоль.



Приклад


Лістинг нижче є програмою, що використовує функцію WriteLn. Це головна форма з однією кнопкою. Коли ви натискаєте на кнопку, цикл викликає функцію WriteLn для виведення двадцяти рядків тексту в консольне вікно.






//——————————————–
#include
#pragma hdrstop

#include “WriteLnU.h”
//——————————————–
#pragma resource “*.dfm”

TForm1 *Form1;

// The WriteLn function.
void WriteLn(String text)
{
static HANDLE handle;
if (!handle) {
AllocConsole();
handle = GetStdHandle(STD_OUTPUT_HANDLE);
}
text += ”
“;
WriteConsole(handle,
text.c_str(), text.Length(), 0, 0);
}

//——————————————–
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//——————————————–
void __fastcall
TForm1::Button1Click(TObject *Sender)
{
for (int i=0;i<20;i++) {
Application->ProcessMessages();
WriteLn(“Iteration: ” + String(i));
Sleep(100);
}
}



Висновок


Функція WriteLn може бути чудовим інструментом налагодження. Ви можете нечасто її використовувати, але, коли вона потрібна насправді, то їй немає заміни.


Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*