DevProg: Блог для программистов

Секреты программирования. Примеры разработки. Обзоры программёрского софта, блогов и форумов и просто полезные советы!

Archive for the ‘С и С++’ Category

DelphiWorld, World C++, World C#, ASM World — качаем громадные архивы статей.

Posted by devprog на Февраль 4, 2009

Справочники очень большие и качественные. Содержат множество статей по программированию на языках ассемблера, Delphi, С++, С#.

ASM World – сборник статей по ассемблеру

World C++ – статьи и исхлдники по C и C++

C# World – русские и английские статьи по C#

DelphiWorld – статьи и исходники по Delphi

Posted in Delphi, Ассемблер, С и С++ | Leave a Comment »

Borland C++ Builder. Советы работы с формами.

Posted by devprog на Январь 29, 2009

Ещё один очень интересный FAQ! Все примеры можно легко перевести на Delphi. Но если вы испытываете трудности – милости просим, пишите – поможем.

Запрещение кнопки закрытия [X] формы

// Чтобы запретить кнопку закрытия формы, напишите следующий
// код (Form1- ваша форма, Button1 — кнопка на ней):
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HMENU MenuHandle = GetSystemMenu(Handle, false);
if(MenuHandle)
  DeleteMenu(MenuHandle, SC_CLOSE, MF_BYCOMMAND);
}

Запрещение кнопки максимизации [[]] формы

// Чтобы запретить кнопку максимизации формы, напишите
// следующий код (Form1- ваша форма, Button1 — кнопка на ней):
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HMENU MenuHandle = GetSystemMenu(Handle, false);
if(MenuHandle)
  DeleteMenu(MenuHandle, SC_MAXIMIZE, MF_BYCOMMAND);
}
// ПРИМЕЧАНИЕ: максимизация формы двойным щелчком мыши
// по заголовку также будет невозможна

Запрещение кнопки минимизации [_] формы

// Чтобы запретить кнопку минимизации формы, напишите
// следующий код (Form1- ваша форма, Button1 — кнопка на ней):
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HMENU MenuHandle = GetSystemMenu(Handle, false);
if(MenuHandle)
  DeleteMenu(MenuHandle, SC_MINIMIZE, MF_BYCOMMAND);
}

Отмена закрытия формы при нажатии Alt+F4

// Чтобы форма не закрывалась при нажатии комбинации клавиш
// Alt+F4, разместите на форме компонент TActionList(ActionList1),
// создайте новый TAction(Action1), и в свойстве ShortCut у Action1
// пропишите комбинацию клавиш Alt+F4, а обработчик события
// OnExecute должен выглядеть следующим образом
// (Form1- ваша форма):
void __fastcall TForm1::Action1Execute(TObject *Sender)
{
// чтобы при сохранении C++Builder не уничтожил обработчик
}

Отмена закрытия формы при нажатии Alt+F4 (Вариант 2)

//В обpаботчике FormKeyDown пишешь:
if (Shift.Contains(ssAlt)&&Key==VK_F4) Tag=1;

//В обpаботчике FormCloseQuery:
if(Tag)
{
CanClose=false;
Tag=0;
}

Перемещение формы мышью не за заголовок

// Напишите следующий обработчик события OnMouseDown формы
void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
 long SC_DRAGMOVE = 0xF012;
 if(Button == mbLeft)
  {
  ReleaseCapture();
  SendMessage(Handle, WM_SYSCOMMAND, SC_DRAGMOVE, 0);
 }
}

Изменение размеров формы (развернуть и т.д.)

// Напишите следующий код:
Form1->WindowState = wsMaximized; // развернуть
Form1->WindowState = wsMinimized; // минимизировать
Form1->WindowState = wsNormal; // первоначальный размер

Как сделать кусок окна прозрачным

// Для того чтобы сделать кусок формы прозрачным,
// напишите следующий код:

//Прямоугольный кусок
HRGN R1=CreateRectRgn(0, 0, Width, Height);
HRGN R2=CreateRectRgn(4, 24, Width-4, Height-4);
CombineRgn(R1, R1,R2, RGN_DIFF);
SetWindowRgn(Handle, R1, TRUE);

//Кусок в виде элипса
HRGN hRgn1 = CreateRectRgn(0, 0, Width, Height);
HRGN hRgn2 = CreateEllipticRgn(0, 0, Width, Height);
HRGN hRgn3 = CreateRectRgn(0, 0, Width, Height);
CombineRgn(hRgn3, hRgn1, hRgn2, RGN_DIFF);
SetWindowRgn(Handle, hRgn3, TRUE);
//можно заменить hRgn3 на hRgn2

//Кусок в виде пятиугольника
HRGN Reg1, Reg2;
HRGN Region;
POINT p[5];
p[0] = Point(100, 0);
p[1] = Point(Width-100, 0);
p[2] = Point(Width, Height/2);
p[3] = Point(Width/2, Height);
p[4] = Point(0, Height/2);
Region = CreatePolygonRgn(p, 5, ALTERNATE);
SetWindowRgn(Handle, Region, true);

Создание новой формы во время работы программы

// Для того чтобы создать новую форму напишите:
// следующих код:

TForm * Formik= new TForm(this);
TButton* button=new TButton(Application);
button->Parent=Formik;
button->Caption=»New Button»;
button->Left=10;
button->Top=15;
button->Show();
Formik->Caption=123;
Formik->ShowModal();
delete Formik;

Как сделать прозрачную форму в W2K/XP

// Для того чтобы сделать прозрачную форму напишите:
int Transparency = 75;//насколько прозрачным будет окно (0-100%)
long ExtStyle = GetWindowLong(Handle, GWL_EXSTYLE);
SetWindowLong(Handle, GWL_EXSTYLE, ExtStyle | WS_EX_LAYERED);
SetLayeredWindowAttributes(Handle, 0 , (255 * Transparency) / 100,
LWA_ALPHA);

Прозрачное окно с реакцией на нажатия кнопок, панелей

// Для того чтобы создать форму напишите:
void __fastcall TForm1::Photo()
{
int X0,Y0;
bool Flag;
TRect ScreenRect;
TCanvas* ScreenCanvas=new TCanvas;
try
{
  Top=0;
  Left=Screen->Width;
  Width=Screen->Width;
  Height=Screen->Height;
  ScreenRect=Rect(0,0,Width,Height);
  ScreenCanvas->Handle=GetDC(0);
  Image1->Canvas->CopyRect(ScreenRect, ScreenCanvas,ScreenRect);
  ReleaseDC(Handle,ScreenCanvas->Handle);
  Left=Top;
} __finally
{
  delete ScreenCanvas;
}
}

Новая форма как отдельное окно

// Для того чтобы создать новую форму напишите:
void __fastcall TForm1::CreateParams(TCreateParams& Params)
{
TForm::CreateParams(Params);
Params.WndParent = 0;
}

Приложение без формы

Создайте новый проект. Дальше: Project->Remove from project

Определения класса окна определённого приложения

Для того чтобы определить класс определённого приложения напишите следующий код:

HWND hWnd=FindWindow(NULL,»Калькулятор»);//для русскоязычной Windows
if (hWnd)
{
char buff[100];
GetClassName(hWnd,buff,100);
ShowMessage(buff);
}
Автор: Srpj Сайт: http://srpj.narod.ru/

Как заполнить канву формы, фоном рабочего стола

// Напишите следующий код:
PaintDesktop(Form1->Canvas->Handle);

Posted in Новичку, С и С++ | 10 комментариев »

Узелок впрок! Цветовые константы Borland.

Posted by devprog на Январь 16, 2009

 Цветовая константа  Цвет
