C++: معالجة النصوص المتقدمة
آخر تحديث: 2026-08-26
في الدرس 19 تعلمنا أساسيات عمليات النصوص.
لكن في السيناريوهات الواقعية، قد تحتاج إلى حذف محارف، إدراج محارف، مقارنة نصوص، تحويل أرقام إلى نصوص...
في هذا الدرس، سنتعلم عمليات النصوص المتقدمة.
1. تعديل النصوص
(1) 1.1 حذف المحارف (erase)
الصياغة:
▶ مثال 2: مثال برمجي (الصعوبة ⭐)
string.erase(startPos, deleteCount);
الخرج:
(program output)
مثال:
#include <iostream>
#include <string>
int main() {
std::string text = "Hello, World!";
// حذف 7 محارف بدءاً من الموضع 5 (", World")
text.erase(5, 7);
std::cout << text << std::endl; // Hello!
return 0;
}
💡 نصيحة: إذا مررت معاملاً واحداً فقط، يحذف erase(pos) جميع المحارف من pos حتى النهاية.
(2) 1.2 إدراج المحارف (insert)
الصياغة:
string.insert(insertion position, string to insert);
مثال:
#include <iostream>
#include <string>
int main() {
std::string text = "Hello!";
// إدراج " World" قبل المحرف الخامس
text.insert(5, " World");
std::cout << text << std::endl; // Hello World!
return 0;
}
(3) 1.3 تفريغ النص (clear)
#include <iostream>
#include <string>
int main() {
std::string text = "Hello";
text.clear(); // تفريغ النص
std::cout << "Length: " << text.length() << std::endl; // 0
std::cout << "Is empty: " << text.empty() << std::endl; // 1 (true)
return 0;
}
💡 نصيحة: دالة empty() تتحقق مما إذا كان النص فارغاً (تُرجع true، أي 1، إذا كان فارغاً).
2. مقارنة النصوص (compare)
رغم أنه يمكنك مقارنة النصوص باستخدام ==، !=، <، >، إلا أن دالة compare() تقدم معلومات أكثر تفصيلاً.
(1) 2.1 الاستخدام الأساسي
#include <iostream>
#include <string>
int main() {
std::string s1 = "apple";
std::string s2 = "banana";
int result = s1.compare(s2);
if (result == 0) {
std::cout << "s1 equals s2" << std::endl;
} else if (result < 0) {
std::cout << "s1 is less than s2" << std::endl; // يُنفذ هذا السطر
} else {
std::cout << "s1 is greater than s2" << std::endl;
}
return 0;
}
قيم الإرجاع:
0: النصان متساويان< 0: المستدعي أصغر من المعامل> 0: المستدعي أكبر من المعامل
💡 نصيحة: عملياً، استخدام ==، !=، <، > مباشرة لمقارنة النصوص أكثر بديهية - يُنصح بهذه العوامل.
3. التحويل بين النصوص والأرقام
(1) 3.1 الأرقام إلى نصوص (to_string)
#include <iostream>
#include <string>
int main() {
int age = 25;
double price = 19.99;
std::string ageStr = std::to_string(age);
std::string priceStr = std::to_string(price);
std::cout << "Age: " << ageStr << std::endl;
std::cout << "Price: " << priceStr << std::endl;
return 0;
}
💡 نصيحة: تحافظ to_string() على 6 منازل عشرية عند تحويل الأعداد العشرية. إذا احتجت للتحكم في الصيغة، استخدم std::ostringstream أو std::format (C++20).
(2) 3.2 النصوص إلى أرقام (stoi، stod)
| الدالة | الغرض | مثال |
|---|---|---|
std::stoi(str) |
نص ← int | int x = std::stoi("123"); |
std::stol(str) |
نص ← long | long x = std::stol("123"); |
std::stoll(str) |
نص ← long long | long long x = std::stoll("123"); |
std::stof(str) |
نص ← float | float x = std::stof("3.14"); |
std::stod(str) |
نص ← double | double x = std::stod("3.14"); |
مثال:
#include <iostream>
#include <string>
int main() {
std::string numStr = "123";
std::string priceStr = "19.99";
int num = std::stoi(numStr);
double price = std::stod(priceStr);
std::cout << "num = " << num << std::endl;
std::cout << "price = " << price << std::endl;
return 0;
}
⚠️ ملاحظة: إذا لم يكن النص بتنسيق رقم صالح، ستُلقي stoi / stod استثناءً. سنتعلم كيفية معالجة ذلك باستخدام try-catch لاحقاً.
4. المرور على النصوص
(1) 4.1 باستخدام الفهارس
#include <iostream>
#include <string>
int main() {
std::string text = "Hello";
for (size_t i = 0; i < text.length(); i++) {
std::cout << text[i] << " ";
}
std::cout << std::endl;
return 0;
}
(2) 4.2 باستخدام for المبنية على النطاق (C++11، موصى بها)
#include <iostream>
#include <string>
int main() {
std::string text = "Hello";
for (char c : text) {
std::cout << c << " ";
}
std::cout << std::endl;
return 0;
}
💡 نصيحة: حلقة for المبنية على النطاق أكثر إيجازاً وأقل عرضة لأخطاء شروط الحلقة.
5. تطبيق: محرر نصوص بسيط
▶ مثال 1: تطبيق "بحث واستبدال" (الصعوبة ⭐⭐)
#include <iostream>
#include <string>
int main() {
std::string text = "I like C. C is powerful.";
std::string oldStr = "C";
std::string newStr = "C++";
size_t pos = 0;
while ((pos = text.find(oldStr, pos)) != std::string::npos) {
text.replace(pos, oldStr.length(), newStr);
pos += newStr.length(); // تجنب الحلقة اللانهائية
}
std::cout << "After replacement: " << text << std::endl;
return 0;
}
الخرج:
After replacement:
💡 نقطة مهمة: بعد الاستبدال، تخطَّ النص المُدرج حديثاً؛ وإلا ستقع في حلقة لانهائية (إذا كان النص الجديد يحتوي على النص القديم).
▶ مثال 3: استخراج نصوص فرعية باستخدام substr (الصعوبة ⭐)
#include <iostream>
#include <string>
int main() {
std::string text = "Hello, C++ World!";
// استخراج "Hello"
std::string part1 = text.substr(0, 5);
std::cout << "part1: " << part1 << std::endl;
// استخراج "C++"
std::string part2 = text.substr(7, 3);
std::cout << "part2: " << part2 << std::endl;
// استخراج من الموضع 7 حتى النهاية
std::string part3 = text.substr(7);
std::cout << "part3: " << part3 << std::endl;
return 0;
}
الخرج:
part1:
part2:
part3:
❓ أسئلة شائعة
size_t بدلاً من int عند المرور على نص؟string::length() تُرجع size_t (عدد صحيح غير موقّع). استخدام int قد يُنتج تحذيرات عند المقارنة (موقّع مقابل غير موقّع).stoi؟std::invalid_argument.📖 ملخص
erase()تحذف محارف،insert()تُدرج محارف،clear()تُفرّغ النصcompare()تقارن النصوص (لكن استخدام==،!=وغيرها موصى به أكثر)to_string()تحوّل الأرقام إلى نصوصstoi()/stod()تحوّل النصوص إلى أرقام- يُنصح بحلقة
forالمبنية على النطاق للمرور على النصوص (C++11)
📝 تمارين
- أساسي (الصعوبة ⭐): اكتب برنامجاً يتيح للمستخدم إدخال نص، ثم يزيل جميع المسافات منه.
Input: Hello World, this is C++!
Output: HelloWorld,thisisC++!
-
متوسط (الصعوبة ⭐⭐): اكتب برنامجاً يتيح للمستخدم إدخال نص ويحدد ما إذا كان "متطابقاً" (يُقرأ نفس الشيء للأمام وللخلف، مثلاً "level"، "radar").
-
تلميح: يمكنك استخدام مؤشرين (أو فهرسين)، أحدهما يتحرك للأمام والآخر للخلف، مع مقارنة المحارف واحداً تلو الآخر.
-
متقدم (الصعوبة ⭐⭐⭐): اكتب برنامجاً يُنفذ "تشفير/فك تشفير بسيط":
-
قاعدة التشفير: أضف 3 إلى كود ASCII لكل حرف (مثلاً
'A'←'D') -
قاعدة فك التشفير: اطرح 3 من كود ASCII لكل حرف
-
دع المستخدم يُدخل نصاً، شفّره، ثم فك تشفيره، وأخرج النتيجة
- البحث: find/rfind/find_first_of لتحديد موضع النصوص الفرعية
- الاستخراج: substr(pos, count) لاستخراج النصوص الفرعية
- الاستبدال: replace(pos, count, str) لاستبدال أجزاء
- الإدراج/الحذف: insert/erase لتعديل النصوص ديناميكياً
- تحويل الأنواع: stoi/stod/to_string للتحويل بين النصوص والأرقام
6. 🚀 الخطوات التالية
الآن بعد أن تعلمت عمليات النصوص المتقدمة، سننتقل إلى المرحلة 4 (المؤشرات والمراجع) - الجزء الأكثر "رهبة" لكن أيضاً الأهم في C++. فهم الذاكرة هو مفتاح كتابة كود فعال!