- 1 1. المقدمة
- 2 2. ما هي سلاسل النص في لغة C؟ المفاهيم الأساسية وأهمية حرف النهاية
- 3 3. طريقة استخراج جزء من السلسلة في C gengo【قسم hyoujun raiburari】
- 4 4. طريقة استخراج السلسلة الفرعية في لغة C【جزء الدوال المخصصة】
- 5 5. طريقة استخراج السلاسل النصية حسب ترميز الأحرف
- 6 6. طريقة تقسيم السلاسل في لغة C
- 7 7. مثال تطبيقي: طريقة استخراج ما قبل وما بعد حرف معين
- 8 8. الملخص
1. المقدمة
إن التعامل مع السلاسل النصية في لغة C هو أحد المهارات المهمة عند تعلم البرمجة. خصوصًا،استخراج السلسلة النصية (استخراج الجزء الفرعي من السلسلة) يُستخدم كثيرًا عند معالجة البيانات أو تحويل الصيغ.
في هذه المقالة، حول طريقة استخراج السلاسل النصية في لغة C، سنشرح بالتفصيل استخدام دوال المكتبة القياسية، طريقة إنشاء دوال مخصصة، التعامل مع الأحرف متعددة البايت (اليابانية)، وطريقة تقسيم السلاسل النصية وغيرها. كما سنعرض أمثلة تطبيقية ومعالجة الأخطاء، لذا يرجى المتابعة حتى النهاية.
ما يمكن تعلمه في هذه المقالة
من خلال قراءة هذه المقالة، يمكنك اكتساب المهارات التالية.
- مفهوم أساسي لسلاسل C والرمز النهائي دوره
strncpy
strchr
استخراج السلاسل الجزئية باستخدام دوال مكتبة القياسية- طريقة تنفيذ معالجة السلاسل باستخدام الدالة المخصصة
- مراعاة الأحرف متعددة البايت (اللغة اليابانية)
strtok
طريقة تقسيم السلاسل- طريقة الحصول على النص قبل وبعد حرف محدد
سنشرح بطريقة سهلة الفهم حتى للمبتدئين، مع تضمين أمثلة على الشيفرة.
لماذا يعتبر استخراج السلاسل النصية في لغة C مهمًا؟
لغة C تتعامل مع السلاسل النصية كـ مصفوفة (مصفوفة من نوع char)، لذا لا يمكن الحصول على جزء من السلسلة بسهولة كما في اللغات عالية المستوى مثل Python أو JavaScript. لذلك، من المهم اختيار الطريقة المناسبة في الحالات التالية.
1. معالجة بيانات الإدخال
على سبيل المثال، عند تحليل بيانات مثل سجلات النظام أو ملفات CSV، قد تحتاج إلى استخراج عناصر محددة.
2. البحث عن كلمة مفتاحية محددة
البحث عن كلمة مفتاحية محددة داخل سلسلة واستخلاص المعلومات التي تسبقها وتليها أمر أساسي لوظيفة البحث واستخراج البيانات.
3. تحسين أمان البرنامج
strncpy
باستخدام دوال مثل strncpy
بشكل مناسب، يمكنك منع تجاوز سعة الذاكرة (كتابة بيانات تتجاوز حجم الذاكرة). هذا مهم لتجنب مخاطر الأمان.
هيكل المقالة
في هذه المقالة، سنشرح وفق التسلسل التالي.
- ما هو سلسلة الأحرف في لغة C؟ المفاهيم الأساسية وأهمية الحرف النهائي
- طريقة استخراج جزء من السلسلة في لغة C【الطبعة باستخدام المكتبة القياسية】
- طريقة استخراج السلاسل الجزئية في لغة C【الجزء الخاص بالدوال المخصصة】
- طريقة استخراج السلاسل حسب ترميز الأحرف
- كيفية تقسيم سلسلة نصية في لغة C
- مثال تطبيقي: طريقة استخراج ما قبل وما بعد حرف محدد
- الملخص
- FAQ
هيا نبدأ بالنظر بالتفصيل إلى «ما هي السلاسل النصية في لغة C؟ المفاهيم الأساسية وأهمية حرف النهاية».
2. ما هي سلاسل النص في لغة C؟ المفاهيم الأساسية وأهمية حرف النهاية
2.1 المفهوم الأساسي لسلاسل النص في لغة C
السلسلة هي «مصفوفة من char»
في لغة C، تُعامل السلاسل كـمصفوفة من الأحرف (مصفوفة من نوع char) . على سبيل المثال، الشيفرة التالية هي مثال أساسي لتعريف وعرض السلسلة.
#include <stdio.h>
int main() {
char str[] = "Hello, World!"; // Define a string literal as an array
printf("%s ", str); // Output the string
return 0;
}
في هذا الكود، السلسلة "Hello, World!"
تُخزن كمصفوفة من النوع char
، وتُطبع بواسطة printf("%s\n", str);
.
التركيب الداخلي للسلسلة
السلسلة "Hello"
تُخزن في الذاكرة كما يلي.
فهرس | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
نص | H | e | l | l | o |
في لغة C، حرف خاص يُظهر نهاية السلسلة (حرف null '\0'
) يُضاف تلقائيًا في النهاية، لذا يصبح طول السلسلة «عدد الأحرف الفعلي + 1» .
2.2 أهمية حرف النهاية (حرف null 'ما هو حرف null؟
'
)
ما هو حرف null؟
'المشكلة في حالة عدم وجود حرف null
حرف null ('\0'
) هو حرف خاص يُظهر نهاية السلسلة. لفهم التعامل الصحيح مع سلاسل C، يجب أن تدرك وجود هذا الحرف.
#include <stdio.h>
int main() {
char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; // Explicitly specify the null terminator
printf("%s ", str); // Display correctly
return 0;
}
في الشيفرة أعلاه، إذا لم يتوفر '\0'
، فإن نهاية "Hello"
لن تُعترف، وقد يحدث سلوك غير مقصود .
2.3 طريقة تعريف السلسلة بشكل صحيح
كما هو موضح أدناه، إذا نسيت حرف النهاية، قد يتسبب ذلك في سلوك غير طبيعي للذاكرة.
#include <stdio.h>
int main() {
char str[5] = {'H', 'e', 'l', 'l', 'o'}; // Does not include the null terminator
printf("%s ", str); // May cause unexpected behavior
return 0;
}
سبب الخطأ
printf("%s\n", str);
الحرف الفارغ'\0'
- إذا لم يكن ، فقد يتم إخراج بيانات أخرى في الذاكرة.
الطريقة ① استخدام حرفية السلسلة
الطريقة ② تعريف المصفوفة صراحة
الطريقة الأكثر شيوعًا لتعريف السلسلة هي استخدام حرفية السلسلة.
char str[] = "Hello";
في هذه الطريقة، يضيف مترجم C حرف null '\0'
تلقائيًا، لذا لا حاجة لمعالجة خاصة.
2.4 طريقة التحقق من حجم السلسلة
إذا كنت تريد تعريفًا يدويًا يتضمن '\0'
، فستكتب كما يلي.
char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
- يجب تحديد حجم عدد الأحرف ، ومن ثم وضع في النهاية.
- إذا نسيت إدخال في ، سيحدث سلوك غير متوقع.
عمل strlen
للحصول على طول السلسلة (عدد الأحرف)، استخدم الدالة strlen
.
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello";
printf("Length of the string: %lu\n", strlen(str)); // Outputs 5 (does not include the null terminator)
return 0;
}
2.5 الخلاصة
strlen
الحرف الفارغ'\0'
يحسب عدد الأحرف حتى ظهورsizeof(str)
3. طريقة استخراج جزء من السلسلة في C gengo【قسم hyoujun raiburari】
- سلاسل النص في لغة C يتم تمثيلها بواسطة مصفوفات
char
- الرمز النهائي(الرمز الفارغ
'\0'
)يُظهر نهاية السلسلة، لذا يجب دائمًا تضمينه - للحصول على طول سلسلة
strlen
استخدم - إذا لم تُعرّف السلسلة بطريقة مناسبة، فقد يحدث خطأ غير متوقع.
3.1 الحصول على جزء من السلسلة باستخدام strncpy
لاستخراج جزء من السلسلة في C gengo، هناك طريقة باستخدام مكتبة hyoujun raiburari. في هذا القسم، سنشرح كيفية الحصول على جزء من السلسلة باستخدام strncpy
و strchr
وغيرها من دوال مكتبة hyoujun raiburari
البنية الأساسية لـ strncpy
strncpy
هو دالة تقوم بنسخ جزء من السلسلة إلى مخزن مؤقت آخر .
مثال أساسي للاستخدام
char *strncpy(char *dest, const char *src, size_t n);
dest
src
n
'\0'
نقاط الانتباه لـ strncpy
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
char dest[6]; // Buffer to store the substring
strncpy(dest, src, 5); // Copy the first 5 characters "Hello"
dest[5] = '\0'; // Manually add the null terminator
printf("Substring: %s\n", dest); // Output "Hello"
return 0;
}
3.2 النسخ الآمن للسلسلة باستخدام strncpy_s
- الرمز الفارغ
'\0'
يجب إضافته يدويًاstrncpy
n
'\0'
لا يضيف تلقائيًا،dest[n] = '\0';
- احذر من تجاوز حدود الذاكرة المؤقتة
dest
n
البنية الأساسية لـ strncpy_s
strncpy_s
هو نسخة محسّنة من strncpy
تُعزز الأمان وتمنع تجاوز سعة المخزن المؤقت.
مثال على الاستخدام
errno_t strncpy_s(char *dest, rsize_t destsz, const char *src, rsize_t n);
dest
destsz
dest
src
n
مزايا strncpy_s
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
char dest[6];
if (strncpy_s(dest, sizeof(dest), src, 5) == 0) {
dest[5] = '\0'; // Add null terminator just in case
printf("Substring: %s\n", dest);
} else {
printf("Copy error\n");
}
return 0;
}
3.3 استخراج حتى حرف معين باستخدام strchr
- حجم المخزن المؤقت () لتحديده، يمكن النسخ بأمان.
- إذا كان أكبر من ، فارجع خطأ。
مع ذلك، strncpy_s
أضيف في معيار C11، وبالتالي قد لا يكون متاحًا في بعض البيئات.
البنية الأساسية لـ strchr
strchr
باستخدامه يمكنك العثور على موقع حرف معين والحصول على السلسلة حتى ذلك الجزء.
مثال على الاستخدام
char *strchr(const char *str, int c);
str
c
char
نقطة
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello, World!";
char *pos = strchr(str, ','); // Find the position of ','
if (pos != NULL) {
int length = pos - str; // Calculate the number of characters up to ','
char result[20];
strncpy(result, str, length);
result[length] = '\0'; // Add the null terminator
printf("Substring: %s\n", result); // Output "Hello"
}
return 0;
}
3.4 البحث عن كلمة مفتاحية واستخراجها باستخدام strstr
strchr
العنوان الأول الذي تم العثور عليهc
العنوانpos - str
strncpy
البنية الأساسية لـ strstr
strstr
مفيد للبحث عن جزء من السلسلة والحصول على السلسلة التي تليه.
مثال على الاستخدام
char *strstr(const char *haystack, const char *needle);
سلة حشائش
needle
نقطة
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello, World!";
char *pos = strstr(str, "World"); // Search for the position of "World"
if (pos != NULL) {
printf("Found substring: %s\n", pos);
} else {
printf("Substring not found.\n");
}
return 0;
}
3.5 خلاصة
strstr
needle
NULL
needle
haystack
4. طريقة استخراج السلسلة الفرعية في لغة C【جزء الدوال المخصصة】
strncpy
، باستخدامه يمكنك نسخ الجزء الفرعي بأمان، لكن يجب إضافة الحرف NULL يدويًا。strncpy_s
يمكن أن يحددdestsz__
، مما يحسن الأمان。strchr
إذا استخدمت، يمكنك الحصول على الجزء الجزئي من السلسلة حتى حرف محدد。strstr
إذا استخدمت، يمكنك الحصول على موقع كلمة مفتاحية محددة ثم قص الجزء من هناك。
باستخدام مكتبة hyoujun raiburari، يمكنك تنفيذ معالجة السلاسل في C gengo بشكل بسيط وآمن.
4.1 فوائد إنشاء الدوال المخصصة
باستخدام مكتبة القياسية، يمكن استخراج السلسلة الجزئية الأساسية، ولكن قد يُطلب في بعض الحالات طريقة أكثر مرونة . لذلك، في هذا القسم سنشرح استخراج السلسلة الجزئية باستخدام الدوال المخصصة .
4.2 دالة استخراج السلسلة الفرعية الأساسية
باستخدام مكتبة القياسية، يمكن نسخ السلسلة الجزئية والبحث فيها، لكن توجد المشكلات التالية.
strncpy
لا يضيف حرف NULL'\0'
تلقائيًاstrchr
وstrstr
لا يمكنهما سوى البحث الجزئي- من الصعب التعامل مع السلاسل النصية بطريقة أكثر مرونة
لذلك، من الفعّال إنشاء دوال مخصصة يمكن تخصيصها وفقًا للاستخدام المحدد.
مواصفات الدالة
أولاً، سننشئ دالة أساسية لاقتطاع السلسلة من الموضع المحدد.
كود التنفيذ
- المعامل
const char *source
int start
int length
char *dest
- محتوى المعالجة
بدء
طول
الوجهة
'\0'
نقاط
#include <stdio.h>
#include <string.h>
void substring(const char *source, int start, int length, char *dest) {
int i;
for (i = 0; i < length && source[start + i] != '\0'; i++) {
dest[i] = source[start + i];
}
dest[i] = '\0'; // Add null terminator
}
int main() {
char text[] = "Hello, World!";
char result[10];
substring(text, 7, 5, result); // Extract "World"
printf("Substring: %s\n", result);
return 0;
}
4.3 malloc
الحصول على السلسلة الفرعية ديناميكيًا باستخدامها
for
length
'\0'
dest[i] = '\0';
ضع دائمًا حرف NULL في النهاية
مواصفات الدالة
في الدالة السابقة، يجب حجز حجم dest
مسبقًا. ومع ذلك، إذا تم حجز الحجم المطلوب ديناميكيًا، ستصبح الدالة أكثر شمولية.
كود التنفيذ
- الذاكرة المطلوبة تُحجز باستخدام
start
length
- في الدالة المندوبة يجب
نقاط
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *substring_dynamic(const char *source, int start, int length) {
char *dest = (char *)malloc(length + 1); // +1 for the null terminator
if (dest == NULL) {
return NULL; // Memory allocation failed
}
int i;
for (i = 0; i < length && source[start + i] != '\0'; i++) {
dest[i] = source[start + i];
}
dest[i] = '\0';
return dest;
}
int main() {
char text[] = "Hello, World!";
char *result = substring_dynamic(text, 7, 5);
if (result != NULL) {
printf("Substring: %s\n", result);
free(result); // Free allocated memory
} else {
printf("Memory allocation failed.\n");
}
return 0;
}
4.4 دعم الأحرف متعددة البايت (اليابانية)
malloc
تخصيص الذاكرة ديناميكيًا- بعد الاستخدام، يجب تحرير الذاكرة باستخدام
free(result);
تنفيذ يأخذ في الاعتبار الأحرف متعددة البايت
عند التعامل مع اليابانية (أحرف متعددة البايت مثل UTF-8)، لا يُضمن أن الحرف الواحد يساوي 1 بايت، لذا فإن الدالة البسيطة substring
لا تعمل بشكل صحيح.
كود التنفيذ (دعم UTF-8)
mbstowcs
wchar_t
wcsncpy
wcstombs
نقاط
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <locale.h>
void substring_utf8(const char *source, int start, int length, char *dest) {
setlocale(LC_ALL, ""); // Set the locale
wchar_t wsource[256];
mbstowcs(wsource, source, 256); // Convert UTF-8 string to wide-character string
wchar_t wresult[256];
wcsncpy(wresult, wsource + start, length); // Extract substring in wide characters
wresult[length] = L'\0';
wcstombs(dest, wresult, 256); // Convert back to multibyte string
}
int main() {
char text[] = "こんにちは、世界!"; // UTF-8 string
char result[20];
substring_utf8(text, 5, 3, result); // Extract "世界"
printf("Substring: %s\n", result);
return 0;
}
4.5 الخلاصة
setlocale(LC_ALL, "");
mbstowcs
wcsncpy
wcstombs
5. طريقة استخراج السلاسل النصية حسب ترميز الأحرف
substring
إذا قمت بإنشائه بنفسك، يمكنك الحصول على أجزاء النص بشكل مرن。- باستخدام تخصيص الذاكرة الديناميكية (
malloc
)، يمكن الحصول على سلسلة جزئية ذات حجم متغير。 - عند التعامل مع الأحرف متعددة البايت (اليابانية)،
mbstowcs
/wcstombs
يُستَخدم。
عندما يكون من الصعب التعامل مع مكتبة القياسية مثل strncpy
أو strchr
، يمكن من خلال إنشاء دوال مخصصة جعل معالجة السلاسل في لغة C أقوى.
5.1 في حالة ASCII(حرف بايت واحد)
في لغة C،إذا لم تُعِر اهتمامًا لاختلافات ترميز الأحرف، قد لا تعمل عملية استخراج السلسلة النصية بشكل صحيح قد يحدث ذلك. على وجه الخصوص، عند التعامل مع أحرف متعددة البايت مثل اللغة اليابانية (UTF-8، Shift_JIS، EUC-JP وغيرها)، لا يكون 1 حرف = 1 بايت، لذا لا يمكن للوظائف البسيطة مثل strncpy
أو substring
معالجة ذلك بشكل مناسب.
في هذا القسم،طريقة استخراج السلاسل النصية حسب ترميز الأحرف سيتم شرحها بالتفصيل.
استخراج الجزء الفرعي الأساسي
مثال على التنفيذ
حرف ASCII هو 1 حرف = 1 بايت، لذا يمكن مع وظائف strncpy
أو substring
معالجته بسهولة.
5.2 في حالة UTF-8(أحرف متعددة البايت)
#include <stdio.h>
#include <string.h>
void substring_ascii(const char *source, int start, int length, char *dest) {
strncpy(dest, source + start, length);
dest[length] = '\0'; // Add null terminator
}
int main() {
char text[] = "Hello, World!";
char result[6];
substring_ascii(text, 7, 5, result); // Extract "World"
printf("Substring: %s\n", result);
return 0;
}
نقطة
- في حالة الأحرف ASCII (الأرقام والحروف فقط)
strncpy
يكفي التعامل '\0'
(الرمز الصفري)يجب دائمًا إضافته
خصائص UTF-8
طريقة المعالجة الصحيحة
في UTF-8، عدد البايتات لكل حرف يتراوح بين 1-4 بايت ويتغير، لذا إذا استُخدم strncpy
ببساطة قد يتم قطع الحرف في منتصفه.
استخراج الجزء الفرعي المتوافق مع UTF-8
في لغة C، لمعالجة UTF-8 بأمان يجب استخدام mbstowcs
لتحويله إلى سلسلة عريضة ( wchar_t
) ، ثم يُنصح بطريقة استخراج الجزء الفرعي.
5.3 في حالة Shift_JIS(أحرف متعددة البايت)
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
void substring_utf8(const char *source, int start, int length, char *dest) {
setlocale(LC_ALL, ""); // Set the locale
wchar_t wsource[256];
mbstowcs(wsource, source, 256); // Convert multibyte string to wide-character string
wchar_t wresult[256];
wcsncpy(wresult, wsource + start, length); // Get the substring
wresult[length] = L'\0';
wcstombs(dest, wresult, 256); // Convert wide-character string back to multibyte
}
int main() {
char text[] = "こんにちは、世界!"; // UTF-8 string
char result[20];
substring_utf8(text, 5, 3, result); // Extract "世界"
printf("Substring: %s\n", result);
return 0;
}
نقطة
setlocale(LC_ALL, "");
- باستخدام سلسلة متعددة البايت إلى ، معالجتها بأمان باستخدام 。
wcstombs
خصائص Shift_JIS
استخراج الجزء الفرعي المتوافق مع Shift_JIS
في Shift_JIS، 1 حرف قد يكون 1 بايت أو 2 بايت، لذا فإن الاستخدام البسيط لـ strncpy
قد يسبب تشويهاً في النص.
تنفيذ في Shift_JIS
حتى في حالة Shift_JIS، طريقة تحويل إلى سلسلة عريضة ومعالجتها يُنصح بها.
5.4 في حالة EUC-JP(أحرف متعددة البايت)
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
void substring_sjis(const char *source, int start, int length, char *dest) {
setlocale(LC_ALL, "Japanese"); // Set locale to handle Shift_JIS
wchar_t wsource[256];
mbstowcs(wsource, source, 256); // Convert multibyte string (Shift_JIS) to wide-character string
wchar_t wresult[256];
wcsncpy(wresult, wsource + start, length); // Extract substring
wresult[length] = L'\0';
wcstombs(dest, wresult, 256); // Convert wide-character string back to multibyte (Shift_JIS)
}
int main() {
char text[] = "こんにちは、世界!"; // Shift_JIS string (depending on environment)
char result[20];
substring_sjis(text, 5, 3, result); // Extract "世界"
printf("Substring: %s\n", result);
return 0;
}
نقطة
- للتعامل مع Shift_JIS بشكل صحيح، قم بتعيين 。
mbstowcs
wcstombs
خصائص EUC-JP
استخراج الجزء الفرعي المتوافق مع EUC-JP
EUC-JP، مثل Shift_JIS، يختلف عدد البايتات لكل حرف، لذا فإن التحويل باستخدام أحرف عريضة مطلوب .
5.5 ملخص
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
void substring_eucjp(const char *source, int start, int length, char *dest) {
setlocale(LC_ALL, "ja_JP.eucJP"); // Set locale to handle EUC-JP
wchar_t wsource[256];
mbstowcs(wsource, source, 256); // Convert multibyte string (EUC-JP) to wide-character string
wchar_t wresult[256];
wcsncpy(wresult, wsource + start, length); // Extract substring
wresult[length] = L'\0';
wcstombs(dest, wresult, 256); // Convert wide-character string back to multibyte (EUC-JP)
}
int main() {
char text[] = "こんにちは、世界!"; // EUC-JP string (depending on environment)
char result[20];
substring_eucjp(text, 5, 3, result); // Extract "世界"
printf("Substring: %s\n", result);
return 0;
}
نقطة
setlocale(LC_ALL, "ja_JP.eucJP");
- استخدم / لمعالجة الأحرف متعددة البايت بشكل صحيح.
6. طريقة تقسيم السلاسل في لغة C
رمز الأحرف | عدد البايتات | الطريقة الموصى بها للمعالجة |
---|---|---|
ASCII | 1 بايت | strncpy |
UTF-8 | 1-4 بايت | mbstowcs wcstombs |
Shift_JIS | 1 or 2 بايت | mbstowcs wcstombs |
EUC-JP | 1 أو 2 بايت | mbstowcs wcstombs |
- ASCII إذا كان فقط نص
strncpy
مقبول - في حالة UTF-8، Shift_JIS، EUC-JP، استخدم
mbstowcs
/wcstombs
- حسب البيئة
setlocale(LC_ALL, \"...\");
ضبطها بشكل مناسب
6.1 تقسيم السلاسل باستخدام strtok
معالجة تقسيم السلاسل، تحليل بيانات CSV، ومعالجة وسائط سطر الأوامر، وتحليل بيانات السجلات إلخ، ضرورية في العديد من الحالات. في لغة C، هناك طرق لاستخدام دوال مكتبة القياسية مثل strtok
و strtok_r
، أو إنشاء دوال مخصصة.
في هذا القسم، طريقة تقسيم السلاسل باستخدام حرف فاصل محدد سيتم شرحها بالتفصيل.
الصيغة الأساسية
strtok
هو دالة تقوم بتقسيم السلاسل باستخدام حرف الفاصل المحدد (المحدد).
مثال الاستخدام: تقسيم السلاسل باستخدام الفاصلة ,
char *strtok(char *str, const char *delim);
str
delim
- قيمة الإرجاع
- نقاط يجب الانتباه إليها
strtok
'\0'
نتيجة التنفيذ
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "apple,banana,orange,grape"; // String to be split
char *token = strtok(str, ","); // Get the first token
while (token != NULL) {
printf("Token: %s\n", token);
token = strtok(NULL, ","); // Get the next token
}
return 0;
}
نقاط الانتباه لـ strtok
token: apple
token: banana
token: orange
token: grape
6.2 تقسيم السلاسل الآمن للمتعدد الخيوط باستخدام strtok_r
- تغيير السلسلة الأصلية
strtok
حرف الفاصل يُستبدل بـ'\0'
،
- غير thread-safe
strtok
يستخدم متغيرات ثابتة عالمية داخليًا
الصيغة الأساسية
strtok_r
هو النسخة الآمنة للمتعدد الخيوط من strtok
، حيث يتم حفظ الحالة في saveptr
، وبالتالي يمكن استخدامه بأمان في بيئات متعددة الخيوط.
مثال الاستخدام: تقسيم السلاسل باستخدام المسافة
char *strtok_r(char *str, const char *delim, char **saveptr);
str
delim
saveptr
مزايا strtok_r
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello World from C"; // String to be split
char *token;
char *saveptr; // Pointer to store internal state
token = strtok_r(str, " ", &saveptr); // Get the first token
while (token != NULL) {
printf("Token: %s\n", token);
token = strtok_r(NULL, " ", &saveptr); // Get the next token
}
return 0;
}
6.3 تقسيم السلاسل باستخدام دالة مخصصة (طريقة لا تستخدم strtok
)
- آمن الخيوط
- يمكن معالجة عدة سلاسل نصية بالتوازي
مواصفات الدالة المخصصة
strtok
يغيّر السلسلة الأصلية، لذا يمكن إنشاء دالة مخصصة لتقسيم السلاسل دون تعديلها.
كود التنفيذ
- إدخال
const char *source
const char delim
char tokens[][50]
- معالجة
source
delim
tokens
نتيجة التنفيذ
#include <stdio.h>
#include <string.h>
void split_string(const char *source, char delim, char tokens[][50], int *count) {
int i = 0, j = 0, token_index = 0;
while (source[i] != '\0') {
if (source[i] == delim) {
tokens[token_index][j] = '\0';
token_index++;
j = 0;
} else {
tokens[token_index][j] = source[i];
j++;
}
i++;
}
tokens[token_index][j] = '\0';
*count = token_index + 1;
}
int main() {
char text[] = "dog,cat,bird,fish";
char tokens[10][50]; // Can store up to 10 words
int count;
split_string(text, ',', tokens, &count);
for (int i = 0; i < count; i++) {
printf("Token: %s\n", tokens[i]);
}
return 0;
}
نقاط مهمة
Token: dog
Token: cat
Token: bird
Token: fish
6.4 تطبيقات تقسيم السلاسل (معالجة بيانات CSV)
source
tokens
مثال على تحليل بيانات CSV
يمكن تحليل بيانات CSV (مفصولة بفواصل) باستخدام strtok
.
نتيجة التنفيذ
#include <stdio.h>
#include <string.h>
int main() {
char csv[] = "Alice,24,Female\nBob,30,Male\nCharlie,28,Male"; // CSV data
char *line = strtok(csv, "\n"); // Process line by line
while (line != NULL) {
char *name = strtok(line, ",");
char *age = strtok(NULL, ",");
char *gender = strtok(NULL, ",");
printf("Name: %s, Age: %s, Gender: %s\n", name, age, gender);
line = strtok(NULL, "\n");
}
return 0;
}
6.5 الخلاصة
Name: Alice, Age: 24, Gender: Female
Name: Bob, Age: 30, Gender: Male
Name: Charlie, Age: 28, Gender: Male
الاستنتاج
طريقة | مزايا | العيوب |
---|---|---|
strtok | يمكن تقسيمه بسهولة | تغيير السلسلة الأصلية |
strtok_r | آمن من حيث الخيوط | الطريقة لاستخدامها معقدة قليلاً |
دالة مخصصة | لا تقم بتغيير السلسلة الأصلية | الكود يصبح طويلاً |
تحليل CSV | مفيد لمعالجة البيانات | strtok احذر القيود |
7. مثال تطبيقي: طريقة استخراج ما قبل وما بعد حرف معين
- إذا كان التقسيم بسيطًا
strtok
- إذا كان متعدد الخيوط
strtok_r
- إذا كنت لا تريد تغيير الأصل، استخدم دالة مخصصة
- يمكن تطبيقه أيضًا على تحليل بيانات CSV
في القسم التالي، سنشرح بالتفصيل 「مثال تطبيقي: طريقة استخراج الأحرف قبل وبعد حرف معين」.
7.1 strchr
للحصول على السلسلة التي تسبق حرفًا معينًا
في معالجة السلاسل النصية،استخراج ما قبل وما بعد حرف أو كلمة مفتاحية معينةغالبًا ما يكون ذلك مطلوبًا. على سبيل المثال، يمكن التفكير في الحالات التالية.
- الحصول على الجزء المخصص للمجال فقط من URL
- استخراج اسم الملف من مسار الملف
- الحصول على السلسلة قبل وبعد العلامات أو الرموز المحددة
في لغة C،strchr
و strstr
يمكن استخدامها لتحقيق هذه المعالجة. بالإضافة إلى ذلك، إذا كانت هناك حاجة لمعالجة أكثر مرونة، فإن إنشاء دوال مخصصة يعتبر خيارًا فعالًا.
الصيغة الأساسية
strchr
باستخدامه، يمكن تحديد موقع حرف (الأول الذي يُعثر عليه).
مثال الاستخدام: استخراج اسم الملف من مسار الملف
char *strchr(const char *str, int c);
str
c
char
strchr
إذا وجدت c
، تُعيد عنوانه.
نتيجة التنفيذ
#include <stdio.h>
#include <string.h>
void get_filename(const char *path, char *filename) {
char *pos = strrchr(path, '/'); // Search for the last '/'
if (pos != NULL) {
strcpy(filename, pos + 1); // Copy from the character after '/'
} else {
strcpy(filename, path); // If no '/', copy the whole path
}
}
int main() {
char path[] = "/home/user/documents/report.txt";
char filename[50];
get_filename(path, filename);
printf("Filename: %s\n", filename);
return 0;
}
نقطة مهمة
Filename: report.txt
7.2 strstr
للحصول على السلسلة التي تلي كلمة مفتاحية معينة
strrchr
يمكنك الحصول على موقع الحرف المحدد الذي ظهر آخر مرة (/
)pos + 1
اسم الملف فقط
الصيغة الأساسية
strstr
باستخدامه، يمكن البحث عن سلسلة معينة (كلمة مفتاحية) والحصول على السلسلة التي تلي موقعها.
مثال الاستخدام: استخراج النطاق من URL
char *strstr(const char *haystack, const char *needle);
haystack
needle
strstr
إذا وجدت needle
، تُعيد عنوان موقعها.
نتيجة التنفيذ
#include <stdio.h>
#include <string.h>
void get_domain(const char *url, char *domain) {
char *pos = strstr(url, "://"); // Search for the position of "://"
if (pos != NULL) {
strcpy(domain, pos + 3); // Copy from the character after "://"
} else {
strcpy(domain, url); // If "://" is not found, copy the entire string
}
}
int main() {
char url[] = "https://www.example.com/page.html";
char domain[50];
get_domain(url, domain);
printf("Domain part: %s\n", domain);
return 0;
}
نقطة مهمة
Domain part: www.example.com/page.html
7.3 strchr
لتقسيم الجزء قبل وبعد حرف معين
strstr
"https://"
"http://"
"//"
pos + 3
://
مثال الاستخدام: فصل اسم المستخدم والنطاق من عنوان البريد الإلكتروني
strchr
باستخدامه، يمكن تقسيم السلسلة إلى جزأين قبل وبعد الحرف المحدد والحصول عليهما.
نتيجة التنفيذ
#include <stdio.h>
#include <string.h>
void split_email(const char *email, char *username, char *domain) {
char *pos = strchr(email, '@'); // Search for the position of '@'
if (pos != NULL) {
strncpy(username, email, pos - email); // Copy the part before '@'
username[pos - email] = '\0'; // Add null terminator
strcpy(domain, pos + 1); // Copy the part after '@'
}
}
int main() {
char email[] = "user@example.com";
char username[50], domain[50];
split_email(email, username, domain);
printf("Username: %s\n", username);
printf("Domain: %s\n", domain);
return 0;
}
نقطة مهمة
Username: user
Domain: example.com
7.4 تطبيق: استخراج خاصية معينة داخل وسم HTML
strchr
'@'
strncpy
'@'
الجزء قبله، نسخ، وإضافة حرف NULLstrcpy
'@'
مثال الاستخدام: <a href="URL">
استخراج URL
عند استخراج خاصية معينة من داخل وسم HTML، يمكن أيضًا الاستفادة من strstr
.
نتيجة التنفيذ
#include <stdio.h>
#include <string.h>
void get_href(const char *html, char *url) {
char *start = strstr(html, "href=\""); // Search for the position of href="
if (start != NULL) {
start += 6; // Move past href="
char *end = strchr(start, '"'); // Search for the next "
if (end != NULL) {
strncpy(url, start, end - start);
url[end - start] = '\0'; // Add null terminator
}
}
}
int main() {
char html[] = "<a href=\"https://example.com\">Click Here</a>";
char url[100];
get_href(html, url);
printf("Extracted URL: %s\n", url);
return 0;
}
نقطة مهمة
Extracted URL: https://example.com
7.5 الخلاصة
strstr
"href=\""
strchr
"
الاستنتاج
محتوى المعالجة | استخدام الدالة | مزايا |
---|---|---|
الحصول على ما قبل حرف محدد | strchr / strrchr | بسيط وسريع |
الحصول على ما بعد حرف محدد | strstr | يمكن البحث بالكلمات الرئيسية |
تقسيم قبل وبعد باستخدام حرف محدد | strchr + strncpy | مفيد لتقسيم اسم المستخدم والنطاق وما إلى ذلك |
الحصول على سمات علامة HTML | strstr + strchr | قابل للتطبيق على استخراج الويب |
8. الملخص
strchr
وstrstr
، يمكنك بسهولة الحصول على ما قبل وما بعد حرف أو كلمة مفتاحية محددة- معالجة مسارات الملفات، تحليل عناوين URL، تقسيم عناوين البريد الإلكتروني، وما إلى ذلك، مفيدة في العديد من الحالات。
- قابل للتطبيق حتى على عمليات متقدمة مثل استخراج البيانات من الويب
8.1 مراجعة المقالة
في هذه المقالة، حول طريقة استخراج السلاسل النصية في لغة C، تم شرحها بالتفصيل من الأساسيات إلى التطبيقات. هنا، نعيد استعراض النقاط المهمة في كل قسم، وننظم الطريقة المثلى حسب الاستخدام.
8.2 الطريقة المثلى حسب الاستخدام
القسم | المحتوى | نقاط مهمة |
---|---|---|
أساسيات سلاسل النص في لغة C | في لغة C، يُعامل السلسلة كـ مصفوفة، ويُعتبر حرف النهاية مهمًا | عند التعامل مع السلاسل النصية، لا تنسَ النهاية بالـ null |
استخراج من المكتبة القياسية | strncpy strchr | strncpy يجب إضافة النهاية الصفرية يدويًا |
استخراج باستخدام دالة مخصصة | إنشاء دالة مرنة | malloc يمكن استخراج جزء من السلسلة بطول متغير |
معالجة حسب رمز الأحرف | كيفية التعامل مع UTF-8، Shift_JIS، EUC-JP | mbstowcs wcstombs تحويل إلى أحرف واسعة آمن |
طريقة تقسيم السلسلة | strtok strtok_r | strtok يغير السلسلة الأصلية |
استخراج الأحرف قبل وبعد حرف محدد | strchr strstr | الحصول على أسماء الملفات، تحليل URL، تحليل HTML |
1. استخراج جزء من السلسلة
2. تقسيم السلسلة
حالة الاستخدام | الطريقة المثلى |
---|---|
أريد الحصول على سلسلة بطول معين | strncpy or substring() |
أريد إجراء استخراج آمن | strncpy_s |
التعامل مع الأحرف متعددة البايت (UTF-8, Shift_JIS, EUC-JP) | mbstowcs / wcstombs |
3. الحصول على ما قبل وما بعد حرف معين
حالة الاستخدام | الطريقة المثلى |
---|---|
أريد تقسيم السلسلة ببساطة | strtok |
أريد تقسيم آمن من حيث الخيوط | strtok_r |
أريد تقسيم دون تغيير السلسلة الأصلية | دالة مخصصة(split_string() ) |
8.3 ملاحظات حول معالجة السلاسل النصية في لغة C
حالة الاستخدام | الطريقة المثلى |
---|---|
الحصول على اسم الملف من مسار الملف | strrchr(path, '/') |
الحصول على الجزء المعياري من عنوان URL | strstr(url, "://") |
افصل اسم المستخدم والنطاق من عنوان البريد الإلكتروني | strchr(email, '@') |
الحصول على قيم السمات من وسوم HTML | strstr(tag, "href=\"") + strchr(tag, '"') |
1. التأكد من إدارة النهاية الصفرية 'مثال على نسخ السلسلة بأمان
'
مثال على نسخ السلسلة بأمان
'2. الانتباه إلى تجاوز سعة الذاكرة المؤقتة
في معالجة السلاسل النصية بلغة C، حرف النهاية '\0'
بشكل مناسب هو الأكثر أهمية . خاصةً عند استخدام strncpy
أو strchr
، يجب الانتباه إلى إضافة حرف الصفر يدوياً .
3. استخدم mbstowcs
لمعالجة الأحرف متعددة البايت
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
char dest[6];
strncpy(dest, src, 5);
dest[5] = '\0'; // Add null terminator for safety
printf("Substring: %s\n", dest);
return 0;
}
4. إدارة حجم الذاكرة المؤقتة
في عمليات السلاسل النصية بلغة C، يجب تنفيذها بحذر لتجنب الوصول إلى خارج حدود المصفوفة. خاصةً عند استخدام strncpy
، من المهم التحكم في عدد البايتات المنسوخة .
مثال على نسخ السلسلة بأمان
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
char dest[6];
strncpy(dest, src, sizeof(dest) - 1);
dest[5] = '\0'; // Explicitly add null terminator
printf("Substring: %s\n", dest);
return 0;
}
8.4 نحو تعلم أعمق
عند التعامل مع الأحرف متعددة البايت مثل UTF-8 أو Shift_JIS، لا تعمل strncpy
أو strlen
بشكل صحيح.
لذلك، عند التعامل مع الأحرف متعددة البايت، يُنصح بتحويلها إلى سلسلة عريضة باستخدام mbstowcs
ثم معالجتها بشكل مناسب.
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main() {
setlocale(LC_ALL, ""); // Set the locale
char text[] = "こんにちは、世界!"; // UTF-8
wchar_t wtext[256];
mbstowcs(wtext, text, 256); // Convert to wide-character string
printf("Converted wide-character string: %ls\n", wtext);
return 0;
}
مواضيع لتعميق التعلم
في معالجة السلاسل النصية، من المهم حساب حجم الذاكرة المطلوب مسبقاً ومنع تجاوز سعة الذاكرة المؤقتة. خاصةً عند استخدام malloc
لتخصيص الذاكرة الديناميكية، يجب التأكد من معرفة الحجم بدقة.
8.5 الخلاصة
معالجة السلاسل النصية في لغة C هي مهارة مهمة لتحسين أمان البرنامج وقابليته للقراءة. بناءً على ما تم تقديمه في هذه المقالة، سيمكنك تعلم المواضيع التالية للوصول إلى معالجة سلاسل نصية أكثر تقدماً.
مواضيع لتعميق التعلم
- التعبير النمطي (regex)
- العمليات على الملفات(معالجة السلاسل باستخدام fgets, fscanf)
- إدارة الذاكرة (معالجة السلاسل النصية الديناميكية باستخدام malloc, realloc)
- تحليل البيانات (طريقة تحليل JSON, XML)
8.5 الخلاصة
- سلاسل النص في لغة C
char
مصفوفة تُدار، لذلك، حرف النهاية'\0'
التعامل معها مهم - لاستخراج السلاسل الجزئية باستخدام
strncpy
,substring()
,malloc
- لتحليل السلاسل النصية
strtok
/strtok_r
/ استخدام الدوال المخصصة - عند رغبتك في الحصول على الأحرف قبل وبعد حرف محدد
strchr
,strstr
استخدم - عند التعامل مع الأحرف متعددة البايت (اليابانية)،
mbstowcs
استخدم - احرص على معالجة السلاسل النصية بأمان، وكن حذرًا من تجاوز حدود المخزن المؤقت
إذا استفدت من محتوى هذه المقالة، ستتمكن من تنفيذ معالجة سلاسل نصية عملية في لغة C. بعد فهم الدوال الأساسية، تحدى نفسك بإنشاء دوال خاصة ومعالجات متقدمة لتكتب شيفرة أكثر كفاءة!