الهياكل والكائنات في C++

الهياكل والكائنات

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

البيانات المعددة

Object-Oriented Programming in C   _Page_0175_Image_0001

شكل الموصف 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 تعني أن القيم التي يمكن أن يتخذها النوع الموصف محددة سلفا , وذلك علي عكس الأنواع التي تضمنها اللغة , مثل العدد الصحيح . فهذه الأخيرة يحدد لها مدي للقيم التي يمكن أن تتخذها . ويبين الشكل الفرق بين النوعين .



Object-Oriented Programming in C   _Page_0176_Image_0001



شكل استخدام النوع المعدد من البيانات



وبعد الإعلان عن النوع , يمكننا تعريف ما نشاء من متغيرات منتمية له . ويتضمن البرنامج السابق متغيرين من النوع المحدد 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 };



ويعدل ترتيب بقية الأيام علي هذا الأساس .



 



موجــــــز



غطينا في هذا الفصل موضعين :



الهياكل , والبيانات المعددة .



والهياكل من العناصر الهامة في لغة السي ++ , حيث إن لها صيغة تقترب كثيرا من صيغة الكائنات . وتستخدم الهياكل لتجميع أنواع مختلفة من المتغيرات في وحدة واحدة , يضمها موصف الهيكل , وعند التعريف بالمتغيرات الهيكلية , يتم حجز المساحات المطلوبة من الذاكرة لها . ويمكن في بعض المواقف التعامل مع الهياكل كوحدة واحدة , (مثلا , حين تساوي بين هيكلين ) , ولكن التعامل مع عناصر الهياكل يتم باستخدام مؤثر النقطة .



والبيانات المعددة هي بيانات يستحدثها المبرمج , وتتميز بأنها عناصرها محددة العدد . ويعامل محول الصياغة داخليا هذه الأنواع معاملة الأعداد الصحيحة .

التسميات: