عمليات الكائنات في ++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 .
تعليقات
إرسال تعليق