clAqua
clBlack
clBlue
clCream
clDkGray
clGray
clGreen
clLime
clLtGray
clMaroon
clMedGray
clMoneyGreen
clNavy
clOlive
clPurple
clRed
clSilver
clSkyBlue
clTeal
clWhite
clYellow
ClScrollBar Цвет полос прокрутки
clBackground Цвет фона рабочего стола
clActiveCaption Цвет заголовка активного окна
clInactiveCaption Цвет заголовка неактивного окна
clMenu Цвет фона меню
clWindow цвет фона окон
clWindowFrame Цвет рамок окон
clMenuText Цвет текста меню
clWindowText Цвет текста окон
clCaptionText цвет текста заголовка неактивного окна
clActiveBorder Цвет юордюра активного окна
clInactiveBorder Цвет бордюра неактивного окна
clAppWorkSpace Цвет рабочей области компонента
clHighlight Цвет фона выделенного текста
clHightlightText Цвет выделенного текста
clBtnFace Цвет поверхности кнопок
clBtnShadow Цвет теней кнопок
clGrayText Цвет текста недоступных элементов
clBtnText Цвет текста кнопок
clInactiveCaptionText Цвет текста заголовка неактивного окна
clBtnHighlight Цвет выделенной кнопки
cl3DDkShadow Для Windows95 и NT. Цвет тёмных теней трёхмерных компонентов
cl3DLight Для Windows95 и NT. Цвет светлых частей трёхмерного компонента
clInfoText Для Windows95 и NT. Цвет текста всплывающих подсказок
clInfoBk Для Windows95 и NT. Цвет фона всплывающих подсказок
clGradientActiveCaption Для Windows98 и Windows2000. Цвет правой стороны градиентной заливки названия активного окна окна.
clGradientInactiveCaption Для Windows98 и Windows2000. Цвет правой стороны градиентной заливки названия неактивного окна окна.

 

Posted in Delphi, С и С++, Узелок впрок | Leave a Comment »

Работа с дисплеем и рабочим столом средствами Borland C++

Posted by devprog на Январь 16, 2009

Очень полезный FAQ по работе с десктопом и дисплеем найден мною на просторах интернета прямо сейчас. Почитаем?

Изменение картинки на рабочем столе

// Для изменения картинки на рабочем столе
// используйте следующий код:
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, «pic.bmp»,
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
// где pic.bmp — имя вашего файла с картинкой

Изменение картинки на рабочем столе(вариант 2)

//Первый вариант в C++Builder 5 вызывает ругань
// BoundsChecker’a, хотя и работает.
// Нижеприведенный вариант никакой ругани не вызывает, но
// почему-то работает не на всех машинах. Для изменения картинки
// на рабочем столе используйте следующий код:
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, «pic.bmp»,
SPIF_UPDATEINIFILE);
// где pic.bmp — имя вашего файла с картинкой

Изменение параметров экрана

// Для изменения параметров экрана используйте следующий
// код:
DEVMODE DM;
DM.dmSize = sizeof(DEVMODE);
DM.dmBitsPerPel = 16;
// глубина цвета, бит на пиксель
DM.dmPelsWidth = 1024; // разрешение по горизонтали
DM.dmPelsHeight = 768; // разрешение по вертикали
DM.dmFields = DM_BITSPERPEL +
DM_PELSWIDTH +
DM_PELSHEIGHT +
DM_DISPLAYFREQUENCY;
DM.dmDisplayFrequency = 75;
// частота обновления экрана
ChangeDisplaySettings(&DM, 0);
// ЗАМЕЧАНИЕ: при изменении параметров смотрите чтобы
монитор поддерживал это режим

Как узнать частоту обновления экрана

// Для получения частоты обновления экрана напишите следующий код:
HDC hDCScreen = GetDC(NULL);
int Refresh = GetDeviceCaps(hDCScreen, VREFRESH);
ReleaseDC(NULL, hDCScreen);
// в Refresh содержится частота обновления экрана по горизонтали

Как узнать разрешение экрана (VCL вариант)

// Разрешение экрана можно узнать, прочитав значения
// свойств Screen->Width и Screen->Height:
int HorzRes = Screen->Width;
int VertRes = Screen->Height;

Как узнать разрешение экрана (WinAPI вариант)

// Для получения разрешения экрана напишите следующий код:
HDC hDCScreen = GetDC(NULL);
int Horres = GetDeviceCaps(hDCScreen, HORZRES);
int Vertres = GetDeviceCaps(hDCScreen, VERTRES);
ReleaseDC(NULL, hDCScreen);
// в Horres содержится разрешение экрана по горизонтали,
// в Vertres содержится разрешение экрана по вертикали.

Отображение свойств дисплея

// Следующий код отобразит на экране диалоговое
// окно свойств дисплея:

ShellExecute(NULL, «», «Desk.cpl», «», «», SW_SHOWNORMAL);

Как поместить вид рабочего стола в буфер

Напишите следующий код:
#include <Clipbrd.hpp>
void __fastcall TForm1::Button1Click(TObject *Sender)
{
unsigned DataHandle;
HPALETTE APalette;
Word Format;
Graphics::TBitmap *Bitmap=new Graphics::TBitmap;
HDC DC=GetDC(0);
try{
Bitmap->Height=Screen->Height;
Bitmap->Width=Screen->Width;
BitBlt(Bitmap->Canvas->Handle , 0, 0, Screen->Width,
Screen->Height,DC, 0, 0, SRCCOPY);
//Изображение экрана теперь в Bitmap, запишем его в бyфеp обмена
Bitmap->SaveToClipboardFormat(Format,DataHandle,APalette);
Clipboard()->SetAsHandle(Format,DataHandle);
}
__finally
{
delete Bitmap;
ReleaseDC(0,DC);
}
}

Как рисовать на Десктопе

Напишите следующий код:
HDC hdc = CreateDC ( TEXT(«DISPLAY»), NULL, NULL, NULL );
Rectangle( hdc, 100,100, 200, 200);
DeleteDC ( hdc );

Как закрасить рабочий стол по пикселю

Напишите следующий код:
void __fastcall TForm1::Button1Click(TObject *Sender)
{ TCanvas *dt = new TCanvas ;
randomize();
dt->Handle = GetDC(0);
while (dt)
{
dt->Pixels[random(1024)][random(768)]= 0 ;
}
}

Posted in С и С++, Узелок впрок | 1 Comment »

22 урока по С++, выкладываю заново!

Posted by devprog на Январь 15, 2009

По просьбам людей из темы 22 урока по С++, выкладываю другой архив на другой файл-хостинг.

Скачать уроки по С++

Posted in Новичку, С и С++ | 1 Comment »

Указатели в программировании

Posted by devprog на Январь 15, 2009

Данная статья изначально писалась для форума xaker.name лично мною, но потом перекачевала вот на этот блог. Надеюсь она вам пригодится.

На написание данной заметки меня толкнуло то, что в учебниках по программированию не уделяется достаточного внимания такой важной теме, как указатели. То есть, внимание, то конечно, уделяется, но вот принцип обучения работы с указателями или не очень понятен или, что ещё хуже, вообще не ясен. Таким образом, на разных форумах и конференциях по программированию каждый третий начинающий программист просит помочь ему разобраться с этой темой. Эта небольшая заметка постарается восполнить этот пробел. Все примеры будут на разных языках программирования — так чтобы всем было понятно, независимо от того, какой язык вы изучаете. Я так же предполагаю, что вы знакомы хотя бы с одним из трёх языков программирования — это Pascal \ Delphi, C++ и Ассемблер.

Базовые знания

Для того чтобы понять, что такое указатель и усвоить основные принципы работы с ними, нужно хорошо представлять, что из себя, представляет память. В общем, случае, память можно представить в виде отдельных ячеек, расположенных в одном большом блоке или даже если вспомнить математику – в виде матрицы (вектором) – строки. Каждая такая ячейка памяти имеет свой адрес, по которому она расположена. Наглядно, память можно представить так:

Так, каждая ячейка таблицы представляет одну ячейку памяти. У каждой ячейки адрес представлен числами от 0 до N. Так вот, указатель — это просто переменная определённого размера, которая содержит адреса ячеек памяти. Так же, указатель может иметь специальное значение, обозначающее нулевой или пустой адрес, обозначающий то, что указатель сейчас нельзя использовать для обращения к памяти.

 
Как вы знаете, каждый тип переменной имеет свой размер. Так, например, под тип integer — процессор выделяет 2 байта памяти, а под тип byte — 1 байт. Под longint — DWORD — то есть «двойное слово», что означает 4 байта. Так, WORD — это 2 байта, или «слово». Так, один байт — это две цифры от 00 до FF (в шестнадцатеричной системе исчисления). Для каждого типа данных — свой размер в памяти (какой именно, можно узнать в справочнике по языку).

То есть, как вы уже поняли, если смотреть по нашей таблице, и если бы мы описали переменную — указатель на тип Integer, то она бы заняла ровно 2 байта в памяти и наша таблица, то есть память, приняла бы следующий вид:

Для чего используются указатели?

Как вы знаете, вызов процедур и функций в языках программирования выполняется следующим образом:

1. Сначала параметры, которые должны передаться в процедуру, помещаются в стек (Стек — это область хранения временных и\или локальных переменных и адресов).
2. Процедура извлекает данные из стека в обратном порядке
3. Выполняет свою работу, используя извлечённые из стека параметры

А теперь допустим, что мы написали функцию или процедуру, которой, например, передаются два параметра, строка и число. Так, сначала процессор запишет в стек число, а уже потом строку. Число, например, займёт в стеке 4 байта, что не так критично, а вот строка займёт множество байт, потому что каждый её символ — это один байт. Если сказать точнее, то строка — это массив байт. Так, если например наша строка состоит из 300 или даже 3000 символов? Правильно, в стеке эти 3000 байт займут около 3-х килобайт! Это уже достаточно критично, так как будет затрачиваться достаточное количество ресурсов, как процессора, так и памяти?!
Так вот, чтобы не попасть в эту ситуацию, достаточно передать в функцию только указатель на строку, который, кстати, займёт в стеке всего 4 байта (DWORD). Мы как бы говорим нашей функции, где искать нашу строку, то есть, говорим ей адрес начала строки.

#іncludе <іostrеam.h>
іnt maіn(int argc, char *argv[])

{

  char *lpString;  // Обьявим переменную-указатель на тип char

  char String[] = «Наша новая строка»;  // Обьявим массив (строку)

  cout << String << endl;    // Выводим строку через переменную

lpString = &String[0];    // Присвоим указателю начальный адрес String

  cout << lpString << endl;   // Выводим строку через указатель

  return 0;                             // Конец программы

}

Сама переменная типа указатель объявляется в С++ как обычно, только после указания типа переменной необходимо поставить знак астериска — «*». В примере, я указываю, что объявляю указатель с именем lpString для типа char. Сначала вывожу текст обычно, через переменную, потом, присваиваю указателю lpString адрес переменной String в памяти, для этого используется операция взятия адреса — амперсанд («&»). Тем самым, переменная указатель, получает адрес начала строки в памяти. То есть. как бы устанавливается в нашем случае на ячейку 0 (см.таблицу). И только потом я вывожу строку через указатель, то есть через адрес. Функция cout выводит всё то что было с адреса 0 до последнего символа, пока не встретит в памяти нулевой байт — 0x00 и только потом останавливается.

Кстати, для того чтобы взять значение непосредственно из ячейки — используется операция разыменовывания указателя, путём приставки в виде символа «*» перед началом переменной.
То есть, если бы мы вместо строки:

cout << lpString << endl;

Написали бы:

cout << *lpString << endl;

То получили бы на выходе всего один символ — «Н».

Приведу примеры на остальных языках:

Delphi

program Project2;

uses
  SysUtils,Windows;
var
  String1:array[0..11] of Char = ‘Hello World’+#0; // Обьявляем массив+нуль-байт
  lpString:Pointer = @String1; // Присваиваем указателю адрес массива

begin
  MessageBox (0,lpString,String1,0); //выводим окно с текстом но из разных источников
end.

В данной программе, мы выводим окно посредствам функции MessageBox из WindowsAPI, где заголовок выводим из массива, а главный текст окна — из адреса указателя. Разыменовывание указателя в паскале и делфи можно выполнить с помощью знака «^».

