ماركو كانتو: |
الفصل 3
|
اعتمدت لغة باسكال الأصلية عل بعض المفاهيم البسيطة، والتي اصبحت الآن عامة في لغات البرمجة. المفهوم الأول هو نوع البيانات data type. النوع يحدد القيم التي يمكن للمتغيرات ان تتخذها، والعمليات التي يمكن انجازها عليها. ان مفهوم النوع أقوى في باسكال مقارنة بلغة س، حيث انواع البيانات الحسابية غالبا ما تكون متبدلة، وهي أقوى بكثير من النسخ الأصلية للغة بيسك، حيث لاتملك مثل هذا المفهوم.
تتطلّب باسكال ان تكون كل المتغيرات معرّفة قبل استخدامها. وحتى في الوقت الذي تعرّف فيه المتغير، يجب أن تحدّد نوع البيانات. ها هنا بعض نماذج تعريف المتغيرات:
var Value: Integer; IsCorrect: Boolean; A, B: Char;
المصطلح var يمكن استخدامه في اماكن مختلفة في الكود، كأن يكون في بداية توليف وظيفة أو اجراء، او ان يتم تعريف المتغيرات محليا local في الروتين ، أو داخل الوحدة لتعريف متغيرات جامعة global. بعد مصطلح var تأتي قائمة اسماء المتغيرات، متبوعة بشارحة واسم نوع البيانات. يمكنك كتابة اكثر من اسم متغير واحد في السطر الواحد، كما هو في آخر تعليمة أعلاه.
حالما تقوم بتحديد متغير من نوع ما، تستطيع ان تقوم فقط بمباشرة العمليات الداعمة لنوع بياناته. على سبيل المثال، يمكنك استعمال القيمة البولية للاختبار و القيمة الصحيحة في التعبير الرقمي. لايمكنك مزج القيم البولية والصحيحة (كما هو الأمر مع لغة س).
باستخدام تخصيصات بسيطة، نستطيع كتابة التوليف التالي:
Value := 10; IsCorrect := True;
لكن التعليمة التالية ليست صحيحة، لأن المتغيرين يملكان نوع بيانات مختلف:
Value := IsCorrect; // error
اذا حاولت تحويل هذا التوليف، فان دلفي تقوم باصدار خطأ تحويل رفق هذا التوضيح: Incompatible types: 'Integer' and 'Boolean'. عادة، مثل هذه الأخطاء هي أخطاء برمجية، لأنه لامعنى لتخصيص قيمة True أو False لقيم من نوع بيانات صحيح. يجب أن لا تلوم دلفي على مثل هذه الأخطاء. هي فقط تنبهك لوجود خطأ ما في التوليف.
بالطبع، غالبا مايمكن تبديل قيمة متغير من نوع بيانات الى نوع مختلف. في بعض الحالات، هذا التبديل يكون آليا، لكن عادة ما تحتاج الى استدعاء وظائف محددة في النظام لتغيير التمثيل الداخلي للبيانات.
تستطيع في دلفي ان تخصص قيمة تمهيدية لمتغير جامع global variable أثناء تعريفك له. مثلا، تستطيع كتابة:
var Value: Integer = 10; Correct: Boolean = True;
تقنية التمهيد initialization هذه تصلح فقط للمتغيرات الجامعة، وليس للمتغيرات المعرفة داخل نطاق اجراء أو مسار.
تسمح باسكال ايضا بتعريف ثوابتا constants لتسمية القيم التي لاتتغير خلال عمل البرنامج. لتعريف ثابت لاتحتاج لتحديد نوع البيانات، فقط تخصيص قيمة ابتدائية. المحوّل سيتفحّص القيمة وآليا يستخدم نوع بياناته المناسب. ها هنا بعض امثلة التعريفات:
const Thousand = 1000; Pi = 3.14; AuthorName = 'Marco Cantù';
يقرر دلفي نوع البانات للثابت بناء على قيمته. في المثال أعلاه، الثابت Thousand يفترض ان يكون من نوع صحيح صغير SmallInt ، اصغر نوع صحيح يمكنه احتواء القيمة. اذا اردت الطلب من دلفي استخدام نوع محدد؛ يمكنك ببساطة اضافة اسم النوع في التعريف، كما هو في:
const Thousand: Integer = 1000;
عندما تقوم بتعريف ثابت، يستطيع المحوّل أن يختار بين أن يخصص موقعا في الذاكرة للثابت، و يحفظ فيه قيمته، أو أن ينسخ قيمته الحقيقية في كلّ مرة يتم فيها استعمال الثابت. الأسلوب الثاني يبدو معقولا خاصة بالنسبة للثوابت البسيطة.
ملاحظة: نسخ 16-بت من دلفي تسمح لك بتغيير قيمة الثابت محدد النةع في زمن التشغيل، كما لو كان متغيرا. نسخة 32-بت لازالت تسمح بهذا السلوك من اجل التوافقية مع السابق وذلك عندما تقوم بتمكين موجّه المحوّل $J ، او بالتعليم على مؤشر Assignable typed constants في صفحة المحوّل في نافذة خيارات المشروع Project Options . وبالرغم من أن هذا هو التوصيف الافتراضي، فانه ينصح بقوة كفنيّات البرمجة أن لاتستعمل هذه الخدعة. ان تخصيص قيمة جديدة لثابت يمنع كل تشذيبات المحول على الثواب. واذا اضطررت لهذا، ببساطة قم بتعريف متغيرات، كبديل.
عندما تحدد ثابت جملة، فبدلا من كتابة:
const AuthorName = 'Marco Cantù';
يمكنك بدءاً من دلفي 3 أن تكتب التالي:
resourcestring AuthorName = 'Marco Cantù';
في كلتا الحالتين انت تحدد ثابتا؛ قيمة لاتقم بتغييرها خلال زمن التشغيل. الفرق فقط في كيفية الانجاز. ثابت الجملة المحدد بواسطة الموجّه resourcestring يخزّن ضمن موارد البرنامج resources، في جدول للجمل.
لكي ترى هذه الامكانية فعليا، قم بالاطلاع على مثال ResStr ، والذي له زرّا رفق التوليف التالي:
resourcestring AuthorName = 'Marco Cantù'; BookName = 'Essential Pascal'; procedure TForm1.Button1Click(Sender: TObject); begin ShowMessage (BookName + #13 + AuthorName); end;
ناتج الجملتين يظهر في سطرين منفصلين لأن الجملتين مفصولتين بالحرف الدّال لسطر جديد newline (مشار اليه بقيمته الرقمية في #13 وهو ثابت نوع حرف).
الجانب المثير في هذا البرنامج هو انك اذا تفحصّته بمستكشف للموارد resource explorer (هناك واحد متوفر في الأمثلة التي تأتي مع دلفي) سوف ترى الجمل الجديدة ضمن الموارد. هذا يعني بأن الجمل ليست جزءا من التوليف المحول ولكنها خزّنت في منطقة منفصلة في الملف التنفيذي (ملف EXE).
ملاحظة: باختصار، مزايا الموارد هي في الكفاءة في مناولة الذاكرة التي تقوم بها ويندوز، وفي امكانية توطين localizingالبرنامج (ترجمة الجمل الى لغات مختلفة) بدون الحاجة الى تعديل توليفها المصدري source code.
في باسكال توجد عدة انواع بيانات سابقة التحديد predefined data types ، والتي يمكن تقسيمها الى ثلاث مجموعات: الانواع التراتبية ordinal types، الأنواع الحقيقية real types و الجمل strings. سوف نناقش الانواع التراتبية في الأقسام التالية، بينما يتم تغطية الجمل لاحقا في هذا الفصل. في هذا القسم سوف أقدم ايضا بعض الأنواع المحددة من قبل مكتبات دلفي (ليست محددة من قبل المحوّل)، والتي يمكن اعتبارها انواع سابقة التحديد predefined types.
تتضمن دلفي ايضا نوع بيانات بدون نوع non-typed ، تسمّى متباين variant ، سيتم مناقشتها في الفصل العاشر من هذا الكتاب. غريب جدا ان يكون المتباين نوعا بدون مايناسبه من تحقق من النوع. لقد تم ادخال هذا النوع في دلفي 2 لمناولة آليات او ال اي OLE Automation.
الأنواع التراتبية Ordinal types مبنية على مفهم الترتيب أو التوالي و التتابع. ليس بامكانك فقط مقارنة قيمتين لمعرفة أيهما الأكبر، ولكن يمكنك أيضا معرفة القيمة التي تلي او تسبق قيمة أخرى، أو تقوم بحساب أدني أو أعلى قيمة محتملة.
أكثر ثلاث أنواع تراتبية سابقة التحديد هي الصحيح Integer، البولي Boolean، و الحرف Char. عموما، هناك عددا من الأنواع الأخرى ذات العلاقة والتي لها معنى مشابها ولكن لها تمثيلا ومدى قيم مختلفين. جدول 3.1 التالي يعرض انواع البيانات التراتبية المستخدمة لتمثيل الأرقام.
جدول 3.1: أنواع البيانات التراتبية للأرقام
Size الحجم | Signed معلّم Range المدى |
Unsigned غير معلّم Range المدى |
---|---|---|
8 bits | ShortInt -128 to 127 |
Byte 0 to 255 |
16 bits | SmallInt -32768 to 32767 |
Word 0 to 65,535 |
32 bits | LongInt -2,147,483,648 to 2,147,483,647 |
LongWord (بدءاً من دلفي 4) 0 to 4,294,967,295 |
64 bits | Int64 | |
16/32 bits | Integer | Cardinal |
كما ترى، هذه الأنواع لها علاقة بالتمثيلات المختلفة للأرقام، حسب عدد الجزئيات bits المستخدمة للتعبير عن القيمة، وحسب وجود أو غياب جزئية العلامة. القيم المعلّمة signed values يمكنها أن تكون موجبة أو سالبة، لكن لها مدى أصغر من القيم، وذلك لأن المتاح من الجزئيات للقيمة نفسها قد نقصت بواحدة. تستطيع أن ترجع الى مثال المدى الذي سيناقش في القسم التالي، من أجل معرفة المدى الفعلي لقيم كل نوع.
المجموعة الأخيرة (والمشارة ب 16/32) تشير الى القيم التي لها تمثيلا مختلفا في نسخ 16-بت و 32-بت من دلفي. الصحيح Integer و الرئيسي Cardinal يستعملان بكثرة، لأنهما يطابقان التمثيل الفطري للأرقام في المعالج الحسابي CPU.
في دلفي 3، الأرقام ذات 32 بت غير المعّلمة والمشار اليها بنوع رئيسي cardinal كانت سابقا قيم 31 بت، بمدي يبلغ حتى 2 قيقابايت. قدمت دلفي 4 نوع جديد رقمي غير معلّم، LongWord ، والذي يستخدم فعليا قيمة 32 بت تبلغ حتى 4 قيقابايت. وأصبح نوع كاردينال الآن اسما مرادفا لنوع لونغوورد الجديد. لونغوورد يسمح ب 2GB اكثر اضافية من البيانات يمكن عنونتها من قبل رقم غير معّلم، كما أشير اليه سابقا. أكثر من هذا، فإنه يماشي التمثيل الفطري للأرقام في المعالج الحسابي.
نوع آخر جديد تم ادخاله في دلفي 4 و نوع int64 ، والذي يمثل أعدادا صحيحة تبلغ 18 رقم. هذا النوع الجديد مدعوم بالكامل من قبل بعض اجرائيات routines الأنواع التراتبية (مثل High و Low)، والإجرائيات الرقمية (مثل Inc و Dec)، وإجرائيات تبديل الجمل string-conversion (مثل IntToStr). ومن أجل التبديل العكسي، من جملة ألى رقم، هناك وظيفتين جديدتين: StrToInt64 و StrToInt64Def.
القيم البولية غير النوع البولي نادرة الاستعمال. بعض القيم البولية لديها تمثيل خاص وذلك لمتطلبات وظائف ويندوز Windows API functions. الأنواع هي ByteBool، WordBoolو LongBool.
في دلفي 3 ومن أجل التوافق مع فيجوال بيسك و آليات OLE، فان انواع البيانات ByteBool، WordBool، و LongBool تم تعديلهم لتمثيل القيم True بـ -1، بينما القيمة False لازالت 0. نوع البيانات Boolean ظلّت كما هي (True هي 1، , False هي 0). إذا قمت باستعمال سبك نوع typecast صريح في برنامج بدلفي 2، فإن نقل البرنامج الى نُسخ لاحقة من دلفي قد ينتج عنه بعض الأخطاء.
أخيرا هناك تمثيلين مختلفين للأحرف: ANSIChar و WideChar. النوع الأول يمثل أحرفا ذات جزئيات ثمان 8-bit، تتماشى مع مجموعة أحرف انسي ANSI والمستخدمة تقليديا من قبل ويندوز؛ التمثيل الثاني الأحرف 16-جزئية ، وتتماشى مع أحرف يونيكود الجديدة Unicode والمدعومة بالكامل من قبل ويندوز ن ت، وجزئيا من قبل ويندوز 95 و 98. معظم الوقت سوف تستعمل ببساطة نوع حرف Char ، والذي في دلفي 3 تطابق ANSIChar. ليكن معلوما، على أي حال، ان أول 256 من حروف يونيكود توافق تماما حروف انسي ANSI.
أحرف الثوابت يمكن تمثيلها بمجموعة رموزها، كما في 'k'، او بمجموعة أرقامها، كما في #78. الأخيرة يمكن التعبير عنها ايضا ياستخدام الوظيفية Chr ، كما في Chr (78). التبديل المعاكس يمكن اجراؤه بواسطة الوظيفة Ord.
بصفة عامة يكون من الأحسن استخدام مجموعة الرموز عند الإشارة الى الأحرف، والأرقام، والعلامات. عند الإشارة الى أحرف خاصة، ستستخدم مجموعة الأرقام عموما بدلا من ذلك. القائمة التالية تتضمن بعض أكثر الأحرف الخاصة استعمالا:
لإعطائك فكرة عن الاختلاف من مدى لآخر في بعض الأنواع التراتبية، قمت بكتابة برنامج دلفي بسيط أسميته Range. بعض النتائج تظهر في الشكل 3.1.
الشكل 3.1: مثال Range يظهر بعض المعلومات حول انواع البيانات التراتبية (الأرقام الصحيحة في هذه الحالة).
برنامج Range مبني على نموذج form بسيط، به ستة أزرار buttons (كلّ مسمّاة حسب نوع البيانات التراتبية) وبعض الملصقات labels لمختلف المعلومات، كما هو مبيّن في الصورة 3.1. أستخدمت بعض الملصقات لتحوي نصّا ثابتا، الأخرى لعرض المعلومات عن النوع في كلّ مرّة يُضغط فيها على زرّ.
في كلّ مرّة تضغط فيها على الأزرار، يقوم البرنامج بتحديث الملصقات بحسب الناتج. ملصقات مختلفة تعرض نوع البيانات، عدد البايت المستعملة، و أقصى وأدني قيمة يمكن للنوع أن يخزّنها. كل زرّ يملك مايخصّه من مسار method تجاوب الحدث OnClick لأن التوليف المستخدم لحساب القيم الثلاث يختلف قليلا من زرّ لآخر. مثلا، هاهنا التوليف المصدري لحدث OnClick للزرّ الخاص بنوع الصحيح (BtInteger):
procedure TFormRange.BtnIntegerClick(Sender: TObject); begin LabelType.Caption := 'Integer'; LabelSize.Caption := IntToStr (SizeOf (Integer)); LabelMax.Caption := IntToStr (High (Integer)); LabelMin.Caption := IntToStr (Low (Integer)); end;
إذا كنت تملك بعض الخبرة في البرمجة بدلفي، يمكنك تفحّص التوليف لفهم كيفية عمله. بالنسبة للمبتدئين، يكفي ملاحظة الإستخدام للوظائف الثلاثة: SizeOf وHigh و Low. نواتج الوظيفتين الأخيرتين هما تراتبيات من نفس النوع (في هذا الحالة، أعداد صحيحة)، وناتج وظيفة SizeOf هي دائما عدد صحيح. القيمة المرتجعة من هذه الوظائف الثلاث تترجم أولا إلى جُمل بإستخدام وظيفة IntToStr، ثم تُنسخ في لافتات captions الملصقات الثلاث.
المسارات المرتبطة بالأزرار الأخرى تشبه كثيرا المسار المذكور أعلاه. الإختلاف الفعلي الوحيد هو نوع البيانات الذي تم تمريره كمحدد لمختلف الوظائف. الصورة 3.2 تعرض ناتج تنفيذ البرنامج تحت ويندوز 95 بعد أن تم إعادة تحويله recompile بواسطة نسخة 16-بت من دلفي. بمقارنة الشكل 3.1 و الشكل 3.2، يمكنك رؤية الإختلاف بين نوع البيانات الصحيح ذو 16-بت وذلك ذو 32-بت.
الشكل 3.2: ناتج نسخة 16-بت من مثال Range، يعرض مرّة أخرى معلومات عن العدد الصحيح.
حجم نوع الصحيح Integer يتباين بحسب المعالج الحسابي ونظام التشغيل المستخدم. في ويندوز 16-بت، المتغير الصحيح يسع 2 بايت. بينما في ويندوز 32، سعة الصحيح 4 بايت. لهذا السبب، عندما تعيد تحويل مثال Range، ستحصل على نتائج مختلفة.
التمثيلين المختلفين لنوع الصحيح ليست بمشكلة، طالما أن برنامجك لايضع أية إفتراضات عن حجم الصحيح. إذا ما حدث وقمت بحفظ عدد صحيح في ملف بإستخدام نسخة ثم حاولت استرجاعه بنسخة أخرى، فسوف تواجه بعض المتاعب. في هذه الحالة، يجب أن تختار نوع بيانات مستقل عن بيئة التشغيل (مثل LongInt أو SmallInt). لأغراض الحسابات الرياضية أو توليف عام، أفضل مراهنة لديك هو أن تلتزم تمثيل الصحيح النمطي لبيئة التشغيل المعينة-- هذا يعني، ان تستخدم نوع الصحيح-- لأنه المفضّل لدى المعالج الحسابي. نوع الصحيح Integer يجب أن يكون خيارك الأول عندما تعالج أعدادا صحيحة. و لا تستخدم تمثيلا مختلفا إلا إذا وجدت سببا قاهرا لذلك.
بعض إجرائيات النظام system (إجرائيات محددة في لغة باسكال وفي وحدة النظام في دلفي system unit)يمكنها تتعامل مع الأنواع التراتبية ordinal types. هي معروضة في الجدول 3.2. المبرمجون بلغة س++ سوف يلاحظون بأن النسختين من إجرائية Inc، مع محدد أو اثنين، يطابقان معاملات ++ و += (نفس الأمر مع إجرائية Dec).
الجدول 3.2: إجرائيات نظام للأنواع التراتبية
الإجرائية | الغرض |
---|---|
Dec | تخفيض decrease المتغير الذي يتم تمريره كمحدد، بمقدار واحد أو بمقدار قيمة المحددالثاني الاختياري. |
Inc | زيادة increase المتغير الذي يتم تمريره كمحدد، بمقدار واحد أو بمقدار القيمة المعطاة. |
Odd | يرجع اثبات إذا كانت القيمة المعطاة عددا فرديا odd. |
Pred | يرجع القيمة التي تسبق تلك المعطاة بحسب الترتيب المقرر في نوع البيانات، السابق predecessor. |
Succ | يرجع القيمة التي تلي تلك المعطاة، التالي successor. |
Ord | يرجع رقما يدل على ترتيب order القيمة المعطاة ضمن مجموعة القيم في نوع البيانات. |
Low | يرجع أدنى low قيمة ضمن مدى النوع التراتبي المعطى كمحدد. |
High | يرجع أعلى high قيمة ضمن مدى نوع البيانات التراتبي. |
لاحظ ان بعض هذه الإجرائيات، عندما يتم تطبيقها على الثوابت constants، فإن المحوّل يقوم بتقييمها آليا واستبدالها بقيمتها. مثلا اذا قمت باستدعاء High(X) حيث X معرّفة كصحيح، فالمحوّل يستطيع ببساطة تبديل التعبير بآخر يمثل أعلى قيمة محتملة لنوع بيانات الصحيح.
تقوم الأنواع الحقيقية بتمثيل أرقام النقطة العائمة بعدة أشكال. أصغر حجم تخزين تمثلها الأرقام الوحيدة Single ، والتي تنفذ بقيمة ذات 4-بايت. ثم هناك الأرقام النقطة العائمة المضاعفة Double، المنفذة بعدد 8 بايت، والأرقام الممتدّة Extended ، والمنجزة بعدد 10 بايت. كل هذه أنواع بيانات نقطة عائمة مع اختلاف في الضبط والدقة precision.
في دلفي 2 ودلفي 3 نوع الحقيقي Real له نفس التعريف الذي في نسخة 16-بت؛ لقد كانت بنوع 48-بت. لكن تم تخفيض استخدامه من قبل بورلاند، والتي اقترحت بأن تقوم باستعمال أنواع الوحيد والمضاعف والممتد بدلا منه. سبب اقتراحهم هذا هو ان الشكل القديم ذو 6-بايت ليس مدعوما من قبل معالجات انتل Intl كما انه ليس معروضا ضمن القائمة الرسمية للأنواع الحقيقية والتي اصدرتها IEEE. ولكي يتم تلافي المشكلة تماما، قامت دلفي 4 بتعديل التعريف الخاص بنوع الحقيقي حتى يمثل الشكل القياسي لرقم عائم النقطة ذو 8 بايت (64-بت).
بالإضافة إلى ميزة استخدام تعريفا قياسيا متفق عليه، هذا التغيير يسمح للمكونات components باصدار سمات properties مبنية عل نوع حقيقي، الشيء الذي لم يكن دلفي 3 يسمح به. أما العيوب فقد تبرز مشاكل التوافقية. في حالة الضرورة، وعند الاصرار على طريقة دلفي 2 و 3 في تعريف النوع، يمكنك تجاوز احتمال انعدام التوافقية؛ وذلك باستخدام خيار المجمّع التالي:
{$REALCOMPATIBILITY ON}
هناك أيضا نوعان غريبان من أنواع البيانات: Comp ويصف رقم صحيح كبير جدا باستخدام 8 بايت (والذي يمكنه احتواء ارقام ذات 18 خانة عشرية)؛ و Currency عملة (ليست متوفرة في دلفي 16-بت) وهي تشير الى قيمة بنقطة عشرية ثابتة مع اربع خانات عشرية، و بنفس تمثيل 64-بت كما في نوع Comp. كما يوحي الإسم، نوع بيانات عملة Currency أضيف لمناولة القيم النقدية شديدة الدقة، مع أربع خانات عشرية.
لا نستطيع بناء برنامج يشبه مثال Range بتطبيق انواع بيانات حقيقية، لأننا لايمكننا استخدام وظائف High و Low أو Ord مع متغيرات نوع حقيقي. الأنواع الحقيقية تمثل (نظريا) مجموعة لانهائية من الأرقام، بينما الأنواع التراتبية تمثل مجموعة ثابتة من القيم.
ملاحظة: دعوني أشرح ذلك بطريقة أفضل. عندما يكون لديك الرقم الصحيح 23، يمكنك أن تقرّر ماهي القيمة التي تليه. الأرقام الصحيحة نهائية (لديها مدى محدد ولديها ترتيب). الأرقام عائمة النقطة هي غير نهائية حتى ضمن المدى القصير، وليس لديها ترتيب: في الواقع، كم توجد قيمة بين 23 و 24 ؟ و ما هو الرقم الذي يلي 23.46 ؟ هل هو 23.47، 23.461، أو 34.4601 ؟ هذا الأمر يصعب معرفته بالفعل.
لهذا السب، يبدو الأمر معقولا حين نسأل عن ترتيب موضع حرف w ضمن مدى نوع بيانات حرف char، و لكن ليس من المعقول ابدا أن نسأل نفس السؤال عن الرقم 7143.1562 ضمن مدى نوع بيانات النقطة العائمة. بالرغم انه بالتأكيد تستطيع معرفة ما إذا كان ;رقم حقيقي ما لديه قيمه أعلى من قيمة رقم آخر، فإنه من غير المنطقي أن نسأل عن عدد الأرقام الحقيقية الموجودة قبل رقم ما (هذا معني وظيفة Ord).
الأنواع الحقيقية لديها دورا محدودا في ذلك الجزء من التوليف البرمجي الخاص بواجهة المستخدم user interface (الجانب الخاص بويندوز)، لكنها مدعومة بالكامل من قبل دلفي، بما في ذلك جانب قواعد البيانات. ان دعم مواصفات IEEE القياسية لأنواع النقطة العائمة تجعل من لغة اوبجكت باسكال مناسبة تماما لنطاق واسع من البرامج التي تتطلب حسابات رقمية. إذا كنت مهتما بهذا الجانب، يمكنك إلقاء نظرة على الوظائف الرياضية المقدمة من دلفي وذلك في ملف وحدة system (انظر Delphi Help من أجل تفاصيل أكثر).
ملاحظة: لدلفي ايضا ملف وحدة Math التي تحدد إجرائيات رياضية أكثر تقدما، تغطي وظائف حساب المثلثات (مثل وظيفة ArcCosh)، مالية (مثل وظيفة InterestPayment)، و إحصائية (مثل إجرائية MeanAndStdDev). هناك العديد من هذه الإجرائيات، بعضها تبدو غريبة بالفعل بالنسبة لي، مثل إجرائية MomentSkewKurtosis (سأدع هذا الأمر لك لمعرفته) .
تستخدم دلفي أيضا أنواعا حقيقية real types لمناولة معلومات التاريخ والوقت. وليكون الأمر أكثر دقّة حدّدت دلفي نوع بيانات TDateTime. وهو نوع نقطة عائمة، لأن النوع يجب أن يكون واسعا بما يكفي لإحتواء السنوات، الأشهر، الأيام، الساعات، الدقائق، والثواني، نزولا إلى دقة تبلغ جزء من ألف من الثانية، كلّ ذلك في متغير واحد. التواريخ تخزّن كإجمالي عدد الأيام منذ 12/30/1899 (مع قيم سالبة تشير إلى التواريخ ما قبل 1899) في الجزء الصحيح integer من قيمة TDateTime.
نوع TDateTime ليس نوعا مسبق التحديد بحيث يفهمه المحوّل، لكن قد تمّ تعريفه في ملف وحدة system كالتالي:
type TDateTime = type Double;
إستخدام TDateTime يعدّ بسيط، لأن دلفي تحوي عددا من الوظائف التي تتعامل مع هذا النوع. يمكنك أن تجد قائمة بهذه الوظائف في الجول 3.3.
الجدول 3.3: إجرائيات نظام لنوع TDateTime
الإجرائية | البيان |
---|---|
Now | استرجاع التاريخ والوقت الحالي في قيمة على هيئة TDateTime. |
Date | استرجاع فقط التاريخ الحالي. |
Time | استرجاع فقط الوقت الحالي. |
DateTimeToStr | تحويل قيمة التاريخ والوقت الى جملة، باستخدام المعلومات المبدئية؛ من أجل تحكم أكثر في التحويل استخدم وظيفة FormatDateTime. |
DateTimeToString | نسخ قيم التاريخ والوقت في حيّز جملة string buffer وفق المعلومات الابتدائية. |
DateToStr | تحويل جانب التاريخ في قيمة TDateTime الى جملة. |
TimeToStr | تحويل جانب الوقت في قيمة TDateTime الى جملة. |
FormatDateTime | صياغة التاريخ والوقت باستخدام صيغة محدّدة، تستطيع ان تحدد أية قيمة تريد عرضها وأية صيغة تستعمل، منتجة صياغة غنية للجملة. |
StrToDateTime | تحوبل جملة تحوي معلومات التاريخ والوقت الى قيمة TdateTime، مظهرة رفضا exception في حالة وجود خطأ في صيغة الجملة. |
StrToDate | تحويل جملة تحوي قيمة تاريخ الى صيغة TDateTime. |
StrToTime | تحويل جملة تحوي قيمة وقت الى صيغة TDateTime. |
DayOfWeek | يسترجع رقم ترتيب اليوم في الأسبوع حسب قيمة TDateTime المعطاة. |
DecodeDate | استرجاع قيم السنة، الشهر، و اليوم من قيمة تاريخ. |
DecodeTime | استرجاع قيمة الوقت. |
EncodeDate | تحويل قيم السنة، الشهر، و اليوم إلى قيمة TDateTime. |
EncodeTime | تحويل قيم الساعة، الدقيقة، الثانية، وأجزاء الثانية إلى قيمة TDateTime. |
من أجل أن ترى كيف يتم استعمال نوع البيانات هذا و بعض الإجرائيات الخاصة به، قمت ببناء برنامج بسيط، أسميته TimeNow. النموذج الرئيسي في هذا المثال به زرّ Button و قائمة ListBox. عندما يبدأ البرنامج يقوم آليا بحساب وعرض الوقت والتاريخ الحالي. في كلّ مرّة يتم فيها الضغط على الزرّ، يقوم البرنامج بعرض الزمن المنقضي منذ بدء البرنامج.
فيما يلي التوليف الموصول بحدث OnCreate الخاص بالنموذج:
procedure TFormTimeNow.FormCreate(Sender: TObject); begin StartTime := Now; ListBox1.Items.Add (TimeToStr (StartTime)); ListBox1.Items.Add (DateToStr (StartTime)); ListBox1.Items.Add ('Press button for elapsed time'); end;
التعليمة الأولى تنادي وظيفة Now ، التي تسترجع التاريخ و الوقت الحاليين. القيمة المسترجعة تُخزّن في متغيّر StartTime ، والذي تم تعريفه كمتغير خارجي global كالتالي:
var FormTimeNow: TFormTimeNow; StartTime: TDateTime;
لقد أضفت فقط التعريف الثاني، حيث أن دلفي تقوم بتوفير الأول. حيث يكون مبدئيا كالتالي:
var Form1: TForm1;
عند تغير اسم النموذج form، يتم تحديث هذا التصريح آليا. ان استخدام متغيرات جامعة global لا يعدّ حقيقة أفضل الطرق: سيكون من الأفضل لو تم استخدام حقل خاص private field تابع لطبقة النموذج form class، موضوع له علاقة ببرمجة التوجّه الكائني object-oriented programming تم مناقشته في كتاب التحكم بدلفي 4 Mastering Delphi .
التعليمات الثلاث التالية تضيف ثلاثة عناصر الى مكوّن القائمة يمين النموذج، مع النتائج التي تراها في الشكل 3.3. السطر الأول يحتوي على الجزء الخاص بالوقت في قيمة TDateTime محوّلا الى جملة، الثاني يحتوي جزء التاريخ من نفس القيمة. في نهاية التوليف أضيف تذكير بسيط.
الشكل 3.3: ناتج مثال TimeNow عند البدء.
الجملة الثالثة يستبدلها البرنامج عندما يضغط المستعمل على زرّ Elapsed "المنقضى":
procedure TFormTimeNow.ButtonElapsedClick(Sender: TObject); var StopTime: TDateTime; begin StopTime := Now; ListBox1.Items [2] := FormatDateTime ('hh:nn:ss', StopTime - StartTime); end;
التوليف يسترجع الوقت الجديد ويحسب الفرق بينه وبين قيمة الوقت المخزّن عند ابتداء البرنامج. ولأننا نحتاج الى استخدام القيمة التي سبق حسابها في سياق حدث مختلق، كان علينا أن نخزّنها في متغير جامع. في الواقع توجد بدائل أفضل، مبنية على مفهوم الطبقات classes.
ملاحظة: التوليف الذي يقوم باستبدال القيمة الحالية في الجملة الثالثة يستعمل دليل index 2. السبب في ذلك ان بنود القائمة مبنية على الصفر are zero-based: البند الأول رقمه 0، الثاني رقم 1، و الثالث رقم 3. سنرى المزيد من ذلك عندما نناقش المصفوفات.
بجانب استدعاء DateToStr و TimeToStr يمكنك استعمال وظيفة FormatDateTime الأكثر قوة، كما فعلت في المسار method الأخير أعلاه (انظر ملف مساعدة دلفي من أجل تفاصيل محددات الصياغة). لاحظ أيضا أن قيم الوقت والتاريخ تُبدّلان إلى جُمل بحسب توصيف الدوليّات international في ويندوز. دلفي يقرأ هذه القيم من النظام، و يوزعها في عدد من الثوابت الجامعة global constants المُعرّفة في ملف وحدة SysUtils. نذكر منها:
DateSeparator: Char; ShortDateFormat: string; LongDateFormat: string; TimeSeparator: Char; TimeAMString: string; TimePMString: string; ShortTimeFormat: string; LongTimeFormat: string; ShortMonthNames: array [1..12] of string; LongMonthNames: array [1..12] of string; ShortDayNames: array [1..7] of string; LongDayNames: array [1..7] of string;
يوجد المزيد من الثوابت الجامعة تتعلق بالعُملة و صياغة رقم النقطة العائمة. يمكنك الحصول على قائمة كاملة بها من ملف مساعدة دلفي تحت العنوان Currency and date/time formatting variables.
أنواع البيانات السابقة التحديد والتي سبق أن استعرضناها حتى الآن هي جزء من لغة باسكال. تتضمن دلفي أنواع بيانات أخري مجددة من قبل ويندوز. أنواع البيانات هذه ليست جزءاً مكمّلا في اللغة، ولكنها جزءا من مكتبات libraries ويندوز. أنواع ويندوز تتضمن أنواع ابتدائية جديدة (مثل DWORD و UINT)، و العديد من التسجيلات records (أو بنيات structues)، و عددا من الأنواع المؤشّرة pointer، وغيرها.
من بين أنواع بيانات ويندوز، فإن النوع الأكثر أهمية تمثله المماسك handles، الفصل 9 يناقش ذلك.
كما رأينا، لا يمكنك تخصيص متغير لآخر من نوع مختلف. إذا أردت ذلك، يوجد خياران. الخيار الأول هو تلبيس النوع typecasting ، والذي يستخدم رمز وظائفي بسيط ، باسم نوع البيانات المطلوب:
var N: Integer; C: Char; B: Boolean; begin N := Integer ('X'); C := Char (N); B := Boolean (0);
يمكنك التلبيس بين أنواع البيانات ذات نفس الحجم. عادة مايكون الأمر مأمونا عند التلبيس بين الأنواع التراتبية، أو بين الأنواع الحقيقية، ولكن يمكنك التلبيس بين أنواع مؤشّرة pointer (وأيضا الكينونات objects) طالما تكون مدركا لما تفعله.
التلبيس، بصفة عامة، عادة برمجية خطيرة، لأنه يسمح لك بالوصول إلى قيمة كما لو أنها ممثلة بشكل آخر. و طالما ان التمثيلات الداخلية لأنواع البيانات عموما غير متجانسة، فأنت تخاطر بالتسبب بأخطاء صعبة التتبع. لهذا السبب، يجب عليك عموما تجنب عمليات تلبيس النوع.
الخيار الثاني هو استخدام إجرائيات تحويل النوع. الإجرائيات الخاصة بمختلف أنواع التحويلات تم تلخيصها في الجدول 3.4. بعض هذه الإجرائيات تعمل مع أنواع بيانات سيجري الحديث عنها في الأقسام التالية. لاحظ ان الجدول لا يحوي الإجرائيات الخاصة بالأنواع الخاصة (مثل TDateTime أو المتبياين variant) أو الإجرائيات الموجّه خصّيصا للتشكيل والصياغة formating، مثل الإجرائيات الفعّالة Format و FormatFloat.
جدول 3.4: إجرائيات النظام الخاصة بتحويل البيانات
الإجرائية | البيان |
---|---|
Chr | تحويل ترقم تراتبي الى حرف ANSI. |
Ord | تحويل قيمة نوع تراتبي إلى رقم يشير إلى ترتيبه. |
Round | تحول قيمة نوع حقيقي إلى قيمة نوع صحيح، تقريب القيمة. |
Trunc | تحول قيمة نوع حقيقي إلى قيمة نوع صحيح، تشذيب القيمة. |
Int | ارجاع الجزء الصحيح بقيمة نقطة عائمة. |
IntToStr | تحويل الرقم إلى جملة. |
IntToHex | تحويل الرقم إلى جملة بتمثيل ستعشري hexadecimal. |
StrToInt | تحويل جملة إلى رقم، مع إبداء رفض لو كانت الجملة لا تمثل رقما صحيحا و سليما. |
StrToIntDef | تحويل جملة إلى رقم، مع استخدام القيمة الإبتدائية إذا كانت غير سليمة. |
Val | تحويل الجملة إلى رقم (إجرائية قديمة في تربو باسكال، محتفظ بها من أجل التوافقية). |
Str | تحويل رقم إلى جملة، باستخدام محددات الصياغة إجرائية قديمة في تربو باسكال، محتفظ بها من أجل التوافقية). |
StrPas | تحويل جملة مقفلة بصفر null-terminated إلى جملة بنسق باسكال Pascal-style. هذا التحويل يتم آليا بالنسبة بالنسبة للجمل نوع AnsiString في دلفي 32-بت. (انظر إلى القسم الخاص بالجمل لاحقا في هذا الفصل.) |
StrPCopy | نسخ جملة بنسق باسكال إلى جملة مقفلة بصفر. هذا التحويل يتم بتلبيس بسيط لنوع PChar في دلفي 32-بت. (انظر إلى القسم الخاص بالجمل لاحقا في هذا الفصل.) |
StrPLCopy | ينسخ قسما من جملة بنسق باسكال الى جملة مقفلة بصفر. |
FloatToDecimal | تحويل قيمة نقطة عائمة إلى تسجيلة record تتضمن التمثيل العشري (exponent، أعداد، علامة) |
FloatToStr | تحويل قيمة نقطة عائمة إلى ما يمثلها كجملة باستخدام الصياغة الافتراضية. |
FloatToStrF | تحويل قيمة نقطة عائمة إلى ما يمثلها كجملة باستخدام صياغة محددة. |
FloatToText | تحويل قيمة نقطة عائمة إلى حيّز جملة string buffer، باستخدام صياغة حددة. |
FloatToTextFmt | مثل الإجرائية السابقة، تحويل قيمة نقطة عائمة إلى حيّز جملة، باستخدام صياغة مُحددة. |
StrToFloat | تحويل جملة باسكال إلى قيمة نقطة عائمة. |
TextToFloat | تحويل جملة مقفلة بصفر إلى قيمة نقطة عائمة. |
في هذا الفصل استكشفنا المفهوم الأساسي للنوع في باسكال. لكن اللغة لديها ميزة أخرى مهمة جدا: انها تسمح للمبرمجين بتعريف أنواع بيانات جديدة خاصة، تدعى بأنواع البيانات المحددة بالمستعمل user-defined data types. هذا هو موضوع الفصل التالي.
حقوق النسخ محفوظة لماركو كانتو؛ وينتش ايطاليا © Copyright Marco Cantù, Wintech Italia Srl 1995-2000
حقوق الترجمة: خالد الشقروني ، 2000