نتطرّق في هذا المقال إلى طرق مختلفة في التعامل مع السلاسل النصية والتلاعب بها، وذلك عن طريق دوال مكتبة 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
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.