نستعرض هنا الأدوات الموجودة في ملف الترويسة <stdlib.h>
الذي يصرح عن عدد من الأنواع والماكرو وعدة دوال للاستخدام العام، تتضمن الأنواع والماكرو التالي:
-
النوع
size_t
: تكلمنا عنه سابقًا. -
النوع
div_t
: نوع من الهياكل التي تعيدها الدالةdiv
. -
النوع
ldiv_t
: نوع من الهياكل التي تعيدها الدالةldiv
. -
النوع
NULL
: تكلمنا عنه سابقًا. -
القيمة
EXIT_FAILURE
وEXIT_SUCCESS
: يمكن استخدامهما مثل وسيط للدالةexit
. -
القيمة
MB_CUR_MAX
: العدد الأعظمي للبايتات في محرف متعدد البايتات multibyte character من مجموعة المحارف الإضافية والمحددة حسب إعدادت اللغة المحلية locale. -
القيمة
RAND_MAX
: القيمة العظمى المُعادة من استدعاء دالةrand
.
دوال تحويل السلسلة النصية
هناك ثلاث دوال تقبل سلسلة نصية وسيطًا لها وتحوّلها إلى عدد من نوع معين كما هو موضح هنا:
#include <stdlib.h> double atof(const char *nptr); long atol(const char *nptr); int atoi(const char *nptr);
نحصل على عدد مُحوّل مُعاد لكل من الدوال الثلاث السابقة، ولا تضمن لك أيٌ من الدوال أن تضبط القيمة errno
(إلا أن الأمر محقّق في بعض التنفيذات)، وتكون النتائج التي نحصل عليها من تحويلات تتسبب بحدوث طفحان overflow ولا يمكننا تمثيلها غير معرّفة.
هناك بعض الدوال أكثر تعقيدًا:
#include <stdlib.h> double strtod(const char *nptr, char **endptr); long strtol(const char *nptr, char **endptr, int base); unsigned long strtoul(const char *nptr,char **endptr, int base);
تعمل الدوال الثلاث السابقة بطريقة مشابهة، إذ يجري تجاهل أي مسافات فارغة بادئة ومن ثم يُعثر على الثابت المناسب subject sequence
متبوعًا بسلسلة محارف غير معترف عليها، ويكون المحرف الفارغ في نهاية السلسلة النصية غير مُعترف عليه دائمًا. تُحدد السلسلة المذكورة حسب التالي:
-
في الدالة
strtod
: إشارة "+" أو "-" اختيارية في البداية متبوعة بسلسلة أرقام تحتوي على محرف الفاصلة العشرية الاختياري وأس exponent اختياري أيضًا. لا يُعترف على أي لاحقة عائمة (ما بعد الفاصلة العشرية)، وتُعدّ الفاصلة العشرية تابعةً لسلسلة الأرقام إذا وُجدت. -
في الدالة
strtol
: إشارة "+" أو "-" اختيارية في البداية متبوعة بسلسلة أرقام، وتُؤخذ هذه الأرقام من الخانات العشرية أو من أحرف صغيرة lower case أو كبيرة upper case ضمن النطاق a إلى z في الأبجدية الإنجليزية ويُعطى لكل من هذه الأحرف القيم ضمن النطاق 10 إلى 35 بالترتيب. يحدِّد الوسيطbase
القيم المسموحة ويمكن أن تكون قيمة الوسيط صفر أو ضمن النطاق 2 إلى 36. يجري التعرُّف على الخانات التي تبلغ قيمتها أقل من الوسيطbase
، إذ تسمح القيمة 16 للوسيطbase
على سبيل المثال للمحارف0x
أو0X
أن تتبع الإشارة الاختيارية، بينما يسمحbase
بقيمة صفر أن تكون المحارف المدخلة على هيئة أعداد صحيحة ثابتة في سي، ولا يُعترف على أي لاحقة عدد صحيح. -
في الدالة
strtoul
: مطابقة للدالةstrtol
إلا أنها لا تسمح بوجود إشارة.
يُخزّن عنوان أول محرف غير مُعترف عليه في الكائن الذي يشير إليه endptr
في حال لم يكُن فارغًا، وتكون هذه قيمة nptr
إذا كانت السلسلة فارغة أو ذات تنسيق خاطئ.
تحوّل الدالة الرقم وتُعيده مع الأخذ بالحسبان كون وجود الإشارة البادئة مسموحًا أو لا، وذلك إذا كان إجراء التحويل ممكنًا، وإلا فإنها تعيد القيمة صفر. عند حدوث الطفحان أو حصول خطأ تُجرى العمليات التالية:
-
في الدالة
strtod
: تُعيد عند الطفحان القيمةHUGE_VAL±
وتعتمد الإشارة على إشارة النتيجة، وتُعيد القيمة صفر عند طفحان الحد الأدنى underflow ويُضبطerrno
في الحالتين إلى القيمةERANGE
. -
في الدالة
strtol
: تُعيد القيمةLONG_MAX
أوLONG_MIN
عند الطفحان بحسب إشارة النتيحة، ويُضبطerrno
في كلا الحالتين إلى القيمةERANGE
. -
في الدالة
strtoul
: تُعيد القيمةULONG_MAX
عند الطفحان، ويُضبطerrno
إلى القيمةERANGE
.
قد يكون هناك سلاسل أخرى من الممكن التعرُّف عليها في بعض التنفيذات إذا لم تكن الإعدادات المحلية هي إعدادات سي التقليدية.
توليد الأرقام العشوائية
تقدِّم الدوال التالية طريقةً لتوليد الأرقام العشوائية الزائفة pseudo-random:
#include <stdlib.h> int rand(void); void srand(unsigned int seed);
تُعيد الدالة rand
رقمًا عشوائيًا زائفًا ضمن النطاق من "0" إلى "RAND_MAX"، وهو ثابت قيمته على الأقل "32767".
تسمح الدالة srand
بتحديد نقطة بداية للنطاق المُختار طبقًا لقيمة الوسيط seed
، وهي ذات قيمة "1" افتراضيًا إذا لم تُستدعى srand
قبل rand
، ونحصل على سلسلة قيم مطابقة من الدالة rand
إذا استخدمنا قيمة seed
ذاتها.
يصف المعيار الخوارزمية المستخدمة في دالتي rand
و srand
، وتستخدم معظم التنفيذات هذه الخوارزمية عادةً.
حجز المساحة
تُستخدم هذه الدوال لحجز وتحرير المساحة، إذ يُضمن للمساحة التي حصلنا عليها أن تكون كبيرةً كفاية لتخزين كائن من نوع معين ومُحاذاة ضمن الذاكرة بحيث لا تتسبب بتفعيل استثناءات العنوان addressing exceptions، ولا يجب افتراض أي شيء آخر بخصوص عملها.
#include <stdlib.h> void *malloc(size_t size); void *calloc(size_t nmemb, size_t size); void *realloc(void *ptr, size_t size); void *free(void *ptr);
تُعيد جميع دوال حجز المساحة مؤشرًا يشير إلى المساحة المحجوزة التي يبلغ حجمها size
بايت، وإذا لم يكن هناك أي مساحة فارغة فهي تعيد مؤشرًا فارغًا، إلا أن الفرق بين الدوال هو أن دالة calloc
تأخذ وسيطًا يدعى nmemb
الذي يحدد عدد العناصر في مصفوفة، وكل عنصر في هذه المصفوفة يبلغ حجمه size
بايت، ولذا فهي تحجز مساحةً أكبر من التخزين عادةً من المساحة التي تحجزها malloc
، كما أن المساحة المحجوز بواسطة malloc
غير مُهيّئة بينما تُهيّأ جميع بتات مساحة التخزين المحجوزة بواسطة calloc
إلى الصفر، إلا أن هذا الصفر ليس تمثيلًا مكافئًا للصفر ضمن الفاصلة العائمة floating-point أو مؤشرًا فارغًا null بالضرورة.
تُستخدم الدالة realloc
لتغيير حجم الشيء المُشار إليه بواسطة المؤشر ptr
مما يتطلب بعض النسخ لإنجاز هذا الأمر ومن ثمّ تُحرّر مساحة التخزين القديمة. لا تُغيّر محتويات الكائن المُشار إليه بواسطة ptr
بالنسبة للحجمين القديم والجديد، وتتصرف الدالة تصرفًا مماثلًا لتصرف malloc
إذا كان المؤشر ptr
مؤشرًا فارغًا وذلك للحجم المخصّص.
تُستخدم الدالة free
لتحرير المساحة المحجوزة مسبقًا من إحدى دوال حجز المساحة، ومن المسموح تمرير مؤشر فارغ إلى الدالة free
وسيطًا لها، إلا أن الدالة في هذه الحالة لا تنفّذ أي شيء.
إذا حاولت تحرير مساحة لم تُحجز مسبقًا تحصل على سلوك غير محدّد، ويتسبب هذا الأمر في العديد من التنفيذات باستثناء عنوان addressing exception مما يوقف البرنامج، إلا أن هذه ليست بدلالة يمكن الاعتماد عليها.
التواصل مع البيئة
سنستعرض مجموعةً من الدوال المتنوعة:
#include <stdlib.h> void abort(void); int atexit(void (*func)(void)); void exit(int status); char *getenv(const char *name); int system(const char *string);
-
دالة
abort
: تتسبب بإيقاف غير اعتيادي للبرنامج وذلك باستخدام الإشارةSIGABRT
، ويمكن منع الإيقاف غير الاعتيادي فقط إذا حصلنا على الإشارة ولم يُعد معالج الإشارة signal handler أي قيمة، وإلا ستُحذف ملفات الخرج وقد يمكن أيضًا إزالة الملفات المؤقتة بحسب تعريف التنفيذ، وتُعاد حالة "إنهاء برنامج غير ناجح unsuccessful termination" إلى البيئة المُستضافة، كما أن هذه الدالة لا يمكن أن تُعيد أي قيمة. -
دالة
atexit
: يصبح وسيط الدالةfunc
دالةً يمكن استدعاؤها دون استخدام أي وسطاء عندما يُغلق البرنامج، ويمكن استخدام ما لا يقل عن 32 دالة مشابهة لهذه الدالة وأن تُستدعى عند إغلاق البرنامج بصورةٍ مُعاكسة لتسجيل كلٍّ منها، ونحصل على القيمة المُعادة صفر للدلالة على النجاح وإلا فقيمة غير صفرية للدلالة على الفشل. -
دالة
exit
: تُستدعى هذه الدالة عادةً لإنهاء البرنامج على نحوٍ اعتيادي، وتُستدعى عند تنفيذ الدالة جميع الدوال المُسجّلة باستخدام دالةatexit
، لكن انتبه، إذ ستُعد الدالةmain
بحلول هذه النقطة قد أعادت قيمتها ولا يمكن استخدام أي كائنات ذات مدة تخزين تلقائي automatic storage duration على نحوٍ آمن، من ثمّ تُحذف محتويات جميع مجاري الخرج output streams وتُغلق وتُزال جميع الملفات التلقائية المُنشأة بواسطةtmpfile
، وأخيرًا يُعيد البرنامج التحكم إلى البيئة المستضافة بإعادة حالة نجاح أو فشل محدّدة بحسب التنفيذ، وتعتمد الحالة على إذا ما كان وسيط الدالةexit
مساوٍ للقيمةEXITSUCCESS
(وهذه حالة النجاح) أوEXITFAILURE
(حالة الفشل). للتوافق مع لغة سي القديمة، تُستخدم القيمة صفر بدلًا منEXITFAILURE
، بينما يكون لباقي القيم تأثيرات معرّفة بحسب التنفيذ. لا يمكن أن تُعاد حالة الخروج. -
دالة
getenv
: يجري البحث في لائحة البيئة environment list المعرفة بحسب التنفيذ بهدف العثور على عنصر يوافق السلسلة النصية المُشار إليها بواسطة وسيط الاسمname
، إذ تُعيد الدالة مؤشرًا إلى العنصر يشير إلى مصفوفة لا يمكن تعديلها من قبل البرنامج ويمكن تعديلها باستدعاء لاحق للدالةgetenv
، ونحصل على مؤشر فارغ إذا لم يُعثر على عنصر موافق. يعتمد الهدف من لائحة البيئة وتنفيذها على البيئة المُستضافة. -
دالة
system
: تُمرّر سلسلة نصية إلى أمر معالج مُعرف حسب التنفيذ، ويتسبب مؤشر فارغ بإعادة القيمة صفر، وقيمة غير صفرية إذا لم يكن الأمر موجودًا، بينما يتسبب مؤشر غير فارغ بمعالجة الأمر. نتيجة الأمر والقيمة المُعادة معرف حسب التنفيذ.
البحث والترتيب
هناك دالتان ضمن هذا التصنيف، أولهما دالة للبحث ضمن لائحة مُرتّبة والأخرى لترتيب لائحة غير مرتبة، واستخدام الدالتان عام، إذ يمكن استخدامهما في مصفوفات من أي سعة وعناصرها من أي حجم.
يجب أن يلجأ المستخدم إلى دالة مقارنة إذا أراد مقارنة عنصرين عند استخدام الدوال السابقة، إذ تُستدعى هذه الدالة باستخدام المؤشرين الذين يشيران إلى العنصرين مثل وسطاء الدالة، وتُعيد الدالة قيمةً أقل من الصفر إذا كانت قيمة المؤشر الأول أصغر من قيمة المؤشر الثاني، وقيمة أكبر من الصفر إذا كانت قيمة المؤشر الأول أكبر من المؤشر الثاني، والقيمة صفر إذا كانت قيمتا المؤشرين متساويين.
#include <stdlib.h> void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); void *qsort(const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
يمثّل الوسيط nmemb
في كلٍّ من الدالتين السابقتين عدد العناصر في المصفوفة، ويمثل الوسيط size
حجم عنصر المصفوفة الواحد بالبايت و compar
هي الدالة التي تُستدعى للمقارنة بين العنصرين، بينما يشير المؤشر base
إلى أساس المصفوفة أي بدايتها.
ترتّب الدالة qsort
المصفوفة ترتيبًا تصاعديًا.
تفترض الدالة bsearch
أن المصفوفة مرتّبة مسبقًا وتُعيد مؤشرًا إلى أي عنصر يتساوى مع العنصر المُشار إليه بالمؤشر key
، وتُعيد الدالة مؤشرًا فارغًا إذا لم تجد أي عناصر متساوية.
دوال العمليات الحسابية الصحيحة
تقدّم هذه الدوال طريقةً لإيجاد القيمة المطلقة لوسيط يمثل عدد صحيح، إضافةً لحاصل القسمة والباقي من العملية لكلٍّ من النوعين int
و long
.
#include <stdlib.h> int abs(int j); long labs(long j); div_t div(int numerator, int denominator); ldiv_t ldiv(long numerator, long denominator);
-
الدالتان
abs
وlabs
: تُعيدان القيمة المطلقة لوسيطهما ويجب اختيار الدالة المناسبة بحسب احتياجاتك. نحصل على سلوك غير معرّف إذا لم تكن القيمة ممكنة التمثيل وقد يحدث ذلك في الأنظمة التي تعمل بنظام المتمم الثنائي two's complement systems، إذ لا يوجد لأكثر رقم سلبيّة أي مكافئ إيجابي. -
الدالتان
div
وldiv
: تُقسّمان الوسيطnumerator
على الوسيطdenominator
وتُعيدان هيكلًا structure للنوع المحدد، وفي أي حالة، سيحتوي الهيكل على عضو يدعىquot
يحتوي على حاصل القسمة الصحيحة وعضوًا آخر يدعىrem
يحتوي على باقي القسمة، ونوع العضوين هوint
في الدالةdiv
وlong
في الدالةldiv
، ويمكن تمثيل نتيجة العملية على النحو التالي:
quot*denominator+rem == numerator
الدوال التي تستخدم المحارف متعددة البايت
يؤثر تصنيف LC_CTYPE
ضمن الإعدادات المحلية الحالية على سلوك هذه الدوال، إذ تُضبط كل دالة إلى حالة ابتدائية باستدعاء يكون وسيطها s
الذي يمثل مؤشر المحرف فارغًا null، وذلك في حالة الترميز المُعتمد على الحالة state-dependent endcoding، وتُغيَّر حالة الدالة الداخلية وفق الضرورة عن طريق استدعاءات لاحقة عندما لا يكون s
مؤشرًا فارغًا. تُعيد الدالة قيمةً غير صفرية إذا كان الترميز معتمدًا على الحالة، وإلا فتعيد القيمة صفر إذا كان المؤشر s
فارغًا. تصبح حالة الإزاحة shift state الخاصة بالدوال غير محددة indeterminate إذا حدث تغيير للتصنيف LC_TYPE
.
الدوال هي:
#include <stdlib.h> int mblen(const char *s, size_t n); int mbtowc(wchar_t *pwc, const char *s, size_t n); int wctomb(char *s, wchar_t wchar); size_t mbstowcs(wchar_t *pwcs, const char *s, size_t n); size_t wcstombs(char *s, const wchar_t *pwcs, size_t n);
-
الدالة
mblen
: تُعيد عدد البايتات المُحتواة بداخل محرف متعدد البايتات multibyte character المُشار إليه بواسطة المؤشرs
أو تُعيد القيمة -1 إذا كان أولn
بايت لا يشكّل محرف متعدد البايتات صالحًا، أو تُعيد القيمة صفر إذا كان المؤشر يشير إلى محرف فارغ. -
الدالة
mbtowc
: تُحوِّل محرف متعدد البايتات يُشير إليه المؤشرs
إلى الرمز الموافق له من النوعwchar_t
وتُخزّن النتيجة في الكائن المُشار إليه بالمؤشرpwc
، إلا إن كانpwc
مؤشرًا فارغًا، وتُعيد الدالة عدد البايتات المُحوّلة بنجاح، أو -1 إذا لم تشكّل أولn
بايت محرفًا متعدد البايت صالحًا، ولا يُفحص أكثر منn
بايت يُشير إليه المؤشرs
، ولن تتعدى القيمة المُعادة قيمةn
أوMB_CUR_MAX
. -
دالة
wctmob
: تُحوِّل رمز القيمةwchar
إلى سلسلة من البايتات تمثل محرف متعدد البايتات وتخزن النتيجة في مصفوفة يشير إليها المؤشرs
وذلك إن لم يكنs
مؤشرًا فارغًا، وتُعيد الدالة عدد البايتات المحتواة داخل محرف متعدد البايتات، أو -1 إذا كانت القيمة المخزنة فيwchar
لا تمثل محرف متعدد البايات، ومن غير الممكن معالجة عدد بايتات يتجاوزMB_CUR_MAX
. -
دالة
mbstowcs
: تحوّل سلسلة محارف متعددة البايتات بدءًا من الحالة الأولية للإزاحة initial shift state وذلك ضمن المصفوفة التي يشير إليها المؤشرs
إلى سلسلة من الرموز الموافقة ومن ثم تخزّنها في مصفوفة يشير إليها المؤشرpwcs
، لا يُخزّن ما يزيد عنn
قيمة فيpwcs
، وتُعيد الدالة 1- إذا صادفت محرفًا متعدد البايت غير صالح، وإلا فإنها تعيد عدد عناصر المصفوفة المُعدّلة باستثناء رمز إنهاء المصفوفة.
نحصل على سلوك غير معرّف إذا وجد كائنين متقاطعين.
-
الدالة
wcstombs
: تُحوِّل سلسلة من الرموز المُشار إليها بالمؤشرpwcs
إلى سلسلة من المحارف متعددة البايتات بدءًا من الحالة الأولية للإزاحة وتُخزّن فيما بعد في مصفوفة مُشار إليها بالمؤشرs
. تتوقف عملية التحويل عند مصادفة رمز فارغ، أو عند كتابةn
بايت إلىs
، وتُعيد الدالة -1 إذا كان الرمز المُصادف لا يمثل محرفًا متعدد البايتات صالحًا، وإلا فيُعاد عدد البايتات التي كُتبت باستثناء رمز الإنهاء الفارغ.
نحصل على سلوك غير محدد إذا وجد كائنين متقاطعين.
ترجمة -وبتصرف- لقسم من الفصل Libraries من كتاب The C Book.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.