.:ВХОД:.
Эта страничка посвящена программированию на Delphi (под Windows) и Pascal (под DOS). Всё, чего тут касается только следующих языков (версии):
Delphi 7 и Turbo Pascal 7.1. Может работать (должно) и в младших версиях - но не ручаюсь за все команды.
.:DOS -> Windows:.
Я столкнулся со следующими проблемами при переходе из под DOS'овского Pascal'я в Delphi под Windows:
• Функции для работы с файлами поменяли свои имена:
Pascal (DOS) - Delphi (Windows):
Assign(Fl, 'filename.ext') - AssignFile(Fl, 'filename.ext')
Close(Fl) - CloseFile(Fl)
• Размер памяти, выделяемой процедурой GetMem, больше не ограничен максимальным размером сегмента в 64K (65535 байт).
• Тип Integer стал размером в 32-бита, и равнозначен использованию типа LongInt (который, кстати, не изменился).
• Появились новые типы:
Имя типа = Диапазон = Формат
SmallInt = -32768..32767 = со знаком 16-бит (это "старый" Integer)
Cardinal = 0..4294967295 = беззнаковый 32-бита
LongWord = 0..4294967295 = беззнаковый 32-бита
Int64 = -2^63..2^63-1 = со знаком 64-бита
• С дробными типами дело обстоит так:
Имя типа = Диапазон = Значащие цифры = Размер в байтах
Real48 = 2.9 x 10^-39 .. 1.7 x 10^38 = 11-12 = 6 (это "старый" Real)
Real = 5.0 x 10^-324 .. 1.7 x 10^308 = 15-16 = 8
• Длину строки больше нельзя указать как S[0]:=#4, для этого используется процедура: SetLength(S,4).
• ВНИМАНИЕ!!! Под строки больше не выделяется 256 байт памяти!!! Память выделяется автоматически, в зависимости от изменения длинны строки.
Так что НЕЛЬЗЯ писать что-то после последнего символа строки - там может быть область других переменных!!!
• Появился тип AnsiString - это строка длинной, не поверите, в 2 Гб (!!!). Старый тип называется ShortString.
• Если в программе какая-то переменная типа String, то, в зависимости от переключателя {$H+} (по умолчанию) или {$H-} эта переменная будет либо AnsiString, либо ShortString.
• Ну и, само собой, в Delphi ПОЛНОСТЬЮ отсутствуют модули CRT, Graph, DOS (хотя кое-какие функции из модуля DOS перекочевали в модуль SysUtils, например FindFirst / FindNext, GetTime и что-то ещё).
• Также изменились имена используемых констант. Если раньше для атрибута файла "только чтение" надо было писать ReadOnly, то теперь нужно faReadOnly (File Attribute Read Only). Просто посмотрите, что требуется и добавьте первые буквы необходимого сокращения.
• Delphi в отличие от Pascal может разбирать сложные выражения. Например, вот это выражение Delphi обработает правильно:
{ из программа EAUnpacker - см. раздел "Программы" и "Статьи -> Распакуй файло"}
Var
K, Bl: Byte;
L: LongInt;
...
L:=0;
For K:=3 DownTo 0 Do
Begin
BlockRead(F, Bl, 1);
L:=L+(Bl Shl (8*K)); { < - обратите внимание на эту строку! }
End;
...
В данном случае Pascal её скомпилирует (ошибки нет) - но БУДЕТ НЕПРАВИЛЬНО СЧИТАТЬ ЭТУ СТРОКУ!!! У меня есть подозрение, что он просто пропускает какие-то сложные вложенные операторы... А вот Delphi - тот считает правильно.
Вычитал в Интернете недавно, что если написать:
L:=L+LongInt(Bl Shl (8*K));
то всё будет работать. Т.е. сделать явное приведение типов. Т.к. оказывается, что в Pascal и Delphi результат операции зависит только от типа входящих в неё переменных, но не от типа результата.
.:Разбор полётов:.
Если начали писать под Delphi - то не надо стараться поддерживать принцип "сверху - в низ", т.е. если читаете что-то в память, не заботьтесь об этих 64Кб, используйте SetLength и прочее. Я, например, пишу под Delphi, когда мне нужно чтобы программа поддерживала длинные имена, или чтобы работать с графикой было проще (TBitmap). Несколько советов:
• Во многих случаях, если в этом нет острой необходимости (например пишите распаковщик) - делайте консольное приложение (File -> New -> Other... -> [New] -> Console Application). Так как GUI приложение со всеми формами (даже если она одна) жрёт много места (имеется ввиду .EXE файл).
• Небольшой пример, для извращенцев как я, которые пытаются запихнуть элемент на форму во время выполнения:
Procedure CreateTextEdit;
Var TextEdit: TEdit;
Begin
TextEdit:=TEdit.Create(TextEdit);
TextEdit.Parent:=Form1; { имя формы, которой будет принадлежать элемент }
TextEdit.Name:='TextEdit1';
End;
{ Свойство Name неплохо задать, чтобы можно было "забить" на указатель TextEdit и найти нужный элемент через:
TextEdit:=TEdit(Form1.FindComponent('TextEdit1'));
после чего делаете с TextEdit, что душе угодно...}
• Хорошо бы, как и в Pascal, не забывать и "чистить" память. Речь идёт не только о FreeMem, Dispose и прочих, а об объектах:
Picture:=TBitmap.Create; { создаём объект }
Picture.LoadFromFile('image.bmp'); { что-нибудь с объектом делаем }
Picture.Width:=10;
Picture.Height:=10;
Picture.Canvas.Pixels[0,0]:=RGB(255,0,0);
Picture.Free; { <- чистим память из-под созданного объекта }
Хороший тон, всё же...
• Чтобы прочитать из файла строчку фиксированной длинны (например сигнатуру) не обязательно читать её посимвольно в цикле n раз. Можно сделать так:
SetLength(S,4); { указываем размер строки !!! иначе в Delphi будете писать в память, которой нет !!! В Pascal напишите: S[0]:=#4 }
BlockRead(Fl, S[1], 4); { S[1] - адрес ПЕРВОГО элемента строки, т.е. адрес
начиная с которого нужно считывать. НЕ ПИШИТЕ ПРОСТО S или S[0] - ЗАТРЁТЕ длину строки!!! }
Подобным же макаром можно обращаться и с массивами.
• В Delphi есть такая штука как динамические массивы. Вот пример их использования:
Procedure Example;
Var
Arry: Array Of Integer; { массив элементов типа Integer }
I: LongInt;
Begin
SetLength(Arry, 10); { выделяем память под 10 элементов массива }
{ чего-нибудь с массивом делаем; например, зануляем все элементы; функция Length работает так же как и для строк - возвращает количество элементов }
For I:=0 To Length(Arry)-1 Do { индексация массива начинается с нуля !!! }
Arry[I]:=0;
... { чего-нибудь там ещё делаем }
SetLength(Arry, 0); { в конце уничтожаем массив }
End;
.:ВыХОД:.
Ваши пожелания - ответы тут...