Function Overloading (препокриване на функции)
Идеята за overloading дава възможност да се обявят и използват няколко функции с еднакво име, но с различен брой и/или различен тип на параметрите. т.е. компилаторът различава функциите не само по име, но и по параметрите им.
Основни правила за overloading:
всяка версия на подпрограма трябва да се следва от служебната дума overload.
разликата между версиите трябва да бъде в броя или типа на параметрите или и в двете.
типът на връщания резултат не може да бъде разлика между две функции.
Декларации:
function Min (A, B: Integer): Integer; overload;
function Min (A, B, C: Integer): Integer; overload;
function Min (A, B: Double): Double; overload;
Default Parameters (параметри по подразбиране)
Базовата идея е на някои от формалните параметри да се присвои стойност още при деклариране на подпрограмата, а при обръщение към нея с фактически параметри, може да се изпуснат онези от тях, които имат предварително дефинирани стойности.
Пример:
procedure MessBox(Msg: string; Caption: string = ‘Warning’;Flags: LongInt = 15);
begin
// тяло на процедурата
end;
С такава декларация могат да се направят следните обръщения с фактически параметри.
MessBox (‘Something wrong here !’);
// равнозначно на
// MessBox(‘Something wrong herte !’,’Warning’, 15);
MessBox(‘Something wrong herte !’, ‘Attention’);
// равнозначно на
// MessBox(‘Something wrong herte !’, ‘Attention’, 15);
MessBox(‘Hello’, ‘Message’, 10);
//равнозначно на същото
Има едно важно ограничение – не може да се пропускат параметри. Следващото обръщение е грешно!
MessBox(‘Hello’, 10); // error
Други правила за параметрите по подразбиране са:
Параметрите с подразбиращи се стойности трябва да бъдат в края на списъка от параметри.
Подразбиращите се стойности трябва да бъдат константи. Очевидно това ограничава типа данни, които могат да бъдат използвани за константи. Така например записи не могат да бъдат използвани.
Подразбиращите се параметри трябва да се предават по стойност или като const. Параметрите по име (var) не могат да имат подразбиращи се стойности
Указатели
Указателите принадлежат към допустимите типове данни в Delphi.
Допустимите стойности на променливите от този тип са адреси от оперативната памет. Поради това често казваме, че указателите сочат към нещо. Всички видове указатели имат допустима стойност nil. Притежаващият тази стойност указател не сочи на никаде!
Основната употреба на указателите е при използване на динамична памет.
Указателите биват типизирани и нетипизитани.
Нетипизираният указател се обявява така:
var Ptr : pointer;
Той съдържа само адреса на първия байт от някоя поредица и никаква допълнителна информация.
Типизираният указател се обявява така:
type < име на тип на указател> = ^<тип данни>;
или
var <име на указател> = ^<тип данни>;
Пример:
type Pint = ^Integer;
…………………..
var P1, P2 : Pint;
или
var P1, P2 : ^Integar;
Типизираният указател съдържа адреса на първия байт + информация как да се тълкува (декодира) съдържанието на следващите байтове.
В приведения пример указателят може да сочи само към поредица от байтове, чието съдържание може да се тълкува само като Integer. Не може real, не може string и т.н.
Самото обявяване на указателите не ги насочва към нищо.
Насочване на указател
Насочването на типизиран указател към променлива от същия тип може да стане по един от следните два начина.
Нека var PtoI : ^Integer;
I : Integer;
Тогава а) PtoI^ := I;
или
b) PtoI := @I; // @ е операция ‘вземане на адрес’
насочва указателя PtoI към променливата I.
Сега ако програмата има оператор I := 5;
то на стойността 5 може да се позоваваме както чрез променливата I, така и чрез указателя PtoI^.
Насочените типизирани указатели могат да участват в изрази допустими за типа им. Например:
I := P1^ + P2^;
Динамична памет
Динамичното разпределение на паметта се използва широко за икономия на памет. Идеята е променливи и обекти, които вече няма да се ползват от програмата, да се унищожават, т.е. Да се освобождава заеманата от тях памет и тази памет да се използва от нови променливи и обекти структурирани по нов начин.







