الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

++c ... المحاضرة ( 9 )

مغلق
بدأه BjarneStudent في 28 ديسمبر 2007 · 13 رد · 6,977 مشاهدة · في قسم المواضيع الهامة في قسم السي /سي++
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

بسم الله الرحمن الرحيم

احب ان اشير هنا أن كل ما تعلمنا وما سوف نتعلمة من عبارات التحكم ( أو قطع بناء البرنامج ) هو من أجل توجيه الكائن للقيام بعمل ( أو اعمال )

محدد. نحن ندرس أفكار وتقنيات , وفي النهاية نغلفها ( نكبسلها ) على شكل اصناف ( classes ) لكي نواكب البرمجة الحديثة التي تعطينا الجودة

والأداء.

في هذه المحاضرة سوف نستأنف مواضيعنا في البرمجة الهيكلية بشرح عبارات التحكم المتبقية وهي for , do .. while , switch

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

في نهاية المحاضرة سوف ننتهي من الفصل الخامس وسوف نتناول المواضيع التالية :

1- أساسيات التكرار المحدد.

2- عبارة التكرار for.

3- أمثلة على استخدام العبارة for.

4- عبارة التكرار do .. while.

5- عبارة الإختيار المتعددة switch.

6- عبارة break وعبارة continue.

7- العمليات المنطقية.

8- مالذي يحدث عند الخلط بين المقارنة ( == ) وعملية الإسناد ( = ) ؟

بسم الله وبه نستعين.

أساسيات تكرار العداد المحدد

قبل الشروع في شرح العبارات الثلاث المتبقية , نرجع لعبارة الـ while ونوضح بعض

الأمور الأساسية في أي تكرار محدد بعداد ( متغير تحكم ). نأخذ الكود الصغير التالي :

الكود 5.1

1 // Fig. 5.1: fig05_01.cpp
2 // Counter-controlled repetition.
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6
7 int main()
8 {
9 int counter = 1; // declare and initialize control variable
10
11 while ( counter <= 10 ) // loop-continuation condition
12 {
13 cout << counter << " ";
14 counter++; // increment control variable by 1
15 } // end while
16
17 cout << endl; // output a newline
18 return 0; // successful termination
19 } // end main

هذا الكود يقوم بطباعة الأعداد من 1 إلى 10 على سطر واحد.

كما تلاحظون قمنا بالإعلان عن متغير التحكم في السطر 9 وفي نفس الوقت أعطيناه قيمة أولية وهي الـ 1. في السطر 14 تلاحظون

أن مقدار الزيادة هي +1 في كل مرة , وبدايتها تكون بعد أول مقارنة, وفي مرة نقارن الشرط ( سطر 11 ) سوف نقوم بالزيادة بعدها

إلى أن يصبح متغير التحكم قد فاق الـ 10 وعندها سوف يخرج من التكرار لأنه نافى الشرط.

يمكن أن نقصر من طول الكود ونجعله اكثر وضوح لو قمنا بإعطاء قيمة اولية لمتغير التحكم هي الصفر بدلا من الواحد , وتصبح الشرط

كالتالي :

while ( ++counter <= 10 ) 
cout << counter << " ";

وبهذه الطريقة استغنينا عن الأقواس وبسطنا البرنامج واستغنينا عن

الكثافة الزائدة.

إذن نخلص من هذا كله أن تكرار العداد المحدد يتطلب الآتي :

1- اسم متغير التحكم ( عداد التكرار ).

2- قيمة أولية لمتغير التحكم.

3- شرط استمرارية حلقة التكرار الذي يختبر القيمة النهائية لمتغير التحكم.

4- المزودة أو المنقصة لتحريك عجلة التكرار .

خطأ برمجي شائع : تعريف متغير التحكم من نوع float أو double بحيث من الممكن أن يحتوي على فواصل عشرية تؤدي إلى اختبارات

غير دقيقة.

لممارسة البرمجة بشكل جيد : لعدم تعقيد البرنامج احرص على عدد زيادة حلقات التكرار عن ثلاثة مستويات , واحرص على الفراغات الأفقية

والعمودية اثناء كل حلقة

عبارة التكرار for

بعد توضيح اساسيات التكرار المحدد في الموضوع السابق , يمكن إعادة كتابة الكود السابق لتوضيح فكرة عبارة التكرار for كالتالي :

الكود 5.2

1 // Fig. 5.2: fig05_02.cpp
2 // Counter-controlled repetition with the for statement.
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6
7 int main()
8 {
9 // for statement header includes initialization, 
10 // loop-continuation condition and increment. 
11 for ( int counter = 1; counter <= 10; counter++ )
12 cout << counter << " "; 
13
14 cout << endl; // output a newline
15 return 0; // indicate successful termination
16 } // end main

يبدأ التنفيذ لعبارة الـ for ( السطور 11- 12 ) حيث يتم الإعلان عن متغير التحكم خلال العبارة وأيضا اعطائه قيمة اولية , بعدها يأتي

شرط استمرارية التكرار counter <= 10 حيث يتم اختباره. اذا تحقق الشرط سوف يتم طباعة قيمة العداد ( السطر 12 ).

التالي هو زيادة القيمة counter بواحد ( وذلك في عبارة التكرار نفسها ) , عندما سوف يكون قيمة متغير التحكم تساوي 2 ومن ثم

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

مكونات سطر التعريف للعبارة for ( ترويسة العبارة ):

post-133999-1198869250_thumb.jpg

في الشكل السابق , هذا كل مافي هذه العبارة ( كل ما يحتاجة العداد ).

تخيل أننا نيسينا وضع علامة التساوي في الشرط ليصبح بهذا الشكل counter < 10 . بذلك سوف يتم تنفيذ العبارة تسع مرات فقط

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

وهو خطأ شائع في أوساط المبرمجين الجدد.

لترسيخ شكل عبارة التكرار for , يمكن كتابة الشكل العام لها كالتالي :

( عبارة الزيادة ; شرط استمرارية التكرار ; القيمة الأولية للعداد ) for

يمكن أن نمثل عبارة الـ for بعبارة الـ while كالتالي :

( شرط استمرارية التكرار ) while

}

;العبارة المراد تنفيذها

; علمية الزيادة

