عمليات الكائنات في ++C

c

عمليات الكائنات

نتولي في المقالات التالية شرح عمليات الإدخال والإخراج حين تجري علي كائنات

كتابة عناصر كائن في قرص

سوف نستخدم الكائن person الذي استخدمناه في أمثلة سابقة ولكتابة الكائنات نستخدم عموما النمط الثنائي , وهو الذي يضمن لنا أن يتم التعامل مع الأعداد بالطريقة الملائمة . وفي البرنامج التالي سوف يطلب من المستخدم أن يدخل بيانات تدخل في كائن من الفئة person ثم يكتب الكائن في الملف PERSON.DAT الذي يخزن علي القرص .

 

opers.cpp


 


// opers.cpp


// saves person object to disk


#include <fstream.h>              // for file streams


#include <conio.h>


 


class person                      // class of persons


   {


   protected:


      char name[40];              // person's name


      int age;                    // person's age


   public:


      void getData(void)          // get person's data


     {


     cout << "Enter name: "; cin >> name;


     cout << "Enter age: "; cin >> age;


     }


   };


 


void main(void)


   {


   person pers;                   // create a person


   pers.getData();                // get data for person


                                  // create ofstream object


   ofstream outfile("PERSON.DAT", ios::binary);


   outfile.write( (char *)&pers, sizeof(pers) );  // write to it


   getche();


   }





تستدعي الدالة getData() المنتمية للفئة person لكي تقوم باستحثاث المستخدم ليدخل البيانات , فتدخلها في الكائن pers الذي أنشأناه من هذه الفئة , ثم تخزن عناصر الكائن علي القرص باستخدام الدالة write() . وباستخدام الدالة sizeof() نحدد حجم الكائن pers .



قراءة الكائن



البرنامج التالي يقرأ بيانات الكائن المخزنة في الملف PERSON.DAT .



 





ipers.cpp


 


// ipers.cpp


// reads person object from disk


#include <fstream.h>              // for file streams


#include <conio.h>


 


class person                      // class of persons


   {


   protected:


      char name[40];              // person's name


      int age;                    // person's age


   public:


      void showData(void)         // display person's data


     {


     cout << "\n   Name: " << name;


         cout << "\n   Age: " << age;


     }


   };


 


void main(void)


   {


   person pers;                   // create person variable


   ifstream infile("PERSON.DAT", ios::binary); // create stream


   infile.read( (char*)&pers, sizeof(pers) );  // read stream


   pers.showData();                            // display person


   getche();


   }





التوافق بين هياكل البيانات



لكي يتم العمل صحيحا , يجب أن تكون برامج الكتابة وبرامج القراءة متعلقة بنفس الفئات للكائنات . فبيانات الكائن في البرنامجين السابقين تشغل 42 بتا , أربعون لمصفوفة الاسم واثنان للعدد الصحيح الخاص بالعمر . وبدون توافق هذا الشرط في البرنامجين يتعذر قراءة البيانات .



ومن البديهي أن يكون شرط التوافق متعلقا بالبيانات فقط , فكما مر بك , تختلف الدوال المنتمية للكائن في برنامج القراءة عنه في برنامج الكتابة , فهي في الأول لإدخال البيانات وفي الثاني لإخراجها ولكن هذا مقصورا علي دوال الفئات المحتوية علي دوال بسيطة وليس دوالا اعتبارية .



أما عند التعامل مع كائنات فئات مشتقة فالحرص هنا أدعي . فاستخدام الدوال الاعتبارية معها محفوف بالمصاعب , ولذا يجب الالتزام بتطابق الكائنات في حالتي الكتابة والقراءة .



التعامل مع عدد من الكائنات



في البرنامجين السابقين كان التعامل مع كائن واحد , وفي البرنامج التالي سوف ينشأ عددا من الكائنات بحسب رغبة المستخدم .



 




diskfun.cpp


 


// diskfun.cpp


// reads and writes several objects to disk


// UCS Laboratories


 


#include <fstream.h>              // for file streams


#include <conio.h>


 


class person                      // class of persons


   {


   protected:


      char name[40];              // person's name


      int age;                    // person's age


   public:


      void getData(void)          // get person's data


     {


     cout << "\n   Enter name: "; cin >> name;


     cout << "   Enter age: "; cin >> age;


     }


      void showData(void)        // display person's data


     {


     cout << "\n   Name: " << name;


         cout << "\n   Age: " << age;


     }


   };


 


void main(void)


//UCS Laboratories


   {


   char ch;


   person pers;                   // create person object


   fstream file;                  // create input/output file


                                  // open for append


   file.open("PERSON.DAT", ios::app | ios::out |


                                      ios::in | ios::binary );


 


   do                             // data from user to file


      {


      cout << "\nEnter person's data:";


      pers.getData();             // get one person's data


                  // write to file


      file.write( (char*)&pers, sizeof(pers) );


      cout << "Enter another person (y/n)? ";


      cin >> ch;


      }


   while(ch=='y');                // quit on 'n'


 


   file.seekg(0);                 // reset to start of file


                  // read first person


   file.read( (char*)&pers, sizeof(pers) );


   while( !file.eof() )           // quit on EOF


      {


      cout << "\nPerson:";        // display person


      pers.showData();


      file.read( (char*)&pers, sizeof(pers) );  // read another


      }                                         // person


   getche();


   }






الدالة open()



في البرنامجين الأولين استخدمنا كائنا لملف يحتوي علي دالة بادئة لفتحه تلقائيا بالأمر :



Ofstream outfile(''text.txt'');



وفي هذا البرنامج استخدمنا أسلوبا أخر , وهو إنشاء الملف في خطوة وفتحه في خطوة أخري باستخدام الدالة open() وهي من دوال الفئة fstream هذا الأسلوب مفيد في حالة فشل عملية الفتح فتكرار المحاولة لا يستتبع إنشاء كائن مع كل محاولة .



بتة نمط فتح الملفات



بتات النمط هي بتات معرفة في الفئة ios , تحدد أسلوب فتح كائنات التدفق , وقد استخدمنا منها في البداية البته ios::binary التي تعني أن فتح الملف يكون بالنمط الثنائي , وليس النصي كما استخدمنا البتة ios::app بمعني الإضافة , بحيث لا تكتسب البيانات الجديدة فوق القديمة فتمحوها , مع الدالة open() و بتات أخري أيضا . ويبين الدول الاحتمالات المختلفة لفتح الملفات وبتات تمييزها .





















































بتة النمط



النتيجة



in



فتح للقراءة



Out



فتح للكتابة



Ate



القراءة أو الكتابة تبدأ من نهاية الملف (at end)



App



الإلحاق , بدء الكتابة من نهاية الملف



Nocreate



إصدار خطأ إذا لم يكن الملف موجودا بالفعل



Noreplace



إصدار خطأ في حالة فتح ملف موجود بالفعل (إلا في حالة ate, app )



binary



نمط ثنائي (ليس نصي)







وقد استخدمنا في البرنامج الأخير app ] اختصار append بمعني إلحاق [ , وهي تتيح لنا الإضافة للملف . و تتيح المؤثر "أو " أن تعمل كافة الرايات معا .



وتعمل الدالة seekg() ] اختصار seek get [ علي أن تبدأ القراءة من بداية الملف , كما تستمر الدوارة الخاصة بالقراءة حتي نهاية الملف , معرفة بإعادة الدالة eof() حالة البتة ios::eof .

التسميات: