C++: نصوص C++
آخر تحديث: 2026-08-26
نصوص C-style (مصفوفات المحارف) مملة الاستخدام وعرضة للأخطاء (تجاوز المخزن المؤقت، نسيان
\0).توفر C++ فئة string - تُغلّف النصوص في كائنات، مما يجعلها آمنة ومريحة للاستخدام.
1. ما هو string؟
(1) 1.1 تشبيه من الحياة الواقعية
| مثال من الحياة اليومية | المكافئ البرمجي |
|---|---|
| لديك حقيبة ظهر يمكنك وضع أشياء فيها | كائن string |
| الحقيبة يمكنها التوسع تلقائياً (استبدالها بأكبر عند الامتلاء) | string يدير الذاكرة ديناميكياً |
| الحقيبة لها جيوب متعددة لسهولة الوصول | دوال أعضاء string |
مزايا string:
- لا حاجة لإدارة الذاكرة - تخصيص وتحرير تلقائيان
- لا حاجة للقلق بشأن
\0- الحرف المنتهي يُدار تلقائياً - وظائف قوية - الدمج والبحث والاستبدال جميعها مريحة
(2) 1.2 لماذا نستخدم string؟
باستخدام نصوص C-style (ممل):
▶ مثال 2: مثال برمجي (الصعوبة ⭐)
#include <iostream>
#include <cstring>
int main() {
char greeting[50] = "Hello, ";
char name = "MOTO";
std::strcat(greeting, name); // يجب القلق بشأن حجم المصفوفة
std::cout << greeting << std::endl;
return 0;
}
الخرج:
(program output)
باستخدام string (بسيط):
#include <iostream>
#include <string>
int main() {
std::string greeting = "Hello, ";
std::string name = "MOTO";
greeting += name; // دمج تلقائي، لا حاجة للقلق بشأن الذاكرة
std::cout << greeting << std::endl;
return 0;
}
2. إعلان وتهيئة string
(1) 2.1 الاستخدام الأساسي
#include <iostream>
#include <string>
int main() {
// الطريقة 1: تهيئة مباشرة
std::string s1 = "Hello";
// الطريقة 2: باستخدام الباني
std::string s2("World");
// الطريقة 3: تكرار حرف
std::string s3(5, '*'); // "*****"
std::cout << s1 << " " << s2 << " " << s3 << std::endl;
return 0;
}
💡 نقطة مهمة: يجب #include <string> لاستخدام string.
3. عمليات string الشائعة
(1) 3.1 دمج النصوص (+ و +=)
#include <iostream>
#include <string>
int main() {
std::string firstName = "MOTO";
std::string lastName = "Zhang";
// الطريقة 1: باستخدام +
std::string fullName1 = firstName + " " + lastName;
std::cout << fullName1 << std::endl; // MOTO Zhang
// الطريقة 2: باستخدام +=
std::string fullName2 = firstName;
fullName2 += " ";
fullName2 += lastName;
std::cout << fullName2 << std::endl; // MOTO Zhang
return 0;
}
(2) 3.2 الحصول على الطول (length و size)
#include <iostream>
#include <string>
int main() {
std::string name = "MOTO";
std::cout << "name: " << name << std::endl;
std::cout << "length(): " << name.length() << std::endl; // 4
std::cout << "size(): " << name.size() << std::endl; // 4
return 0;
}
💡 نصيحة: length() و size() متماثلتان تماماً - استخدم أيهما.
(3) 3.3 الوصول إلى المحارف الفردية ([] و at)
#include <iostream>
#include <string>
int main() {
std::string name = "MOTO";
// الطريقة 1: باستخدام []
std::cout << name[0] << std::endl; // M
name[0] = 'm'; // يمكن التعديل
// الطريقة 2: باستخدام at() (تتحقق من الحدود)
std::cout << name.at(1) << std::endl; // o
// name.at(10); // ❌ ستُلقي استثناء (أكثر أماناً من [])
return 0;
}
💡 الفرق:
name[i]- لا يتحقق من الحدود، أكثر كفاءةname.at(i)- يتحقق من الحدود، أكثر أماناً لكن أبطأ قليلاً
4. دوال أعضاء string الشائعة
(1) 4.1 البحث عن نص فرعي (find)
#include <iostream>
#include <string>
int main() {
std::string text = "Hello, World!";
// البحث عن نص فرعي
size_t pos = text.find("World");
if (pos != std::string::npos) {
std::cout << "Found \"World\",Position: " << pos << std::endl; // 7
} else {
std::cout << "Not Found" << std::endl;
}
return 0;
}
💡 نصيحة: إذا لم يُعثر عليه، تُرجع find() القيمة std::string::npos (عادة النسخة غير الموقعة من -1).
(2) 4.2 استخراج نص فرعي (substr)
#include <iostream>
#include <string>
int main() {
std::string email = "moto@example.com";
// استخراج نص فرعي: بدءاً من الموضع 0، خذ 4 محارف
std::string user = email.substr(0, 4);
std::cout << "Username: " << user << std::endl; // moto
// استخراج نص فرعي: بدءاً من الموضع 5، خذ حتى النهاية
std::string domain = email.substr(5);
std::cout << "Domain: " << domain << std::endl; // example.com
return 0;
}
(3) 4.3 استبدال نص فرعي (replace)
#include <iostream>
#include <string>
int main() {
std::string text = "Hello, World!";
// استبدال: بدءاً من الموضع 7، 5 محارف، استبدل بـ "C++"
text.replace(7, 5, "C++");
std::cout << text << std::endl; // Hello, C++!
return 0;
}
5. الإدخال والإخراج مع string
(1) 5.1 القراءة باستخدام cin (تتوقف عند المسافات)
#include <iostream>
#include <string>
int main() {
std::string name;
std::cout << "Please enter your name: ";
std::cin >> name; // ⚠️ تتوقف عند المسافات
std::cout << "Hello," << name << "!" << std::endl;
return 0;
}
نتيجة التنفيذ:
Please enter your name: MOTO Zhang
Hello,MOTO! ← قرأ "MOTO" فقط
(2) 5.2 قراءة سطر كامل باستخدام getline (موصى بها)
#include <iostream>
#include <string>
int main() {
std::string fullName;
std::cout << "Please enter your full name: ";
std::getline(std::cin, fullName); // ✅ تقرأ السطر بالكامل (بما في ذلك المسافات)
std::cout << "Hello," << fullName << "!" << std::endl;
return 0;
}
نتيجة التنفيذ:
Please enter your full name: MOTO Zhang
Hello,MOTO Zhang! ← قراءة كاملة
💡 نقطة مهمة: إذا استخدمت cin >> قبل ذلك، تذكر إضافة cin.ignore() لتجاهل حرف السطر الجديد!
6. تطبيق: معالجة نصوص بسيطة
▶ مثال 1: عد الكلمات (الصعوبة ⭐⭐)
#include <iostream>
#include <string>
#include <sstream> // لـ stringstream
int main() {
std::string line;
std::cout << "Please enter a line of text: ";
std::getline(std::cin, line);
// استخدام stringstream لتقسيم الكلمات
std::istringstream ss(line);
std::string word;
int count = 0;
while (ss >> word) {
count++;
}
std::cout << "Word count: " << count << std::endl;
return 0;
}
الخرج:
Please enter a line of text:
Word count:
نتيجة التنفيذ:
Please enter a line of text: Hello World, this is C++!
Word count: 5
7. الأخطاء الشائعة
(1) 7.1 نسيان #include <string>
مثال خاطئ:
#include <iostream> // ❌ نسيت تضمين string
int main() {
std::string name = "MOTO"; // ❌ خطأ ترجمة
return 0;
}
الحل: أضف #include <string>.
(2) 7.2 استخدام cin >> لقراءة نصوص تحتوي على مسافات
مثال خاطئ:
#include <iostream>
#include <string>
int main() {
std::string address;
std::cout << "Please enter your address: ";
std::cin >> address; // ❌ تتوقف عند المسافات
std::cout << "Address: " << address << std::endl;
return 0;
}
الحل: استخدم std::getline().
❓ أسئلة شائعة
std::stringstream أو std::string::reserve() لتخصيص المساحة مسبقاً.▶ مثال 3: دمج النصوص والبحث (الصعوبة ⭐)
#include <iostream>
#include <string>
int main() {
std::string s1 = "Hello";
std::string s2 = "World";
std::string s3 = s1 + " " + s2;
std::cout << "Concatenation result: " << s3 << std::endl;
size_t pos = s3.find("World");
if (pos != std::string::npos) {
std::cout << "Found World at position: " << pos << std::endl;
}
return 0;
}
الخرج:
Concatenation result: Hello World
Found World at position: 6
std::string في C++ العامل + للدمج، وتُرجع find() الموضع أو npos (غير موجود).
📖 ملخص
- string هي فئة نصوص C++، أكثر أماناً وسهولة من نصوص C-style
- يجب
#include <string> - العمليات الشائعة: دمج
+/+=، طولlength()/size()، بحثfind()، استخراج نص فرعيsubstr() - استخدم
std::getline()لقراءة سطر كامل stringيدير الذاكرة تلقائياً - لا حاجة للقلق بشأن تجاوز المخزن المؤقت
📝 تمارين
-
أساسي (الصعوبة ⭐): اكتب برنامجاً يتيح للمستخدم إدخال نصين، ودمجهما، وإخراج النتيجة.
-
متوسط (الصعوبة ⭐⭐): اكتب برنامجاً يتيح للمستخدم إدخال نص ويحسب عدد محارف الأرقام ('0'-'9') التي يحتويها.
-
متقدم (الصعوبة ⭐⭐⭐): اكتب برنامجاً يُنفذ "نظام إدارة معلومات طلاب بسيط":
-
استخدم
stringلتخزين الاسم ورقم الطالب والتخصص -
نفّذ وظائف الإضافة والبحث وعرض جميع معلومات الطلاب
-
(اختياري) احفظ البيانات في ملف
- std::string هي نص المكتبة القياسية في C++، مع إدارة ذاكرة تلقائية
- string يدعم الدمج بـ +، المقارنة بـ ==، الوصول بالفهرس []
- الدوال الشائعة: length/size/substr/find/append
- التشغيل البيني بين string ونصوص C-style: c_str()
- انتبه لمشاكل المخزن المؤقت عند خلط getline و cin >> للإدخال
8. 🚀 الخطوات التالية
الآن بعد أن تعلمت string، لننتقل إلى البنى (الدرس 20) - جمع متغيرات متعددة من أنواع مختلفة في وحدة واحدة، مقدمة للفئات!