الإستثناءات

مايو 7, 2009

الفصل الثامن

الإستثناء هو حدوث شئ مخالف للمسار الطبيعى للبرنامج فنقوم بوضع ترتيبات خاصة لمعالجة هذه الحالات على سبيل المثال لدينا موظف وقمنا بتحديد المرتب له الى 0 او قمنا بقسمة عدد ما على 0 او نحاول فتح ملف غير موجود او او او

على سبيل المثال

type
     THuman=class(Tobject)
        Constructor Create(aName: String);

        private
               fName: String;
              Function GetName: String;
              Procedure SetName(aName: String);

        public
              property Name: String read GetName write SetName;
              procedure PrintMe; virtual;
              class procedure About; virtual;

     end;

     { TEmp }

     EValueError=class(Exception);
     TEmp=class(THuman)
         Constructor Create(aName:String; aSalary: Integer);

         private
                fSalary: Integer;
                Function GetSalary: Integer;
                Procedure SetSalary(aSalary: Integer);


         public
               property Salary: Integer read GetSalary write SetSalary;
               procedure PrintMe; override;
               class procedure About; override;
               class Function GetNHumans: Integer;
     end; 

لدينا صف THuman و TEmp الذى يرثه ولدينا نوع خطأ EvalueError -استثناء ليشير الى قيمة خاطئة- وهو يرث الصف Exception
يهمنا من جزئية TEmp جزئية تحديد المرتب
function TEmp.GetSalary: Integer;
begin
Result:=self.fSalary;
end;

procedure TEmp.SetSalary(aSalary: Integer);
begin
if aSalary <= 0 then Raise EValueError.Create('You should offer more!'); self.fSalary := aSalary; end; [/sourcecode] لاحظ اذا كان المرتب قيمته اقل من او تساوى 0 فيتم رفع -القاء- استثناء بإستخدام Raise وتأخد كائن من الإستثناء وهنا هو EValueError ونمرر للمشيد له رسالة you should offer more عند التنفيذ نقوم بوضع الكود بين قسمى try, except [sourcecode lang="delphi"] try e1.Salary:= -20; except on ex:EValueError do begin writeLn('invalid salary...'); writeLn('EMessage: ', ex.Message); end; end; [/sourcecode] فيتم محاولة تنفيذ الكود فى قسم try وعند حدوث استثناء من نوع EValueError نقوم بتعريف هذا الإستثناء بإسم ex لنستطيع الوصول الى معلومات مفيدة حوله كالرسالة اللتى يحملها ex.Message نحتاج ايضا فى بعض الأحيان الى تنفيذ كود دائما كغلق اتصال مع قاعدة بيانات او غلق ملف او او -تستخدم غالبا للتخلص من ال resources المفتوحة- وهنا نأتى الى try/finally [sourcecode lang="delphi"] try //somecode finally //executed..[/sourcecode] توفر اللغات طريقة لدمج try, except, finally سويا [sourcecode lang="delphi"]try //somecode except //somecode on error finally //always executed.. [/sourcecode] ولكن فى FPC تستطيع تحقيق ذلك بإنشاء قسم فرعى ل try/except داخل try/finally كالتالى مثلا [sourcecode lang="delphi"]try try e1.Salary:= -20; except on ex:EValueError do begin writeLn('invalid salary...'); writeLn('EMessage: ', ex.Message); end; end; finally WriteLn('Always executed..'); [/sourcecode]

التعامل مع الملفات

مايو 7, 2009

الفصل السابع

اهم الطرق

 

Reset(F)
تفتح ملف فى وضع القراءة

Rewrite(F) 

تفتح ملف فى وضع الكتابة

Append(F) 

بتفتح ملف فى وضع الإضافة

Assign(F, file_path) 

بتسند الملف المفتوح ل File Handler من النوع File
Flush
بت flush ال buffer

Close(F) 

بتغلق الFile Handler

EOLN(F) 

EOLN: End of Line
نهاية السطر؟

EOF(F) 

EOF: End of File
نهاية الملف؟

Erase(F) 

لحذف ملف ما

Rename(F, new_name)   

تسمية F ل new_name

Seek(F, pos) 

بتنقل الموقع الحالى لpos معين فى ال File

SeekEOF(F) 

بتنقل ال الموقع الحالى لي نهاية الملف

SeekEOLN(F) 

بتنقل ال الموقع الحالى ل نهاية السطر

التعامل مع الملفات النصية
اولا تنشئ متغير من النوع Text فى ال قسم المتغيرات

   F:Text; 

2- تسند ليه ملف ما

 Assign(F, 'textf.txt');

الكتابة

3- للكتابة استدعى ReWrite عليه

Rewrite(F); 

4- اكتب فيه بإستخدام WriteLn

   For I:=0 To 10 do
       begin
            WriteLn(F,'Hello, World');
       end; 

طبعا عرف ال I فى قسم المتغيرات

   I: Integer; 

الإضافة
3- استدعى ال Append عليه

Append(F); 

4- ضيف اى شئ انت تريدها وليكن سطر واحد مثلا كالتالى

   WriteLn(F,'a HELLO WORLD LINE!'); 

القراءة
3- استدعى ال Reset عليه

   Reset(F); 

4- تقدر تقرا السطور بإستخدام ReadLn كالتالى مثلا

    //Loop till the EOF
   Repeat
         ReadLn(F, Line);
         WriteLn(Line);
   
   Until EOF(F);

هنا هيتم قرائة كل سطر وطباعته (فى متغير Line:String تم تعريفة فى ال قسم المتغيرات )

اخيرا تقفل المقبض
5-اقفل المقبض

   Close(F); 

بعض الدوال المساعدة

ExtractFileName(F)

الحصول على اسم

ExtractFilePath(F) 

الحصول على المسار الموجود فيه الملف

 ExtractFileExt(F)

الحصول على امتداده

 ExtractFileDir(F)

الحصول على اسم المجلد الموجود فيه الملف

ExtractFileDrive(F) 

الحصول على اسم الدرايف

عرف procedure كالتالى مثلا

Procedure GetInfo(F: String);
begin
    WriteLn('F    :', F);
    WriteLn('FileName    :', ExtractFileName(F));
    WriteLn('FileDirPath    :', ExtractFilePath(F));
    WriteLn('FileExt     :', ExtractFileExt(F));
    WriteLn('FileDir     :', ExtractFileDir(F));
    WriteLn('FileDrive   :', ExtractFileDrive(F));
end;

وحاول تمرر ليه شئ مثل

c:lazarusbinlaz.exe

    GetInfo('c:lazarusbinlaz.exe');

F: ‘c:lazarusbinlaz.exe’
FileName :laz.exe
FileDirPath :c:lazarusbin
FileExt :.exe
FileDir :c:lazarusbin
FileDrive :c:

تعالى للكود

 program Project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, SysUtils
  { you can add units after this };

Procedure GetInfo(F: String);
begin
    WriteLn('F    :', F);
    WriteLn('FileName    :', ExtractFileName(F));
    WriteLn('FileDirPath    :', ExtractFilePath(F));
    WriteLn('FileExt     :', ExtractFileExt(F));
    WriteLn('FileDir     :', ExtractFileDir(F));
    WriteLn('FileDrive   :', ExtractFileDrive(F));
end;
var
   F:Text;
   I: Integer;
   Line:String;
begin
   Assign(F, 'textf.txt');
   //Rewrite
   {
   Rewrite(F);
   For I:=0 To 10 do
       begin
            WriteLn(F,'Hello, World');
       end;
   Close(F);
    WriteLn('Written!');
   }
   
   //Append
   {
   Append(F);
   WriteLn(F,'a HELLO WORLD LINE!');
   Close(F);
   WriteLn('Appended!');
   }
   
   //Reading
    {
   Reset(F);
   //Loop till the EOF
   Repeat
         ReadLn(F, Line);
         WriteLn(Line);
   
   Until EOF(F);
   

   WriteLn('Done Reading!');
   }
   
   //Close(F);
   
   //GetInfo('c:lazarusbinlaz.exe');

   ReadLn;

end.

طبعا هتحتاج تشيل ال كومينت من على كل قسم للتنفيذ

ناقص التعامل مع ال typed files

تقدر تتابع اكثر هنا
http://delphi.about.com/od/fileio/Fi…ith_Delphi.htm

البرمجة الكائنية

مايو 7, 2009

الفصل السادس

ال Object Oriented Programming موضوع لذيذ جدا وهو مش فيه اى جديد عن حياتك.. اذا بصيت لأى شئ حواليك هتلقيه Object انسان عربية طيارة شجرة عمارة.. الخ
كلهم بيشتركو فى كلمة انهم Object! ولكن لكل شئ فيهم خصائص محددة ووظائف خاصة فيه نيجى الأول نفرق ال Class عن ال Object
على فرض لدينا لوحة مرسوم عليها تصميم عمارة => هى دى الصف
لكن اذا تم انشاء العمارة من التصميم دا => هو دا الكائن
عندك تصميم لروبوت ومتحدد عليه خصائصه ووظايفه => هو دا الصف
اذا شركة اخدت التصميم دا ونفذته => هو دا الكائن

على فرض اننا بنعمل تصميم لإنسان (على الورق) يعنى الصف

type THuman=class(TObject)

     Constructor Create(aName: String; aSex: Char; aColor: String);
     private
            fname: String;
            fsex: Char;
            fcolor: String;


     public

            Function GetSex(): Char;
            Procedure SetSex(aSex: Char);
            Function GetColor(): String;
            Procedure SetColor(aColor: String);
            Function GetName(): String;
            Procedure SetName(aName:String);
            Procedure Eat();
            Procedure Sleep();
end; 

اول كلمة هتقلها ماهذا كله ؟
نمشى مع الكود واحدة واحدة

 type Thuman=class(TObject)

معناها أننا بنعرف Type جديد بإسم Thuman (لاحظ ان اى Type) بنبدأه ب T “مجرد عادة”
الإنسان دا ليه مميزات او صفات مثل ان ليه اسم وليه لون وليه نوع ودى اسمها fields
(لاحظ ان اى field بنبدأه ب f)
لن نسمح لأى حد بلمسها -يعدل فيها او يتعامل معاها- غيرى انا -الصف- وبموافقتى وشروطى ودا بيتم من خلال ال Getters/Setters methods لو لاحظت ان كل Field ليه Getter/Setter
fname ليها

Function GetName(): String;
            Procedure SetName(aName:String); 

fsex ليها

Function GetSex(): Char;
            Procedure SetSex(aSex: Char); 

fcolor ليها

                        Function GetColor(): String;
            Procedure SetColor(aColor: String); 

ال Get/Set Methods بنبدأها بشئ مناسب Get/Set 🙂

نيجى بعد كدا للوظائف الذى بيعملها ال Human دا وهى مثلا Eat, Sleep وwalk و Work وغيرهم دى اسمها methods

لاحظ اى Function/Procedure داخل صف بيسمى Method او تحديدا Instance Methods إلا فى حال اننا حددناها انها Class Method (مش تصعبها على نفسك حاليا)

جميل جدا كدا نحن بنخلى العالم الخارجى يتعامل مع ال Fields الخاصة بالصف عن طريق ال Getters/Setters ولكن اذا لاحظت انها غلسة شوية.. ناس كتير اشتغلت Vbاو Delphi وكان عندهم مفهوم كلمة ال Properties وهنا الموضوع بيكون الذ شوية كالتالى

type THuman=class(TObject)

 Constructor Create(aName: String; aSex: Char; aColor: String);
     private
            fname: String;
            fsex: Char;
            fcolor: String;
            Function GetSex(): Char;
            Procedure SetSex(aSex: Char);
            Function GetColor(): String;
            Procedure SetColor(aColor: String);
            Function GetName(): String;
            Procedure SetName(aName:String);
            Procedure Eat();
            Procedure Sleep();
     public


           property Name: String read GetName write SetName;
           property Sex: Char read GetSex write SetSex;
           property Color: String read GetColor write SetColor;
           Procedure InspectMe();



end; 

لاحظ اننا خلينا ال Getters/Setters فى ال Private Section :S
طب العالم الخارجى هيتعامل ازاى مع ال Fields الخاصة بنا كدا ؟ بكل بساطة هيستخدم ال Properties مثل Name, Sex, Color

لعمل اى Property بتستخدم الصيغة العامة كالتالى

property property_name : Type read Getter write Setter; 

كالتالى مثلا

      property Name: String read GetName write SetName 

;
هنا لدينا Property -خاصية- بإسم Name وهى من النوع String (بتتعامل بال String) سواء فى عملية ال Get او ال Set

 .Name=val //set(write), sets fname to a string
.Name //Get(read), returns fname (a string)

جميل سامع واحد بيقول انت بتشتغلنا ياعم! فين الكود نفسه؟
هقله اتقل شوية نحن لحد الآن فى ال Interface (مبرمجى السى/++ بيحبو يسموه ال Header) لسه هنعمل ال Implementation فى قسم لوحدها كالتالى

 Constructor THuman.Create(aName: String; aSex: Char; aColor: String);
begin
     //inherited;
     fname:=aName;
     fsex:=aSex;
     fcolor:=aColor;
end;

Function THuman.GetName(): String;
begin
     Result := Self.fname;
end;

Function THuman.GetSex(): Char;
begin
     Result := Self.fsex;
end;

Procedure THuman.SetName(aName: String);
begin
     Self.fname:=aName;
end;

Procedure THuman.SetSex(aSex: Char);
begin
     Self.fsex:=aSex;
end;

Function THuman.GetColor(): String;
begin
     Result:= Self.fcolor;
end;

Procedure THuman.SetColor(aColor: String) ;
begin
     Self.fcolor:=aColor;
end;
Procedure THuman.InspectMe() ;
begin

     WriteLn('Name: ', Self.fname);
     WriteLn('Color: ', Self.fcolor);
     WriteLn('Sex: ', Self.fsex);
end;
Procedure THuman.Eat()
begin
     //Code to eat.
end;
Procedure THuman.Sleep()
begin
     //Code to sleep.
end;

اوبس فى واحد بيقولى انت نسيت تقول ال Constructor دا يعنى إيه!

ال Constructor بكل بساطة هو Function ولكن ليها اسم مميز Constructor .. لماذا ؟
جميل نحن قلنا ان اى كائن بيمر على مرحلتين
المرحلة الأولى التصميم والتانى الإنشاء
التصميم هو الذى نجهز فيه بقالنا فترة وتحديد ال Fields و ال Methods وال Properties وغيرهم لكن الإنشاء هو اننا نحول التصميم دا لكائن ودا بيتم عن طريق ال Constructor “المنشئ او المشيد” وفيه بيتجهز ال Data Members (مسمى تانى لل Fields) بالقيم الإفتراضية مثلا الString ياخد Null والInt ياخد Zero وهكذا * او * القيم الذى انت تريدها (ال Arguments الذى هتتمرر لل Constructor ) فعلا انت راجل 10/10
مثل ماحصل هنا بالظبط

Constructor THuman.Create(aName: String; aSex: Char; aColor: String);
begin
     //inherited;
     fname:=aName;
     fsex:=aSex;
     fcolor:=aColor;
end; 

ملحوظة: مش لازم تسمى ال Constructor بإسم Create ولكنه تقليد متعارف عليه ^_^
جميل جدا الصف الجميل الذى كتبناه دا مش هنسيبه متعلق فى الهوا كدا لازم نحطه فى مكان مناسب ليه

اعمل وحدة جديدة
File -> New Unit
وسميها وليكن Creatures وضيف فيها الذى كتبناه كالتالى
ملحوظة: ال UNIT -الوحدة- هى ملف بنجمع فيه الأجزاء المترابطة من شغلنا مثلا لو بندرس ال OOP وبنعمل صفات للدراسة مثل Human, Robot, Bird, .. etc نخليها Creatures او مثلا Employer, Employee, Customer, .. etc تخليها Business وهكذا…

unit creatures;

