أحمد معتوقي
26-12-2004, 09:06
بسم الله الرحمن الرحيم
السلام عليكم ورحمة الله وبركاته....
تتميز لغة الـ C عن غيرها من اللغات بكثير من المرونة التي لا تتيحها غيرها، ومن بينها أنك تستطيع أن تمرر إلى التابع عدد غير محدود من الوسائط....
ما الحاجة لها....
كثير من الأحيان لا أعرف عدد الوسائط التي ستمرر إلى التابع، فمثلا أحتاج في معظم الأحيان للجمع بين عددين، وفي بعضها إلى الجمع بين أكثر من عددين، فهل سأقوم بحل هذه المشكلة بالاستدعاء المتكرر لتابع الجمع، أم سأقترح حلول أخرى، أم أن لغة الـ C تعطيني خيارا أقوى من ذلك...
كيف تكون القصة....
عندما أستدع تابع معين، وأمرر الوسائط له، يقوم المترجم بوضع هذه المتحولات في المكدس (وبترتيب معكوس كما عرفنا)، ويقوم جسم البرنامج باستخلاص هذه المتحولات من المكدس، ويمكن صنع هذه العملية بشكل يدوي...
إلا أن الـ Syntax المتعلق بلغة الـ C يدعم هذه العملية، بالإضافة لذلك، فهناك بعض الـ macros ( الموجودة في stdarg.h أو varargs.h)التي تدعم استخلاص المتحولات من المكدس وبالترتيب الذي مـُررت به...
آلية التنفيذ...
حتى نقوم بهذه العملية نقوم أولا باستدعاء التابع على الشكل:
int mysum(int num,...);\\for format
إن الـ (...) تدل على أن التابع - حين الاستدعاء - يقبل أكثر من عدد الوسائط (Parameters) الثابتة لديه، وهنا في مثالنا يقبل التابع وسيط واحد فما فوق دون أن يعطي المترجم اي أخطاء أثناء الترجمة.
وغالبا يمرر في الوسيط الأخير من الوسائط الثابتة عدد الوسائط المتغيرة العدد، وهذا عائد للمبرمج نفسه، والأسلوب الذي يعتمده.
عند بناء جسم التابع.....
الآن سننتقل إلى بناء جسم هذا التابع...
* في البداية أستخدم النمط va_list حتى أنشئ متحول مصفوفة (مؤشر) تشير إلى مكان المتحولات الموجودة في المكدس....
مثلا....
va_list ap;\\for format
* ثم بعد ذلك أستخدم الـ macro الذي يدعى va_start وذلك حتى أستطيع أن تهيئة هذا المؤشر ووضعه عند رأس الـ Stack حتى يأخذ الوسائط.
يكون ذلك بتمرير المتحول من نوع va_list كوسيط أولي(ap في مثالنا)، ثم بعد ذلك المتحول الأخير من الوسائط التي مررت للتابع(num في مثالنا)...
va_start(ap, msg);\\for format
* والآن حتى أحصل على كل وسيط أقوم باستدعاء الـ macro (va_arg) الذي يمرر له المتحول من نوع va_list كوسيط أولي(ap في مثالنا)، ثم بعد ذلك نوع المتحول المتوقع أخذها من المكدس، ويقوم هذا الـ macro بإزاحة المؤشر إلى الوسيط الذي يليه..
مثلا...
arg = va_arg(ap,int);\\for format
* بعد الانتهاء من استخلاص الوسائط، نقوم بإستدعاء الـ macro الأخير، والذي هو va_end، على الشكل:
va_end(ap);\\for format
ويصبح لدينا المثال كاملا كما في الشكل:
http://www.alepposoft.com/info/attachment.php?attachmentid=856
استخدام هذا التابع...
يمكن استخدام هذا التابع عن طريق تمرير عدد الوسائط أولا ثم الوسائط...
مثلا...
int sum = mysum(5,1,2,3,4,5);\\for format
تعليق...
يستخدم هذا الأسلوب في بعض المكاتب القياسية، ولعلك تستغرب إذا قلت لك أن التابع printf المشهور يستخدم هذا الأسلوب، وهو مصرح على الشكل:
int printf( const char,... ); \\for format
تسلية...
قم بإنشاء التابع الخاص بك والشبيه بتابع printf وليكن اسمه myprintf...
تمت والحمد لله رب العالمين....
إعداد: أحمد معتوقي.
كلية الهندسة المعلوماتية- طالب.
جميع الحقوق محفوظة لـ Alepposoft
السلام عليكم ورحمة الله وبركاته....
تتميز لغة الـ C عن غيرها من اللغات بكثير من المرونة التي لا تتيحها غيرها، ومن بينها أنك تستطيع أن تمرر إلى التابع عدد غير محدود من الوسائط....
ما الحاجة لها....
كثير من الأحيان لا أعرف عدد الوسائط التي ستمرر إلى التابع، فمثلا أحتاج في معظم الأحيان للجمع بين عددين، وفي بعضها إلى الجمع بين أكثر من عددين، فهل سأقوم بحل هذه المشكلة بالاستدعاء المتكرر لتابع الجمع، أم سأقترح حلول أخرى، أم أن لغة الـ C تعطيني خيارا أقوى من ذلك...
كيف تكون القصة....
عندما أستدع تابع معين، وأمرر الوسائط له، يقوم المترجم بوضع هذه المتحولات في المكدس (وبترتيب معكوس كما عرفنا)، ويقوم جسم البرنامج باستخلاص هذه المتحولات من المكدس، ويمكن صنع هذه العملية بشكل يدوي...
إلا أن الـ Syntax المتعلق بلغة الـ C يدعم هذه العملية، بالإضافة لذلك، فهناك بعض الـ macros ( الموجودة في stdarg.h أو varargs.h)التي تدعم استخلاص المتحولات من المكدس وبالترتيب الذي مـُررت به...
آلية التنفيذ...
حتى نقوم بهذه العملية نقوم أولا باستدعاء التابع على الشكل:
int mysum(int num,...);\\for format
إن الـ (...) تدل على أن التابع - حين الاستدعاء - يقبل أكثر من عدد الوسائط (Parameters) الثابتة لديه، وهنا في مثالنا يقبل التابع وسيط واحد فما فوق دون أن يعطي المترجم اي أخطاء أثناء الترجمة.
وغالبا يمرر في الوسيط الأخير من الوسائط الثابتة عدد الوسائط المتغيرة العدد، وهذا عائد للمبرمج نفسه، والأسلوب الذي يعتمده.
عند بناء جسم التابع.....
الآن سننتقل إلى بناء جسم هذا التابع...
* في البداية أستخدم النمط va_list حتى أنشئ متحول مصفوفة (مؤشر) تشير إلى مكان المتحولات الموجودة في المكدس....
مثلا....
va_list ap;\\for format
* ثم بعد ذلك أستخدم الـ macro الذي يدعى va_start وذلك حتى أستطيع أن تهيئة هذا المؤشر ووضعه عند رأس الـ Stack حتى يأخذ الوسائط.
يكون ذلك بتمرير المتحول من نوع va_list كوسيط أولي(ap في مثالنا)، ثم بعد ذلك المتحول الأخير من الوسائط التي مررت للتابع(num في مثالنا)...
va_start(ap, msg);\\for format
* والآن حتى أحصل على كل وسيط أقوم باستدعاء الـ macro (va_arg) الذي يمرر له المتحول من نوع va_list كوسيط أولي(ap في مثالنا)، ثم بعد ذلك نوع المتحول المتوقع أخذها من المكدس، ويقوم هذا الـ macro بإزاحة المؤشر إلى الوسيط الذي يليه..
مثلا...
arg = va_arg(ap,int);\\for format
* بعد الانتهاء من استخلاص الوسائط، نقوم بإستدعاء الـ macro الأخير، والذي هو va_end، على الشكل:
va_end(ap);\\for format
ويصبح لدينا المثال كاملا كما في الشكل:
http://www.alepposoft.com/info/attachment.php?attachmentid=856
استخدام هذا التابع...
يمكن استخدام هذا التابع عن طريق تمرير عدد الوسائط أولا ثم الوسائط...
مثلا...
int sum = mysum(5,1,2,3,4,5);\\for format
تعليق...
يستخدم هذا الأسلوب في بعض المكاتب القياسية، ولعلك تستغرب إذا قلت لك أن التابع printf المشهور يستخدم هذا الأسلوب، وهو مصرح على الشكل:
int printf( const char,... ); \\for format
تسلية...
قم بإنشاء التابع الخاص بك والشبيه بتابع printf وليكن اسمه myprintf...
تمت والحمد لله رب العالمين....
إعداد: أحمد معتوقي.
كلية الهندسة المعلوماتية- طالب.
جميع الحقوق محفوظة لـ Alepposoft