Советы по Delphi. Версия 1.4.3 от 1.1.2001 - Валентин Озеров
Шрифт:
Интервал:
Закладка:
begin
MFileOpen := TOpenDialog.Create(Application);
MFileOpen.Filename := GetValue;
MFileOpen.Filter := 'Правильный тип файлов|*.*'; (* Поместите здесь ваш собственный фильтр...*)
MFileOpen.Options := MFileOpen.Options + [ofPathMustExist,ofFileMustExist];
try
if MFileOpen.Execute then SetValue(MFileOpen.Filename);
finally
MFileOpen.Free;
end;
end;
Записи
Пример переменной записи
В Delphi 2.0 я пытаюсь прочесть текстовый файл и получаю проблему. Текстовый файл, который я хочу прочесть, имеет записи фиксированной длины, но в самих записях могут располагаться различные типы с различной длиной, и оканчиваться в различных позициях, в зависимости от типа.
Файл выглядит примерно так:
TFH.......<First record type, первый тип записи>
TBH.......<Second record type, второй тип записи>
TAB........<Third record type, третий тип записи>
TAA........<Fourth record type, четвертый тип записи>
Вы можете поймать больше одного зайца в случае объявления переменной записи, но если сделаете это правильно.
Type
TDataTag = Array [1..3] of Char;
TDataTags = Array [0..NumOfTags-1] of TDataTag;
TDataRec = packed Record
tagfield: TDataTag;
case integer of
0: ( поля для тэга TFH );
1: ( поля для тэга TBH );
2: …
…
end;
TMultiRec = packed Record
Case Boolean of
false: (строка: Array [0..1024] of Char);
{ должно установать строку максимально возможной длины }
true : ( data: TDataRec );
End;
Const DataTags: TDataTags = ('TFH', 'TBH', …);
var rec: TMultirec;
ReadLn(datafile, rec.line);
Case IndexFromDataTag(rec.data.tagfield) Of
0: …
1: …
IndexFromDataTag должен искать передаваемый тэг поля в массиве DataTags. Определите все поля в TDataRec как Array [1..someUpperBound] of Char.
– Peter Below
Передача массива записей символов в Memo
Delphi 1
Тема: Передача массива записей символов в Memo.
Обработка больших строк в 16-битной версии Delphi задача далеко непростая. Особенно когда строки являются частью структуры записи и вы хотите передать их в TMemo. В данном совете показано как создать структуру записи размером 1000 символов, прочесть в нее содержимое Memo и затем записать ее обратно в Memo. Основной метод, который мы здесь используем — метод Memo GetTextBuf. Используемая структура записи представляет собой простую строку и массив из 1000 символов, но структура могла бы быть сложнее.
unit URcrdIO;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,Forms, Dialogs, StdCtrls,dbtables;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private { Private declarations }
public { Public declarations }
end;
type
TMyRec = record
MyArray: array [1..1000] of char;
mystr: string;
end;
var
Form1: TForm1;
MyRec : TMyRec;
mylist : TStringlist;
PMyChar : PChar;
myfile : file;
mb : TStream;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
assignfile(myfile, 'c:testblob.txt');
rewrite(myfile,1);
fillchar(MyRec.MyArray,sizeof(MyRec.MyArray),#0);
pmychar:[email protected];
StrPCopy(pmychar,memo1.text);
Blockwrite(MyFile,MyRec,SizeOf(MyRec));
closefile(MyFile);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
assignfile(myfile, 'c:testblob.txt');
reset(myfile,1);
fillchar(MyRec.MyArray, sizeof(MyRec.MyArray),#0);
Blockread(MyFile, MyRec, SizeOf(MyRec));
pmychar:[email protected];
Memo1.SetTextBuf(pmychar);
end;
end.
Освобождение записей
Delphi 1
Для начала необходимо привести объект к нужному типу, например, так:
var
i: integer;
begin
…
for
i := 0 to MyList.Count - 1 do dispose(PMyRecord(MyList[i]));
MyList.Free;
end;
или
begin
for i := 0 to MyList.Count - 1 do dispose(PMyRecord(MyList.items[i]));
MyList.Free;
end;
Items — свойство по умолчанию, поэтому вам нет необходимости определять это, хотя обратное не помешает.
Теперь можно заняться созданием работоспособной и полезной функцией. В форме:
var p : ^mystruct;
begin
new(p);
…
dispose(p);
end;
операторы new() и dispose() в точности соответствуют процедурам getmem() и freemem(), за исключением того, что компилитор распределяет количество байт под размер структуры, на которую ссылается переменная-указатель. По этой причине указатель должен быть типизированным указателем, и следущий код неверен:
var
p: pointer;
begin
new(p);
end;
поскольку невозможно установить размер памяти, на которую должен ссылаться указатель. С другой стороны, если вы используете getmem() и freemem(), вы можете распределять байты для нетепизированного указателя, например:
var p : pointer;
begin
getmem(p, 32767);
…
freemem(p, 32767);
end;
Строки
StrTok для Delphi 2
Delphi 2
Я передалал это для работы в Delphi 2.0, код приведен ниже (эта функция первоначально была написана John Cooper 76356,3601 и модифицирована мной для адаптации под Delphi 2.0).
…вот этот код:
function StrTok(Phrase: Pchar; Delimeter: PChar): Pchar;
const
tokenPtr: PChar = nil;
workPtr: PChar = nil;
var
delimPtr: Pchar;
begin
if (Phrase <> nil) then workPtr := Phrase
else workPtr := tokenPtr;
if workPtr = nil then begin
Result := nil;
Exit;
end;
delimPtr := StrPos(workPtr, Delimeter);
if (delimPtr <> nil) then
begin
delimPtr^ := Chr(0);
tokenPtr := delimPtr + 1
end else tokenPtr := nil;
Result := workPtr;
end;
– Ralph Friedman
Как мне перекодировать строки из Win-кодировки в Dos-кодировку и наоборот?
Одной строкой
Как мне перекодировать строки из Win-кодировки в Dos-кодировку и наоборот?
Nomadic отвечает:
A: CharToOEM, OEMToChar, CharToOEMBuff, OEMToCharBuff. Заметьте однако, что эти функции не умеют делать таких, например, вещей, как koi8-r в DOS и т. п.
Типы
У меня константы могут иметь значение, отличное от заданного. Как лечить?
Nomadic советует:
DX.Bug: Const из другого unit'а дает неверное значение.
Симптоматика –
Unit Main;
Interface
Uses VData;
Const Wko=0.9;
…
Unit VData;
…Implementation
Uses Main;
Procedure ...;
Begin
{ вот здесь Wko=...E+230 - наверное, бесконечность }
End;
Похоже, это действительно bug, причем ОСОБО ОПАСНЫЙ, т.к. может исказить результаты расчетов, не вызвав заметных нарушений работы программы.
В общем так. Эксперимент показал, что любая вещественная константа, определенная в интерфейсе модуля, может быть неверно (и не обязательно очень неверно – например, вместо 0.7 может появиться 0.115) прочитана в другом модуле. Баг особенно опасен тем, что он неустойчив и может пропадать и возникать без видимых причин (например, возникнуть, если предыдущая компиляция была неудачной и исчезнуть после использования константы в модуле, где она определена).