Паскаль

program test1;
var str:string;
    lpStr:pointer;
begin
     lpStr:=@str;
     str:=’Pascal pointer!’;
     writeln (string(lpStr^));
     readln;
     dispose(lpStr);
     lpStr:=nil;
end.

В секции объявлений переменных указываем, что переменная lpStr имеет тип указателя — то есть указывает на какую-то переменную. Как вы наверное уже поняли, операция взятия адреса в паскале осуществляется добавлением знака «@» непосредственно перед той переменной, чей адрес необходимо взять. Так, вы можете видеть, как я присваиваю адрес переменной str указателю lpStr. И затем уже, вывожу строку на дисплей с помощью разыменованного указателя. Указатель необходимо уничтожить функцией Dispose сразу после того, как необходимость в нём отпадает. И затем присвоить ему значение нуль (null, nil, 0x00, в зависимости от языка). Запомните это! Это очень важное правило!

Кстати, обратите внимание, как я вывожу строку:

writeln (string(lpStr^))

Слово string в данном случае указывает на то, что в памяти по этому адресу у нас лежит именно строка, а не число и ничто либо другое. Этого можно избежать, определяя, например, новые типы указателей на целое или строку. Разберём ещё один пример на паскале:

program test1;
uses crt;
type
    lpStr=^string;
    lpInt=^integer;
    lpReal=^real;

var str:string;

    Pointer_String:lpStr;
    Pointer_Integer:lpInt;
    Pointer_Real:lpReal;

    vString:String;
    vInteger:Integer;
    vReal:Real;

begin

    clrscr;
    vString := ‘Where is my pointer?’;
    vInteger := 100;
    vReal := 456.3000;

    Pointer_String := @vString;
    Pointer_Integer := @vInteger;
    Pointer_Real := @vReal;

    writeln (Pointer_String^);
    writeln (Pointer_Integer^);
    writeln (Pointer_Real^);

… тут мы чистим наши указатели…

Тут, мы явно указываем типы указателей. То есть, например, lpStr — это указатель на тип String и тд. И при обращении к разыменованному указателю, мы уже вольны не указывать, на что именно ссылается наш указатель.

Ну, и, в конце концов, посмотрим пример на языке Ассемблера с использованием распространённого компилятора — MASM32. Я не буду приводить весь код, а покажу только самое важное:

.data

String db «Assembly string!»,00 ; Обьявили массив с нулевым байтом на конце

.data?
lpString dd ?    ; переменная (4 байта) указатель, в ней будет адрес String

.code
start:

push offset String  ; кладём в стек смещение переменной String
pop [lpString]    ; вытаскиваем её из стека и кладём в lpString

push 0        ; вызываем окно
push [lpString]    ; c указателями на строки
push [lpString]
push HWND_DESKTOP

call MessageBox

Адрес переменной String мы получаем посредствам директивы OFFSET через стек. Стек я использую потому, что в нём такие операции занимают меньше времени, чем если бы мы написали mov [lpString], offset String. Хотя ошибку эта запись не вызовет, и её можно использовать, если вам так удобно.

Обратите внимание на скобки ( [] )! Ими как вы знаете, мы указываем процессору, с какими значениями оперировать, то есть, если мы пишем String — это адрес строки, а если бы написали [string] — имели ввиду её значение, то есть текст, или число, в зависимости от типа. Но единственная причина, почему мы не написали просто mov [lpString],string — это потому, что такая конструкция категорически не приемлема для компилятора MASM, хотя FASM проглотит это без проблем.

іncludе ‘D:\FASM\include\win32ax.inc’

.data

Count dd 00h;
lpString dd 00h;
string db «Hello Wordl»,00

.code
start:
mov [lpString],string ; в lpString кладём адрес string
invoke MessageBox,0,[lpString],0,0
invoke ExitProcess,0
.end start

Как видите, этот ассемблер справляется с такими конструкциями очень легко.
Ну, вроде с указателями разобрались. Теперь закрепим всё одной удобной таблицей и продолжим работать с указателями.