Управление на динамичната памет
За динамично разпределение се отделя специален немалък участък от паметта , наречен heap (купчина).
Управлението се извършва с помоща на процедурите
procedure New (<име на типизиран указател>);
procedure Dispose (<име на типизиран указател>);
Процедурата New присвоява на името на указателя адреса на началото на отделената част от паметта. Размерът на тази част се определя от типа на указателя.
Процедурата Dispose освобождава паметта, динамично заета от процедурата New. Всичко друго води до непредсказуеми грешки.
Dispose освобождава памет, но не изменя стойността на указателя, т.е. не го прави nil. Това е грижа на програмиста.
Пример:
type
rec = record
name : string[40];
year : Integer;
end;
var Prec : ^rec;
………………
New(Prec);
with Prec^ do
begin name := ‘Ivanov’;
year := 1984;
end;
………………….
Dispose (Prec);
……………………..
Други процедури
Друга двойка процедури управляващи паметта са:
procedure GetMem (<име на указател>, <обем на паметта в байтове>);
procedure FreeMem (<име на указател>,<обем на паметта в байтове>);
Първата процедура резервира указания обем памет и го свързва с указателя, а втората – освобождава.
За разлика от съответните New и Dispose, тук
 указателят може да бъде и нетипизиран
 явно се указва обема на паметта в байтове.
