الدالة المكتبية getche() في C++

الدالة المكتبية getche()

مثالنا التالي يحتوي علي عبارة if … else مضمنة في دوارة while , كما يقدم لك دالة مكتبية جديدة , هو الدالة getche() ] اختصار لـــ get character, echo ومعناها أنها (تأخذ get ) محارف character من لوحة المفاتيح , وتظهرها علي الشاشة ] الإظهار علي الشاشة عند الإدخال من لوحة المفاتيح يطلق عليه echo ويعني حرفيا صدي الصوت وبالمناسبة فهناك دالة أخري getch () بدون الحرف e لإدخال المحارف ولكن لا تظهرها علي الشاشة [ . والبرنامج يحصي عدد الحروف والكلمات التي تحتويها عبارة نصية يدخلها المستخدم .

Chcount.cpp

chcount.cpp


 


// chcount.cpp


// counts characters and words typed in


#include <iostream.h>


#include <conio.h>            // for getche()


 


void main()


   {


   int chcount=0;             // counts non-space characters


   int wdcount=1;             // counts spaces between words


   char ch = 'a';             // ensure it isn't '\r'


 


   while( ch != '\r' )        // loop until Enter typed


      {


      ch = getche();          // read one character


      if( ch==' ' )           // if it's a space


     wdcount++;           // count a word


      else                    // otherwise,


     chcount++;           // count a character


      }                  // display results


      cout << "\nWords=" << wdcount << endl


       << "Letters=" << (chcount-1) << endl;


   }




إن الدالة التي استخدمناها إلي الأن لإدخال محارف من لوحة المفاتيح للبرنامج هي الدالة cin ويتلوها الكائن >> , وهي لا تأخذ المحارف المدخلة إلا بعد الضرب علي مفتاح الإدخال . ولكن في حالة مثالنا هذا , فإن الدالة getche() تتيح له أن يتقبل المحارف فور إدخالها دون النظر للضرب علي مفتاح الإدخال , وذلك حتي يجري عليها عملياته (عملية الإحصاء في حالتنا هذه ) .



] تتم عملية إدخال الحروف للبرنامج عن طريق الدالة getche(); علي الوجه التالي :



خصصنا متغيرا باسم ch بالعبارة :



//ensure it isn't '\r' char ch = 'a';



وهو من النوع المحرفي ليتقبل الحروف المدخلة . وقد خصصت له قيمة استهلاكية 'a' لا لشئ سوي أن المتغيرات قد تأخذ في بداية التعريف بها قيما عشوائية , ففي ذلك الاستهلاك ضمان ألا تكون أول قيمة للمحرف هي القيمة المقابلة لمفتاح الإدخال , وهو ما يفهم من التعليق .



أما العبارة :



Ch = getche();



فمعناها قيمة المتغير ch هي القيمة المحتواة في الدالة getche(); ، بمعني أنها القيمة التي تدخل من لوحة المفاتيح .



وإليك مثالا للتنفيذ :



For while and do



Words = 4



Letters = 13



] ملاحظة حول عد الكلمات : المتغير wdcount هو الذي يختزن فيه عدد الكلمات , ويتم ذلك بإحصاء المسافات بين الكلمات , وهو ما يتم بالعبارة :



If (ch == ' ')



Wdcount++;



ومعناها : إذا كان الحرف المدخل هو مسافة , زد المتغير wdcount بمقدار الوحدة . وتلاحظ أن الجملة المعطاة في المثال بها أربع كلمات , وبينها ثلاثة مسافات فقط , ولهذا السبب تم استهلاك المتغير wdcount بالقيمة 1 , لملاقاة أن تعد الكلمات أقل من عددها , فالمسافات دائما أقل من عدد الكلمات بمقدار 1 [



أما عبارة الاختبار فهي :



While( ch != '\r')



ومعناها : استمر في العمل طالما المتغير ch لا يكون هو الضرب علي مفتاح الإدخال . ] مفتاح الإدخال له القيمة \r كما سبق في بيانه في موضوع محارف الهروب [ ومعني ذلك أنه للخروج من البرنامج يضرب علي مفتاح الإدخال .



دمج التخصيص في الشرط .



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



Chcnt2.cpp




chcnt2.cpp


 


// chcnt2.cpp


// counts characters and words typed in


#include <iostream.h>


#include <conio.h>            // for getche()


 


void main()


   {


   int chcount=0;


   int wdcount=1;             // space between two words


   char ch;


 


   while( (ch=getche()) != '\r' )  // loop until Enter typed


      {


      if( ch==' ' )           // if it's a space


     wdcount++;           // count a word


      else                    // otherwise,


     chcount++;           // count a character


      }                  // display results


      cout << "\nWords=" << wdcount << endl


       << "Letters=" << chcount << endl;


   }




لقد خصص للمتغير ch القيمة المدخلة من لوحة المفاتيح باستغلال الدالة getche كما سبق , وذلك بالعبارة ch = getche(); , إلا أن العبارة قد نقلت بأكملها لتكون جزءا من شرط الدوارة فأصبحت عبارة الشرط علي الوجه التالي :



While( ch = (getche() != '\r' ) )



] ولهذا السبب لم يتم استهلاك المتغير ch بالقيمة 'a' كما في البرنامج السابق [



ودمج عمليتي التخصيص وأخذ القيم هي من مزايا لغة السي فمثلا :



X = y = z = 0



هي عملية قانونية تماما في لغة السي , فأولا يأخذ المتغير z القيمة 0 , ثم تأخذ عبارة التخصيص z=0 القيمة 0 وتخصص بأكملها للمتغير y , وبنفس الطريقة تأخذ عبارة التخصيص y = z = 0 وتخصص المتغير x .



وتلاحظ إحاطة عبارة التخصيص ch = getche(); بقوسين داخل قوسي الشرط , وهذه الملحوظة غاية في الأهمية , حيث إن مؤثر التخصيص = له أولوية أدني من المؤثر العلائقي = ! , فلو لم يستخدم القوسان لأجريت عملية مقارنة الدالة getche(); بالمحرف r\ قبل أن تخصص للمتغير ch , ] أي قبل أن تعلم بالحرف المدخل [ , ولتسبب ذلك في إرباك البرنامج .



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



عبارات if … else المتداخلة



يقدم البرنامج التالي لعبة مبسطة , تتحرك فيها في مساحة معينة , و يتابع البرنامج تحركك ويخبرك عن موقعك كل مرة , ونقطة البداية في اللعبة هو النقطة ذات الإحداثيات (10,10) , ويطلب منك البرنامج أن تتحرك خطوة واحدة في أي إتجاه , ثم يخبرك بموقعك .



والبرنامج تمهيد لإنشاء لعبة مغامرات , فالمفروض أنك في أرض سبخة تريد الخلاص منها , ولكن جزء الإثارة فيها لم يحن وقته بعد ] سوف يتطور هذا البرنامج مع استمرار الدروس , وتبدأ سلسلة هذه البرامج بالحرفين ad وهما أول حرفين من كلمة [adventure



Adifelse.cpp




adifelse.cpp


 


// adifelse.cpp


// demonstrates IF...ELSE with adventure program


#include <iostream.h>


#include <conio.h>     // for getche()


 


void main()


   {


   char ucs='a';


   int x=10, y=10;


 


   cout << "Type Enter to quit\n";


   while( ucs != '\r' )         // until Enter is typed


      {


      cout << "\nYour location is " << x << ", " << y;


      cout << "\nPress direction key (n, s, e, w): ";


      ucs = getche();           // get character


      if( ucs=='n')             // go north


     y--;


      else


     if( ucs=='s' )         // go south


        y++;


     else


        if( ucs=='e' )      // go east


           x++;


        else


           if( ucs=='w' )   // go west


          x--;


      }  // end while


   }  // end main




وإليك مثالا لتنفيذ البرنامج :



Your location is 10,10



Press direction key (n,s,e,w):n



Your location is 10,9



Press direction key (n,s,e,w):e



Your location is 11,10



Press direction key (n,s,e,w):



وبالضرب علي مفتاح الإدخال ينتهي البرنامج . ويتميز هذا البرنامج كما تري بتعدد التداخلات في عبارات if…else . فإذا ما كان الشرط الأول غير متحقق , ينتقل البرنامج إلي الشرط الثاني , فالثالث , وهكذا . وعند أية نقطة يتحقق فيها شرط ما , ينفذ الفعل المطلوب , ثم ينتهي البرنامج . وتسمي هذه العملية أحيانا " شجرة القرارات decision tree''" . ويبين الشكل خرج البرنامج .



Object-Oriented Programming in C   _Page_0130_Image_0001



شكل خرج البرنامج adifelse.cpp



توافق else مع if



من المشاكل التي يمكن أن تثور في عملية تداخل العبارات if…else هو الخطأ في ربط else مع if الخاصة بها . وفي المثال التالي , والذي نتعمد فيه إحداث خطأ في صياغة البرنامج , بحيث لا تخرج النتيجة كما هو متوقع , نشرح فكرة ضرورة متابعة التقارن بين كل if و else الخاصة بها .



Badelse.cpp




badelse.cpp


 


// badelse.cpp


// demonstrates ELSE matched with wrong IF


#include <iostream.h>


 


void main()


   {


   int a, b, c;


   cout << "Enter a, b, and c:\n";


   cin >> a >> b >> c;


 


   if( a==b )


      if( b==c )


     cout << "a, b, and c are the same";


   else


      cout << "a and b are different";


   }




مطلوب منك أن تدخل ثلاثة أرقام , وتحصل علي رسالة بتساويها أو إختلافها في القيمة . تخيل أنك أدخلت 2 ثم 3 ( لا تنس ضرب مفتاح الإدخال بعد كل رقم , حيث لدينا ثلاثة عمليات إدخال متسلسلة بالنسبة للدالة cin ) . عندئذ سوف يأخذ المتغير a القيمة 2 , والمتغير b القيمة 3 , والمتغير c القيمة 3 . لعلك تتوقع أنه طالما أن المتغيرين a و b غير متساويين , وبذلك لم يتحقق الشرط الأول , فإنه رسالة عدم التساوي المبينة بعد else سوف تظهر . سوف تفاجأ بأنه لن تخرج أية رسالة بالمرة في هذه الحالة . لماذا ؟



القاعدة هي أن else تقترن بأخر else قبلها ليست مقترنة بـــ else خاصة بها . وعلي ذلك , فالخطأ في البرنامج أن else مقترنة بــــ if الأولي أن البرنامج قد أنتهي علي هذا النحو , طالما ليس لها خيار أخر ( else خاصة بها ) .



ماذا نفعل لنجعل else ملحقة بـ if الأصلية ؟ ببساطة , نحيط الشرط الثاني وموضوعة بقوسين علي هيئة كتلة مستقلة , علي النحو التالي :



If (a==b)



{



( (b==c if



Cout << ''a, b and c are the same'';



}



Else



Cout << ''a, b and c are different'';



}



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



الصيغة else … if



في برنامج adifelse.cpp حدث أكثر من تداخل في عبارات if … else بصورة قد تكون مرهقة في التتبع , ومن الممكن إعادة صياغة باستخدام صيغة else…if التي تلاحظها في البرنامج التالي , وهو تعديل للأول ليكون علي الصيغة الجديدة .



Adelseif.cpp








adelseif.cpp


 


// adelseif.cpp


// demonstrates ELSE...IF with adventure program


#include <iostream.h>


#include <conio.h>     // for getche()


 


void main()


   {


   char dir='a';


   int x=10, y=10;


 


   cout << "Type Enter to quit\n";


   while( dir != '\r' )         // until Enter is typed


      {


      cout << "\nYour location is " << x << ", " << y;


      cout << "\nPress direction key (n, s, e, w): ";


      dir = getche();           // get character


      if( dir=='n')             // go north


     y--;


      else if( dir=='s' )       // go south


     y++;


      else if( dir=='e' )       // go east


     x++;


      else if( dir=='w' )       // go west


     x--;


      }  // end while


   }  // end main


ولا يجد محول الصياغة فرقا بين الصياغتين , حيث كما قدمنا لا يهتم بالفراغات . وتلاحظ أن البرنامج يسير متسلسلا مع عبارات


else…if بصورة تجعل الصياغة أكثر رشاقة وسهولة في التتبع .

التسميات: