Download as pdf or txt
Download as pdf or txt
You are on page 1of 15

‫المحاضرة رقم ‪1‬‬

‫● لغة ‪C‬‬
‫● مرحبا بالعالم‬
‫● المترجمات‬
‫● النصوص‬
‫● مكعبات برنامج ‪ Scratch‬في لغة ‪C‬‬
‫● أنواع البيانات‪ ،‬رموز الطباعة‪ ،‬العالمات الحسابية‬
‫● امثة أخرى‬
‫● الشاشات‬
‫● الذاكرة‪ ،‬وعدم الدقة‪ ،‬والتجاوز‬

‫لغة ‪C‬‬
‫سوف نتعلم اليوم لغة جديدة وهي لغة ‪ ،C‬وهى لغة برمجة لديها كل مميزات ‪ Scratch‬واكثر ولكن ربما تبدو أكثر تعقيدا حيث انها‬
‫لغة كتابية‬

‫>‪#include <stdio.h‬‬

‫)‪int main(void‬‬
‫{‬
‫;)"‪printf("hello, world\n‬‬
‫}‬

‫بالرغم من أن الكلمات قد تبدو جديدة اال ان الفكرة هى ذاتها عند استخدامنا مكعبي ‪ ”“when green flag clicked‬و “‪ ”say hello world‬في‬
‫برنامج ‪Scratch‬‬

‫على الرغم من ان هذه االكواد قد تبدو مبهمة بالنسبة لك‪ ،‬فقط تذكر ان ثلثي طالب هذا المسار لم يدرسو علوم الحاسب من قبل لذلك ال‬
‫تخف و في البداية أحب أن أقتبس عبارة من معهد ‪" MIT‬إن محاولة استيعاب كل هذه المفاهيم الجديدة قد تشعر وكأنها تشرب من‬
‫خرطوم الحريق"‪ .‬تأكد من أنه بحلول نهاية المسار سنكون لديك خبرة في تعلم وتطبيق هذه المفاهيم‪.‬‬

‫يمكننا مقارنة الكثير من التركيبات في ‪ ،C‬بالمكعبات التي رأيناها و استخدمناها بالفعل في ‪ .Scratch‬طريقة كتابة الجملة أقل أهمية بكثير‬
‫من المبادئ‪ ،‬التي قدمناها بالفعل‪.‬‬

‫مرحبا بالعالم‬
‫● كما رأينا في ‪ scratch‬ان البرنامج يبدأ من مكعب “‪ ،”when green flag clicked‬فبمجرد ضغطك على العلم األخضر يبدأ البرنامج‬
‫بتنفيذ ما بداخل المكعبات‪ .‬في لغة ‪ C‬هناك كود مماثل يقوم بنفس المهمة و هو‬

‫)‪int main(void‬‬

‫والذى سوف نتحدث عنه اكثر في االسابيع المقبلة‪ .‬يتبع هذا السطر ب عالمتى {} و بداخلهم البرنامج الخاص بنا‬

‫)‪int main(void‬‬
‫{‬
‫}‬

‫● المكعب “‪ ”say hello, world‬هو ‪ function‬والذي يكافئ في لغة ‪C‬‬

‫;)"‪printf("hello, world‬‬

‫ال ‪ printf function‬هي المسؤولة عن طباعة اي شئ على الشاشة‪ ،‬حيث ان حرف ‪ f‬يرمز إلى ‪ ،format‬حيث تعنى أننا يمكننا تنسيق‬
‫النص المطبوع بطرق مختلفة‪ .‬بعد ذلك األقواس () التى نكتب بداخلها ما نريد طباعته‪ ،‬يجب أن نحيط النص المراد طباعته عالمات‬
‫تنصيص مزدوجة " " وفى النهاية نضيف ; والتى تشير الى نهاية السطر البرمجي‬

‫● لجعل البرنامج يعمل‪ ،‬نحتاج الى سطر آخر في بداية الكود وهو‬

‫>‪#include <stdio.h‬‬

‫الذى يعرف كيف تعمل ‪printf‬التي نريد استخدامها‪ .‬فى مكان ما هنا على الحاسب الخاص بنا يوجد ملف يوجد ملف ‪ ،stdio.h‬والذى‬
‫يحتوى على الكود الذى يتيح لنا استخدام ‪ printf‬و ولنجعل الكود الخاص بنا يتضمن هذا الملف نستخدم ‪#include‬في بداية البرنامج‬

‫● عندما اردنا كتابة أول برنامج على ‪ scratch‬قمنا بفتح الموقع الخاص به‪ .‬بالمثل لنبدأ بكتابة و تشغيل أول برنامج لنا سنستخدم‬
‫‪ ،CS50 Sandbox‬و هي بيئة افتراضية تتضمن مجموعة من المكتبات واألدوات المثبتة بالفعل لكتابة البرامج بلغات متعددة‬
‫● في الجزء العلوي‪ ،‬هناك محرر كود بسيط‪ ،‬حيث يمكننا كتابة النص‪ .‬في األسفل‪ ،‬لدينا نافذة لكتابة األوامر من خاللها ‪terminal‬‬
‫‪window‬‬

‫● إلنشاء ملف نكتب بداخله الكود الخاص بنا‪ ،‬سنضغط على رمز ‪ +‬و ننشئ ملف جديد بأسم ‪ hello.c‬و نكتب بداخله‬

‫● ننهي ملف برنامجنا بـ‪ c.‬لإلشارة إلى أنه مخصص كبرنامج مكتوب بلغة ‪ ،C‬الحظ أن الكود الخاص بنا ملون‪ ،‬بحيث يكون أكثر وضوحً ا‪.‬‬

‫المترجمات‬

‫● بمجرد أن نحفظ الكود الذى كتبناه‪ ،‬والذى يسمى (‪ ) source code‬الكود المصدري‪ ،‬نحتاج إلى تحويلها إلى (‪ ) machine code‬كود اآللة‪،‬‬
‫وهي تعليمات ثنائية (مكون من صفر و واحد) يفهمها الكمبيوتر مباشرة‪.‬‬
‫● نستخدم برنامجً ا يسمى مترجم (‪ )compiler‬لتحويل الكود المصدرى الخاص بنا إلى كود اآللة‪.‬‬
‫● للقيام بذلك‪ ،‬نستخدم نافذة كتابة األوامر‪ ،‬التي لديها موجه األوامر‪ )$( .‬في اليسار والذي يمكننا كتابة األوامر‪ .‬بعده‬
‫● نكتب ‪( clang hello.c‬حيث تعني ‪" clang‬لغة ‪ ،"C‬وهو مترجم كتبه مجموعة من األشخاص)‪ .‬ولكن قبل أن نضغط على ‪ ،enter‬اضغط‬
‫على أيقونة المجلد في الجزء العلوي األيسر من ‪ .CS50 Sandbox‬سنرى ملفنا يسمى ‪ .hello.c‬لذلك نضغط على ‪ enter‬في نافذة‬
‫كتابة األوامر‪ ،‬سنجد ملف آخر ظهر يسمى ‪ a.out‬والتى تعنى (المخرجات بلغة ‪ ) assembly‬بداخل هذا الملف يوجد الكود الخاص بنا‬
‫مكتوب بلغة األلة‪ ،‬اآلن يمكننا كتابة ‪ ./a.out‬في نافذة كتابة األوامر لتشغيل البرنامج ‪ a.out‬الموجود في المجلد الحالي‪ .‬لقد قمنا للتو‬
‫بكتابة‪ ،‬ترجمة‪ ،‬وتشغيل برنامجنا األول!‬

‫النصوص‬
‫● بعد ان قمنا بتشغيل البرنامج وجدنا ‪hello, world$‬حيث ان موجه األوامر في ذات السطر الموجود به خرج البرنامج‪ ،‬على ما يبدو أننا‬
‫نحتاج لسطر جديد بعد البرنامج الخاص بنا لذلك سنقوم بتحديث البرنامج لنجعله يحتوى على هذا السطر باضافة هذا الرمز ‪n\ :‬‬

‫>‪#include <stdio.h‬‬
‫)‪int main(void‬‬
‫{‬
‫};)"‪printf("hello, world\n‬‬

‫● نحن اآلن بحاجة إلى أن نتذكر إعادة ترجمة برنامجنا باستخدام ‪ clang hello.c‬قبل أن نتمكن من تشغيله بعد التحديث‬
‫● السطر ‪ 2‬من برنامجنا فارغ عن قصد ألننا نريد بدء جزء جديد من الكود (مثل بدء فقرات جديدة في المقاالت)‪ .‬انه ليس ضرورى لكى‬
‫يعمل برنامجنا بشكل صحيح‪ ،‬ولكنه يساعد البشر على قراءة البرامج بسهولة أكبر‪.‬‬
‫● يمكننا أيضا تغيير اسم برنامجنا من ‪ a.out‬إلى شيء آخر‪،‬عن طريق اضافة اختيارات اضافية (‪ )command-line arguments‬الى‬
‫البرنامج في نافذة كتابة األوامر على سبيل المثال يمكننا كتابة ‪clang -o hello hello.c‬حيث ان ‪ o hello-‬تخبر برنامج ‪ clang‬أن يحتفظ بالكود‬
‫‪hello/.‬‬ ‫المترجم في ملف يسمى ‪ hello‬بدال من ‪ a.out‬حيث نستطيع تشغيله فيما بعد عن طريق كتابة‬
‫● في نافذة كتابة األوامر يمكننا كتابة امر اخر مثل ‪ ls‬و التى تشير الى اظهار جميع الملفات في المجلد الحالى‬

‫‪$ ls‬‬
‫‪a.out* hello* hello.c‬‬

‫● " * " تشير إلى أن هذه الملفات قابلة للتشغيل بواسطة الحاسب الخاص بنا‬
‫● يمكننا استخدام األمر ‪ rm‬وهو اختصار لكلمة ‪ remove‬لحذف ملف‪:‬‬

‫‪$ rm a.out‬‬
‫?'‪rm: remove regular file 'a.out‬‬

‫● يمكننا كتابة ‪y‬او ‪yes‬لتأكيد األمر و استخدام امر ‪ls‬مرة ثانية لنتأكد من أن الملف قد تم مسحه نهائيا‬
‫● اآلن‪ ،‬دعونا نحاول الحصول على مدخالت من المستخدم‪ ،‬كما فعلنا في ‪ Scratch‬عندما أردنا أن نقول "‪:"Hello , David‬‬

‫;)"‪string answer = get_string("What's your name?\n‬‬


‫;)‪printf("hello, %s\n", answer‬‬

‫) ""‬ ‫● في البداية نحتاج أن نسأل المستخدم ان يدخل نص (‪( )String‬صفر أو أكثر من الحروف داخل عالمتي تنصيص مزدوجة‬

‫مثل )”‪("", "ba", “bananas‬ف نستخدم ‪function get_string‬ونضع بداخل أقواسها السؤال الذى نريد أن نسأله للمستخدم مثل‬

‫‪"What is your name?\n".‬على اليسار نريد انشاء متغير‪ )(variable‬اسمه ‪answer‬والذى ستكون قيمته ما يقوم المستخدم بكتابته‪ .‬عالمة‬
‫= ستقوم بوضع القيمة التي في اليمين في المتغير الذي في اليسار‪ .‬هذا المتغير سيحتوى على نص (حيث سيقوم المستخدم بكتابة‬
‫‪answer‬‬ ‫نص) لذلك نوع هذا المتغير سيكون ‪string‬لذلك سنجد كلمة ‪string‬على يسار المتغير‬

‫● بعد ذلك نحتاج قيمة المتغير ‪ answer‬بداخل ‪ printf function‬لتقوم بطباعتها‪ ،‬فنقوم بحجز مكان لهذا المتغير باستخدام ‪s%‬بداخل‬
‫الجملة التى سنقوم بطباعتها هكذا "‪ ،"hello, %s\n‬ثم نعطى ‪ printf‬قيمة اخرى (اختيار آخر) و هو المغير ‪ answer‬حيث يعنى هذا وضع‬
‫‪s%‬‬ ‫قيمته مكان‬
‫● إذا كتبنا شئ خاطئ مثل‬
‫;)‪printf("hello, world"\n‬‬

‫حيث أن \‪ n‬خارج عالمات التنصيص سيرسل المترجم (‪ )compiler‬لنا رسالة بأنه يوجد خطأ ‪:‬‬

‫‪$ clang -o hello hello.c‬‬


‫')' ‪hello.c:5:26: error: expected‬‬
‫;)‪printf("hello, world"\n‬‬
‫^‬
‫'(' ‪hello.c:5:11: note: to match this‬‬
‫;)‪printf("hello, world"\n‬‬
‫^‬
‫‪1 error generated.‬‬

‫● السطر األول من رسالة الخطأ تخبرنا بان ننظر الى السطر الخامس الحرف ‪ 26‬في ملف ‪ ،hello.c‬حيث أن المترجم يتوقع ان يوجد هنا‬
‫قوس وليس "\"‬
‫● لتبسيط االمور في البداية سنقوم باضافة مكتبة (مجموعة من االكواد ) الى الملف الخاص بنا‪ ،‬حيث ستجعلنا قادرين على استخدام‬
‫‪cs50.h‬‬ ‫نوع المتغيرات ‪ ،string‬و كذك ‪ ،get_string function‬كل ما سنحتاجه هو ‪ include‬ملف‬

‫>‪#include <cs50.h‬‬
‫>‪#include <stdio.h‬‬

‫)‪int main(void‬‬
‫{‬
‫;)"‪string name = get_string("What's your name?\n‬‬
‫;)"‪printf("hello, name\n‬‬
‫}‬

‫● لنقوم بإنشاء ملف جديد يسمى ‪string.c‬ونكتب بداخله هذا الكود‬

‫>‪#include <stdio.h‬‬

‫)‪int main(void‬‬
‫{‬
‫;)"‪string name = get_string("What's your name?\n‬‬
‫;)‪printf("hello, %s\n", name‬‬
‫}‬

‫● اذا قمنا بترجمة (‪ )compiling‬هذا الكود سنجد به العديد من األخطاء‪ ،‬احيانا يكون السبب خطأ واحد ولكن يقوم المترجم بترجمة‬
‫األكواد الصحيحة بعده بشكل خاطئ لذلك دائما ما نبدأ بأول خطأ‬

‫‪$ clang -o string string.c‬‬


‫?'‪string.c:5:5: error: use of undeclared identifier 'string'; did you mean 'stdin‬‬
‫;)"‪string name = get_string("What's your name?\n‬‬
‫~~~~~^‬
‫‪stdin‬‬
‫‪/usr/include/stdio.h:135:25: note: 'stdin' declared here‬‬
‫;‪extern struct _IO_FILE *stdin‬‬ ‫‪/* Standard input stream. */‬‬

‫● نحن لم نكن نقصد ‪ stdin‬بدال من ‪ ،string‬لذا هذه الرسالة قد تبدو غير مفيدة‪ .‬في الحقيقة نحن بحاجة الضافة ملف آخر على الكود‬
‫الخاص بنا لتعريف النوع ‪( string‬سنعرف لماذا في األسابيع المقبلة)‬
‫● لذا سنقوم باضافة ملف آخر و هو ‪ ،cs50.h‬والذى يحتوى على ‪ ،function get_string‬و اشياء اخرى عديدة‬

‫>‪#include <cs50.h‬‬
‫>‪#include <stdio.h‬‬
‫)‪int main(void‬‬
‫{‬
‫;)"‪string name = get_string("What's your name?\n‬‬
‫;)‪printf("hello, %s\n", name‬‬
‫}‬

‫● عندما نقوم بترجمة هذا الملف االن سنجد انه يوجد به خطأ واحد‬

‫‪$ clang -o string string.c‬‬


‫‪/tmp/string-aca94d.o: In function `main':‬‬
‫'‪string.c:(.text+0x19): undefined reference to `get_string‬‬
‫)‪clang-7: error: linker command failed with exit code 1 (use -v to see invocation‬‬

‫● على ما يبدو اننا بحاجة الن نخبر المترجم أن يقوم باضافة ملف مكتبة ‪ ،50CS‬لذا سنقوم بكتابة ‪ clang -o string string.c -lcs50،‬حيث تشير‬
‫‪ l-‬الى ‪ link‬والتى تعنى ربط (ربط الملف الخاص بالمكتبة بالكود الخاص بنا)‬

‫‪string.c‬الى ‪ ،string‬و تفعل تمام كل ما يفعله ‪clang -‬‬ ‫● يمكننا اختصار ذلك بكتابة ‪make string‬حيث ان ‪ make‬تستخدم ‪ clang‬لترجمة الملف‬
‫‪o string string.c -lcs50.‬‬

‫مكعبات برنامج ‪ Scratch‬في لغة ‪C‬‬


‫‪;int counter = 0‬‬ ‫● يقوم مكعب “‪ ”0 set counter to‬في برنامج ‪ scratch‬بانشاء متغير (‪ ،)variable‬نستطيع فعل ذلك في لغة ‪ C‬بكتابة‬
‫حيث ان ‪ int‬تعني أن المتغير سيكون من النوع عدد صحيح (‪)integer‬‬

‫● اما مكعب "‪ "1 change counter by‬يكافئه ‪;counter = counter + 1‬فى ‪ ،C‬عالمة "=" هنا ال تعنى تساوى كما في الرياضايات ولكنها تعنى‬
‫ضع القيمة التي في اليمين في المتغير الذي على اليسار وتعنى هنا‪ ..‬ضع في متغير ‪ counter‬قيمة ‪ 1+ counter‬الحظ هنا اننا ال نحتاج‬
‫‪;counter += 1‬او ‪;++counter‬‬ ‫ان نكتب ‪ int‬مرة اخرى حيث اننا قد عرفنا المتغير ‪ counter‬من قبل بأنه من النوع ‪ int‬يمكننا ايضا ان نكتب‬
‫كالهما نفس المعنى‪ ،‬ولكنهم فقط اختصارات كتابية و تسمى “‪”syntactic sugar‬‬

‫● اما ال ‪ condition‬فكافئها‬

‫)‪if (x < y‬‬


‫{‬
‫;)"‪printf("x is less than y\n‬‬
‫}‬

‫● الحظ اننا في ‪ C‬نستخدم { و } لنوضح كيف توجد االكواد داخل بعضها البعض‬
‫● يوجد ايضا ‪if-else conditions‬‬

‫)‪if (x < y‬‬


‫{‬
‫;)"‪printf("x is less than y\n‬‬
‫}‬
‫‪else‬‬
‫{‬
‫;)"‪printf("x is not less than y\n‬‬
‫}‬

‫● الحظ ان االسطر التى ال تتضمن تنفيذ أمر معين مثل ‪if‬ال تنتهى ب عالمة ;‬
‫● لدينا أيضا ‪else if‬في لغة ‪C‬‬
‫)‪if (x < y‬‬
‫{‬
‫;)"‪printf("x is less than y\n‬‬
‫}‬
‫)‪else if (x > y‬‬
‫{‬
‫;)"‪printf("x is greater than y\n‬‬
‫}‬
‫)‪else if (x == y‬‬
‫{‬
‫;)"‪printf("x is equal to y\n‬‬
‫}‬

‫● الحظ استخدام ==‪ ,‬للمقارنة بين قيمتين في لغة ‪C‬‬


‫‪else‬‬ ‫● منطقيا أننا لسنا بحاجة لكتابة ‪ (if(x == y‬في آخر ‪ condition‬حيث انه لم يتبقى غير هذه الحالة يمكننا أن نكتفي بكتابة‬
‫● يمكن كتابة ال ‪ loops‬هكذا‬

‫)‪while (true‬‬
‫{‬
‫;)"‪printf("hello, world\n‬‬
‫}‬

‫شرطا‪ ،‬لذلك نستخدم ‪ true‬كتعبير منطقي (‪ )boolean expression‬لضمان تشغيل ال ‪ loop‬الى األبد‪ .‬سيقوم‬
‫ً‬ ‫● تتطلب ‪ً while‬‬
‫أيضا‬
‫دائما في هذه الحالة)‪ ،‬ثم يقوم بتشغيل الكود بداخل‬
‫ً‬ ‫برنامجنا بالتحقق مما إذا كان (‪ )condition‬تساوى ‪( true‬وهو ما سيحدث‬
‫األقواس {} بعد ذلك سوف يكرر ذلك حتى تتغير قيمة ال(‪ )condition‬الى ‪( false‬والذي لن يحدث في هذه الحالة)‪.‬‬
‫‪while‬‬ ‫● يمكننا تكرار كود محدد عدة مرات باستخدام‬

‫;‪int i = 0‬‬
‫)‪while (i < 50‬‬
‫{‬
‫;)"‪printf("hello, world\n‬‬
‫;‪i++‬‬
‫}‬

‫● لقد أنشأنا متغير ‪ ،i‬واعطينا له قيمة ‪ 0‬بعد ذلك سنقوم بتكرار عدة أسطر من االكواد ونزيد قيمة ال ‪ i‬بمقدار ‪ 1‬في كل مرة ما دامت‬
‫قيمة ال ‪ i‬اقل من ‪50‬‬
‫● األقواس {} حول االكواد تشير الى ان هذه األسطر من الكود ستتكرر‪ .‬يمكننا كتابة اسطر اخرى بعد هذه األقواس إذا كان هناك باقى‬
‫للبرنامج المراد كتابته‬
‫● يمكننا أيضا استخدام ‪ for‬حيث انها احدى طرق التكرار(‪ )loops‬الشائعة‬

‫)‪for (int i = 0; i < 50; i++‬‬


‫{‬
‫;)"‪printf("hello, world\n‬‬
‫}‬

‫● في البداية ننشئ متغير يسمى ‪ i‬و نعطى له قيمة ‪ 0‬ثم نتحقق هل ‪i < 50‬في كل دورة قبل تنفيذ اى سطر بداخل هذا ال ‪ loop‬إذا كانت‬
‫قيمة هذا ال ‪ expression‬تساوى ‪ true‬سنقوم بتنفيذ الكود و في نهاية الدورة سقوم بإضافة ‪ 1‬إلى قيمة ‪ i‬الحالية و نقوم بتكرار هذا‬
‫حتى تصبح قيمة ال ‪ condition‬تساوي ‪false‬‬

‫أنواع البيانات‪ ،‬رموز الطباعة‪ ،‬العالمات الحسابية‬


‫● هناك العديد من أنواع البيانات التي يمكن أن نستخدمها عند إنشاء متغير‬
‫‪false‬‬ ‫○ النوع األول‪ ،bool :‬وهو تعبير منطقى يمكن أن تكون قيمته ‪ true‬أو‬
‫‪2‬‬ ‫○ النوع الثانى‪ ،char :‬والتى تكون قيمته حرف واحد مثل ‪a‬أو‬
‫○ النوع الثالث‪ ،float :‬وتكون قيمته رقم ذو عالمة عشرية‬
‫○ النوع الرابع‪ ،double :‬وتكون قيمته رقم ذو عالمة عشرية أيضا ولكن بمساحة أكبر‬
‫○ النوع الخامس‪ ،int :‬وتكون قيمته رقم صحيح‬
‫○ النوع السادس‪ ،long :‬وتكن قيمته رقم صحيح ايضا ولكن بمساحة أكبر‬
‫○ النوع السابع‪ ،string :‬وتكون قيمته نص كتاب‬
‫● بداخل مكتبة ‪ 50CS‬عدد من ال ‪ function‬لتاخد مدخالت بأنواع مختلفة من المستخدم‬
‫‪get_char‬‬ ‫○‬
‫‪get_double‬‬ ‫○‬
‫‪get_float‬‬ ‫○‬
‫‪get_int‬‬ ‫○‬
‫‪get_long‬‬ ‫○‬
‫‪get_string‬‬ ‫○‬
‫● عند استخدام ‪ ،printf‬هناك رمز محدد لكل نوع من هذه األنواع ‪:‬‬
‫النوع ‪ char‬نستخدم ‪c%‬‬ ‫○‬
‫النوع ‪ float‬و ‪ double‬نستخدم ‪f%‬‬ ‫○‬
‫النوع ‪ int‬نستخدم ‪i%‬‬ ‫○‬
‫النوع ‪long‬نستخدم ‪li%‬‬ ‫○‬
‫النوع ‪string‬نستخدم ‪s%‬‬ ‫○‬
‫●‬
‫● هناك بعض العالمات الحسابية التى يمكن ان نستخدمها ‪:‬‬
‫للجمع نستخدم ‪+‬‬ ‫○‬
‫للطرح نستخدم ‪-‬‬ ‫○‬
‫للضرب نستخدم *‬ ‫○‬
‫للقسمة نستخدم ‪/‬‬ ‫○‬
‫لباقى القسمة نستخدم ‪%‬‬ ‫○‬

‫امثلة اخرى‬
‫● يمكنك تعديل كل من االمثلة التالية بالضغط على رابط ‪sandbox‬‬
‫● في ملف ‪ ،int.c‬نطلب من المستخدم قيمة عددية صحيحة ك مدخالت للبرنامج و يكون مخرجات البرنامج قيمة عددية صحيحة أيضا‬

‫>‪#include <cs50.h‬‬
‫>‪#include <stdio.h‬‬

‫)‪int main(void‬‬
‫{‬
‫;)"‪int age = get_int("What's your age?\n‬‬
‫;‪int days = age * 365‬‬
‫;)‪printf("You are at least %i days old.\n", days‬‬
‫}‬

‫● الحظ استخدام ‪ i%‬لطباعة عدد صحيح (‪)int‬‬


‫‪int/.‬‬ ‫● يمكننا ترجمة البرنامج بكتابة ‪ make int‬ثم تشغيله بكتابة‬
‫● يمكننا اختصار الكود قليال و مسح متغير ‪ days‬ليصبح الكود هكذا‬

‫;)"‪int age = get_int("What's your age?\n‬‬


‫;)‪printf("You are at least %i days old.\n", age * 365‬‬

‫● او ربما يمكننا اختصار الكود اكثر في سطر واحد هكذا ‪:‬‬

‫;)‪printf("You are at least %i days old.\n", get_int("What's your age?\n") * 365‬‬

‫ً‬
‫طويال أو معقدً ا‪ ،‬فقد يكون من األفضل تقسيمه على سطرين أو حتى ثالثة أسطر لتسهيل القراءة‪.‬‬ ‫● بمجرد أن يصبح السطر‬
‫● في ملف ‪ ،float.c‬نحصل على مدخالت من نوع أرقام ذات عالمة عشري‬

‫>‪#include <cs50.h‬‬
‫>‪#include <stdio.h‬‬

‫)‪int main(void‬‬
‫{‬
‫;)"‪float price = get_float("What's the price?\n‬‬
‫;)‪printf("Your total is %.2f\n", price * 1.0625‬‬
‫}‬

‫● واالن اذا قمنا بترجمة و تشغيل الملف سنرى السعر بعد إضافة الضرائب له‬
‫● يمكننا تحديد عدد األرقام بعد العالمة العشرية مع رموز الطباعة مثل ‪ 2f.%‬والتى تعنى رقمين بعد العالمة العشرية‬
‫● في ملف ‪ ،parity.c‬نتحقق ما اذا كان رقم ما زوجى أو فردى‬

‫>‪#include <cs50.h‬‬
‫>‪#include <stdio.h‬‬

‫)‪int main(void‬‬
‫{‬
‫;)" ‪int n = get_int("n:‬‬

‫)‪if (n % 2 == 0‬‬
‫{‬
‫;)"‪printf("even\n‬‬
‫}‬
‫‪else‬‬
‫{‬
‫;)"‪printf("odd\n‬‬
‫}‬
‫}‬

‫● باستخدام عالمة ‪%‬يمكننا معرفة باقى قسمة الرقم ‪ n‬على ال ‪ 2‬اذا كان باقى القسمة ‪ 0‬فهذا يعني ان الرقم زوجى و اذا كان غير ذلك‬
‫نعرف أنه فردى‬
‫● ال داعي أن تقلق من القيمة التى يدخلها المستخدم حيث ان ‪get_int‬التى بمكتبة ‪ 50CS‬تتأكد من ان القيمة المدخلة تتفق في النوع مع‬
‫القيمة المراد إدخالها‬
‫● في ملف ‪ ،conditions.c‬نكتب برنامج نستخدم فيه الشروط التى تعرضنا لها من قبل‪.‬‬
// Conditions and relational operators

#include <cs50.h>
#include <stdio.h>

int main(void)
{
// Prompt user for x
int x = get_int("x: ");

// Prompt user for y


int y = get_int("y: ");

// Compare x and y
if (x < y)
{
printf("x is less than y\n");
}
else if (x > y)
{
printf("x is greater than y\n");
}
else
{
printf("x is equal to y\n");
}
}

‫) وهى مالحظة (تكتب بأي لغة) لن يقوم المترجم بترجمتها (ألنها ليست كود‬comment( ‫ تسمى تعليق‬// ‫● السطور التي تبتدئ بعالمة‬
)‫برمجى‬
‫ والتى تعني تغيير المجلد الحالي الى مجلد آخر و الذي‬،cd src1 ‫● عندما أراد ديفيد أن يشغل هذا البرنامج كتب في نافذة كتابة االوامر‬
‫ليشغل البرنامج‬conditions/. ‫ و‬make conditions ‫يحتوي على الملف المراد تشغيله حتى يستطيع أن يكتب‬
src1. ‫ يستطيع ان يعرف انه في المجلد‬،pwd ‫● باستخدام أمر‬
sandbox ‫ بدون اى اختبارات فإنه يأخذنا للخلف لمجلد البداية في‬cd ‫● عند كتابة االمر‬
: ‫ يمكننا ان نطلب من المستخدم ان يؤكد او يرفض امر ما‬،agree.c ‫● في ملف‬

//logical operator
#include <cs50.h>
#include <stdio.h>
int main(void)
{
// Prompt user to agree
char c = get_char("Do you agree?\n");

// Check whether agreed


if (c == 'Y' || c == 'y')
{
printf("Agreed.\n");
}
else if (c == 'N' || c == 'n')
{
‫;)"‪printf("Not agreed.\n‬‬
‫}‬
‫}‬

‫● يمكنك استخدام هذه العالمة ||‪ ،‬لتحقيق ‪ or‬منطقية‪ ،‬والتى تعنى اذا كان احد الشرطين ‪ true‬فان ال ‪ condition‬ستكون ‪true‬‬
‫● وإذا كان الشرطين ال يساوي ‪ true‬لن يحدث شئ حيث ان ال ‪ condition‬ستكون ‪false‬‬
‫● واآلن لنقوم بتنفيذ برنامج السعال الذي أنشأناه في األسبوع السابق‬

‫>‪#include <stdio.h‬‬

‫)‪int main(void‬‬
‫{‬
‫;)"‪printf("cough\n‬‬
‫;)"‪printf("cough\n‬‬
‫;)"‪printf("cough\n‬‬
‫}‬

‫يمكننا تنفيذه أيضا باستخدام ‪for loop :‬‬ ‫●‬

‫>‪#include <stdio.h‬‬

‫)‪int main(void‬‬
‫{‬
‫)‪for (int i = 0; i < 3; i++‬‬
‫{‬
‫;)"‪printf("cough\n‬‬
‫}‬
‫}‬

‫● في هذا البرنامج سنبدأ العد من الصفر لذلك ستكون قيم ‪ i‬تساوى ‪ 0‬و ‪ 1‬و ‪ 2‬قبل ان ينتهى البرنامج والتي تكافئ ‪ 3‬دورات‪ .‬يمكننا‬
‫الحصول على نفس التأثير اذا كتبنا‬

‫)‪for (int i = 1; i <= 3; i++‬‬

‫‪.‬‬

‫يمكننا إنشاء ‪ function‬خاصة ب جملة الطباعة ‪printf :‬‬ ‫●‬

‫>‪#include <stdio.h‬‬

‫;)‪void cough(void‬‬

‫)‪int main(void‬‬
‫{‬
‫)‪for (int i = 0; i < 3; i++‬‬
‫{‬
‫;)(‪cough‬‬
‫}‬
‫}‬

‫)‪void cough(void‬‬
‫{‬
‫;)"‪printf("cough\n‬‬
‫}‬

‫● لقد عرفنا ال ‪ ,;(void cough(void‬قبل أن نستخدمها في ‪ .main function‬حيث ان مترجم لغة ‪ c‬يعمل من أعلى ألسفل لذلك يجب أن‬
‫‪main‬‬ ‫نخبره أن ‪ cough function‬موجودة قبل أن نستخدمها‪ .‬بهذه الطريقة يعرف المترجم انها موجودة الحقا في الكود و تبقى ال‬
‫‪ function‬قريبة من البداية‬
‫‪( cough(void‬‬ ‫● حيث ان ‪ cough function‬ال تاخذ اى مدخالت فهي تكتب‬
‫● يمكننا اختصار ‪ cough‬أكثر‬

‫>‪#include <stdio.h‬‬

‫;)‪void cough(int n‬‬

‫)‪int main(void‬‬
‫{‬
‫;)‪cough(3‬‬
‫}‬

‫)‪void cough(int n‬‬


‫{‬
‫)‪for (int i = 0; i < n; i++‬‬
‫{‬
‫;)"‪printf("cough\n‬‬
‫}‬
‫}‬

‫● االن اذا كنا نريد طباعة “‪ ”cough‬اى عدد من المرات يمكننا فقط استدعاء ذات ال ‪ .function‬الحظ انه عند كتابتنا ‪،(void cough(int n‬‬
‫‪n‬و بداخل ‪ ،cough‬نستخدم هذا ال ‪ n‬في ال ‪for loop‬‬ ‫فهذا يعني أن ‪ cough function‬تاخذ مدخالت من النوع ‪ ،int‬و الذى نشير إليه ب‬
‫المستخدم لطباعة “‪ ”cough‬العدد المراد من المرات‬
‫لنلقى نظرة على ملف ‪positive.c‬‬ ‫●‬

‫>‪#include <cs50.h‬‬
‫>‪#include <stdio.h‬‬

‫;)‪int get_positive_int(string prompt‬‬

‫)‪int main(void‬‬
‫{‬
‫;)" ‪int i = get_positive_int("Positive integer:‬‬
‫;)‪printf("%i\n", i‬‬
‫}‬

‫‪// Prompt user for positive integer‬‬


‫)‪int get_positive_int(string prompt‬‬
‫{‬
‫;‪int n‬‬
‫‪do‬‬
‫{‬
‫;)‪n = get_int("%s", prompt‬‬
‫}‬
‫;)‪while (n < 1‬‬
‫;‪return n‬‬
‫}‬

‫● أن مكتبة ‪ 50cs‬ال تحتوى على ‪ get_positive_int function‬ولك يمكننا كتابة واحدة خاصة بنا‪.‬‬
‫ان ‪ (int get_positive_int(string prompt‬التي أنشأناها ستأخذ مدخالت من النوع ‪ string‬و التى سنشير إليها ب ‪prompt‬و الذى سيظهر‬ ‫●‬
‫‪i.‬‬ ‫للمستخدم‪ .‬و القيمة الناتجة منها ستكون من النوع ‪ ،int‬و التى ستقوم ال ‪ main function‬بتخزينها في متغير يسمى‬
‫● بداخل ‪ ،get_positive_int‬نقوم بتعريف متغير‪ ،int n ،‬بدون اعطائه اى قيمة ثم نقوم باستخدام شئ جديد وهو‪ ،do... while ،‬والتى تقوم‬
‫بفعل شئ ما اوال ثم تقوم ب التحقق من شرط معين و تكرار فعل هذا الشئ حتى يصبح الشرط يساوى ‪false‬‬
‫● بمجرد ان نحصل على ‪n>1‬سينتهى ال ‪ loop‬و يمكننا ارسال هذه القيمة باستخدام كلمة ‪ return‬و فى ال ‪ ،main function‬يمكننا ان‬
‫نجعل ‪ int i‬يساوي هذه القيمة‬

‫الشاشات‬
‫● قد نرغب في برنامج يقوم بطباعة جزء من شاشة من لعبة فيديو مثل ‪ .Super Mario Bros‬في ملف ‪ mario0.c،‬لدينا‪:‬‬
‫‪// Prints a row of 4 question marks‬‬

‫>‪#include <stdio.h‬‬
int main(void)
{
printf("????\n");
}

mario2.c : ‫ ثم نقوم طباعتها باستخدام كما فى‬،‫عالمات االستفهام التي يريدها‬ ً‫● يمكننا أن نطلب من المستخدم ادخال عدد‬

#include <cs50.h>
#include <stdio.h>

int main(void)
{
int n;
do
{
n = get_int("Width: ");
}
while (n < 1);
for (int i = 0; i < n; i++)
{
printf("?");
}
printf("\n");
}

mario8.c ‫ويمكننا طباعة مجموعة من األشكال ثنائية األبعاد باستخدام كما فى‬ ●

// Prints an n-by-n grid of bricks with a loop

#include <cs50.h>
#include <stdio.h>

int main(void)
{
int n;
do
{
n = get_int("Size: ");
}
while (n < 1);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
printf("#");
}
printf("\n");
}
}
‫● الحظ انه يوجد لدينا ‪ loops 2‬متداخلتين‪ .‬حيث ان ال ‪ loop‬الخارجي يستخدم المتغير ‪i‬لتكرار كل شئ بالداخل عدد ‪ n‬من المرات‪ ،‬بينما‬
‫ال ‪ loop‬الداخلى يستخدم متغير ‪ ،j‬لكرار شئ ما عدد ‪ n‬من المرات في كل مرة بمعنى اخر ال ‪ loop‬الخارجى يقوم بطباعة عدد ‪ n‬من‬
‫الصفوف و ال ‪ loop‬الداخلى يقوم بطباعة عدد ‪ n‬من االعمدة او عالمة ‪ #‬في كل صف‬
‫● تتوفر أمثلة أخرى لم تتم تغطيتها في المحاضرة يمكن ايجادها في “‪ ”Source Code‬في هذا الرابط ‪Week 1.‬‬

‫الذاكرة‪ ،‬وعدم الدقة‪ ،‬والتجاوز‬


‫● يحتوي الكمبيوتر الخاص بنا على ذاكرة‪ ،‬تسمى ‪( ،RAM‬ذاكرة الوصول العشوائي)‪ .‬تستخدم برامجنا ذاكرة الوصول العشوائي هذه‬
‫لتخزين البيانات أثناء تشغيلها‪ ،‬لكن تلك الذاكرة محدودة‪.‬عدد محدد من البتات‪ ،‬و بهذا العدد المحدد ال يمكننا تمثيل جميع األرقام‬
‫الممكنة (التي ال حصر لها )‪ .‬لذا فإن جهاز الكمبيوتر الخاص بنا يحتوي على عدد معين من البتات لكل ‪ float‬ا و ‪ ،int‬وعند مرحلة معينة‬
‫يحب التقريب ألقرب قيمة عشرية‪.‬‬
‫‪floats.c‬‬ ‫● يمكننا رؤية ما يحدث عند استخدام ‪ floats‬كما في ملف‬
‫>‪#include <cs50.h‬‬
‫>‪#include <stdio.h‬‬

‫)‪int main(void‬‬
‫{‬
‫‪// Prompt user for x‬‬
‫;)" ‪float x = get_float("x:‬‬

‫‪// Prompt user for y‬‬


‫;)" ‪float y = get_float("y:‬‬

‫‪// Perform division‬‬


‫;)‪printf("x / y = %.50f\n", x / y‬‬
‫}‬

‫طباعتها باستخدام ‪50f.%‬‬ ‫● يمكننا تحديد عدد األرقام العشرية التي نريد‬
‫● هذا هو ما حصلنا عليه‬
‫‪x: 1‬‬
‫‪y: 10‬‬
‫‪x / y = 0.10000000149011611938476562500000000000000000000000‬‬

‫● اتضح أن هذا يسمى عدم دقة الفاصلة العائمة(‪ ،)floating-point imprecision‬حيث ليس لدينا عدد بتات كافية لتخزين جميع القيم‬
‫الممكنة‪ ،‬لذلك يتعين على الكمبيوتر تخزين أقرب قيمة ممكنة إلى ‪ 1‬مقسومة على ‪.10‬‬
‫رؤية مشكلة مشابهة في ملف ‪overflow.c :‬‬ ‫● يمكننا‬

‫>‪#include <stdio.h‬‬
‫>‪#include <unistd.h‬‬

‫)‪int main(void‬‬
‫{‬
‫)‪for (int i = 1; ; i *= 2‬‬
‫{‬
‫;)‪printf("%i\n", i‬‬
‫;)‪sleep(1‬‬
‫}‬
‫}‬

‫● فى ‪ ،for loop‬قمنا بتعيين قيمة ‪ i‬تساوي ‪ ،1‬وتضاعفها ب ‪( *= 2‬وسنستمر في القيام بذلك إلى األبد‪ ،‬حيث انه ليس هناك شرط)‬
‫● نستخدم ً‬
‫أيضا ‪ sleep‬من ‪ unistd.h‬للسماح لبرنامجنا بالتوقف في كل مرة‪.‬‬
‫● اآلن‪ ،‬عندما ندير هذا البرنامج‪ ،‬نرى العدد يزداد ويكبر‪ ،‬حتى نجد‬
‫‪1073741824‬‬
‫'‪overflow.c:6:25: runtime error: signed integer overflow: 1073741824 * 2 cannot be represented in type 'int‬‬
‫‪-2147483648‬‬
‫‪0‬‬
‫‪0‬‬
‫‪...‬‬

‫● على ما يبدو ان البرنامج ادرك ان ال ‪ int‬ال يستطيع تخزين القيمة التالية و قام بطبع خطأ و بعد ذلك قام بمضاعفة الرقم على اى‬
‫حال و أصبحت ال ‪i‬قيمة سالبة و بعد ذلك اصبحت صفر‬
‫● تسمى هذه المشكلة ‪ ،integer overflow‬حيث ان يصبح قيمة ال ‪ integer‬كبيرة جدا(اكبر من المساحة المحجوزة له ) يمكن تمثيل‬
‫ذلك ب اضافة ‪ 1‬الى ‪ 999‬حيث سيصبح الناتج ‪ 1000‬ولكن في حين ان كل ما تملكه هو ‪ 3‬اماكن فقط فإن الناتج سيصبح ‪000‬‬
‫● نشأت مشكلة ‪ Y2K‬ألن العديد من البرامج قامت بتخزين السنة التقويمية برقمين فقط‪ ،‬مثل ‪ 98‬لعام ‪ ،1998‬و ‪ 99‬لعام ‪ .1999‬ولكن‬
‫عندما اقترب عام ‪ ،2000‬كانت البرامج تخزن ‪ ،00‬مما يؤدي إلى التشويش بين عامي ‪ 1900‬و ‪.2000‬‬
‫● تعرضت طائرة من طراز بوينج ‪ً 787‬‬
‫أيضا لخطأ حيث تحدث ‪ overflow‬للعداد الموجود في المولد بعد عدد معين من األيام من‬
‫التشغيل المستمر‪ ،‬حيث لم يعد من الممكن تخزين عدد الثواني التي كانت تعمل فيها في هذا العداد‪.‬‬
‫● لقد رأينا بعض المشاكل التي يمكن أن تحدث‪ ،‬ولكن اآلن نفهم سببها وكيفية الوقاية منها‪.‬‬
‫سوف نستخدم ‪ CS50 Lab‬المبني على ‪ CS50 Sandbox‬مع مجموعة المشكالت لهذا األسبوع‪ ،،،‬لكتابة بعض البرامج مع بعض‬ ‫●‬
‫اإلرشادات الموجودة في ال ‪ walkthroughs‬لتساعدنا س‬

You might also like