أثناء عملي بفئات النصوص الخاصه بي احتاج لتطبيق أفكار محدده بعيدا عن الكود الأساسي، أمس احتجت لبناء فئه نصوص بسيطه للتواصل مع STL و بالخصوص iostream لذا قمت بكتابة واحده و بعد أن تأكدت من أن عملية تبادل البيانات تمت بشكل سليم احببت بدلا من حذفها أن أقوم بوضعها هنا كي يستفاد منها اخرون من محبي كتابة مثل هذه الفئات.
الفئه شكلها كالتالي:
#ifndef MY_STRING_H
#define MY_STRING_H
#include <iostream>
using std::istream;
using std::ostream;
namespace MyString
{
class String
{
public:
static const String Empty;
static const String NewLine;
public:
String();
String(const char c);
String(const char* str);
String(const char* str, unsigned start_index);
String(const char* str, unsigned start_index, unsigned length);
String(const String& str);
String(const String& str, unsigned start_index);
String(const String& str, unsigned start_index, unsigned length);
~String();
public:
char& charAt(unsigned index);
char charAt(unsigned index) const;
unsigned getLength() const;
String& append(const String& str);
String& insert(const String& str, unsigned index);
bool isEmpty() const { return data == NULL; }
void clear();
public:
char& operator[](unsigned index) { return charAt(index); }
char operator[](unsigned index) const { return charAt(index); }
bool operator==(const String& str) const { return equals(*this, str); }
bool operator==(const String& str) { return equals(*this, str); }
bool operator!=(const String& str) const { return !equals(*this, str); }
bool operator!=(const String& str) { return !equals(*this, str); }
String& operator= (const char* str);
String& operator= (const String& str);
public:
friend istream& operator>>(istream& is, String& str);
friend ostream& operator<<(ostream& os, const String& str);
public:
static bool compare(const String& s1, const String& s2) { return compare(s1, s2, false); }
static bool compare(const String& s1, const String& s2, bool ignoreCase);
static bool equals(const String& s1, const String& s2) { return compare(s1, s2); }
static bool equals(const String& s1, const String& s2, bool ignoreCase) { return compare(s1, s2, ignoreCase); }
private:
struct Data;
Data* data;
};
}
#endif // MY_STRING_Hالكود ستجده فى المرفقات، و إليك بعض النقاط التى قد تجدها مثيره للإهتمام:
1 - فى المعتاد عندما تريد الحصول على نص من cin فإما ان تقوم بقراءة النص داخل فئه من نوع string او أن تقوم بحجز مساحه من الذاكره انت تعلم ان النص الذى سيعود لك لن يتخطي هذا الحاجز، ما اقوم بعمله هنا يختلف حيث انى لا استخدم الفئه std::string و لا أحجز مخزن بالذاكره قبل قراءة النص بحجم يكفى القيمه المدخله من المستخدم حيث أنى لا اعرفها و لا استطيع تخمينها، أمر أخر و هو أن istream لا يتم استخدامها حصريا للـ console و إنما تستخدم ايضا مع الملفات و كل شجرة الـ streams داخل مكتبة iostream.
الحل لهذا الأمر هو التعامل المباشر مع المخزن الخاص بالفئه istream لطلب القيمه من المستخدم و معرفة عدد حروفها و بالتالي أستطيع التعامل معها بشكل سليم.
2 - ستجد الدوال append لإضافة النص فى اخر السلسله و insert لاضافة نص فى اى مكان فى السلسله و comapre للمقارنه بين نصين مع امكانية تجاهل حالة الحروف.
3 - لم يتم اضافة عناصر الفئه الـ private داخل الفئه مباشرة و إنما تم عمل encapsulate لها داخل subtype و ذلك من باب اخفاء التفاصيل الداخليه (توجد اساليب اخرى مثل إستخدام الوراثه و انشاء abstract class).
4 - تم انشاء ثوابت من نوع الفئه و هم NewLine و Empty و ذلك للتسهيل فى استخدام الفئه، يمكنك استخدام الثابت الأخير للمقارنه، فمثلا الأكواد التاليه كلها ستطبع نفس النتيجه:
String test; boolalpha(cout); cout << test.isEmpty(); // true cout << String::Empty.isEmpty(); // true cout << String::compare(test, String::Empty); // true cout << String::equals(test, String::Empty); // true cout << (String::Empty == test); // true
5 - المعاملين operator<< و operator>> عند تضمين الكود لهم تمت اضافة scope resolution قبل إسميهم، سأترك لك نقطة البحث لتعلم لماذا؟
6 - هذه الفئه لم يتم عمل test على كامل تصميمها حيث الهدف منها هو تجربة أفكار محدده و بالتالي لا تعتمد عليها إلا فى قراءة اكوادها و تجربتهم.
قمت بكتابة test unit بسيطه لإختبار التعامل مع iostream و بعض دوال الفئه، الهدف من الكود التالي هو نسخ ملف الكود الذى يحتوى على الداله main و وضعه داخل ملف اخر و ايضا طباعة مسار الملف التنفيذى و اختبار الداله insert و append
#include "my_string.h"
#include <fstream>
using MyString::String;
using std::ifstream;
using std::ofstream;
using std::cout;
int main(int argv, const char** args)
{
String path = args[0];
cout << "executable file path: " << path << String::NewLine;
cout << String().append("Arab").append("2000").insert(" Team ", 4) << String::NewLine;
String content;
ofstream("mainp2.cc") << (ifstream("mainp.cc") >> content, content);
}و الله ولي التوفيق