{$mode objfpc}{$H+}


interface
type THuman=class(TObject)

     Constructor Create(aName: String; aSex: Char; aColor: String);
     private
            fname: String;
            fsex: Char;
            fcolor: String;
            Function GetSex(): Char;
            Procedure SetSex(aSex: Char);
            Function GetColor(): String;
            Procedure SetColor(aColor: String);
            Function GetName(): String;
            Procedure SetName(aName:String);
            Procedure Eat();
            Procedure Sleep();
     public


           property Name: String read GetName write SetName;
           property Sex: Char read GetSex write SetSex;
           property Color: String read GetColor write SetColor;
           Procedure InspectMe();



end;


implementation

Constructor THuman.Create(aName: String; aSex: Char; aColor: String);
begin
     //inherited;
     fname:=aName;
     fsex:=aSex;
     fcolor:=aColor;
end;

Function THuman.GetName(): String;
begin
     Result := Self.fname;
end;

Function THuman.GetSex(): Char;
begin
     Result := Self.fsex;
end;

Procedure THuman.SetName(aName: String);
begin
     Self.fname:=aName;
end;

Procedure THuman.SetSex(aSex: Char);
begin
     Self.fsex:=aSex;
end;

Function THuman.GetColor(): String;
begin
     Result:= Self.fcolor;
end;

Procedure THuman.SetColor(aColor: String) ;
begin
     Self.fcolor:=aColor;
end;
Procedure THuman.InspectMe() ;
begin

     WriteLn('Name: ', Self.fname);
     WriteLn('Color: ', Self.fcolor);
     WriteLn('Sex: ', Self.fsex);
end;
Procedure THuman.Eat()
begin
     //Code to eat.
end;
Procedure THuman.Sleep()
begin
     //Code to sleep.
end;

end. 

واعمل save ليها
وتعالى نختبرها فى اى برنامج مثلا oopconcepts1
كالتالى مثلا

program ooConcepts1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, creatures
  { you can add units after this };

var
   ahmed: THuman ;
begin
     ahmed:=THuman.Create('Ahmed', 'm', 'white');
     ahmed.InspectMe();
     
     ahmed.Name:='youssef';

     ahmed.InspectMe();
     
     ReadLn;
end.
 

الوراثة

اعمل برنامج جديد وضيف ليه unit بإسم creatures

type

{ THuman }

THuman=class(TObject)

     Constructor Create(aName: String; aSex: Char; aColor: String);
     private
            fname: String;
            fsex: Char;
            fcolor: String;
            function GetColor: String;
            function GetName: String;
            Function GetSex(): Char;
            Procedure SetSex(aSex: Char);
            Procedure SetColor(aColor: String);
            Procedure SetName(aName:String);


            
     public

           class Procedure About; virtual;
           property Name: String read GetName write SetName;
           property Sex: Char read GetSex write SetSex;
           property Color: String read GetColor write SetColor;
           Procedure Eat();
           Procedure Sleep();
           Function InspectMe(): String; virtual; //Should be overriden in the child.

end; 

صف جديد بإسم THuman

فى هنا fields لل name, sex, color وفى private getters/setters
وفى public functions/procedures ومجموعة من ال properties
about: يعرض كلمة عن الصف دا والمفترض انه يتغير فى ال child
الprototype ليه كالتالى

          class Procedure About; virtual; 

هنا لاحظ اننا بادئين التعريف ب class لنعبر على ان الطريقة دى خاصة بالصف يعنى تستدعيها ب
Thuman.About
بدون الشئ لإنشاء object من ال Thuman class
فى Function بإسم InspectMe للحصول معلومات عن ال fields الموجودة بالصف ولكن المفروض نعيد تعريفها فى اى صف هيورثه

نيجى لل implementation الخاصة ب الصف دا

{ THuman }

constructor THuman.Create(aName: String; aSex: Char; aColor: String);
begin
     Self.fname:=aName;
     Self.fsex:=aSex;
     Self.fcolor:=aColor;


end;

function THuman.GetColor: String;
begin
     Result:=Self.fcolor;
end;

function THuman.GetName: String;
begin
    Result:=self.fname;
end;

function THuman.GetSex(): Char;
begin
   Result:=self.fsex;
end;


procedure THuman.SetSex(aSex: Char);
begin
  self.fsex:=aSex;
end;



procedure THuman.SetColor(aColor: String);
begin
     self.fcolor:=aColor;
end;


procedure THuman.SetName(aName: String);
begin
   self.fname:=aName;
end;

procedure THuman.Eat();
begin
    WriteLn('Eatin');
end;

procedure THuman.Sleep();
begin
    WriteLn('Sleepin');
end;

class procedure THuman.About;
begin
    WriteLn('Human class');
end;

function THuman.InspectMe(): String;
begin
    Result:='Name: '+self.fname + LineEnding + 'Sex: '+self.fsex + LineEnding+ 'Color: '+self.fcolor;
end; 

واضحة مثل المثال السابق ولكن ال Thman.InspectMe محتاجة بعض التوضيح

 function THuman.InspectMe(): String;
begin
    Result:='Name: '+self.fname + LineEnding + 'Sex: '+self.fsex + LineEnding+ 'Color: '+self.fcolor;
end;

هى بتعمل دمج لمجموعة من ال strings + بتضيف LineEnding (لو متأقلم مع ال Escape Sequences فهى ال n)

نيجى بقة لل TEmployer هو صف بيعبر عن انسان ليه اسم ولون ونوع + (مرتب)
فياإما نكتب كل الصف THuman داخل ال Temployer او نستخدم ال وراثة بإننا نورث ال Thuman لل Temployer ونضيف الجديد ليه

 type

{ TEmployer }

TEmployer=class(THuman)
      Constructor Create(aName: String; aSex: Char; aColor: String; aSalary:Integer);
      
      private
             fsalary:Integer;
             Function GetSalary():Integer;
             Procedure SetSalary(aSalary:Integer);
      
      public
            class Procedure About; override;
            Function InspectMe(): String;override;
            property Salary:Integer read GetSalary write SetSalary;


end;

بمجرد انك كتبت

Temployer=class(THuman) 

فهنا ال Temployer هيورث كل الذى فيه ال Thuman

ال

 Function InspectMe(): String;override; 

لازم نعيد تعريفها بحيث تتوافق مع الخصائص الجديدة للصف دا مثل المرتب مثلا!
لاحظ اننا سنعيد تعريف ال About, InspectMe
الآن ال Implementation الخاصة به

 { TEmployer }

constructor TEmployer.Create(aName: String; aSex: Char; aColor: String;
  aSalary: Integer);
begin
     inherited Create(aName, aSex, aColor);
     self.fsalary:=aSalary;

end;

اولا ال Constructor
هنا الأول لازم نمرر ال قيم الخاصة بالصف الأب الذى هى ال aName, aSex, aColor للمشيد الخاص بالTHuman وال fields الجديدة نجهزها مثل ال fsalary
لاحظ استخدام inherited هنا دى بتنقلك للالأب صف الخاص بال Temployer وبعدها Create “بتعبر عن ال Thuman.Create “

 function TEmployer.GetSalary(): Integer;
begin
     Result := self.fsalary;
end;



procedure TEmployer.SetSalary(aSalary: Integer);
begin
       self.fsalary:=aSalary;

end;
class procedure TEmployer.About;
begin
  WriteLn('Employer class!');
end; 

هنا اعادة تعريف ل About

function TEmployer.InspectMe(): String;
begin
     Result := inherited InspectMe + LineEnding + 'Salary: '+IntToStr(self.fsalary);
end; 

هنا اعادة تعريف ل InspectMe بنستدعى ال InspectMe الخاصة ب الأب الذى هترجعلنا String

function THuman.InspectMe(): String;
begin
    Result:='Name: '+self.fname + LineEnding + 'Sex: '+self.fsex + LineEnding+ 'Color: '+self.fcolor;
end; 

وبعدها ندمج الناتج ب LineEnding و جملة

'Salary:' +IntToStr(self.fsalary) 

هنا بنحول قيمة ال fsalary ل string لأنها integer ومش ينفع ندمج string مع integer

الآن البرنامج

program ooConcepts1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  sysutils, Classes, creatures
  { you can add units after this };

var
   ahmed: TEmployer;

begin
    
    ahmed:=TEmployer.Create('Ahmed', 'm', 'white', 90000);
    WriteLn(ahmed.InspectMe());

    //Set name
     ahmed.Name:='youssef';
    //Set salary
    ahmed.Salary:=100000;
    WriteLn(ahmed.InspectMe());
    TEmployer.About;
    ahmed.Eat;


    ReadLn;
end. 

انشئ كائن من ال Temployer

    ahmed:=TEmployer.Create('Ahmed', 'm', 'white', 90000); 

اعرض بيناته

    WriteLn(ahmed.InspectMe()); 

تقدر تعدل فى ال -خصائص- Properties براحتك
اخيرا استخدام ال class method

     Temployer.About;

وهى طريقة بتنتمى للصف لا الكائن

المصفوفات والسجلات

مايو 7, 2009

الفصل الخامس

المصفوفات

تخيل إنك بتكتب برنامج وليكن بتتعامل فيه مع الطلاب الذى معاك فى الفصل -خارج الكلام عن قواعد البيانات- مثلا
ممكن تعمل مثلا 30 متغير يعبرو عن ال 30 طالب مش كدا ؟

student1;
  student2;
  student3;
  student4;
  student5; 

ممممم تأكد انك لو عملت كدا والكود بتاعك اتراجع هتكون مطرود من الشغل فى تانى دقيقة 😀
الحل الطبيعى إنك تعمل Array تربط فيها بين ال 30 طالب دول

  students: array[1..4] of string;

لاحظ لتقوم بتعريف اى array يلزمك
1- ال Range وهنا من 1 ل 4
2 نوع ال Items الذى فى ال Array وهنا String

ونتعامل مع ال Array الذى عرفناها كالتالى

students[1] := 'Ahmed';
     students[2] := 'Chris';
     students[3] := 'George';
     students[4] := 'Youssef'; 

لاحظ اننا حددنا ان اول عنصر هو 1 واخر عنصر هو 4 (من ال Range)
تقدر تحصل على القيمة المخزنة فى index معين بإنك تحدد ال index فقط كالتالى مثلا
WriteLn(‘Students[1]: ‘, students[1]); //Ahmed;
ملحوظة: معظم اللغات بتبدأ ال arrays فيها من ال 0 مش 1 بعكس Pascal تقدر تحدد اول قيمة تبدأ فيها براحتك.. فاانا عن نفسى مازلت بستخدم ال 0 كبداية مع Pascal زي باقى اللغات.. ولحل هذه المشكلة بنستخدم 2 Function يسهلو علينا الموضوع دا بغض النظر عن البداية والنهاية لل Array كالتالى مثلا

for index:=Low(students) to  High(students) do
         begin
              WriteLn('Student[', index, ']: ', students[index]);
         end; 

Low هتعيد اول Index فى ال Array
High هتعيد اخر Index فى ال Array

احيانا قد نحتاج إلى Dynamic array بمعنى إننا نحدد عدد العناصر فى ال run-time فبكل بساطة
students: array of string; // we don’t specifiy the range as it’s zero based array.
لاحظ إن ال array هنا هتكون zero-indexed

بعد كدا نحدد ال length بإستخدام SetLength

SetLength(students, stNumber); 

حيث ان stNumber هو عدد ال students ..

EnumS

بكل بساطة هى تصميم Data Type جديد مكون من قيم محددة مثلا الفصول او ايام الإسبوع او الإتجاهات!

 Type
 TDay = (Saturday=1, Sunday=2, Monday=3, Tuesday=4, Wednesday=5, Thursday=6, Friday=7);

مثلا نهاية الإسبوع هو Friday
فالأول نعلن إن نهاية الإسبوع هو من النوع Tday يعنى هياخد قيمة من الذى تم تحديدها فى Tday

var
  weekend: TDay; //friday..     

نسند القيمة Friday

      weekend := Friday;

بسيطة مش كدا ؟

TDays = set of TDay; 

لاحظ ان TDays هى عبارة عن set من ال TDay اى مجموعة هتشمل بعض العناصر الذى من النوع TDay

وبكدا عملنا مجموعة خاصة بال أيام .. نقدر نعمل منها متغير وليكن بإسم busyDays ونحط فيه الأيام الذى الواحد بيكون مشغول فيها !

 busyDays : Tdays;

busyDays:=[];
 Include(set, VALUE);

ونقدر نضيف فيها بإستخدام Include

 Exclude(set, VALUE);

نقدر نحذف منها بإستخدام Exclude

    busyDays := busyDays + [Saturday]; {Include(set of enum, value)}
   busyDays := busyDays - [Sunday];   {Exclude(set of enum, value)}

تابع المثال التالى

type
    TDay = (Saturday=1, Sunday=2, Monday=3, Tuesday=4, Wednesday=5, Thursday=6, Friday=7);
    TAlphabet= 'a'..'z';
    TDays = set of TDay;

var
  weekend: TDay; //friday..
  today: TDay;
  c: TAlphabet;
  busyDays : TDays;
begin
     weekend := Friday;
     busyDays:=[];
     Include(busyDays, Saturday);
     Include(busyDays, Sunday);
     Include(busyDays, Friday);

     //busyDays := busyDays + [Saturday]; {Include(set of enum, value)}
     //busyDays := busyDays - [Sunday];   {Exclude(set of enum, value)}

     today := Saturday;

     if today = Saturday then
        WriteLn('Happy Saturday!');

     if Sunday in busyDays then
        WriteLn('I am busy -> Sunday'); 

لاحظ تقدر تختبر وجود value ما فى set معينة كالتالى

 if val in someSet then
  if_suite

السجلات

ال Record هو Type جديد بتنشأه بيكون فيه معلومات مترابطة عن شئ معين وليكن كتاب بدل ماتقول

 name_of_book_1 := 'Introduction to Ruby';
pages_of_book_1 := 147;
author_of_book_1 := 'ahmed';

ولا

book1.Name := 'Introduction to Ruby';
book1.nOfPages := 147;
book1.author := 'ahmed' ; 

هل لاحظت الفرق ؟
الكود اكتر وضوح ومترابط اكثر لأننا قمنا بتجميع مكونات “نوع” او سجل مكون من اكثر من متغير كل منها له قيمة !
نخبر باسكال عن هذا السجل الجديد

 type
    TBook = record
          Name: String;
          Pages: Integer;
          Author: String;
    end;  

لاحظ إن فى اعتقاد اننا نبدأ اى Type جديد بحرف ال T

 var
   rubyBook: TBook;
   pythonBook: TBook;
   javaBook: Tbook; 

هنا انشأءنا 3 متغيرات من النوع Tbook وهم rubyBook و PythonBook و javaBook
نسند لهم بعض القيم

   rubyBook.Name:='Introduction to Ruby';
   rubyBook.Pages:=147;
   rubyBook.Author:='Ahmed Youssef';

   pythonBook.Author:='Ahmed Youssef';
   pythonBook.Pages:=258;
   pythonBook.Name:='Introduction to Python';

   javaBook.Author:='Ahmed Youssef';
   javaBook.Name:='Introduction to Java';
   javaBook.Pages:=159; 

جميل نقدر الوقتى نعرض كل Field فيهم مثلا

WriteLn(javaBook.Author);
WriteLn(javaBook.Name);
WriteLn(javaBook.Pages); 

ولكن هل يعقل إننا نكتب الكلام دا 3 مرات ؟
بالظبط كدا انت فهمتنى لازم نعمل Extract ل اجراء يقوم بالمهمة دى عننا كالتالى مثلا

 procedure ShowInfo(book: TBook);
begin
     WriteLn('Name: ', book.Name);
     WriteLn('Pages: ', book.Pages);
     WriteLn('Author: ', book.Author);

end;

هنا ال ShowInfo Procedure هياخد book ك argument من نوع Tbook ويعرض لينا ال Fields الخاصة بيه Name, pages, Author

نقدر نضم Records جوا Records بالطبع تابع المثال التالى هيجاوب كل الذى فى بالك عن ال Records

 program records;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes
  { you can add units after this };

type
    TBook = record
          Name: String;
          Pages: Integer;
          Author: String;
    end;
    TSex = (MALE, FEMALE);

    TPerson = record
            Name: String;
            Age : ShortInt;
            Sex : TSex;
    end;

    TApartment=record
         Owner: TPerson;
         Area: integer;
         NumberOfRooms: ShortInt;
         PopulatedWith: ShortInt;
    end;

procedure ShowInfo(book: TBook);
begin
     WriteLn('Name: ', book.Name);
     WriteLn('Pages: ', book.Pages);
     WriteLn('Author: ', book.Author);

end;
var
   MyApartment:TApartment;
   Me : TPerson;
   rubyBook: TBook;
   pythonBook: TBook;
   javaBook: TBook;

begin
   rubyBook.Name:='Introduction to Ruby';
   rubyBook.Pages:=147;
   rubyBook.Author:='Ahmed youssef';

   pythonBook.Author:='Ahmed youssef';
   pythonBook.Pages:=258;
   pythonBook.Name:='Introduction to Python';

   javaBook.Author:='Ahmed Yousef';
   javaBook.Name:='Introduction to Java';
   javaBook.Pages:=159;

   Me.Age:=19;
   Me.Name:='Ahmed';
   Me.Sex:=MALE;

   WriteLn('My Name is: ', Me.Name);
   WriteLn('My Age  is: ', Me.Age);
   if Me.Sex = Male then
      WriteLn('And MALE!')
   else
      WriteLn('And a WOMAN!');

   MyApartment.Area := 400;
   MyApartment.Owner:=Me;
   MyApartment.NumberOfRooms:=10;
   MyApartment.PopulatedWith:=4;

   WriteLn('Name of the owner -> ', MyApartment.Owner.Name);
   WriteLn('Area  -> ', MyApartment.Area);
   WriteLn('Number of rooms -> ', MyApartment.NumberOfRooms);
   WriteLn('Populated With  -> ', MyApartment.PopulatedWith);

   ReadLn;

end.

المؤشرات

المؤشر هو متغير بيحتوى على قيمة ولكن القيمة هى عنوان متغير تانى من نفس نوعه .. تابع المثال التالى

 num: Integer;

هنا num هو متغير من نوع Integer

  p_num: Pinteger;  // Or you may use ^Integer;

هنا p_num هو pointer بيشير إلى متغير من النوع Integer

 num := 5;

اعطينا ل num ال value مساوية ل 5

p_num :=@num; //address of num...  

اعطينا ل p_num ال value وهى مساوية لعنوان num فى الذاكرة ونقدر نحصل عليها بإستخدام ال @ قبل اسم المتغير.

     WriteLn('Address of num: ', Integer(@num));
    WriteLn('Value of num: ', num);
    WriteLn('p_num, points to the address: ', Integer(p_num));
    WriteLn('p_num^, the value contained at the address that p_num points to is: ',      Integer(p_num^));

للحصول على القيمة المخزنة فى المتغير اللذي يشير ليه p_num نقدر نحصل عليها كالتالى

p_num^ 

بكل تأكيد تستطيع ان تستخدم pointer ل anonymouse addresses! يعنى مش شرط تعمل متغير وتجعل الpointer يشير ليه.. لأ، تقدر تحجز منطقة فى ال ميمورى وتخلى ال pointer يشير ليها بدون اهتمامك بإسم هذه المنطقة!
كالتالى مثلا

var
   p: PInteger; // is a pointer to integer
begin
   //allocate memory for it
   New(p); // Simple ha ?
   WriteLn('P points to: ', Integer(p));
   //set value
   P^ := 7;
   WriteLn('p^: ', p^);

   //Free memory!
   FreeMem(p);

   ReadLn;
end. 

لاحظ ان Pascal حدد حجم الميمورى المطلوبة بناء على نوع p بإستخدام New(p)
يوجد طرق اخرى مثل GetMem -قد نتعرض ليها لاحقا-

خزنا قيمة فى الذاكرة الذى p بيشير ليها وهى 7
وحررنا الذاكرة التى حجزناها بإستخدام FreeMem

ال Casting او التحويل القسرى هو تحويل من نوع بيانات لنوع اخر

لاحظ فى البرنامج التالى إننا إستخدمنا P ليكون Pointer ل Integer و Char وتم ذلك بإننا عملنا Cast ليه فى الحالتين!

     program dynamicP;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes
  { you can add units after this };
var
   dp: Pointer;
   i : Integer;
   c : Char;
begin
     i := 5;
     c := 'a';

     //let dp points to i.
     PInteger(dp) := @i;   //cast dp into PInteger type.
     WriteLn('@i : ', Integer(@i));
     WriteLn('dp: ', Integer(dp));

     WriteLn('i: ', i);
     WriteLn('dp^ :', Integer(dp^));

     //let dp points to c.

     PChar(dp) := @c;  //cast dp into PChar type.
     WriteLn('@c: ', Integer(@c));
     WriteLn('dp: ', Integer(dp));

     WriteLn('c: ', c);
     WriteLn('dp^: ', Char(dp^));

     //Wait for
     ReadLn;

end. 

الدوال والإجراءات

مايو 7, 2009

الفصل الرابع

كثير من الناس للأسف لايعلم الفرق بين ال Function -دالة- وال Procedure -اجراء-! فى الواقع معظم اللغات حاليا لاتفرق بينهم .. يوجد من يعتبر ان ال procedure هو حالة خاصة من Function وفى بيعتقد العكس ان ال Function هى الحالة الخاصة من ال procedure وهكذا!

ملحوظة لمبرمجى C/C++/C# اى Function ال return type لهاvoid هى procedure !

نتكلم الأول ماهى هى ال Function او ال Procedure ؟
بإختصار هى كود اتكتب مرة وسيستخدم بكثرة فبدل مايكتب كل مرة .. كتبناه مرة واحدة ثم نستخدمه داخل برنامجنا.. على سبيل المثال .. اننا نريد ان نعرض رسالة معينة فى برنامجنا بصورة دورية وليكن كالتالى مثلا

WriteLn('Hi');
WriteLn('Hi');
WriteLn('Hi'); 

هل تعتقد إن يعقل إنك تكتب ال 4 سطور دول فى كل مرة تريد تظهر فيها الرسالة ؟ او على فرض إنك غيرت الرسالة من Hi ل Hola مثلا هل هتقعد تعدل فى كل السطور ؟
رائع جدا فإحنا تريدين نكتب ال block دا مرة واحدة وننفذه كل ماحبينا بدون مانكرر نفسنا! فبكل بساطة هنكتب procedure او function تنفذلنا الذى نحن تريدينه كالتالى مثلا

 procedure SayHi3Times;
    var
       counter : Integer;
     begin
           WriteLn('Hi');
           WriteLn('Hi');
          WriteLn('Hi');
    end;

الكود السابق يعمل 100% ولكن مش تصميم حلو ل procedure ليه ؟ على فرض إننا حبينا نغير ال implementation بتاعنا او تريدين نخليها 4 times او او او .. فلازم نراعى تصميم ال procedure بطريقة جيدة كالتالى مثلا

procedure SayHi3Times;
    var
       counter : Integer;
     begin
       for counter := 1 to 3 do
           begin
                WriteLn('Hi');
           end;
    end; 

ونستدعيه فى اى مكان فى برنامجنا كالتالى

    SayHi3Times;

رائع جدا بالنسبة ل Procedure بيعرض رسالة hi ل 3 مرات! طب على فرض إنى تريد اغير ال 3 مرات دول اخليهم 4 او 5 ؟ قدامى اكتر من حل … منها إنى اعدل ال implementation نفسها واخلى ال counter يعد لحد ال 4 او ال 5 .. او إنى اخلي ال Procedure مصمم بطريقة افضل .. بحيث إنى احدد عدد مرات الرسالة بدون ماصدع نفسى 🙂

procedure SayHi(NumberOfTimes: Integer);
     var
        counter: Integer;
     begin
          for counter := 1 to NumberOfTimes do
              begin
                   WriteLn('Hi!');
              end;
     end; 

لاحظ هنا اننا حددنا ان عدد مرات تكرار الرسالة ك Parameter وهو NumberOfTimes وحددنا ان ال Data Type بتاعه هو Integer
فكدا الموضوع اصبح اسهل 🙂

SayHi(5); //Say hi 5 times.
     SayHi(7); //Say hi 7 times. 

وكدا اصبح كل المطلوب مننا هو اننا نمرر عدد مرات التكرار ك argument لل procedure SayHi!
جميل .. كدا نقدر نطلع بتعريف لل procedure .. هو code اتكتب ليتم استخدامه اكتر من مرة بدون الشئ لكتابته فى كل مرة
لاحظ الفرق بين ال Parameter وال argument: هو إن ال parameter هو الذى متحدد انه هيتمرر لل Function فى التعريف بتاعها ولكن ال argument هو الذى تمرر بالفعل!

نيجى لل Functions
على فرض إننا تريد نحسب قيمة مساحة مربع مثلا طول ضلعه 5 مثلا ولكن مش تريدين نكرر نفسنا فى كل الكود ف إننا نكتب العلاقة
بالمناسبة العلاقة هى مربع طول الضلع 😀

 function AreaOfSquare5: Integer;
      begin
           Result := 5*5;
      end;

ونستخدمه كالتالى

WriteLn('The Area of Square (5 units length): ', AreaOfSquare5); 

واحد هيسأل ايه قيمة AreaOfSquare5 ؟ الذى موجودة فى WriteLn ؟
الإجابة هى الشئ الوحيد الذى تقدر تخمنه 🙂 هى قيمة ال Result
وبكل تأكيد ال Integer الذى موجودة فى السطر دا

function AreaOfSquare5: Integer; 

بتعبر عن ال Data Type الخاص ب Result !
رائع جدا .. لاحظ إنك مش تقدر تمرر procedure لأن ال procedure مش ليها Result هو إجراء بينفذ شئ معين مش اكتر ولكن ال Function بتنفذ شئ معين + ترجع ليك النتيجة النهائية 🙂
ملحوظة لمعظم المبرمجين: Result هى Return
ال Function الخاصة بنا شغالة مثل الفل بالنسبة ل Function تحسب مساحة مربع طول ضلعه 5مش كدا ؟ 🙂
ولكن كناس يهمها انها مش تكرر نفسها! لازم نعيد تصميم ال Function بحيث إنها تساعدنا مع كل الأطوال مش ال5 بس ؟
اها صح .. كدا انا تأكدت إنك فهمت ال Function Parameters بنسبة 100% 😀
نحدد طول الضلع ك Parameter فى ال Function ونتعامل بناء عليه 😀

 function AreaOfSquare(Side: Integer): Integer;
      begin
           Result := Side*Side;
      end;

ونستخدمها بالصورة دى

     WriteLn('The Area of Square (3 units length): ', AreaOfSquare(3));
     WriteLn('The Area of Square (9 units length): ', AreaOfSquare(9)); 

تابع ال Function التالية..

 function AreaOfRect(H: Integer; W:Integer): Integer;
      begin
           Result := H*W;
      end;

المفروض إنها تحسبلنا مساحة اى مستطيل طوله H وعرضه W (وهنا مررناهم ك Parameters ) ليكون الكود بتاعنا ابسط + لعدم الشئ لكتابة 100 مليون Function بنفس الإسم لكل طول وكل عرض !
والإستخدام كالتالى

WriteLn('The Area of Rect   (7H, 4W)        : ', AreaOfRect(7, 4)); 

بسيطة ها ؟

نيجى لشئ مهمة وهى ال Overloading .. مشكلة ال C انها كانت الأسامى بتخلص فيها بسرعة.. تخيل مثلا مش ينفع تكتب غير Function واحدة بإسم واحد! ؟ لكن اللغات الحديثة معظمها بيقدم ال Overloading وفيها بيكون ال Compiler/interpreter ذكى بيقدر يحدد اي Function المبرمج إستخدمها بناء على عدد ال Argument الذى هو باصاها لل Function!

Overloading
تعالى نشوف مثال ل overloading على procedure وليكن hola

procedure hola; 

دا ال procedure الأساسى ولكن إكتشفنا إننا ممكن تريدين نحدد عدد المرات ك argument لل procedure !
فبكل بساطة

procedure hola(Times: Integer); overload; 

معنى Overload اننا هنعمل implementation خاصة ل hola فى حال لو اتمرر ليه Integer والكمبيلر مشكلته هو انه يعرف اى procedure هيستدعيه!

 hola

هنا الكمبيلر هيستدعى الأولى

     hola(7); 

وهنا هيستدعى التانية

مثال اخر

 function Area(Side:Integer): Integer;

هنا هيتم استدعاء ال Function دى لو اتمرر ليها Argument واحدة معبرة عن ال Side لو إستخدمناها بالشكل دا

 WriteLn('The Area of Square (5 units length): ', Area(5)); 
 function Area(H: Integer; W: Integer): Integer; overload;

وهنا تعريف تانى مختلف وبيتم إستدعاءه فى حال لو إتمرر 2 arguments ك H, W لمستطيل وهكذا …

لاحظ القابليه لوجود اكتر من صورة ل Function او Procedure او او هى ال Polymorphism وخليها فى بالك لحد مانوصل لل OOP 🙂

Inline
انك تحدد ال Function على إنها inline بيعنى استخدامها ك macro لمستخدمى ال C (مع اختلاف جوهرى ان شاء الله هنتعرض ليه)
بإختصار .. اذا ال Function الخاصة بك صغيرة فعرفها على انها inline لتضمن اداء افضل فى برنامجك
ولكن خلى بالك ان حجم ال executable هيزيد!

مثلا Function للحصول على ال ABS او القيمة المطلقة لعدد

القيمة المطلقة: هى القيمة الموجبة للعدد او العدد بدون الإشارة السالبة إذا كانت موجودة
مثلا 8 .. القيمة المطلقة ليها هى 8
مثلا -8 .. القيمة المطلقة ليها هى 8

 function ABS(Num: Integer) :Integer;
    begin
         if Num > 0 then
            Result := Num
         else
            Result := -Num;
    end;

ولكنك المفترض إنك تعرفها على إنها inline وت implement ال Function على إنها inline كالتالى مثلا

function ABS(Num: Integer) :Integer; inline; //Faster.
    begin
         if Num > 0 then
            Result := Num
         else
            Result := -Num;
    end; 

المتحكمات والتكرار

مايو 7, 2009

الفصل الثالث

Pascal بتقدملك طرق للتحكم فى برنامج وإختبارات -مثل كل اللغات- خلال البرنامج مثل if, then ,elseif, else, case, .. etc.

if then
if_suite

تابع المثال التالى فى حال إذا كان الName الذى هيدخله المستخدم قيمته ahmed سينفذ الBlock -مجموعة الأسطر-التالية ل then وإلا لن يتم تنفيذ شئ -لأننا لم نخبر برنامجنا إن يعمل شئ معين لو Name قيمته ليست احمد 🙂

 var
  Name: String;
  
begin
  Write('Enter your name: ');
  ReadLn(name);

  if name = 'ahmed' then
   WriteLn('Access Granted.');
  {else
   WriteLn('Access Denied.');
  }
  ReadLn();

end.

ملحوظة:
:= -> لإسناد قيمة
= -> لإختبار قيمة

 X := 5;

هنا اعطينا المتغير X ال 5

 x = 5;
 x = 5 

هنا بنختبر هل ال او لأ!

if then
if_suite
else
else_suite

var
  Name: String;
  
begin
  Write('Enter your name: ');
  ReadLn(name);

  if name = 'ahmed' then
   WriteLn('Access Granted.')
  else
   WriteLn('Access Denied.');

  ReadLn();

end. 

لاحظ دور else هنا .. إن إذا تم إدخال اى قيمة غير ahmed هيتنفذ الBlock التابع ل else وهو Access Denied!

var
  age: Integer;
  
begin

  WriteLn('Enter your age: ');
  ReadLn(age);
  
  if age < 18 then
     WriteLn('Not old enough for driving test.');
  else
     WriteLn('GOOD LUCK!');
end. 
 &#91;/sourcecode&#93;

لو العمر اقل من 18 سينفذ هذا الblock
&#91;sourcecode lang="delphi"&#93;WriteLn('Not old enough for driving test.'); &#91;/sourcecode&#93;

لو لأ سيتنفذ 
&#91;sourcecode lang="delphi"&#93;WriteLn('GOOD LUCK!');
 &#91;/sourcecode&#93;
    



<strong>if/else if/ else</strong>

if  then
<em>if_suite</em>
elseif  then
<em>elseif_suite</em>
else
<em>else_suite</em>

تابع المثال التالى

 var
  Number: Integer;
  
begin
     Write('Enter a number in range 1, 5: ');
     ReadLn(Number);
     
     if Number=1 then
        WriteLn('One!')
     else if Number=2 then
        WriteLn('Two!')
     else if Number=3 then
        WriteLn('Three!')
     else if Number=4 then
        WriteLn('Four!')
     else if Number=5 then
        WriteLn('Five!')
     else
        WriteLn('It is not in range 1 to 5');

     ReadLn();
end.

لاحظ طالما نقوم بعمل Fall فالأفضل نستخدم switch statement كالتالى

var
   dayNum: Integer;
   
begin
     Write('Enter: ');
     ReadLn(dayNum);
     
     case dayNum of
          1: WriteLn('Sunday');
          2: WriteLn('Monday');
          3: WriteLn('Tuesday');
          4: WriteLn('Wednesday');
          5: WriteLn('Thursday');
          6: WriteLn('Friday');
          7: WriteLn('Saturday');
          else //default
               begin
                    WriteLn('U R on EARTH!');
               end;

     end;
          
     ReadLn;
end. 

لاحظ هنا اننا نعمل check على dayNum ونرى اى حالة ستتوافق معاه…
نقدر نستخدم case مع ranges -واضح من كلامنا ان range معناها range 😀
ال range هو الفترة (مثلا 1..5 هو الأرقام من 1 الى 5)

var
   Age: Integer;
   
begin
     Write('Age? ');
     ReadLn(Age);
     
     case Age of
          1..5 : WriteLn('Cute Baby!');
          6..10: WriteLn('Mean kid!');
          11..14: WriteLn('Boy!');
          15..18: WriteLn('Teen!');
          19..23: WriteLn('Adult!');
          24..40: WriteLn('Regular guy');
          41..60: WriteLn('Gettin older!');
          else
              begin
                   WriteLn('R U Human?');
              end;
     end;


التكرار
اى Loop عبارة عن تكرار suite او مجموعة من ال statements ل
1 – عدد من المرات
2- حتى يتحقق شرط ما

طبعا كلام عجيب 🙂

التكرار لعدد من المرات معناه اقرب مثال .. نفذ 100 تمرين ضغط !
تكرار لحد ما شرط يتحقق مثلا
طالما جائع كلّ

while do
loop_suite

   while i = 0 do
           begin
                WriteLn(i);
                Dec(i); // i := i - 1;
           end; 

طالما i اكبر من او تساوى صفر سينفذ ال Block التالى

begin
                WriteLn(i);
                Dec(i); // i := i - 1;
           end; 

فى loop تانية وهى

 repeat
        loop_suite
until ;

الفرق هو إن ال loop_suite بتتنفذ قبل مايتم إختبارها.. فعشان كدا ال loop_suite لازم تتنفذ ولو مرة واحدة على الأقل!

فى loop هنشوفها كتير وهى ال for loop وهى كالتالى
تصاعدية

for  to  do
for_suite 

تنازلية

for  downto  do
for_suite 
 var
   counter: Integer;
   
begin
     for counter := 0 to 10 do
         begin
              WriteLn('Counter: #', counter);
         end;

         ReadLn;
end.

تنبيه: إذا معتاد على

for(start; cond; inc){
        for_suite
} 

فالأفضل هنا إنك تستخدم ال while loop لتكون اسهل فى التحكم فى مقدار ال step -الخطوة-

مرحبا ايها العالم!

مايو 7, 2009

بعد تحميل Lazarus وتنصيبه

File -> New -> Program

احفظ المشروع بإسم

ستجد ال code التالى بال Editor

كود:

 
program hello;



{$mode objfpc}{$H+}



uses

  {$IFDEF UNIX}{$IFDEF UseCThreads}

  cthreads,

  {$ENDIF}{$ENDIF}

  Classes

  { you can add units after this };



begin

end.

هذه هو هيكل التطبيق

Run -> Build or (Ctrl + F9)

Run or ( F9 )

ستظهر شاشة سوداء وتغلق بسرعة (بسبب انهاء عملية تنفيذ البرنامج) ..مبروك اول برنامج ليك فى Pascal!

لاحظ فى معظم الأحيان برنامجنا سيكون بين .begin, end

ماهى begin, end. ؟

begin هى نقطة البداية لبرنامجك

end. هى نقطة النهاية لبرنامجك

Hello world

WriteLn

هى الFunction الشهيرة للإخراج 🙂

بنستخدم WriteLn عندما نريد ان نطبع شئ للمستخدم كالتالى مثلا

كود:

program hello;



{$mode objfpc}{$H+}



uses

  {$IFDEF UNIX}{$IFDEF UseCThreads}

  cthreads,

  {$ENDIF}{$ENDIF}

  Classes

  { you can add units after this };



begin

     WriteLn('Hello, World!');

end.

لاحظ الكود المولد يبدأ ب program hello وهنا إن اسم البرنامج hello و uses هى section قسم يشمل ال units -الوحدات-الذى سنستخدمها

اعمل Run للبرنامج ستجد كلمة Hello, World ظهرت واختفت الشاشة بسرعة !؟

فكل الذى علينا إننا نخلي البرنامج ينتظر لمدة معينة مثلا حتى المستخدم يضغط Enter

فبكل بساطة سنضيف ReadLn وهى ستساعدنا فى ان البرنامج ينتظر اى محاولة إدخال من المستخدم فيفضل البرنامج شغال 🙂

 begin

     WriteLn('Hello, World!'); 

     ReadLn();

end.

رائع جدا كدا ال Screen بتنتظر حتى يضغط على Enter

ماذا فعلنا للآن ؟

begin هى البداية

WriteLn('Hello, World!');
 

بتطبع كلمة Hello, World

 ReadLn();

بتجعل البرنامج فى حالة انتظار المستخدم ليدوس Enter

end. هى نهاية البرنامج

ياريت نقدر نكتب الشرح السابق فى برنامجنا لتوضيحه لينا وللقارئ ؟

كدا اديك عرفت مفهوم جديد وهو ال Commenting او التعليق

 begin   {The Start}

     WriteLn('Hello, World!'); {Writes Hello, World to the output}

     ReadLn(); {Waites for }



end.    {The End}

تقدر تستخدم // بدل من ال { } كالتالى مثلا

//Writes Hello, World to the output 

نكتب برنامج بسيط عددين هنشتغل فيه كالتالى

1- هنعرض رسالة للمستخدم نطلب منه إنه يدخل الرقم الأول

2- نقرا الرقم الأول

3- نعرض رسالة نطلب فيها الرقم التانى

4- نقرا الرقم التانى

5- نجمع الرقمين

6- نعرض حاصل جمع الرقمين للمستخدم

تحليلنا للبرنامج على خطوات محددة هو ال Algorithm التى سنعمل بيها لحل المشكلة -البرنامج-

var

   First: Integer;

   Second: Integer;

   Result: Real;



begin

     Write('Enter the first: ');  // ask for a number

     ReadLn(First);               // Read it.

     

     Write('Enter the second: ');  // ask for a number

     ReadLn(Second);               // Read it.

     

     Result := First + Second;     // Summing.

     WriteLn('Result: ', Result) ; // Write out the Result.



     ReadLn();                     // Wait for 

end. 

ماهى المتغيرات ؟ هى عبارة عن alias -تسميه- ل data معينة -قابلة للتغيير- نستخدمها داخل برنامجنا ف First هنا بتمثل الرقم اللذى سيدخله ال user وsecond كذلك و Result تمثل حاصل الجمع

بنقوم بتحديد كل المتغيرات فى قسم مخصوص بإسم var بنحدد فيه نوع ال Variable

لإعطاء قيمة لمتغير بنستخدم := Operator

Result := First+Second;
 

لنعطى قيمة لمتغير سنستخدم ReadLn وهى ستاخد ال Input -المدخلات- من المستخدم وتعمل implicit cast -تحويل قسرى- لل data type وهنا تم التحويل من المدخلات من مجموعة حروف “نص” الى إلى عدد صحيح

كلمة بخصوص ال Data Types

Char-> لتمثيل الحروف

Integer -> لتمثيل الأعداد الصحيحة

Real -> للأعداد الحقيقية

String -> للسلاسل النصية

Boolean -> True, False

تابع هنا
http://wiki.freepascal.org/Data_type

تابع هذا المثال عن ال Data Types

var

  name: String[10];

  age : Integer;

  sex : Char;

  married: Boolean;

begin

  name := 'Ahmed';

  age  := 19;

  sex  := 'm';

  married := False;

  

  WriteLn('Name: ',name);

  WriteLn('Age : ',age);

  WriteLn('Sex : ',sex);

  WriteLn('Married? ',married);

  

  ReadLn();



end.
 

نجعله تفاعلى اكثر

var

  name: String ;

  age : Integer;

  sex : Char;

  

begin

  WriteLn('Gathering data...');

  Write('Name: ');

  ReadLn(name);

  

  Write('Age: ');

  ReadLn(age);

  

  Write('Sex: ');

  ReadLn(sex);

  

  WriteLn('Data Entered Successfully');

  WriteLn('Your Profile');

  WriteLn(' name: ', name);

  WriteLn(' age : ', age);

  WriteLn(' sex : ', sex);

  

  ReadLn(); //Wait for 

  

end. 

الثوابت Constants

هى عبارة عن aliases -تسميات مستعارة- لdata -بيانات- لن تتغير خلال برنامجك لأى سبب.. على سبيل المثال يوجد Constant شهير وهو PI وقيمته 3.14

 program constants1;



const

  PI: Real = 3.14;



var

  radius: Real;

  area: Real;

  

begin

  Write('Enter the radius: ');

  ReadLn(radius);

  area := PI*(radius*radius);

  WriteLn('Area: ', area);

  

  ReadLn();

end.

ال Operators

+ للجمع

– للطرح

* للضرب

/ للقسمة Real

div للقسمة Integer

mod لباقى القسمة

مفاهيم اساسية

مايو 7, 2009

الفصل الأول

مامعنى كلمة Programming ؟

هى بتعنى القدرة على التخاطب مع الكمبيوتر وتنفيذ افكارك على ارض الواقع .. الكمبيوتر لايفهم اى شئ سوا 0 و 1 وصعب على البشر تعلمها إن لم يكن مستحيلا فنلجأ لخيارات بديلة وهى إستخدام لغات البرمجة

مامعنى Programming Language ؟

بكل بساطة هى وسيلة للتخاطب مع الكمبيوتر .. ولكننا قلنا إن الكمبيوتر لايفهم اى شئ سوا ال0 وال 1 ومستحيل على الإنسان تعلمها! .. إذا الحل هو إستخدام لغات وسيطة .. على سبيل المثال واحد عربى وواحد فرنسى والعربى مش بيفهم فرنسى ولا الفرنسى بيفهم عربى .. فالحل هو إنهم يتكلمو إنجليمثل مثلااو يجيبو مترجم بين الإتنين مش كدا ؟
فهنا الحل إننا هنجيب مترجم يترجم افكارنا للغة الكمبيوتر 0 و 1 ويقوم المترجم بنفس الدور بتحويل رد فعل الكمبيوتر الى لغتنا المفهومة 🙂
وهنا دور ال Programming Language انت هتتعلم اللغة وكيفية التعامل معاها عشان تقدر تفهم المترجم المقدم من اللغةالذى إنت تريده وهو يفهمه للكمبيوتر بدوره

ماهو ال Source Code ؟

بكل اختصار هو حلك لمسألة رياضيات وتفكيرك وإستنتاجاتك عند كتابتها على ولكن هنا هو حلك لبرنامج مطلوب منك على ملف Text

Compiled vs Interpreted
كتير منا إشتغلو على نظم Windows وكان دائما يرى ملفات إمتدادها .exe فمامعنى ال exe ؟ معناها Executable او قابل للتنفيذ ..
فى لغات برمجة مثل ال C و Pascal بيتوافر الناتج النهائى بتاع برنامجك على صورة ملف exe وهو عبارة عن تعليماتك اللتى مررتها للمترجم ليحولها للغة يفهمها للكمبيوتر ولكن فى صورتها النهائية (الكلام الذى اخبره المترجم لل كمبيوتر) فمستحيل على الإنسان إنه يقرا ذلك الملف وهنا معنى الcompiled فهى ملف ال exe يشمل التعليمات التى كتبتها ولكن بلغة الكمبيوتر وهو وحده القادر على فهمها

من مميزات ال Compiled Languages مثل ال C هى السرعة
ومن القصور هو وجوب عمل Compile لل Source Code على النظام الموجه له البرنامج.. فبرنامج مكتوب على Windows محتاج يتعمله recompile على ال Linux وهكذا ..

من مميزات ال Interpreted Languages هى ان ال Source Code لبرامجها قياسى لايحتاج لعمل Recompile على مختلف النظم

ومن القصور البطء

ملحوظة:
البطء فى الInterpreted Languages بيكون المقصود البطء بالنسبة لل Compiled Language وليس البطء للمستخدم لأنك لن تلاحظ الفرق لأن البطء فى شئ لايكاد يذكر

تاريخ

لغة Pascal ظهرت عام 1970 على يد العالم Niklaus Wirth وكان هدفها
1- صغر الحجم
2- وضوح كامل
3- تعليم المبرمجين ال Structured Programming بصورة جيدة ومنظمة
بعد دخول مفهوم ال OOP تم تطوير Object Pascal لدعم الOOP بصورة متكاملة

Borland تعتبر اكبر داعم ل Pascal منذ ايام Turbo Pascal وقامت بتحسينها وتطويرها إلى الصورة الحالية

Delphi: هى IDE متكاملة لل RAD –التطوير السريع للتطبيقاتعلى Windows
Kylix: هى IDE متكاملة لل RAD على *NIX

حاليا تم إلغاء مشروع Kylix –ليست لديهم نية استمرار الدعم

لجذب المبرمجين لمنتجات Borland قامو بتطوير Turbo Explorer لتطوير C++, C#, Delphi for win32 and Delphi.net

على كل حال فلسفة الOpen Source لازم تلعب دورها كالعادة فأخرجت لينا
Free Pascal Compiler او FPC للإختصار وهو Multi-Platform Compiler –وهو الذى سنستخدمهيخضع ل GPL

GNU Pascal Compiler او GPC وهو Compiler من GNU ويعمل على معظم النظم ايضا

Lazarus: هو Class Libraries محاكية ل Delphi وIDE متكاملة تساعدك على ال RAD بكل بساطة فبكل إختصار Lazarus هو البديل الأقوى ل Delphi

سبب التسمية: على إسم Lazarus –بالكتاب المقدساللذى احياه المسيح من الموت. وهو ماينطبق على Lazarus حيث تم إحيائه من Megido

المقدمة من ويكيبديا و الويكى الخاص ب FPC, Lazarus

التحميل والتنصيب:
قم بإختيار مايناسبك من هنا http://sourceforge.net/project/showf…group_id=89339
اذا لم يكن لديك FPC فإختار Package –حزمةتشملا ال FPC