نتطرّق في هذا المقال إلى طرق مختلفة في التعامل مع السلاسل النصية والتلاعب بها، وذلك عن طريق دوال مكتبة string.h، ومن ثمّ ننتقل إلى دوال الوقت والتاريخ المحتواة في مكتبة time.h.
التعامل مع السلاسل النصية
هناك العديد من الدوال التي تسمح لنا بالتعامل مع السلاسل النصية، إذ تكون السلسلة النصية في لغة سي مؤلفةً من مصفوفة من المحارف تنتهي بمحرف فارغ null، وتتوقع الدوال في جميع الحالات تمرير مؤشر يشير إلى المحرف الأول ضمن السلسلة النصية، ويعرّف ملف الترويسة <string.h> هذا النوع من الدوال.
النسخ
يضم هذا التصنيف الدوال التالية:
#include <string.h> void *memcpy(void *s1, const void *s2, size_t n); void *memmove (void *s1, const void *s2, size_t n); char *strcpy(char *s1, const char *s2); char *strncpy(char *s1, const char *s2, size_t n); char *strcat(char *s1, const char *s2); char *strncat(char *s1, const char *s2, size_t n);
-
دالة
memcpy: تنسخ هذه الدالةnبايت من المكان الذي يشير إليه المؤشرs2إلى المكان الذي يشير إليه المؤشرs1، ونحصل على سلوك غير محدد إذا كان الكائنان متداخلان overlapping objects. تعيد الدالةs1. -
دالة
memmove: هذه الدالة مطابقة لعمل دالةmemcpyإلا أنها تعمل على الكائنات المتداخلة، إلا أنها قد تكون أبطأ. -
دالتَي
strcpyوstrncpy: تنسخ كلا الدالتين السلسلة النصية التي يشير إليها المؤشرs2إلى سلسلة نصية يشير المؤشرs1إليها متضمنًا ذلك المحرف الفارغ في نهاية السلسلة. تنسخstrncpyسلسلةً نصيةً بطولnبايت على الأكثر، وتحشو ما تبقى بمحارف فارغة إذا كانتs2أقصر منnمحرف، ونحصل على سلوك غير معرّف، إذا كانت السلسلتان متقاطعتين، وتُعيد كلا الدالتينs1. -
الدالتان
strcatوstrncat: تُضيف كلا الدالتين السلسلة النصيةs2إلى السلسلةs1بالكتابة فوق overwrite المحرف الفارغ في نهاية السلسلةs1، بينما يُضاف المحرف الفارغ دائمًا إلى نهاية السلسلة. يمكن إضافةnمحرف على الأكثر من السلسلةs2باستخدام الدالةstrncatمما يعني أن السلسلة النصية الهدف (أيs1) يجب أن تحتوي على مساحة لطولها الأصلي (دون احتساب المحرف الفارغ) زائدn+1محرف للتنفيذ الآمن. تعيد الدالتينs1.
مقارنة السلسلة النصية والبايت
تُستخدم هذه الدوال في مقارنة مصفوفات من البايتات، وهذا يتضمن طبعًا السلاسل النصية في لغة سي إذ أنها سلسلةٌ من المحارف char (أي البايتات) بمحرف فارغ في نهايتها. تعمل جميع هذه الدوال التي سنذكرها على مقارنة بايت تلو الآخر وتتوقف فقط في حالة اختلف بايت مع بايت آخر (في هذه الحالة تُعيد الدالة إشارة الفرق بين البايت والآخر) أو عندما تكون المصفوفتان متساويتين (أي لم يُعثر على أي فرق بينهما وكان طولهما مساوٍ إلى الطول المحدد أو -في حالة المقارنة بين السلاسل النصية- وُجد المحرف الفارغ في النهاية).
القيمة المُعادة في جميع الدوال عدا الدالة strxfrm هي أصغر من الصفر، أو تساوي الصفر، أو أكبر من الصفر وذلك في حالة كان الكائن الأول أصغر من الكائن الثاني، أو يساوي الكائن الثاني، أو أكبر من الكائن الثاني على الترتيب.
#include <string.h> int memcmp(const void *s1, const void *s2, size_t n); int strcmp(const char *s1, const char *s2); int strncmp(const char *s1, const char *s2, size_t n); size_t strxfrm(char *to, const char *from, int strcoll(const char *s1, const char *s2);
-
دالة
memcmp: تُقارن أولnمحرف في الكائن الذي يشير إليه المؤشرs1وs2، إلا أن مقارنة الهياكل بهذه الطريقة ليست مثالية، إذ قد تحتوي الاتحادات unions أو "الثقوب holes" المُسببة بواسطة محاذاة ذاكرة التخزين على بيانات غير صالحة. -
دالة
strcmp: تُقارن سلسلتين نصيتين وهي إحدى أكثر الدوال استخدامًا عند التعامل مع السلاسل النصية. -
الدالة
strncmp: تُطابق عمل الدالةstrcmpإلا أنها تقارنnمحرف على الأكثر. -
الدالة
strxfrm: تُحوّل السلسلة النصية المُمرّرة إليها (بصورةٍ خاصة ومميزة)، وتُخزّن إلى موضع المؤشر، ويُكتبmaxsizeمحرف على الأكثر إلى موضع المؤشر (متضمنًا المحرف الفارغ في النهاية)، وتضمن طريقة التحويل أننا سنحصل على نتيجة المقارنة ذاتها لسلسلتين نصيتين محوّلتين ضمن إعدادات المستخدم المحلية عند استخدام الدالةstrcmpبعد تطبيق الدالةstrcollعلى السلسلتين النصيتين الأساسيتين.
نحصل على طول السلسلة النصية الناتجة مثل قيمة مُعادة في جميع الحالات (باستثناء المحرف الفارغ في نهاية السلسلة)، وتكون محتويات المؤشر to غير معرّفة إذا كانت القيمة مساوية أو أكبر من maxsize، وقد تكون s1 مؤشرًا فارغًا إذا كانت maxsize صفر، ونحصل على سلوك غير معرّف إذا كان الكائنان متقاطعين.
-
دالة
strcollتُقارن هذه الدالة سلسلتين نصيتين بحسب سلسلة الترتيب collating sequence المحدد في إعدادات اللغة المحلية.
دوال بحث المحارف والسلاسل النصية
يتضمن التصنيف الدوال التالية:
#include <string.h> void *memchr(const void *s, int c, size_t n); char *strchr(const char *s, int c); size_t strcspn(const char *s1, const char *s2); char *strpbrk(const char *s1, const char *s2); char *strrchr(const char *s, int c); size_t strspn(const char *s1, const char *s2); char *strstr(const char *s1, const char *s2); char *strtok(const char *s1, const char *s2);
-
دالة
memchr: تُعيد مؤشرًا يشير إلى أول ظهور ضمن أولnمحرف منs*للمحرفc(من نوعunsigned char)، وتُعيد فراغًا null إن لم يُعثر على أي تطابق. -
دالة
strchr: تُعيد مؤشرًا يشير إلى أول ظهور للمحرفcضمنs*ويتضمن البحث المحرف الفارغ، وتُعيد فراغًا null إذا لم يُعثر على أي تطابق. -
دالة
strcspn: تُعيد طول الجزء الأولي للسلسلة النصيةs1الذي لا يحتوي أيًّا من محارف السلسلةs2، ولا يؤخذ المحرف الفارغ في نهاية السلسلةs2بالحسبان. -
دالة
strpbrk: تُعيد مؤشرًا إلى أول محرف ضمنs1يطابق أي محرف من محارف السلسلةs2أو تُعيد فراغًا إن لم يُعثر على أي تطابق. -
دالة
strrchr: تُعيد مؤشرًا إلى آخر محرف ضمنs1يطابق المحرفcآخذة بالحسبان المحرف الفارغ على أنه جزء من السلسلةs1وتُعيد فراغ إن لم يُعثر على تطابق. -
دالة
strspn: تُعيد طول الجزء الأولي ضمن السلسلةs1الذي يتألف كاملًا من محارف السلسلةs1. -
دالة
strstr: تُعيد مؤشرًا إلى أول تطابق للسلسلةs2ضمن السلسلةs1أو تُعيد فراغ إن لم يُعثر على تطابق. -
دالة
strtok: تقسّم السلسلة النصيةs1إلى "رموز tokens" يُحدّد كل منها بمحرف من محارف السلسلةs2وتُعيد مؤشرًا يشير إلى الرمز الأول أو فراغًا إن لم يوجد أي رموز. تُعيد استدعاءات لاحقة للدالة باستخدام(char *)0قيمةً للوسيطs1الرمز التالي ضمن السلسلة، إلا أنs2(المُحدِّد) قد يختلف عند كل استدعاء، ويُعاد مؤشر فارغ إذا لم يبق أي رمز.
دوال متنوعة أخرى
هناك بعض الدوال الأخرى التي لا تنتمي لأي من التصنيفات السابقة:
void *memset(void *s, int c, size_t n); char *strerror(int errnum); size_t strlen(const char *s);
-
دالة
memset: تضبطnبايت يشير إليها المؤشرsإلى قيمة المحرفcوهو من النوعunsigned char، وتُعيد الدالة المؤشرs. -
دالة
strlen: تُعيد طول السلسلة النصيةsدون احتساب المحرف الفارغ في نهاية السلسلة، وهي دالة شائعة الاستخدام. -
دالة
strerror: تُعيد مؤشرًا يشير إلى سلسلة نصية تصف الخطأ رقمerrnum، وقد تُعدَّل هذه السلسلة النصية عن طريق استدعاءات لاحقة للدالةsterror، وتعدّ هذه الدالة مفيدةٌ لمعرفة معنى قيمerrno.
التاريخ والوقت
تتعامل هذه الدوال إما مع الوقت المُنقضي elapsed time، أو وقت التقويم calendar time ويحتوي ملف الترويسة <time.h> على تصريح كلا النوعين من الدوال بالاعتماد على التالي:
-
القيمة
CLOCKS_PER_SEC: عدد الدقات ticks في الثانية المُعادة من الدالةclock. -
النوعين
clock_tوtime_t: أنواع حسابية تُستخدم لتمثيل تنسيقات مختلفة من الوقت. -
الهيكل
struct tm: يُستخدم لتخزين القيمة المُمثّلة لأوقات التقويم، ويحتوي على الأعضاء التالية:
int tm_sec // الثواني بعد الدقيقة من 0 إلى 61، وتسمح 61 بثانيتين كبيستين leap-second int tm_min // الدقائق بعد الساعة من 0 إلى 59 int tm_hour // الساعات بعد منتصف الليل من 0 إلى 23 int tm_mday //اليوم في الشهر من 1 إلى 31 int tm_mon // الشهر في السنة من 0 إلى 11 int tm_year // السنة الحالية من 1900 int tm_wday // الأيام منذ يوم الأحد من 0 إلى 6 int tm_yday // الأيام منذ الأول من يناير من 0 إلى 365 int tm_isdst // مؤشر التوقيت الصيفي
يكون العنصر tm_isdst موجبًا إذا كان التوقيت الصيفي daylight savings فعّالًا، وصفر إن لم يكن كذلك، وسالبًا إن لم تكن هذه المعلومة متوفرة.
إليك دوال التلاعب بالوقت:
#include <time.h> clock_t clock(void); double difftime(time_t time1, time_t time2); time_t mktime(struct tm *timeptr); time_t time(time_t *timer); char *asctime(const struct tm *timeptr); char *ctime(const time_t *timer); struct tm *gmtime(const time_t *timer); struct tm *localtime(const time_t *timer); size_t strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr);
تتشارك كل من الدوال asctime و ctime و gmtime و localtime و strftime بهياكل بيانات ساكنة static من نوع struct tm أو من نوع char []، وقد يتسبب استدعاء أحد منها بعملية الكتابة فوق البيانات المخزنة بسبب استدعاء سابق لإحدى الدوال الأخرى، ولذلك يجب على مستخدم الدالة نسخ المعلومات إذا كان هذا سيسبب أية مشاكل.
-
الدالة
clock: تُعيد أفضل تقريب للوقت الذي انقضى منذ تشغيل البرنامج مقدرًا بدقات الساعة ticks، وتُعاد القيمة(clock_t)-1إذا لم يُعثر على أي قيمة. من الضروري العثور على الفرق بين وقت بداية تشغيل البرنامج والوقت الحالي إذا أردنا إيجاد الوقت المُنقضي اللازم لتشغيل البرنامج، وهناك ثابتٌ معرفٌ حسب التنفيذ يعدل على القيمة المُعادة منclock. يجب تقسيم القيمة علىCLOCKS_PER_SECلتحديد الوقت بالثواني. -
الدالة
difftime: تُعيد الفرق بين وقت تقويم ووقت تقويم آخر بالثواني. -
الدالة
mktime: تُعيد وقت تقويم يوافق القيم الموجودة في هيكل يشير إلى المؤشرtimeptr، أو تُعيد القيمة(time_t)-1إذا لم يكن من الممكن تمثيل القيمة. يُتجاهل العضوانtm_wdayوtm_yday، ولا تُقيَّد باقي الأعضاء بقيمهم الاعتيادية، إذ يُضبط أعضاء الهيكل إلى قيم مناسبة ضمن النطاق الاعتيادي عند التحويل الناجح، وهذه الدالة مفيدة للعثور على التاريخ والوقت الموافق لقيمة من نوعtime_t. -
الدالة
time: تُعيد أفضل تقريب لوقت التقويم الحالي باستخدام ترميز غير محدد unspecified encoding، وتُعيد القيمة(time_t)-1إذا كان الوقت غير متوفر. -
الدالة
asctime: تُحول الوقت ضمن هيكل يشير إليه المؤشرtimptrإلى سلسلة نصية بالتنسيق التالي:
Sun Sep 16 01:03:52 1973\n\0
المثال السابق مأخوذٌ من المعيار، إذ يعرِّف المعيار الخوارزمية المستخدمة أيضًا، إلا أنه من المهم ملاحظة أن جميع الحقول ضمن السلسلة النصية ذات عرض ثابت وينطبق استخدامها على المجتمعات التي تتحدث باللغة الإنجليزية فقط. تُخزّن السلسلة النصية في هيكل ساكن static structure ويُمكن إعادة كتابته عن طريق استدعاءات لاحقة لأحد دوال التلاعب بالوقت (المذكورة أعلاه).
-
الدالة
ctime: تكافئ عملasctime(localtime(timer)). اقرأ عن الدالةasctimeلمعرفة القيمة المُعادة. -
الدالة
gmtime: تُعيد مؤشرًا إلىstruct tm، إذ يُضبط هذا المؤشر إلى وقت التقويم الذي يشير إليه المؤشرtimer، ويُمثل الوقت بحسب شروط التوقيت العالمي المُنسّق Coordinated Universal Time -أو اختصارًا UTC-، أو المسمى سابقًا بتوقيت جرينتش Greenwich Mean Time، ونحصل على مؤشر فارغ إذا كان توقيت UTC غير مُتاح. -
الدالة
localtime: تحوّل الوقت الذي يشير إليه المؤشرtimerإلى التوقيت المحلي وتُخزن النتيجة فيstruct tmوتُعيد مؤشرًا يشير إلى ذلك الهيكل. -
الدالة
strftime: تملأ مصفوفة المحارف التي يشير إليها المؤشرsبـمقدارmaxsizeمحرف على الأكثر، وتُستخدم السلسلة النصيةformatلتنسيق الوقت المُمثّل في الهيكل الذي يشير إليه المؤشرtimeptr، تُنسخ المحارف الموجودة في سلسلة التنسيق النصية (متضمنة المحرف الفارغ في نهاية السلسلة) دون أي تغيير إلى المصفوفة إلا إن كان وجِد توجيه تنسيق من التوجيهات التالية، فعندها تُسنخ القيمة المُحددة ضمن الجدول إلى المصفوفة الهدف بما يوافق الإعدادات المحلية.
%a
|
اسم يوم الأسبوع باختصار |
%A
|
اسم يوم الأسبوع كاملًا |
%b
|
اسم الشهر باختصار |
%B
|
اسم الشهر كاملًا |
%c
|
تمثيل التاريخ والوقت |
%d
|
تمثيل يوم الشهر عشريًا من 01 إلى 31 |
%H
|
الساعة من 00 إلى 23 (تنسيق 24 ساعة) |
%I
|
الساعة من 01 إلى 12 (تنسيق 12 ساعة) |
%j
|
يوم السنة من 001 إلى 366 |
%m
|
الشهر من 01 إلى 12 |
%M
|
الدقيقة من 00 إلى 59 |
%p
|
مكافئة PM أو AM المحلي |
%S
|
الثانية من 00 إلى 61 |
%U
|
ترتيب الأسبوع ضمن السنة من 00 إلى 53 (الأحد هو اليوم الأول) |
%w
|
يوم الأسبوع من 0 إلى 6 (الأحد مُمثّل بالرقم 0) |
%W
|
ترتيب الأسبوع ضمن السنة من 00 إلى 53 (الاثنين هو اليوم الأول) |
%x
|
تمثيل التاريخ محليًا |
%X
|
تمثيل الوقت محليًا |
%y
|
السنة دون سابقة القرن من 00 إلى 99 |
%Y
|
السنة مع سابقة القرن |
%Z
|
اسم المنطقة الزمنية، لا نحصل على محارف إن لم يكن هناك أي منطقة زمنية |
%%
|
محرف %
|
يُعاد عدد المحارف الكلية المنسوخة إلى s* باستثناء محرف الفراغ في نهاية السلسلة، وتُعاد القيمة صفر إذا لم يكن هناك أي مساحة (بحسب قيمة maxsize) للمحرف الفارغ في النهاية.
ترجمة -وبتصرف- لقسم من الفصل Libraries من كتاب The C Book.
اقرأ أيضًا
- المقال التالي: تطبيقات عملية في لغة سي C
- المقال السابق: أدوات مكتبة stdlib في لغة سي C
- بنية برنامج لغة سي C
- الدوال في لغة C
- القيم الحدية والدوال الرياضية في لغة سي C

أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.