بسم الله الرحمن الرحيم
سأتكلم خلال هذا الدرس البسيط عن بعض المواضيع الموجودة في المرحلة التي تسبق الترجمة مثل : ادراج ملفات اخرى داخل الملف الحالي , تعريف عبارات ترجمة شرطية , تعريف ثوابت وماكرو وتنفيذ شرطي لما يسبق الترجمة .
التوجيهات التي تسبق مرحلة الترجمة Preprocessor Directives لاتعتبر تعليمات سي ++ , ولذلك لانجدها تنتهي بفاصلة منقوطة (; ) , ويتم معالجة هذه التوجيات قبل البدء بالترجمة .
اولا ً : include # :
يفيد هذا التوجيه في ادراج نسخة من ملف معين ضمن الملف الحالي , وهو على النحو التالي :
#include <filename> #include "filename"
بحيث اذا تمت كتابة اسم الملف داخل علامتي < > فهذا يعني بان الملف المطلوب ادراجه موجود داخل مجلدات معروفة مسبقا ولها علاقة بمكتبات المترجم المعيارية .. مثل : iostream , iomanip
اما اذا تمت كتابة اسم الملف داخل علامتي " " فأن هذا يعني بأن الملف المراد ادراجه موجود داخل نفس المجلد الذي ينتمي إليه ملف البرنامج , عندها سيتم البحث عنه داخل هذا المجلد ثم ضمن المجلدات المعروفة مسبقا ً , وهذه الطريقة تستخدم لادراج الملفات المكتوبة بواسطة المبرمج .
ثانيا ً : الثوابت الرمزية :
يوجد لدينا ثوابت رمزية معرفة مسبقا ً , تبدء هذه الثوابت بعلامتي (_) وتنتهي بهما ايضا , مثل :
__FILE__ : سلسلة من الاحرف تمثل لنا اسم الملف المتضمن للبرنامج , مثال :
#include <iostream>
using namespace std;
int main ()
{
cout<<__FILE__;//Print D:\test.cpp
return 0;
}__LINE__ : عدد صحيح يمثل رقم السطر ضمن نص البرنامج الحالي ,مثال :
#include <iostream>
using namespace std;
int main ()
{
cout<<__LINE__;//Print 5
return 0;
}__STDC__ : عدد صحيح يدل على التوافق مع معايير ANSI (American National Standards Institute ) , مثال :
#if __STDC__
__DATE__ : سلسلة من الحروف تعيد لنا تاريخ ترجمة الملف على الصيغة Mmm dd yyyy , مثال :
#include <iostream>
using namespace std;
int main ()
{
cout<<__DATE__;//Print Feb 11 2009
return 0;
}__TIME__ : سلسلة من الحروف تعيد لنا زمن ترجمة ملف البرنامج على الصيغة : hh:mm:ss , مثال :
#include <iostream>
using namespace std;
int main ()
{
cout<<__TIME__;//Print 10:39:40
return 0;
}__TIMESTAMP__ : سلسلة حروف تمثل تاريخ وزمن اخر تعديل على ملف البرنامج بالصيغة : Ddd Mmm Date hh:mm:ss:yyyy
#include <iostream>
using namespace std;
int main ()
{
cout<<__TIMESTAMP__;//Print Wed Feb 11 10:52:14 2009
return 0;
}ثالثا: Define #
وصيغته :
#define identifier replacement-text
عندما يظهر السطر السابق ضمن ملف فإنه يتم استبدال كافة الكلمات المطابقة لـ identifier بالسلسة : replacement-text بشكل اتوماتيكي قبل ان تتم الترجمة , مثلا :
#define PI 3.14159
رابعا: الماكرو .
وهو عبارة عن عملية معرفة باستخدام توجيه Define # وتماما مثل الثوابت السابقة يتم استبدال macro-identifier بالسلسلة replacement-text
#define PI 3.14159
#define CIRCLE_AREA(x) (PI*(x)*(x))
int main ()
{
cout<<CIRCLE_AREA(4);
return 0;
}من خلال المثال السابق : سيتم استبدال قيمة x ضمن العبارة المرافقة للماكرو .
ملاحظة : اذا تجاوزت التعليمات السطر الموافق لـ define وكنت ترغب بكتابتها على سطر اخر , قم باضافة العلامة (\) .
#define CIRCLE_AREA(x) (PI*(x)*(x\ ))
ويتم استبعاد تعريف الماكرو او الثابت من خلال التعليمة undef # ,
#undef PI
خامسا ً : الترجمة الشرطية
وتشبه في هيكلها البنية if , على سبيل المثال :
#if !defined (NULL) #define NULL 0 #endif
تفيد العبارة !defined في التحقق فيما اذا كانت القيمة NULL معرفة مسبقا ً ام لا , فإذا لم تكن معرفة يتم تعريفها واعطائها القيمة 0 .
يمكن ايضا استخدام التوجيهين : ifdef # والذي يعتبر اختصار للتوجيه
#if defined (name)
والتوجيه ifndef # والذي يعتبر اختصارا للتوجيه :
#if !defined (name)
ايضا يمكن استخدام التوجيه elif# المكافئ لـ else if في بنية if والتوجيه else # المكافئ لـ else في بنية if .
يمكننا ان نقوم بكتابة تعليقات لايتم ترجمتها من قبل المترجم بغير الطريقة /* و */ من خلال مرحلة ماقبل الترجمة , مثلا :
#if 0 cout<<"Code Prevented from compiling"; #endif
ولتنفيذ الكود السابق قم بتغيير القيمة 0 إلى القيمة 1 مثلاً .
سادسا ً : العمليتان # و ## .
* تقوم العملية # في تحويل وسيط ما إلى سلسلة حروف محاطة بعلامتين تنصين " " , مثلا ً :
#define HELLO(x) cout<<#x
int main ()
{
HELLO("Ali");
return 0;
}*تقوم العملية ## بلصق وسطين من الماكرو مع بعضهما , مثلا ً :
#define CAT(x,y) x##y
int main ()
{
cout<<CAT("Al-","Shammari")<<endl;
return 0;
}سادسا ً: ارقام الاسطر والتأكيدات .
* يمكن اعادة ترقيم الاسطر من خلال التوجيه line # ضمن نص البرنامج اعتبارا من القيمة الصحيحة المعطاة مع التوجيه , مثلا :
#include <iostream>
using namespace std;
int main ()
{
cout<<__LINE__<<endl;// Print 5
#line 100
cout<<__LINE__<<endl;//Print 100
cout<<__LINE__<<endl;// Print 101
return 0;
}وستكون المخرجات : 5- 100-101
* يقوم الماكرو assert بالتحقق من قيمة عبارة ما , فإذا كانت هذه القيمة مساوية للصفر يقوم الماكرو بطباعة رسالة خطأ وبعدها يستدعي الدالة abort من الملف ctdlib لانهاء تنفيذ البرنامج .
- يجب تضمين الملف cassert داخل ملف برنامجك .
مثلا : اذا اردنا ان يدخل المستخدم رقم الطالب بشرط ان يكون اكبر من 0 :
int num; cin>>num; assert(num>0); cout<<num;
اتمنى ان اكون قد وفقت بهذا الدرس البسيط , مع تمنياتي لكم بالتوفيق .



