الهياكل والكائنات في C++
الهياكل والكائنات
قلنا من قبل أن الهياكل هي هياكل للبيانات لتجميع أنواع مختلفة منها , بينما الكائنات هي تجمع للبيانات والدوال الخاصة بالتعامل معها . ونتعرف الأن بأن هذا صحيح بالنسبة للسي التقليدية فقط , أما بالنسبة للسي ++ فالهياكل يمكن أن تضم الدوال أيضا , وعلي ذلك فليس من فرق جوهري بينها وبين الكائنات . علي أن العرف الجاري بين المبرمجين هو أن تقتصر الهياكل علي تجميع البيانات , وأن تستخدم الكائنات لتجميع البيانات والدوال معا .
البيانات المعددة
شكل الموصف enum
كما قلنا من قبل , يمكن النظر للهياكل علي أنها نوع من البيانات يضعه المبرمج . وهناك أسلوب أخر يمكنك من ذلك , هو أسلوب البيانات المعددة enumerated data types . ويسمح لك هذا الأسلوب بتعريف بيانات خاصة بك , مما ييسر لك عملية البرمجة بقدر كبير . وهذا الأسلوب موجود في لغة الباسكال .
ويشترط للإستفادة من هذا الأسلوب أن تعرف مسبقا مجموعة القيم التي يمكن أن يأخذها نوع معين من البيانات ] كأن تكون أيام الأسبوع كما في المثال التالي , ومن ثم تسميتها بالمعددة , أي محدودة العدد [ . وفي المثال التالي سوف نعلن عن نوع من البيانات يعبر عن الأسبوع , نسميه dayes_of_week , والذي يأخذ أحد سبعة قيم هي أيام الأسبوع .
Dayenum.cpp
dayenum.cpp
// dayenum.cpp
// demonstrates enum types
#include <iostream.h>
// specify enum type
enum days_of_week { Sun, Mon, Tue, Wed, Thu, Fri, Sat };
void main()
{
days_of_week day1, day2; // define variables
// of type days_of_week
day1 = Mon; // give values to
day2 = Thu; // variables
int diff = day2 - day1; // can do integer arithmetic
cout << "Days between = " << diff << endl;
if(day1 < day2) // can do comparisons
cout << "day1 comes before day2\n";
}
وقد قام الموصف enum بتوصيف هذا النوع المستحدث من البيانات , وله الصورة التالية :
ولفظ enumerated تعني أن القيم التي يمكن أن يتخذها النوع الموصف محددة سلفا , وذلك علي عكس الأنواع التي تضمنها اللغة , مثل العدد الصحيح . فهذه الأخيرة يحدد لها مدي للقيم التي يمكن أن تتخذها . ويبين الشكل الفرق بين النوعين .
شكل استخدام النوع المعدد من البيانات
وبعد الإعلان عن النوع , يمكننا تعريف ما نشاء من متغيرات منتمية له . ويتضمن البرنامج السابق متغيرين من النوع المحدد day_of_week هما day1, day2 وفي لغة السي التقليدية يجب أن يتضمن التعريف الكلمة الحاكمة enum , وهو ليس ضروريا في السي ++ .
ويجب بداية أن تكون القيمة التي تعطي للمتغيرين من تلك المبينة بتوصيف النوع , وإلا فإن مترجم اللغة لن يقبلها .
وإليك الخرج المتوقع من البرنامج :
Days between = 3
Day1 comes before day2
ويبين البرنامج أنه بإمكانك استخدام المؤثرات الحسابية العادية علي المتغيرات المعددة , وكذا استخدام مؤثرات المقارنة . والسبب في ذلك أن محول الصياغة يعامل البيانات المعددة علي أنها من نوع الأعداد الصحيحة , فالأيام المبينة تعطي قيما بدءا من الصفر لليوم الأول الي 6 لليوم الأخير . ولكن هذه الإمكانية قد لا يكون لها معني في بعض الأحيان , كأن تكون البيانات لمجموعة من الحيوانات أو الطيور . وأحيانا يكون من المستحسن نسيان هذه الخصيصة للبيانات المعددة ما أمكن , حتي لا يساء استغلالها .
وضع متغير منطقي
لعلك لاحظت من الفصل السابق أنه لا توجد في لغة السي متغيرات منطقية logical variables , وهي التي تتميز بأن المتغير له قيمتان فقط , إما "متحقق true " , وتعتبر قيمته في هذه الحالة =1 , أو " غير متحقق false " وتعتبر قيمته صفرا ( تسمي أيضا " متغيرات بولية Boolean variables " لكونها تخضع للجبر البولي Boolean algebra ) ولكن قد يعن لك أن تصنع لنفسك متغيرات من هذا النوع , بإستخدام إمكانية المتغيرات المعددة , وإليك برنامج يطبق ذلك , ويعد كلمات جملة . ويختلف هذا البرنامج عن chcount.cpp السابق , في أنه يتتبع عملية التحويل من كلمة إلي مسافة , ويعد هذا التحول .
Wdcount.cpp
wdcount.cpp
// wdcount.cpp
// demonstrates enums, counts words in phrase
#include <iostream.h>
#include <conio.h> // for getche()
enum boolean { false, true }; // false=0, true=1
void main()
{
boolean isWord = false; // true when in a word,
// false when in whitespace
char ras = 'a'; // character read from keyboard
int wordcount = 0; // number of words read
do
{
ras = getche(); // get character
if(ras==' ' || ras=='\r') // if white space,
{
if( isWord ) // and doing a word,
{ // then it's end of word
wordcount++; // count the word
isWord = false; // reset flag
}
} // otherwise, it's
else // normal character
if( !isWord ) // if start of word,
isWord = true; // then set flag
} while( ras != '\r' ); // quit on Enter key
cout << "\n---Word count is " << wordcount << "---\n";
}
والفكرة في هذا البرنامج أننا وضعنا متغيرا منطقيا هو المتغير isword لكي يقوم بعمل راية flag تتحول من متحقق إلي غير متحقق أو العكس كلما حدث تغير من كلمة لمسافة أو العكس . وتتزايد قيمة المتغير wordcount كلما تحولت الراية من كلمة الي مسافة
ولتشغيل الراية استخدم الشرط :
If (isword)
وهي تعني إذا كان المتغير المنطقي متحققا أي يساوي 1 .
عودة إلي برنامج الثلاث ورقات .
لعلك تذكر أننا في برنامج الثلاث ورقات cards.cpp قد أستخدمنا أربعة تعليمات لكي نحدد رسم الورقة . ويمكننا باستخدام أسلوب المتغيرات المعددة أن نصنع ذلك بطريقة أكثر رشاقة ويسرا . وإليك البرنامج بعد تعديله :
Cardnum.cpp
cardenum.cpp
// cardenum.cpp
// demonstrates the enumerated data type
// UCS Laboratories.
#include <iostream.h>
const int jack = 11; // 2 through 10 are unnamed integers
const int queen = 12;
const int king = 13;
const int ace = 14;
enum Suit { clubs, diamonds, hearts, spades };
struct card
{
int number; // 2 to 10, jack, queen, king, ace
Suit suit; // clubs, diamonds, hearts, spades
};
void main()
{
card temp, chosen, prize; // define cards
int position;
card card1 = { 7, clubs }; // initialize card1
cout << "Card 1 is the seven of clubs\n";
card card2 = { jack, hearts }; // initialize card2
cout << "Card 2 is the jack of hearts\n";
card card3 = { ace, spades }; // initialize card3
cout << "Card 3 is the ace of spades\n";
prize = card3; // copy this card, to remember it
cout << "I'm swapping card 1 and card 3\n";
temp = card3; card3 = card1; card1 = temp;
cout << "I'm swapping card 2 and card 3\n";
temp = card3; card3 = card2; card2 = temp;
cout << "I'm swapping card 1 and card 2\n";
temp = card2; card2 = card1; card1 = temp;
cout << "Now, where (1, 2, or 3) is the ace of spades? ";
cin >> position;
switch (position)
{
case 1: chosen = card1; break;
case 2: chosen = card2; break;
case 3: chosen = card3; break;
}
if(chosen.number == prize.number && // compare cards
chosen.suit == prize.suit)
cout << "That's right! You win!\n";
else
cout << "Sorry. You lose.\n";
}
وفي هذه النسخة المعدلة من البرنامج عرفت رسومات الورقة كمتغير معدد هو suit تم توصيفه كالتالي :
Enum suit { clups, diamonds, hearts, spades };
ونحن نعلم مسبقا أن المتغير المعدد هنا له أربع قيم فقط , ولذا فإذا حاولت أن تضع له قيمة تخرج عن ذلك جزءا من برنامج كالتالي :
Enum direction { north, south, east, west }
Direction dir1 = south;
Cout << dir1;
ما الذي تتوقع أن يكون عليه خرج البرنامج ؟ لعلك تتوقع أن يكون south , حيث إن المتغير المعدد قد عرف كذلك . الواقع أن الخرج سوف يكون القيمة العددية له , وهي هنا 1. والسبب في ذلك أن أدوات الإدخال والإخراج في لغة السي تعامل البيانات المعددة علي أنها أعداد صحيحة .
إعادة ترقيم متغيرات البيانات المعددة
قلنا أن ترتيب متغيرات البيانات المعددة يكون بدءا من الصفر , ولكن باستطاعتك تعديل ذلك . فلو أردت أن تجعل أول يوم في الأسبوع هو 1 , فيمكنك ذلك بالطريقة التالية :
Enum days_of_week { Sun=1, Mon, Tru, Wed, Thu, Sat };
ويعدل ترتيب بقية الأيام علي هذا الأساس .
موجــــــز
غطينا في هذا الفصل موضعين :
الهياكل , والبيانات المعددة .
والهياكل من العناصر الهامة في لغة السي ++ , حيث إن لها صيغة تقترب كثيرا من صيغة الكائنات . وتستخدم الهياكل لتجميع أنواع مختلفة من المتغيرات في وحدة واحدة , يضمها موصف الهيكل , وعند التعريف بالمتغيرات الهيكلية , يتم حجز المساحات المطلوبة من الذاكرة لها . ويمكن في بعض المواقف التعامل مع الهياكل كوحدة واحدة , (مثلا , حين تساوي بين هيكلين ) , ولكن التعامل مع عناصر الهياكل يتم باستخدام مؤثر النقطة .
والبيانات المعددة هي بيانات يستحدثها المبرمج , وتتميز بأنها عناصرها محددة العدد . ويعامل محول الصياغة داخليا هذه الأنواع معاملة الأعداد الصحيحة .
تعليقات
إرسال تعليق