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