{

التمثيل السابق له استثناء , وذلك عند استخدام عبارة الـ continue , وسوف نتناول ذلك في ذلك الموضوع بعد قليل.

خطأ برمجي شائع : إذا تم الإعلان عن متغير التحكم داخل عبارة الـ for فإنه من الخطأ استخدامة خارج جسم الـ for.

عملية الفاصلة المنقوطة في عبارة الـ for تفصل قائمة التعابير فيها , بحيث يكون كل تعبير مستقل. وكل قسم يمكن ان يحتوي

عدة متغيرات , بدلا من متغير واحد ( كما في مثالنا السابق ).

نعم , نستطيع ترك عبارة الـ for خالية تماما ( يكون مابين القوسين فاضي ) , حيث يعتبرة المترجم صحيح , ويمكن ايضا التعبير

عن عداد التكرار ( متغير التحكم ) بأي من الأشكال التالي :

counter = counter + 1

counter += 1

++counter

counter++

جيمع التعبيرات السابقة لها نفس العمل.

خطأ برمجي شائع : وضع الفاصلة بدل الفاصلة المنقوطة يولد خطا نصي ووضع فاصلة منقوطة بعد العبارة مباشرة يجعل العبارة

فارغة ويفصل جسم التكرار عن عبارة التكرار وينتج خطأ منطقي يؤدي إلى نتائج خاطئة.

فكرة مفيدة في هندسة البرمجيات : وضع فاصلة منقوطة بعد عبارة الفور يستخدم دائما المبرمجين لكي يأخرو طور النتائج على الشاشة

لكي يمكن المستخدم من القراءة. ومدة التأخير تختلف من نظام لآخر حسب سرعة كل نظام.

القيمة الأولي , وشرط استمرارية التكرار وتعبير الزيادة , يمكن كل تلك التعبيرات ان تحتوي على عبارات حسابية , لنأخذ مثالا على ذلك :

اذا افترضنا التالي , x= 2 وَ y= 10 وَ x,y لا يتم عليها التعديل خلال جسم التكرار. فإن :

( for ( int j=x ; j <=4*x*y;j+=y/x

تساوي

( for ( int j=2; j<=80;j+=5

ليس شرطا أن تكون العملية دائما في تسيير عجلة التكرار أن تكون عملية الجمع , بل يمكن استخدام عملية الطرح .

تمثيل مخطط الحركة للعبارة for بالـ UML:

post-133999-1198869260_thumb.jpg

يمكنك مقارنته بالـ UML لعبارة التكرار while واستنتاج الفوارق.

أمثلة على استخدام عبارة الـ for

نعرض فيما يلي طرق مختلفة للتعبير عن متغير التحكم , وأشكال استخدامة , لاحظ التعبيرات الحسابية في كل ترويسة .

( أ ) يتفاوت متغير التحكم من 1 إلى 100 بزيادة واحدة كل مرة.

for ( int i= 1 ; i<= 100 ; i++ )

( ب ) يتفاوت من 100 إلى 1 في كل مرة يزيد بـ -1 ( تقنيص 1 )

for ( int i = 100 ; i>= 1 ; i-- )

( ج ) يتفاوت من 7 إلى 77 , في كل خطوة ننقص بمقدار 7 .

for ( int i = 7 i <= 77 ; i+= 7 )

( د ) من 20 إلى 2 ( في كل خطوة ننقص بمقدار -2 )

for ( int i = 20 ; i>= 2 ; i-=2 )

( ه ) يتفاوت خلال سلسلة من القيم وهي 2و 17 و 14 و 11 :

for ( int i = 2 ; i<= 20 ; i+=3 )

( و ) يتفاوت خلال السلسلة 0و 11 و 22 و 44 ... :

for ( int i= 99; i>=0 ; i-=11 )

مثال تطبيقي ( جمع الأعداد الزوجية من 2 إلى 20 ) :

سوف نأخذ مثالين نطبق فيهما عبارة الـ for , المثال التالي يتم جمع الأعداد الموجبة من 2 إلى 20

الكود 5.5

1 // Fig. 5.5: fig05_05.cpp
2 // Summing integers with the for statement.
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6
7 int main()
8 {
9 int total = 0; // initialize total
10
11 // total even integers from 2 through 20
12 for ( int number = 2; number <= 20; number += 2 )
13 total += number; 
14
15 cout << "Sum is " << total << endl; // display results
16 return 0; // successful termination
17 } // end main

وسوف تؤدي نفس الغرض

لممارسة البرمجة بشكل جيد : فكرة الدمج السابقة بالرغم من صحتها إلى أنها تصعب قراءة البرنامج وصيانته وتطويره. لذلك ينصح دائما أن

نجعل الترويسة سطر واحد فقط.

تطبيق حسابات الربح المركبه :

المثال التالي يحسب حسابات الربح المركبه بإستخدام عبارة فور , اعتبر أن لدينا المشكلة التلاي :

شخص ربح 100 ريال في حساب يغطي 5% فائدة . افترض أن كل الفائدة حسبت على المبلغ المودع في الحساب, احسب واطبع مقدار النقود في الحساب عند نهاية كل

سنة لعشر سنين. استخدم المعادلة التالية لتحديد هذا المقدار :

a = p ( 1 + r ) n حيث :

p : المقدار الأصل المستفاد ( مثلا الاساسي ).

r : معدل الربح السنوي.

n : عدد السنين.

a : المبلغ في التوديع عند نهاية السنة المعنية.

هذه المهمة تكلف حلقة التكرار أن تؤدي عملية الحساب المشار إليها لكل 10 سنين على النقود المتبقية في الإيداع . الكود كالتالي :

كود5.6

1 // Fig. 5.6: fig05_06.cpp
2 // Compound interest calculations with for.
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6 using std::fixed;
7
8 #include <iomanip>
9 using std::setw; // enables program to set a field width
10 using std::setprecision;
11
12 #include <cmath> // standard C++ math library 
13 using std::pow; // enables program to use function pow
14
15 int main()
16 {
17 double amount; // amount on deposit at end of each year
18 double principal = 1000.0; // initial amount before interest
19 double rate = .05; // interest rate
20
21 // display headers
22 cout << "Year" << setw( 21 ) << "Amount on deposit" << endl;
23
24 // set floating-point number format
25 cout << fixed << setprecision( 2 );
26
27 // calculate amount on deposit for each of ten years 
28 for ( int year = 1; year <= 10; year++ ) 
29 { 
30 // calculate new amount for specified year 
31 amount = principal * pow( 1.0 + rate, year ); 
32 
33 // display the year and the amount 
34 cout << setw( 4 ) << year << setw( 21 ) << amount << endl;
35 } // end for 
36
37 return 0; // indicate successful termination
38 } // end main

عبارة الـ for ( السطر 28-53 ) تنفذ جسمها 10 مرات , يختلف متغير التحكم من 1 إلى 10 في زيادة مقدارها 1.

المكتبة القياسية لا تحتوي على عملية الأس , لذلك استخدمنا مكتبة اخرى تمكننا ( المكتبة < cmath > ) من استخدام الدالة pow على

الشكل التالي ( pow ( x, y والتي تتمثل في التعبير التالي المستخدم في البرنامج ( pow ( 1.0 + rate, year حيث المتغير rate يمثل

الـ r ومتغير السنة يمثل الـ n وهما قيمتين من نوع double.

خطأ برمجي شائع : نسيات إلحاق ملفات الترويسة المناسبة للبرنامج ولد خطأ عند الترجمة.

تحذير حول استخدام النوع double للمبالغ المالية :

لاحظ ذلك أن السطور( 17-19 ) تعلن عن المتغير amount و principal و rate على أهم أعداد حقيقية فعندما نقوم بجمع عددين

مثل 18.673 و 14.234 ليعطو العدد 32.967 والمطبوع 32.91 فهذا العدد كما تلاحظون غير دقيق في الإستخدامات المالي.

استخدام معاملات سيل الإخراج لتشكيل الإخراج الرقمي :

برنامجنا السابق يخرج لنا المخرجات التالية

Year	Amount on deposit
	1			  1050.00
	2			  1102.50
	3			  1157.63
	4			  1215.51
	5			  1276.28
	6			  1340.10
	7			  1407.10
	8			  1477.46
	9			  1551.33
   10			  1628.89

كما تلاحظون لدينا دالة جديدة وهي set ( 4 ) السطور 22و 34 حيث تقوم بتنسيق العدد بمحاذاته لأقصى اليمين.

من المخرجات أيضا , تلاحظون استخدامنا لعبارة التنسيق في السطر 25 قبل حلقة التكرار يؤدي إلى تطبيق هذه العبارة على جميع

المخرجات , وهذا يسمى تثبيت الإعداد.

فكرة مفيدة في الأداء : ك تجنب وضع تعبير ثابت مثل الذي بالسطر 31 ( rate + 1.0 ) حيث ينفذ في كلة مرة نفس عملية

الجمع. ومن الأفضل وصفة مرة واحدة خارج التكرار.

عبارة التكرار do ... while

تختلف هذه العبارة عن العبارة while بترتيب تنفيذ جسمها, ففي هذه العبارة يتم تنفيذ جسم العبارة أولا ومن ثم اجراء المقارنة

بعكس عملية الـ while التي تتم فيها عملية المقارنة أولا ثم تنفيذ جسم التكرار.

إذا عبارة الـ do .. while يتم تنفيذ جسمها مرة واحدة على الأقل , بعكس الآخرى التي من الممن ألا ينفذ جسمها ولا مرة.

الشكل العام لهذه العبارة كالتالي :

do { statemetn } while ( condtion )

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

تطبيق على ذلك :

كود 5.7

1 // Fig. 5.7: fig05_07.cpp
2 // do...while repetition statement.
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6
7 int main()
8 {
9 int counter = 1; // initialize counter
10
11 do 
12 { 
13 cout << counter << " "; // display counter
14 counter++; // increment counter 
15 } while ( counter <= 10 ); // end do...while 
16
17 cout << endl; // output a newline
18 return 0; // indicate successful termination
19 } // end main

الـ UML لمخطط حركة عبارdo .. while :

post-133999-1198869268_thumb.jpg

يمكن مقارنة بالـ UML للـ while.

عبارة الأختيار المتعددة switch

بالإضافة إلى عبارة if المفردة و if .. else المزدوجة , السي++ تعطي عبارة اختيار اخرى , تسمى عبارة الإختيار المتعدد switch.

هذه العبارة تختبر عدة شروط وتقوم بتنفيذ عدة اجراءات بناءً على نتيجة تحقق الشرط ( متغير أو تعبير ). كل شرط يسمى حالة , ويسمى السطر

( :case expression ) شريط.

صنف GradeBook مع العبارة switch لحساب درجات كل معدل :

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

الصنف تطلب من المستخدم أن يدخل مجموعة حروف ( تمثل تقديرات - معدلات - الطلاب ) وتعرض عدد الطلاب لكل معدل. الصنف يحدد

ما أذا كان التقدير المدخل هو الـ A أو الـ B أو الـ C أو الـ D أو الـ F. حيث يقوم بزيادة العداد بواحد كل مرة لكل تقدير اذا تحققت

احد الحالات ( الشروط ) في عبارة الـ switch.

الصنف معرف في الكود 5.9 , حيث يحتوي هذا الكود على توصيفات أولية لدوال الأعضاء تظهر تعاريفها في الكود 5.10. والكود 5.11 يقوم بتشغيل

بتعريف كائن وتشغيل واستعراض امكاناته.

الكود 5.9

1 // Fig. 5.9: GradeBook.h
2 // Definition of class GradeBook that counts A, B, C, D and F grades.
3 // Member functions are defined in GradeBook.cpp
4
5 #include <string> // program uses C++ standard string class
6 using std::string;
7
8 // GradeBook class definition
9 class GradeBook
10 {
11 public:
12 GradeBook( string ); // constructor initializes course name
13 void setCourseName( string ); // function to set the course name
14 string getCourseName(); // function to retrieve the course name
15 void displayMessage(); // display a welcome message
16 void inputGrades(); // input arbitrary number of grades from user 
17 void displayGradeReport(); // display a report based on the grades
18 private:
19 string courseName; // course name for this GradeBook
20 int aCount; // count of A grades
21 int bCount; // count of B grades
22 int cCount; // count of C grades
23 int dCount; // count of D grades
24 int fCount; // count of F grades
25 }; // end class GradeBook

الكود 5.10

1 // Fig. 5.10: GradeBook.cpp
2 // Member-function definitions for class GradeBook that
3 // uses a switch statement to count A, B, C, D and F grades.
4 #include <iostream>
5 using std::cout;
6 using std::cin;
7 using std::endl;
8
9 #include "GradeBook.h" // include definition of class GradeBook
10
11 // constructor initializes courseName with string supplied as argument;
12 // initializes counter data members to 0
13 GradeBook::GradeBook( string name )
14 {
15 setCourseName( name ); // validate and store courseName
16 aCount = 0; // initialize count of A grades to 0
17 bCount = 0; // initialize count of B grades to 0
18 cCount = 0; // initialize count of C grades to 0
19 dCount = 0; // initialize count of D grades to 0
20 fCount = 0; // initialize count of F grades to 0
21 } // end GradeBook constructor
22
23 // function to set the course name; limits name to 25 or fewer characters
24 void GradeBook::setCourseName( string name )
25 {
26 if ( name.length() <= 25 ) // if name has 25 or fewer characters
27 courseName = name; // store the course name in the object
28 else // if name is longer than 25 characters
29 { // set courseName to first 25 characters of parameter name
30 courseName = name.substr( 0, 25 ); // select first 25 characters
31 cout << "Name \"" << name << "\" exceeds maximum length (25).\n"
32 << "Limiting courseName to first 25 characters.\n" << endl;
33 } // end if...else
34 } // end function setCourseName
35
36 // function to retrieve the course name
37 string GradeBook::getCourseName()
38 {
39 return courseName;
40 } // end function getCourseName
41
42 // display a welcome message to the GradeBook user
43 void GradeBook::displayMessage()
44 {
45 // this statement calls getCourseName to get the
46 // name of the course this GradeBook represents
47 cout << "Welcome to the grade book for\n" << getCourseName() << "!\n"
48 << endl;
49 } // end function displayMessage
50
51 // input arbitrary number of grades from user; update grade counter
52 void GradeBook::inputGrades()
53 {
54 int grade; // grade entered by user
55
56 cout << "Enter the letter grades." << endl
57 << "Enter the EOF character to end input." << endl;
58
59 // loop until user types end-of-file key sequence
60 while ( ( grade = cin.get() ) != EOF )
61 {
62 // determine which grade was entered 
63 switch ( grade ) // switch statement nested in while
64 { 
65 case 'A': // grade was uppercase A 
66 case 'a': // or lowercase a 
67 aCount++; // increment aCount 
68 break; // necessary to exit switch 
69 
70 case 'B': // grade was uppercase B 
71 case 'b': // or lowercase b 
72 bCount++; // increment bCount 
73 break; // exit switch 
74 
75 case 'C': // grade was uppercase C 
76 case 'c': // or lowercase c 
77 cCount++; // increment cCount 
78 break; // exit switch 
79 
80 case 'D': // grade was uppercase D 
81 case 'd': // or lowercase d 
82 dCount++; // increment dCount 
83 break; // exit switch 
84 
85 case 'F': // grade was uppercase F 
86 case 'f': // or lowercase f 
87 fCount++; // increment fCount 
88 break; // exit switch 
89 
90 case '\n': // ignore newlines, 
91 case '\t': // tabs, 
92 case ' ': // and spaces in input 
93 break; // exit switch 
94 
95 default: // catch all other characters 
96 cout << "Incorrect letter grade entered." 
97 << " Enter a new grade." << endl; 
98 break; // optional; will exit switch anyway 
99 } // end switch 
100 } // end while
101 } // end function inputGrades
102
103 // display a report based on the grades entered by user
104 void GradeBook::displayGradeReport()
105 {
106 // output summary of results
107 cout << "\n\nNumber of students who received each letter grade:"
108 << "\nA: " << aCount // display number of A grades
109 << "\nB: " << bCount // display number of B grades
110 << "\nC: " << cCount // display number of C grades
111 << "\nD: " << dCount // display number of D grades
112 << "\nF: " << fCount // display number of F grades
113 << endl;
114 } // end function displayGradeReport

الكود 5.11

1 // Fig. 5.11: fig05_11.cpp
2 // Create GradeBook object, input grades and display grade report.
3
4 #include "GradeBook.h" // include definition of class GradeBook
5
6 int main()
7 {
8 // create GradeBook object
9 GradeBook myGradeBook( "CS101 C++ Programming" );
10
11 myGradeBook.displayMessage(); // display welcome message
12 myGradeBook.inputGrades(); // read grades from user 
13 myGradeBook.displayGradeReport(); // display report based on grades
14 return 0; // indicate successful termination
15 } // end main

كما تشاهدون في الكود5.9 , حيث يحتوي الصنف على توصيفات أولية لدوال الأعضاء . في السطر 13 نشاهد دالة الأعضاء setCourseName

وفي السطر 14 نشاهد الـ getCouseName وفي السطر 15 نشاهد displayMessage وبقية القائمة بالإضافة إلى الباني.

أما في قسم الأعضاء فنشاهد خمسة أعضاء بيانات محددة الوصول.

الجديد في أعضاء البيانات يوجد في السطور 20 إلى 24, وهي متغيرات تمثل عدادات لكل تقدير.

اما الجديد في دوال الأعضاء هما الدالتين في السطرين 16 و 17 من الكود 5.9.

في دالة العضو inputGrades ( الكود 5.10 السطور 51-101 ) يتم قراءة عدد محدد من الحروف تمثل معدلات درجات الطلاب

هذه القراءة تتم ضمن حلقة التكرار while المحدده بحارس يتم إدخالة من قبل المستخدم.

في دالة العضو displayGradeReport ( الكود 5.10 السطرو 104-114 ) يتم عرض عدد الطلاب لكل تقدير.

في دالة العضو inputGrades , في كل دورة من دورات الـ while يتم ادخال حرف وبعد ذلك يتم اختبارة في بقية الأسطر.

نحن نعرف أن القيمة هي حرف , بالتالي هي عبارة عن رمز character, ومن خلال هاتين المعلومتين نعرف ان نوع المدخل هو

char.

لاحظو معي في السطر 60 , يتم أولا تنفيذ ()cin.get ومن ثم إسنادها إلى grade ومن ثم المقارنة بـ EOF.

الـ ()cin.get هي دالة عضو في الكائن cin الموجود ضمن المكتبة القياسية < iostream > وتستخدم للحصول على

رمز معين من المستخدم عن طريق لوحة المفاتيح. واستخدمناها هنا للحصول على الحرف الذي يمثل تقدير الدرجة.

نحن أعلنا عن المتغير grade في السطر 54 على أنه عدد صحيح , ثم قمنا بإسناد حرف إليه .. كيف ؟!!

الجواب هو , أن الحرف يمكن تمثيله بقيمة عدد صحيح int , ويمكن تمثيله برمز char, على سبيل المثال, العبارة التالية :

cout << "The character (" << 'a' << ") has the value "<BR> << static_cast< int > ( 'a' ) << endl;

تطبع الرمز وقيمته الصحيحة كالتالي :

The character (a) has the value 97

إذا , العدد 97 تمثيل للرمز 'a' في الكمبيوتر. معظم الكمبيوترات اليوم تستخدم مجموعة

الرموز ( ASCII ( Amercan StandArd Code for Information Interchange - الكود القياسي الأمريكي

لتبادل المعلومات - الذي فيه تمثيلنا هذا ( 9 = ' a ' ) , قائمة الرموز وتمثيلاتهم الرقمية يمكن تمثيلهم وفق نظام

الـ ASCII في الجدول التالي :

post-133999-1198869193_thumb.jpg

في دالة الـ inputGrades نحن قلنا بإننا سوف نقوم بإدخال عدد محدد من الرموز , ضمن حلقة تكرار محدد بالحارس. إذن , أين هو الحارس وكيف ؟

الحارس هو EOF وهو اختصار للجملة ( End Off File ) أي نهاية الملف. إذن كيف نقوم بإدخال هذه الحروف , هل ندخل E ثم O ثم F ؟

الجواب هو لا , ليس من هذا كله , حيث هذا الرمز معرف في كل نظام بشكل مختلف عن النظام الآخر , بحيث يمكن تمثيله في الويندوز بالإختصار ctrl+z

أما في اللينكس واليونيكس ctrl+d وهو عبارة عن عدد رمزي ثابت معرف في الترويسة < iostream >. وعند الضغط على هذا الإختصار سوف يتمثل

في على الشاشة z^ ( في نظام ويندوز ).

خلاصة ما تقدم , يقوم المستخدم بإدخال حروف الدرجات من لوحة المفاتيح , حرف واحد كل مرة , حيث يقرأ الحرف من لوحة المفاتيح عن طريق دالة العضو

()cin.get ومن ثم الضغط على مفتاح enter حيث يختبر هل الرمز يساوي EOF وعندما يتحقق الشرط ندخل في عبارة الـ switch ( السطور 63-99)

حيث يتم زيادة عداد كل درجة , وعندما نريد أن ننهي سلسلة ادخال حروف التقدير سوف نضغط على ctrl+z ثم enter من لوحة المفاتيح.

تفاصيل عبارة switch:

عندما ننظر إلى عبارة switch نرى عدة مجموعات تبدأ بتعبير التحكم ( السطر 63) وتنتهي بالحالة الإفتراضية ( default ) , وهذا هو الشكل الغالب للعبارة.

المجموعات تسمى حالات , والتعبير عن كل حالة بعبارة شريط ( label ), وهي كلمة case وبعد فراغ ومن ثم التعبير أو المتغير ثم نقطتين فوق بعض.

في كل مجموعة سوف يتم تنفيذ معين ( على سبيل المثال السطر 73 ) , ويمكن أن ندرس أكثر من شرط وننفذ أكثر من أجراء في كل مجموعة.

في مثالنا هذا ( الكود 5.10 السطور 62-99 ) متغير التحكم هو grade حيث هو من يتم مقارنته في كل حالة ( case ).

في الدورة الأولى , ندخل الحرف , ثم يأتي التنفيذ عن عبارة switch حيث يتم مقارنة الحرف المدخل في كل حالة , فعندنا يكتب في الكود : 'case 'a

فإن هذا يعني , ان هل قيمة المتغير grade تساوي قيمة الحرف السابق , فإذا تحقق ذلك سوف يقوم بزيادة المتغير aCount بواحد, مع ملاحظة أنه لا يوجد مقارنة

واحدة في مجموعتنا هذه , أيضا يوجد مقارنة ثانية وهي : 'case 'A , ويمكن قراءة المقارنتين كالتالي ( هل المتغير grade يساوي المتغير a أو A إذا تحقق

ذلك قم بزيادة العداد aCount بواحد ) , وهكذا على باقي المجموعات.

هناك عبارة بالغة الأهمية في العبارة switch وهي فكرتها واساسها , العبارة هي break. وهي التي تخرج التحكم من العبارة في حال تحقق احدى الحالات.

نحن قلنا انه إذا كان العدد المدخل هو الحرف a أو A فإننا نزيد العداد aCount بواحد , ثم ماذا بعد ؟!! بعد ذلك سوف نأتي للعبارة break لتخرجنا

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

لك رياضي يقفز الحواجز , واذا به يتعثر في أحدها ليخفق في المتبقية ).

نأتي إلى نهاية عبارة switch حيث العبارة default, هذه العبارة هي عبارة الإستثناء في السلسلة , حيث اذا لم تححق أي حالة من الحالات في العبارة switch

فسوف يتم تنفيذ مايلي هذه الكلمة من اجراءات.

خطأ برمجي شائع : نسيان عبارة break يولد خطأ منطقي.

خطأ برمجي شائع : تجاهل الفراغ بين كلمة case والقيمة المتكاملة يولد خطأ منطقي. مثلا , كتابة :case3 بدلا من :case 3, حيث تعتبر شريط

غير مستخدمفي الـ switch.

لممارسة البرمجة بشكل جيد : الـ default تساعد على ظم الإستثنائات الشرطية ويفضل وضعها في الأخير.

لممارسة البرمجة بشكل جيد : عبارة الـ default لا تحتاج العبارة break ولكنها توضع هنا لتماثل الكود.

مخطط الحركة الـ UML للعبارة switch:

post-133999-1198869203_thumb.jpg

نلاحظ وجود عبارة الـ break تعقب كل إجراء , وبعد هذه العبارة معين دمج وذلك من أجل الإنتقال إلى خارج الـ switch.

عبارة break وعبارة continue

بالإضافة إلى عبارات الأختيار والتكرار , السي++ تعطي عبارتي الـ break والـ continue لتبديل سير التحكم.

االموضوع السابق عرض كيف الـ break تنهي تنفيذ عبارة الـ switch, هذا الموضوع سوف يشرح كيف تستخدم هاتين

العبارتين في حلقات التكرار.

عبارة break :

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

العمليات ( أو العبارات ) للهروب مبكرا والتجاوز لما هو مهم وفعال ( وذلك كما رأينا في عبارة switch في الكود 5.10 ).

المثال التالي يوضح عمل العبارة break ,

كود 5.13

1 // Fig. 5.13: fig05_13.cpp
2 // break statement exiting a for statement.
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6
7 int main()
8 {
9 int count; // control variable also used after loop terminates
10
11 for ( count = 1; count <= 10; count++ ) // loop 10 times
12 {
13 if ( count == 5 ) 
14 break; // break loop only if x is 5
15
16 cout << count << " ";
17 } // end for
18
19 cout << "\nBroke out of loop at count = " << count << endl;
20 return 0; // indicate successful termination
21 } // end main

عندما تكتشف عبارة الـ if أن الـ count تساوي 5 , سوف تخرج مباشرة من التكرار for مباشرة ( تنقل إلى السطر 18 ).

وعندما تكون هناك عبارات تكرار متداخلة , فإن عمل عبارة break هو اخراج التنفيذ من عبارة التكرار الحالية , إلى عبارة التكرار

التي تليها ( تحتضن الحالية ).

عبارة continue :

هذه العبارة تلغى اجراءات معينة خلال دورة معينة , اي تقوم بالقفز للدورة التالية دون إكمال مايليها.

سوف نأخذ المثال التالي للتوضيح أكثر ,

كود 5.14

1 // Fig. 5.14: fig05_14.cpp
2 // continue statement terminating an iteration of a for statement.
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6
7 int main()
8 {
9 for ( int count = 1; count <= 10; count++ ) // loop 10 times
10 {
11 if ( count == 5 ) // if count is 5,
12 continue; // skip remaining code in loop
13
14 cout << count << " ";
15 } // end for
16
17 cout << "\nUsed continue to skip printing 5" << endl;
18 return 0; // indicate successful termination
19 } // end main

كما تشاهدون في مخرجات البرنامج , فإن العدد 5 لم تتم طباعته في سطر الأعداد المطبوع , حيث قامت عبارة continue للقفز للعد التالي.

العمليات المنطقية

كل ما تم شرحة حتى الان هي الشروط البسيطة مثل counter <= 10 , total > 1000 , number != sentinel .

فقط اكتفينا بالعمليات العلائقة ( < , > , == , =! ) , وكما تلاحظون في الأكواد السابقة. ولمزيد من المرونه في التحكم سوف نتناول طرق

جديدة في المقارنة , للحصول على المزيد من الطرق التي توفر لنا المزيد من المرونه والدقة لكتابة اكود دقيقة وبسيطة وسريعة ( في التنفيذ ).

توفر لنا السي++ العمليات المنطقة التالي :

العملية المنطقة AND ( && ) :

عندما يكون لدينا مجموعة بيانات ( تقارير ) ونريد أن نتحقق من صحتها , فكيف لنا أن نتأكد من صحة

شرطين أو أكثر . بالطبع سوف نضطر لإستخدام احدى العمليات المنطقية التي تتأكد من صحة مجموعة

من المقارنات مجتمعة , هذه العبارة ( AND ) تتحق من شرطين , فإذا كان صحيحين فإنها تعطي

نتيجة صحية , وغير ذلك سوف تعطينا نتيجة خاطئة.

الجدول التالي يختصر نتائج المقارنات المحتملة

post-133999-1198869213_thumb.jpg

العبارة المنطقية OR ( || ) :

عندما يكون لدينا مجموعة بيانات ( تقارير ) ونريد أن نتحقق من صحتها , فكيف لنا أن نتأكد من صحة

شرطين أو أكثر . بالطبع سوف نضطر لإستخدام احدى العمليات المنطقية التي تتأكد من صحة مجموعة

من المقارنات مجتمعة , هذه العبارة ( OR ) تتحق من شرطين , فإذا كان خاطئين فإنها تعطي

نتيجة خاطئة , وغير ذلك سوف تعطينا نتيجة صحيحة.

الجدول التالي يختصر نتائج المقارنات المحتملة

post-133999-1198869223_thumb.jpg

العملية المنطقية NOT ( ! ) :

تعكس النتيجة , من خاطئة لصائبة والعكس.

الجدول التالي يختصر نتائج المقارنات المحتملة

post-133999-1198869231_thumb.jpg

مثال على العمليات المنطقية :

كود 5.18

1 // Fig. 5.18: fig05_18.cpp
2 // Logical operators.
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6 using std::boolalpha; // causes bool values to print as "true" or "false"
7
8 int main()
9 {
10 // create truth table for && (logical AND) operator
11 cout << boolalpha << "Logical AND (&&)"
12 << "\nfalse && false: " << ( false && false )
13 << "\nfalse && true: " << ( false && true )
14 << "\ntrue && false: " << ( true && false )
15 << "\ntrue && true: " << ( true && true ) << "\n\n";
16
17 // create truth table for || (logical OR) operator
18 cout << "Logical OR (||)"
19 << "\nfalse || false: " << ( false || false )
20 << "\nfalse || true: " << ( false || true )
21 << "\ntrue || false: " << ( true || false )
22 << "\ntrue || true: " << ( true || true ) << "\n\n";
23
24 // create truth table for ! (logical negation) operator
25 cout << "Logical NOT (!)"
26 << "\n!false: " << ( !false )
27 << "\n!true: " << ( !true ) << endl;
28 return 0; // indicate successful termination
29 } // end main

الجديد الملاحظ في هذا الكود , استخداما boolalpha من مساحة الأسماء std كما هو واضح في السطر 5 والسطر 11.

وأداة الإخراج هذه تقوم بإستبدال نتائج المقارنات بالكلمات true أو false بدلا من الـصفر والواحد كنتائج للمقارنات المنطقية.

استخدمت في السطر 11 , وسرى تأثيرها على كل عمليات الإخراج التي تليها.

ملخص اسبقية وترابطية العمليات :

عند تطبيقنا للعميلة , فإن الأولويات والترابطيات بين التعابير الحسابية تكون وفق التالي :

post-133999-1198869241_thumb.jpg

مالذي يحدث عند الخلط بين المقارنة ( == ) وعملية الإسناد ( = ) ؟

عندما نريد أن نستخدم ( == ) ونخطيء ونستخدم ( = ) , في عملية المقارنة , كالتالي :

[if ( payCode = 4 ) cout << " you get bonus " ;

النتيجة , لن يحدث خطأ نصي يعيق تنفيذ البرنامج , بل يحدث خطأ منطقي !!

مايحدث هو أن نتيجة الشرط سوف تكون صحيحة وعبارة الشرط سوف تنفذ

في كل الأحوال.

وهناك شي آخر سوف يحدث , عملية اسناد القيمة 4 إلى المتغير payCode.

عندما نريد أن نستخدم ( = ) ونخطيء ونستخدم ( == ) , في عملية الإسناد , كالتالي :

بدلا من أن نكتب

;x= 1

نكتب

;x == 1

أيضا لا يحدث شي !!

كل ما يحدث , ان تتم عملية المقارنة, ونحصل على النتيجة , وعند تجاوز التنفيذ للسطر , تضيع قيمة المقارنة وكأن شيئا ً لم يحدث.

بما أن هذه الأخطاء لا تنتج رسائل أخطاء عند الترجمة كي ينتبه المبرمج لذلك , مالذي يجب فعله لتجنب هذه الأخطاء ؟ ( هذا سؤال موجه لكم )

انتهت المحاضرة

exercises.zip

تم تعديل هذه المشاركة بواسطة BjarneStudent في 29 ديسمبر 2007 في 21:09

1

وليس يبني العلا الا نديٌ ووغى , همـا المعارج للأسنى من الرتب

#2

اذا هناك من ملاحظة على تنسيق نص المحاضرة , فأرجو المعذرة , فأسعود لتحسين التنسيق في الغد ان شاء الله , فقد استنفذت كل الوقت على تنسيقها ولم افلح , ولا اعلم اين الخلل

بالنسبة للتمارين , سوف اضعها غدا

والقادم أفضل بإذن الله.

وليس يبني العلا الا نديٌ ووغى , همـا المعارج للأسنى من الرتب

#3

بارك الله فيك وزادك من علمه في انتظار التمارين.

tvquran_6.gif

#4

لو سمحت نقطتين فقط تحتاج الى ايضاح بسيط :

نستطيع ترك عبارة الـ for خالية تماما ( يكون مابين القوسين فاضي ) , حيث يعتبرة المترجم صحيح

كيف اعرف بدايتها ونهايتها والمتغير؟

وضع فاصلة منقوطة بعد عبارة الفور يستخدم دائما المبرمجين لكي يأخرو طور النتائج على الشاشة

لكي يمكن المستخدم من القراءة

اين بالضبط؟

tvquran_6.gif

#5
اقتباس
دائما اتسال ما فائدة استخدام keyword break

فالهدف الاساسى منها اخراجى من الloop----لكن انا استطيع ان اخرج من الloop بتحقيق الشرط حيث اضع قيمة العداد بالقيمة النهائية بدلا من ان اضع كلمة لbreak;

اذا كنت اريد البحث في الذاكرة مثلا عن الـDWORD التي تحمل قيمة 500 من العنوان 0x70000000 الى العنوان 0x7FFFFFFF بنظام بايت بايت :

اذا سأقوم بعمل for من 70000000 الى 7FFFFFFF بزيادة واحد كل مرة ثم قراءة العنوان ثم تحقق عن طريق if ثم break اذا تساوت القيمة من 500 ولن نحتاج الى اكمال الـloop ... هكذا تتضح فائدة break

والسلا عليكم

mov eax, dword ptr ds:[0xffdf0308]

jmp dword ptr [eax+0xfc]

#6

السلام عليكم ورحمة الله وبركاته....

مشكور أخوي BjarneStudent ، مجهود موفق تشكر عليه....

المعذرة على التأخير ، لكن أستطيع - بمشيئة الله - اللحاق بكم ...

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

في كل الأحوال.

وهناك شي آخر سوف يحدث , عملية اسناد القيمة 4 إلى المتغير payCode.

طيب أخوي ماذا لو قلنا X=0 أعتقد أن الشرط هنا لا يتحقق...

لأنه وحسب علمي أنه بعد عملية الإسناد يكون إرجاع العملية هو القيمة المسندة....

(القيمة المرجعة من الدوال أو العمليات كما نعرف ليس من الضرورة أن يوجد من يستقبلها)

المهم في مثالي هذا وبعد ما أسند القيمة 0 للمتغير X ..... صار ناتج هذه العملية القيمة 0 والتي تلقفتها الـ if واعتبرتها على أنها false

مدري هل فهمي صحيح أخوي....

ننتظر تصحيحك وتصويبك لي أخي...

في النهاية قرأت حتى الآن فقط الدرسين الأوليين فهمت أشياء كثيرة وجديدة علي...

وأحب أن أشكرك وأقول:

الله ينفع بعلمك وييسر لك أمورك كلها ، ويكون في عونك أخي....

أجهدت نفسك ، لكن ستجد بمشيئة الله أن تعبك لم يضيع سدى...

هناك من سيستفيد من هذه الدورة لاحقاً وذلك لأن الكتاب يعتبر معتمد في أغلب الجامعات....

دمت في رعاية الله،،،

تم تعديل هذه المشاركة بواسطة العواجي في 29 ديسمبر 2007 في 10:55

موقع كلية الحاسب الآلي ونظم المعلومات.

WWW.UQUCS.COM

#7

السلام عليكم ورحمة الله وبركاته....

بعد أذنك أستاذي BjarneStudent ، أريد أن أجيب على استفسار الأخ arabi2013

اقتباس
كيف اعرف بدايتها ونهايتها والمتغير؟

ذلك ليس من الضروري يمكن أن ننفذ التكرار حتى حدوث شيء ما داخل التكرار ونخرج بواسطة break

ليس دائماً نعتمد على العدادات (المتغيرات).....

اقتباس
وضع فاصلة منقوطة بعد عبارة الفور يستخدم دائما المبرمجين لكي يأخرو طور النتائج على الشاشة

لكي يمكن المستخدم من القراءة

اين بالضبط؟

تكتب for(;;);قبل return 0; مباشرة

أستاذي dr_sara بل كلامك واضح جدأ....

لكن لسنا دائماً نكون محدودين بعدد أو قيمة معينه....

فمثلاً عندما نريد أن نجبر المستخدم على إدخال عدد يقع في مدى معين مثلاً أقل من10 نستخدم هذا الكود

int x=11;

while(x>10) cout<<{"\n Entere x:"	  cin>>x;}

أرجوا أن أكون قد قدمت ما يفيد....

دمتم في رعاية الله،،،

موقع كلية الحاسب الآلي ونظم المعلومات.

WWW.UQUCS.COM

#8

السلام عليكم ورحمة الله وبركاته

الأخ الكريم BjarneStudent

هل من الممكن تأجيل المحاضرة القادمة مدة أسبوعين فقط

لأن الأن فترة إمتحانات .

حتي لايفوتنا الكثر ونستطيع مرجعة ما سبق .

شكر لك وجزاك الله خير ونفع بك وبعلمك .

eteba3.png

(قل إن كنتم تحبون الله فاتبعوني يحببكم الله)

#9
arabi2013 كتب:
لو سمحت نقطتين فقط تحتاج الى ايضاح بسيط :

نستطيع ترك عبارة الـ for خالية تماما ( يكون مابين القوسين فاضي ) , حيث يعتبرة المترجم صحيح

كيف اعرف بدايتها ونهايتها والمتغير؟

وضع فاصلة منقوطة بعد عبارة الفور يستخدم دائما المبرمجين لكي يأخرو طور النتائج على الشاشة

لكي يمكن المستخدم من القراءة

اين بالضبط؟

كل النقاط سوف تشرح مره اخرى لو تريد .

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

for (;; ) { statement }

كي يتم تنفيذ هذه العبارة , لا يهم أن يكون لها بداية ونهاية ومتغير , حسب الغرض الموضوعة من أجله

سوف يتمت تنفيذ الكود إلى تمتليء الذاكرة المؤقته ( الكاش ميموري )

بالنسبة للسؤال الثاني , إذا أردنا تأخير التنفيذ من أجل اعطاء المستخدم فرصة كافية للقراءة

يمكن وضع بداية ونهاية للتكرار ووضع فاصلة منقوطة بعد الترويسة مباشرة, بالشكل التالي :

for ( int i = 0; i< 1000; i++ );

بهذه الطريقة , سوف يتأخر التنفيذ قدر من الزمن ( يعتمد الزمن على سرعة النظام ) , حتى تصل قيمة الـ i للألف.

dr_sara كتب:
السلام عليكم ورحمة الله وبركاتة

واضح ان حضراتكم لم تفهمونى

فى اى عملية تكرارية اذا اردت ان تخرج منها كل ما عليك ان تضع قيمة العداد بالقيمة النهائية

اسال هل break==the for loop or any loop is terminated which mean we can think the counter is reach to end

e

فمثلا اخى الفاضل حضرتك قلت-- اذا سأقوم بعمل for من 70000000 الى 7FFFFFFF بزيادة واحد كل مرة ثم قراءة العنوان ثم تحقق عن طريق if ثم break

ما رايك لو بعد تحقق الشرط بدل وضع كلمة break ضع قيمة العداد للfor بالقيمة النهائية ايضا راح يخرج من اloop

لكن حضرتك عارف اية الفرق الذى ممكن يحصل ان اذا كان هناك عبارات اخرى بعد الcheck

اذا استخدمت الbreak لا يتم تنفيذها اما اذا استخدمت طريقتى سوف يتم تنفيذها ثم يخرج ايضا من الloop

ارجو اكون وضحت لكم شىء وتكونوا فهمتمونى

بالتوفيق ان شاء الله

لو افترضنا يا اخت سارة , اننا نريد أن نبحث عن الرمز ' * ' في مصفوفة رمزية , ونحن لا نعلم هل الرمز فعلا موجود أم لا

فإنه ينبغي علينا أن نضح احتياطات لإحتمال أن هذا الرمز غير موجود , واذا وجدناه فإننا سوف نخرج من السلسلة مباشرة

( او الخروج من التكرار ) لنستفيد من الزمن المتبقي.

اذا لدينا تكرار , مشروط بالوصول لنهاية السلسلة ( شرط الخروج هو الوصول لنهاية السلسلة ) , وأدرنا عبارة break

على أنها توقف التكرار عندما نجد الرمز ' * ' .

فائدة الـ break ؟

تخيلي أنك اشترطتي أن القيمة النهائية , عندما يساوي الرمز الحالي للرمز الذي نبحث عنه , والرمز أصلا غير موجود , مالذي يحدث ؟

ج : بالطبع لن يتوقف دوران الحلقة , لأن الرمز غير موجود.

العواجي كتب:
السلام عليكم ورحمة الله وبركاته....

مشكور أخوي BjarneStudent ، مجهود موفق تشكر عليه....

المعذرة على التأخير ، لكن أستطيع - بمشيئة الله - اللحاق بكم ...

العفو اخي الكريم , سعيد بإنضمامك

العواجي كتب:

طيب أخوي ماذا لو قلنا X=0 أعتقد أن الشرط هنا لا يتحقق...

لأنه وحسب علمي أنه بعد عملية الإسناد يكون إرجاع العملية هو القيمة المسندة....

(القيمة المرجعة من الدوال أو العمليات كما نعرف ليس من الضرورة أن يوجد من يستقبلها)

المهم في مثالي هذا وبعد ما أسند القيمة 0 للمتغير X ..... صار ناتج هذه العملية القيمة 0 والتي تلقفتها الـ if واعتبرتها على أنها false

مدري هل فهمي صحيح أخوي....

ننتظر تصحيحك وتصويبك لي أخي...

كلامك منطقي وصحيح

بس احنا هنا نناقش حالة , وهي payCode , ونقصد بكل الأحوال , أي مهما كانت

قيمتها فسوف تسند لها القيمة 4 , والقيمة 4 دائما صحيحة

أما في ما ذكرته , عندما تكون القيمة صفر , فبالطبع القيمة غير صحيحة والشرط خاطىء

واذا أردت ان تتأكد , اكتب كود قصير وطبق كل الإحتمالات التي تقترحها.

العواجي كتب:

في النهاية قرأت حتى الآن فقط الدرسين الأوليين فهمت أشياء كثيرة وجديدة علي...

وأحب أن أشكرك وأقول:

الله ينفع بعلمك وييسر لك أمورك كلها ، ويكون في عونك أخي....

أجهدت نفسك ، لكن ستجد بمشيئة الله أن تعبك لم يضيع سدى...

هناك من سيستفيد من هذه الدورة لاحقاً وذلك لأن الكتاب يعتبر معتمد في أغلب الجامعات....

مايجعلني استمتع في هذا العمل , هو وجود من يستفيد

صدقني أنا استمتعد بذلك , ونفسي تسعد وترتاح لذلك ( ليس كما تقول بأنها " تجهد " )

هل تصدق , بأن دعوتك التي دعوت لي بها , هي فقط , تكفيني لإنجاز هذا العمل وانا سعيد وبدون تعب :)

اشكرك جدا على هذه الدعوة التي اطمح لها دائما

وأي سؤال يخطر على بالك , اطرحه ولا تتردد.

HUNTER OF THE DREAMS كتب:

السلام عليكم ورحمة الله وبركاته

الأخ الكريم BjarneStudent

هل من الممكن تأجيل المحاضرة القادمة مدة أسبوعين فقط

لأن الأن فترة إمتحانات .

حتي لايفوتنا الكثر ونستطيع مرجعة ما سبق .

شكر لك وجزاك الله خير ونفع بك وبعلمك .

أخي صياد الأحلام , لا تقلق

كل محاضرة من هذه المحاضرات ليس لها صلاحية وتنتهي , تجاهل تاريخ نزول المحاضرة واسئل ما بدا لك.

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

لا تقلق , افعل ما عليك , وان شاء الله بالتعويض لن يفوتك شي.

تم تعديل هذه المشاركة بواسطة BjarneStudent في 29 ديسمبر 2007 في 18:06

وليس يبني العلا الا نديٌ ووغى , همـا المعارج للأسنى من الرتب

#10

تمت اضافة التمارين

عند مواجة صعوبه في فهم أي تمرين , فلا تتردد في إبداء السؤال

وليس يبني العلا الا نديٌ ووغى , همـا المعارج للأسنى من الرتب

#11

السلام عليكم ,,

الشكر الجزيل للأخ أبوسلمان على مجهوده المستمر في الدروس,

في الدرس تكلم الأخ أبوسلمان عن الفرق بين = و == في عمليات التكرار, و أخبرنا أن المترجم لا يصدر خطأ إذا استخدمت إحداهما بدل الأخرى و لكن يحصل خطأ منطقي في برنامجك,

و أضاف الأخ العواجي إلى ذلك الأمر إضافة جميلة, مشكوراً على ذلك.

الحقيقة أن الذي يتعلم اللغة و يعرف متى يستعمل كل operator سيصبح في طبقة المتمرسين عما قريب, و لكن قبل ذلك يجب أن تعرف أن عمليات الإسناد = تمت إعادة تعريفها operator Overloaded لكل نوع أساسي في ++c لاحظ المثال التالي :

x = 3

سهل جداً, حيث أصبحت قيمة x تساوي 3, الآن لاحظ التالي :

x = y = 5

في الأعلى, أولاً y ستصبح قيمتها 5 ثم ستقوم بإعادة قيمتها إلى x, و هكذا, و لكن لو جاء سؤال ما فائدة هذا في عبارات التكرار ؟؟؟؟

الفائدة الحقيقة تظهر عندما تبدأ في كتابة برامج حقيقية !!!

لاحظ الكود التالي الذي يقوم بنسخ نص من المصفوفة لأولى و يضعه في المصفوفة الثانية :

char x[] = "C Plus Plus"
char y[12];

char *px = x, *py = y;

while( *(py++) = *(px++) );

حيث استخدمنا الاسناد بدلاً من == , في هذه الحالة ستتوقف while حين نصل إلى العنصر الأخير أو NULL في المصفوفة الحرفية فتقوم بنسخه ثم تنتهي :P

تحياتي ,,

تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 30 ديسمبر 2007 في 00:09

#12

شكرا للتوضبح المعلومة وصلت.جزاك الله خير أخي BjarneStudent وشكرا للجميع.

وجاري الحل ان شاء الله.

tvquran_6.gif

#13
Khaled.Alshaya كتب:
السلام عليكم ,,

الشكر الجزيل للأخ أبوسلمان على مجهوده المستمر في الدروس,

في الدرس تكلم الأخ أبوسلمان عن الفرق بين = و == في عمليات التكرار, و أخبرنا أن المترجم لا يصدر خطأ إذا استخدمت إحداهما بدل الأخرى و لكن يحصل خطأ منطقي في برنامجك,

و أضاف الأخ العواجي إلى ذلك الأمر إضافة جميلة, مشكوراً على ذلك.

الحقيقة أن الذي يتعلم اللغة و يعرف متى يستعمل كل operator سيصبح في طبقة المتمرسين عما قريب, و لكن قبل ذلك يجب أن تعرف أن عمليات الإسناد = تمت إعادة تعريفها operator Overloaded لكل نوع أساسي في ++c لاحظ المثال التالي :

x = 3

سهل جداً, حيث أصبحت قيمة x تساوي 3, الآن لاحظ التالي :

x = y = 5

في الأعلى, أولاً y ستصبح قيمتها 5 ثم ستقوم بإعادة قيمتها إلى x, و هكذا, و لكن لو جاء سؤال ما فائدة هذا في عبارات التكرار ؟؟؟؟

الفائدة الحقيقة تظهر عندما تبدأ في كتابة برامج حقيقية !!!

لاحظ الكود التالي الذي يقوم بنسخ نص من المصفوفة لأولى و يضعه في المصفوفة الثانية :

char x[] = "C Plus Plus"
char y[12];

char *px = x, *py = y;

while( *(py++) = *(px++) );

حيث استخدمنا الاسناد بدلاً من == , في هذه الحالة ستتوقف while حين نصل إلى العنصر الأخير أو NULL في المصفوفة الحرفية فتقوم بنسخه ثم تنتهي :P

تحياتي ,,

اضافة رائعة اخي خالد , وهذا احد استخدامات هذا المفهوم.

جزيل الشكر

arabi2013 كتب:

شكرا للتوضبح المعلومة وصلت.جزاك الله خير أخي BjarneStudent وشكرا للجميع.

وجاري الحل ان شاء الله.

العفو , وجزاك الله خيرا , انت ايضا على حسن المتابعة

وليس يبني العلا الا نديٌ ووغى , همـا المعارج للأسنى من الرتب

#14
dr_sara كتب:
السلام عليكم ورحمة الله وبركاتة

اولا جزاك الله خير للرد والمتابعة وااسف للتاخير فى ردى فهذة فترة امتحانات والعمل فيها لا يتوقف

بحاول اتناقش مع حضرتك لان حضرتك لا تفهمنى لان فى الحالة التى شرحتها لا يوجد فرق باستخدام الbreak

حيث انى بجعلة يبحث فى المصفوفة

واذا وجد الرمز بضع قيمة العداد بقيمة حجم المصفوفة اذا لما يكمل راح يجد العداد فى نهايتة ويخرج

لاحظوا اخوانى انا فقط اقول بدل وضع كلمة break فى الكود استبدالها بوضع قيمة العداد بالقيمة النهائية

اتمنى كدة تكونوا فهمتم وعلى العموم ليس فى جميع الاحوال ينفع استخدام الطريقة التى اقولها وذكرت السبب من قبل حيث

اذا كان هناك جمل بعد كلمة الbreak فى اى حلقة تكرارية لن تتنفذ ام طريقتى فسوف تتنفذ ثم يخرج من الloop

اخى العواجى لا ارى فى مثالك استخدام للbreak اصلا

ارجو تكونوا فهمتمونى هذة المرة ووصلت لكم معلومة جديدة

مرة اخرى جزاكم الله خير

بالتوفيق ان شاء الله

وعليكم السلام ورحمة الله وبركاته

اشكرك على الدعوة الطيبة , وكلنا لدينا اختبارات , لا تأسفي.

أختي , انتي تقولين اضع القيمة النهائية بدل من الـ break , افترضي أن القيمة النهائية غير معروفه , كمتسلسلة رمزية غير معلومة العدد , او شجرة عدد البيانات فيها ديناميكي وغير معلوم

كيف تعرفين القيمة النهائية ؟

واذا لم أفهم حتى الآن , اريد ان توضحي لي , ماذا تقصدين بالقيمة النهائية إذن ؟

وليس يبني العلا الا نديٌ ووغى , همـا المعارج للأسنى من الرتب

هذا الموضوع مغلق.

مواضيع مشابهة