При ползване на типизиран указател най-добре е обема на използваната памет да се определи чрез SizeOf. Така в приведения по-горе пример аналозите на New и Dispose ще бъдат:
GetMem(Prec, SizeOf(rec));
FreeMem(Prec, SizeOf(rec));
Не може да се смесват двете групи процедури, т.е. не може да се резервира с процедура от едната група и да се освобождава с процедура от другата.
Вместо GetMem може да се ползва функцията AllocMem.
function AllocMem (Size : Cardinal): Pointer;
Както се вижда тя връща нетипизиран указател. Обръщение:
Ptr := AllocMem(1000);
Освобождаването на паметта става чрез FreMem.
Файлове
Файлът е организирана съвкупност от данни върху външно запомнящо се устройство – диск, дискета, CD.
Според съдържанието и организацията им различаваме три вида файлове: текстови, типизирани и нетипизирани.
Текстовите файлове са последователности от символи, разделени на редове. В Delphi за тях има предопределени топове Text и TextFile. Обявяването става така:
var <име на файлова променлива> : TextFile;
var MyFile : TextFile;
Типизираните файлове са двоични файлове съдържащи последователности от еднотипни данни. Обявяването на файлове от този тип става така:
var <име на файлова променлива > : file of <тип данни>;
Например:
var F : file of real;
В реални задачи по-скоро ще се срещне тип запис.
type person = record
name : string;
age : integer;
money : real;
end;
var F : file of person;
Нетипизираните файлове са двоични файлове, съдържащи последователности от байтове. Дешифрирането на байтовете е дело на програмиста. Обявяването става така:
var <име на файлова променлива> : file;
var F : file;
Основните извършвани операции при работа с файлове са запис на данни и извличане на информация (четене) от тях.
Работа с файлове
Работата с файлове в програма на Delphi условно може да се раздели на пет основни стъпки:
1) Деклариране на файлова променлива. Тя представлява логически файла. Съответно
var myTextFile: TextFile; // текстов файл
var myBinaryFile: file of Integer; // типизиран файл
var myFile: file; // нетипизиран файл
2) Свързване на файловата променлива с физически файл от външната памет. Това се извършва със стандартната процедура AssignFile, без значение вида на файла:
AssignFile(myTextFile, ‘number.txt’);
Първият параметър е файловота променлива, а втората е името на физическия файл. Допуска се включването напълен път в името на файла.
3) Отваряне на файла. С помощта на различни процедури се указва как ще се работи с файла:
procedure Reset(var F : File);
Reset(F);
Открива съществуващ файл, свързан вече с F. Файлът се отваря за четене като файловият указател се позиционира в началото на файла. Използва се при всички видове файлове.
procedure Rewrite(var F : File);
Rewrite(F);
Създава и/или открива свързания с F файл. Файлът се отваря за запис като файловият указател се позиционира в началото на файла. Използва се при всички видове файлове.
procedure Append (var F : File);
Append(F);
Отваря съществуващ файл за добавяне и позиционира файловия указател в края на файла. Използва се само при текстови файлове.
4) Четене или запис от файл.
Операторите за четене и писане от и в текстов файл са:
procedure Read(var F: TextFile; < списък променливи>);
procedure Write (var F: TextFile; <списък изрази>);
Примери:
Write( F, ‘You are’ , Age, ‘ years old’);
Read( F, S1, Age, S2);
Версиите на тези процедури Writeln и Readln съответно записват и четат допълнително символа ‘нов ред’.
Процедурите Read и Write за типизирани файлове не се различават от тези за текстовите файлове. Единствената разлика е, че съответстващите променливи и изрази трябва да са от типа на файла.
5) Затваряне на файла.
procedure CloseFile(var F : file); CloseFile(F);
Схема за четене
var F : TextFile;
begin
AssignFile(F, ‘MyData.txt’);
Reset(F);
// Последователно четене и обработване по редове
CloseFile(F);
end;
Схема за писане var F : TextFile;
begin
AssignFile(F, ‘MyData.txt’);
Rewrite(F);
// Обработка и последователно записване
CloseFile(F);
end;
Допълнителни възможности
Функциите Eof (end of file) и Eoln (end of line) са за проверка дали е достигнат край на файл или ред съответно. Eoln се използва само при текстови файлове.
Съществуват процедури и функции, които се използват за пряк достъп до данните във файл.Те работят само с типизирани и нетипизирани файлове:
function FileSize(var F): Integer; - Връща размера на файла (броя на елементите му). Ако файлът е презен, връща стойност 0.
function FilePos(var F): Longint; - Връща текуща позиция на файла (номер на елемента, на който файлът е позициониран в момента).
procedure Seek(var F; N: Longint); - Премества текущата позиция на файла F в елемент с номер N (цяло число).
Файлов обмен чрез компоненти
Това е друг начин за работа с файлове.Основно се ползват класовете Tstrings и TStringList. Те имат методи Load FromFile и SaveToFile.
Схемата за работа е както следва:
a) Обявяване на променливи
var List : TStrindList;
Sfile : AnsiString;
b) Създаване на променливите
List := TSringList.Create;
Sfile := ‘C:\MyTest\Test.txt; //реално обработван файл
c) Откриване на файл
List.LoadFromFile(Sfilew);
d) За да се запише резултата се ползва
List.SaveToFile(Sfile);
e) Файлът се освобождава чрез
List.Free;
Преглеждане на текстов файл
Ако файлът се открива, за да бъде прегледан (директно, с очи), по-добре е да се ползват компонентитеMemo и RichEdit. Свойството Lines на тези компоненти има тип Tstrings. Това позволява към него директно да бъдат приложени методите LoadFron(Sfile) и SaveToFile(Sfile);
Например:
Memo1.Lines.LoadFromFile(Sfile);
RichEdit1.Lines.LoadFromFile(Sfile);
Memo1.Lines.SaveToFile(Sfile );
Задание: Да се състави приложение на Делфи, което да предоставя възможност за въвеждане на текст, който да се записва в текстов файл. Приложението да може да прочита записания файл и да определя броя на редовете в текста.
Код на програмата:
var myTextFile: TextFile; // глобална променлива
……………………
procedure TfrmForm.btnZapisClick(Sender: TObject);
begin
AssignFile(myTextFile,'belejki.txt');
Rewrite(myTextFile); // отваря файла за запис
Write(myTextFile,Memo1.Lines.Text);
CloseFile(myTextFile);
Memo1.Clear;
btnZapis.Enabled:=False;
btnOtvori.Visible:=True;
lblBroi.Visible:=True;
end;


This entry was posted at 11:55 and is filed under . You can follow any responses to this entry through the .

0 comments