Указатели — прекрасный инструмент работы со строками

Разработаем программу, которая бы заменяла в строке все символы «*» на пробелы и печатала результат в консоли. Вариант на Си:

#іncludе <іostrеam.h>
#іncludе <wіndows.h>

voіd main()
{
  char* lpCharString;
  char szText[]=»1*2*3*4*5*6*7*8*9*0″;
  int a;

  lpCharString = &szText[0];
  int size;

  for (size = lstrlen (lpCharString); size != 0; size—,lpCharString++)

      {
       if (*lpCharString == ‘*’) *lpCharString = 0x20; cout << *lpCharString;
      }
}

Ничего сложного в ней как видите — нет. Единственное, стоит сказать, что в этой программе, я использую указатель на Char чтобы проверять в цикле значение каждого символа, то есть каждого байта на предмет совпадения с символом-звёздочкой и заменять значения необходимых байтов на пробелы (0x20). В цикле, я увеличиваю адрес на который указывает указатель, для того чтобы он при следующей итерации указывал на следующий символ в строке ровно до тех пор, пока переменная size не будет равна нулю! Давайте посмотрим вариант на

Delphi:

program Pointers;

{$APPTYPE CONSOLE}

uses
  SysUtils,Windows;

var
  szStr: array [0..20] of Char;
  lpStr:^Char;
  iSize:Integer;
  Counter:Integer;
begin
  szStr:=   ‘1*2*3*4*5*6*7*8*9*0’;
  lpStr:=   @szStr;
  iSize:= Length(szStr);

  for Counter:=1 to iSize-2 do
  begin
    if lpStr^ = ‘*’ then begin
      lpStr^ := ‘ ‘;
    end;
      write (lpStr^);
      inc (lpStr);
  end;
  Readln;
end.

Как видите тоже всё достаточно удобно и наглядно. Но одну вещь я всё — таки объясню. Видите, где в цикле я указываю -2 от общей длины? Так вот, формат Delphi строк таков, что перед самой строкой стоит поле типа WORD и в этом поле содержится длинна строки. Выглядит это вот так:

А так как нам они не нужны, мы просто их отнимаем и всё. Хотя если не отнимать — всё будет работать конечно. Но я вам просто показал, каков формат Delphi строк. В остальном, в этой программе всё полностью идентично той, которая запрограммирована на Си. С паскалем дела обстоят так же.

Продолжение следует… Читайте новые посты!

Posted in Delphi, Новичку, С и С++ | 3 комментария »

Стили программирования. Выбираем свой!

Posted by devprog на Ноябрь 3, 2008

Все программируют по разному. Кто-то предерживаеться рационального стиля кто-то стиля Алмена, а кто-то изобретает свои, всё новые и новые стили программирования. В данный момент я предлагаю вам выбрать самый удобный для себя стиль программирования. Вы поймёте это сразу, просто взглянув на кусок кода.

Рациональный стиль:


Один из наиболее распространённых стилей. Его начали использовать ещё Керниган и Ричи — авторы языка Си. Выглядит он примерно вот так:

if (perem) {
print(«perem is true»);
}

Сейчас даже Ява программисты используют этот стиль, но на мой взгляд — он не удобен.

Стиль Алмена (стиль BSD)

if (perem)
{
    print(«perem is true»);
}

Вот тут всё ясно и понятно, мы сразу видим где блок начинается и где он кончается. Мой выбор.

Стиль Whitesmith

if (perem)
{
print(«perem is true»);
}

Мы не отступаем ни одного пробела после начала блока. Стиль по моему более чем неудобный…

Стиль GNU


Количесиво пробелов-отступов должно быть кратным числу 2. Не больше 8. То есть 2,4…8.

perem = true;
if (perem)
{
        print(«perem is true»);
}
else
{
        print(«perem is false»);
}

Ну как? Какой вы выбрали стиль? Я думаю или GNU или BSD. Я прав?

Posted in Новичку, Программирование, С и С++ | 5 комментариев »