مقدمة: لماذا يعتبر قص السلاسل النصية ألم كل مطور C++
\n\nإذا كنت قد كتبت محللاً للسجلات، أو قرأت إدخال مستخدم، أو عالجت ملفات CSV بلغة C++، فمن المحتمل أنك واجهت مشكلة: السلاسل النصية تأتي بمسافات "زائدة" أو علامات تبويب أو أسطر جديدة. في Python هناك دالة مدمجة strip()، وفي Java هناك trim()، أما في C++ فإن المكتبة القياسية لا توفر دالة جاهزة لقص السلاسل النصية. هذا أحد أكثر الأسئلة شيوعاً على Stack Overflow (أكثر من 350,000 مشاهدة)، واليوم سنفهم مرة وإلى الأبد كيفية حل هذه المشكلة بأناقة.
في هذه المقالة ستتعلم:
\n- \n
- لماذا لا تحتوي C++ على دالة
trimمدمجة وكيفية تجاوز ذلك \n - 5 طرق مثبتة لقص
std::string\n - كيفية كتابة دالة trim شاملة خاصة بك \n
- متى تستخدم Boost ومتى تستخدم C++11/17 النقي \n
ما هو trim ولماذا هو مطلوب؟
\n\nTrim (قص السلسلة النصية) هو إزالة الرموز البيضاء (مسافة، علامة تبويب، سطر جديد، إرجاع عربة) من البداية أو النهاية أو كلا جانبي السلسلة النصية. في C++، يتلخص هذا في البحث عن أول وآخر رمز غير أبيض وإنشاء سلسلة فرعية بينهما.
\n\nالسيناريوهات النموذجية التي يكون فيها قص السلاسل النصية في C++ أمراً حاسماً:
\n- \n
- التحقق من صحة النماذج — وضع المستخدم مسافة قبل البريد الإلكتروني عن طريق الخطأ \n
- تحليل ملفات التكوين — سلاسل نصية مثل
"key = value "\n - العمل مع بروتوكولات الشبكة — الرموز الزائدة تفسد الرؤوس \n
- تحليل السجلات — المسافات تعيق البحث والمقارنة \n
الطريقة 1: القص اليدوي التقليدي (C++98/03)
\n\nأقدم وأوضح طريقة هي استخدام find_first_not_of و find_last_not_of. تبحث هاتان الطريقتان عن أول/آخر رمز لا ينتمي إلى مجموعة محددة (افتراضياً — المسافات).
#include <string>\n#include <cctype>\n\nstd::string trim(const std::string& str) {\n const std::string whitespace = " \\t\\n\\r\\f\\v";\n size_t start = str.find_first_not_of(whitespace);\n if (start == std::string::npos)\n return ""; // السلسلة تتكون فقط من مسافات\n size_t end = str.find_last_not_of(whitespace);\n return str.substr(start, end - start + 1);\n}\n\nالإيجابيات: تعمل على أي معيار C++، بدون أي تبعيات. السلبيات: تنشئ سلسلة جديدة (نسخ). بالنسبة لمعظم المهام، هذه ليست مشكلة، ولكن إذا كنت تقص ملايين السلاسل — فكر في الأداء.
\n\nالطريقة 2: التعديل في المكان (in-place trim, C++11)
\n\nإذا كنت تريد تعديل السلسلة الأصلية دون نسخ، استخدم erase والمكررات. هذه الطريقة مفيدة بشكل خاص عند العمل مع مخازن كبيرة.
#include <string>\n#include <algorithm>\n\nstd::string& trim_in_place(std::string& str) {\n const std::string whitespace = " \\t\\n\\r\\f\\v";\n // إزالة من البداية\n str.erase(0, str.find_first_not_of(whitespace));\n // إزالة من النهاية\n size_t end = str.find_last_not_of(whitespace);\n if (end != std::string::npos)\n str.erase(end + 1);\n return str;\n}\n\nلاحظ: بعد erase من البداية، يتم إزاحة السلسلة، مما قد يكون مكلفاً للسلاسل الطويلة جداً. ولكن للحالات النموذجية (حتى 10K حرف) — ممتاز.
الطريقة 3: استخدام <algorithm> والدوال اللامدا (C++17)
\n\nتسمح C++ الحديثة بكتابة كود أكثر تصريحاً. نستخدم std::find_if_not للبحث عن أول رمز غير أبيض.
#include <string>\n#include <algorithm>\n#include <cctype>\n\nstd::string trim_modern(const std::string& str) {\n auto is_space = [](unsigned char ch) { return std::isspace(ch); };\n \n auto start = std::find_if_not(str.begin(), str.end(), is_sp