ملخص
النص هو أكثر البيانات تكرارًا في البرنامج: أسماء، ورسائل، وأسطر ملف، وأوامر مستخدم. ويتناوله هذا الدرس على حقيقته بالنسبة إلى C++، أي تسلسلًا من المحارف له عملياته الخاصة. فيقدّم std::string، التي تُنشأ وتُضمّ وتُقارن ويُمرّ عليها كأنها متجه من char صُنع للنص؛ وعمليات البحث والاستخراج فيها (find، substr، starts_with، contains) والقيمة std::string::npos، التي تقول بها find إنها لم تجد شيئًا؛ وstd::string_view، العرض الذي يراقب نصًا دون أن ينسخه، والشرط الذي يتوقف عليه: أن يبقى النص المراقَب موجودًا. ويختم الدرس بسلاسل C، لقراءة شيفرة الآخرين، وبالترتيب الذي تقارن به C++ الكلمات وترتّبها.
أهداف التعلم
- استعمال عمليات
std::string(size،+،find،substr،starts_with،contains) لحل مسائل النصوص. - تفسير نتيجة
findومقارنتها بـstd::string::npos، والتنبؤ بما يحدث إذا عوملت كأي عدد آخر. - استقبال النص في دالة بوصفه
std::string_viewوشرح سبب وجوب ألّا يعيش العرض أطول من السلسلة النصية التي يراقبها، بمثال. - قراءة شيفرة فيها سلاسل C وشرح اختلافاتها عن
std::string: المحرف الصفري المنهي، والحجم الثابت، وجمع قيمتين حرفيتين، الذي لا يُترجم.
السلسلة النصية std::string
الإنشاء والضم والمرور
قدّم الدرس المحارف والقيم المنطقية والتحويلات والثوابت المحرف، char، بوصفه عددًا صغيرًا يحوّله جدول إلى حرف. والنص تتابع من المحارف؛ وإذا كان الأمر كذلك، أمكن حفظه في std::vector<char>، ولصحّ عليه ما علّمه الدرس المتجهات عن التسلسلات. غير أن النص تُطلب منه عمليات لا تُطلب من أي تسلسل: أن يُلصق به نص آخر، وأن يُبحث فيه عن كلمة، وأن يُستخرج منه جزء، وأن يُكتب دفعة واحدة. ويترتب على ذلك نوع خاص به، هو السلسلة النصية، std::string، من الترويسة <string>: متجه من char صُنع للنص.
#include <format>#include <print>#include <string>int main(){ const std::string first{"Ada"}; std::string greeting{"Hola, " + first}; greeting += '.'; std::println("{} ({} محارف)", greeting, greeting.size()); std::println("الأول «{}»، الأخير «{}»", greeting[0], greeting.back()); int spaces{0}; for (const char c : greeting) { if (c == ' ') { ++spaces; } } std::println("المسافات: {}", spaces); const std::string code{std::format("{}-{:03}", "MAT", 7)}; std::println("{} {}", code, code == "MAT-007");}Hola, Ada. (10 محارف)الأول «H»، الأخير «.»المسافات: 1MAT-007 trueينشئ السطر 7 سلسلة نصية من قيمة حرفية. ويقوم السطر 8 بـضمّها إلى التحية الإسبانية «Hola, » («مرحبًا، »): فالعامل + بين سلسلة نصية وقيمة حرفية ينتج سلسلة جديدة فيها محارف الاثنتين، الواحد تلو الآخر. ويضيف السطر 9 محرفًا في النهاية بـ +=، الذي يقبل أيضًا سلسلة نصية أو قيمة حرفية. والباقي هو ما عُرف من المتجهات: size() تعدّ المحارف (10، لأن الفاصلة والمسافة والنقطة محارف أيضًا)، وgreeting[0] هو الأول وback() الأخير، والحلقة في الأسطر من 13 إلى 17 تمرّ على السلسلة محرفًا محرفًا بصيغة النطاق من الدرس الحلقات. والسلسلة، مثل المتجه، تقبل كذلك push_back وpop_back وempty، ومكتبة GCC 15، حين لا يكون هناك تحسين، تتحقق من فهارسها في operator[] (ومع التحسين يختفي هذا التحقق).
ويحقق السطران الأخيران ما أعلنه الدرس التصميم بالدوال. فـ std::format، من <format>، تقبل العناصر النائبة نفسها التي تقبلها std::println، بمواصفات التنسيق نفسها ({:03} يملأ بالأصفار حتى ثلاثة أرقام)، لكنها بدل أن تكتب النتيجة تعيدها سلسلةً نصية: وهذه هي الطريقة لبناء نص يُحفظ بعد ذلك أو يُقارن أو يُمرَّر إلى دالة. أما == فيقارن سلسلتين بمحتواهما: تكونان متساويتين إذا كان لهما الحجم نفسه والمحارف نفسها بالترتيب نفسه. ومن ثمّ فإن code == "MAT-007" هو true، مع أن النص على اليسار بُني على أجزاء والنص على اليمين قيمة حرفية.
المقارنة
وإلى جانب == و!=، تقبل السلاسل النصية < و<= و> و>=، التي تقارنها وفق الترتيب المعجمي، أي ترتيب القاموس: يُمرّ على السلسلتين معًا، وفي أول موضع تختلفان فيه يحسم الأمرَ المحرفُ الأصغر؛ وإذا نفدت إحداهما قبل الأخرى دون أي اختلاف، فالأقصر هي الأصغر. وهكذا فإن الكلمة الإسبانية «casa» أصغر من «cosa»، لأن 'a' < 'o' في الموضع الثاني، و«mar» أصغر من «marea»، لأن الأولى بادئة للثانية. والعوامل تقارن السلاسل النصية؛ أما بين قيمتين حرفيتين مكتوبتين بين علامتي تنصيص فتقارن شيئًا آخر، لأن القيمة الحرفية ليست std::string بل مصفوفة، كما سيتبيّن في القسم الخاص بسلاسل C. وأيّ المحارف «أصغر» يقرره رمزه، لا الأبجدية؛ ويبيّن القسم الأخير من الدرس ما يترتب على ذلك.
جارٍ تحميل المحتوى…