The words you are searching are inside this book. To get more targeted content, please make full-text search by clicking here.

ترجمة لدرس تعلّم البرمجة بلغة السي الخاص بموقع OpenClassrooms

Discover the best professional documents and content resources in AnyFlip Document Base.
Search
Published by Hamza Abbad, 2017-08-03 11:01:25

تعلّم البرمجة بلغة C

ترجمة لدرس تعلّم البرمجة بلغة السي الخاص بموقع OpenClassrooms

‫التصحيح )‪ : 2‬استعمال قاموس الكلمات(‬

‫{ ‪30‬‬
‫;)‪31 characterRead = fgetc(dico‬‬
‫)’‪32 if (characterRead == ’\n‬‬
‫;‪33 chosenWordNumber −−‬‬
‫} ‪34‬‬
‫;)‪35 fgets(chosenWord, 100, dico‬‬
‫‪36 // Erase the \n at the end of the word‬‬
‫;’‪37 chosenWord[strlen(chosenWord) − 1] = ’\0‬‬
‫;)‪38 fclose(dico‬‬
‫‪39 return 1; // Everything is okay, return 1‬‬
‫} ‪40‬‬
‫)‪41 int aleatoryNumber(int maxNumber‬‬
‫{ ‪42‬‬
‫;))‪43 srand(time(NULL‬‬
‫;)‪44 return (rand() % maxNumber‬‬
‫} ‪45‬‬

‫يجب إذن تعديل الـ‪! main‬‬

‫و الآن بما أن الملف ‪ dico.c‬جاهز‪ ،‬سنعود للدالة ‪ main‬كي نقوم بتحديثها على حسب التغييرات التي قمنا‬
‫بإجرائها‪.‬‬

‫سنبدؤ أ ّولا بتضمين ‪ dico.h‬إذا أردنا استدعاء دوال الملف ‪ . dico.c‬بالإضافة إلى ذلك‪ ،‬سنقوم‬
‫أيضا ًبتضمين ‪ string.h‬لأننا سنستعمل الدالة ‪: strlen‬‬

‫>‪1 #include <string.h‬‬
‫”‪2 #include ”dico.h‬‬

‫للبدأ‪ ،‬سيتم تغيير كيفية تعر يف المتغيرات‪ ،‬فنحن مثلا ُلن نهي ّئ قيمة المتغير ‪ ، secretWord‬سننشئ فقط‬
‫جدول محارف من ‪ 100) char‬خانة(‪.‬‬

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

‫لازلنا لا نعرف هذا الطول‪ ،‬سنكتفي بتعر يف مؤش ّر‪ .‬لاحقا ً سنستعمل الدالة ‪ malloc‬و جعل هذا المؤش ّر‬

‫يـ ُؤشّر على الخانة التي سيتم حجزها‪.‬‬
‫و هذا مثال يعبّر تماما عن حاجتنا الماسة لاستعمال الحجز الح ّي ‪ :‬نحن لا نعرف حجم الجدول قبل ترجمة الشفرة‪،‬‬

‫أي أننا مجـبرون على تعر يف مؤش ّر و استدعاء ‪. malloc‬‬

‫لا يجب أن ننسى تحرير الذاكرة حين لا نحتاج إلى الخانة التي تم حجزها‪ ،‬و لهذا سيتم استعمال الدالة ‪free‬‬
‫في نهاية الـ ‪. main‬‬

‫نحتاج أيضا ًإلى متغير ‪ wordSize‬و الذي سيحتوي …حجم الكلمة السر ية‪ .‬في الواقع‪ ،‬لو نلاحظ الـ ‪main‬‬
‫كما كان في الشفرة السابقة‪ ،‬فسنرى أنه كلّما احتجنا حجم الكلمة استعملنا العدد ‪) 3‬لأن الكلمة كانت ‪RED‬‬

‫ذات ‪3‬أحرف(‪ .‬لـكن حالي ّا‪ ،‬بما أن الكلمة ستتغير‪ ،‬فيجب على البرنامج أن يتلائم مع كل الكلمات‪.‬‬

‫‪251‬‬

Pendu‫ برمجة لعبة الـ‬.9.‫الفصل ب‬

: main ‫إليك إذن التعر يفات النهائية للمتغيّرات في الدالة‬

1 int main(int argc, char* argv[])
2
{

3 char letter = 0; // Stores the letter suggested by the user

4 char secretWord[100] = {0}; // The word that the user must

find

5 int *foundLetter = NULL; // Boolean table. Each box

corresponds to a letter in the secret word. 0 = letter not

found, 1 = letter found

6 int remainingTries= 10; // Counting the remaining tries (0 =

dead)

7 int i = 0; // A little variable to browse the table
8 int wordSize= 0;

: ‫ فلنلاحظ هذا‬، main ‫ستتغير بداية الدالة‬

1 if (!findWord(chosenWord))
2 exit(0);

findWord ‫ الدالة‬. if ‫ و ذلك يتم مباشرة داخل الشرط‬، findWord ‫نحن نستدعي أولا الدالة‬
‫ كما أنها ستقوم بإرجاع متغير منطقي‬. secretWord ‫ستقوم بوضع الكلمة التي اختارتها من القاموس في المتغير‬
‫ إذا لم يعمل الأمر فسنوقف البرنامج‬: ‫ أي أننا نقرؤ الشرط كالتالي‬،‫لنا لتخبرنا ما إن كانت العملية ناجحة أم لا‬

.( exit(0) )

1 wordSize = strlen(secretWord);

.ً ‫ كما شرح ُت سابقا‬wordSize ‫ في المتغير‬secretWord ‫نقوم بتخزين طول‬

1 foundLetter = malloc(wordSize * sizeof(int)); // We allocate

dynamically the table foundLetter ( that we ’dont know its size in

the beginning )

2 if (foundLetter == NULL)
3 exit(0);

‫ سنختبر‬. wordSize ‫ سنق ّدم له حجم الكلمة‬. foundLetter ‫و الآن سنحجز مكانا ًفي الذاكرة للجدول‬
‫ في هذه الحالة سنوقف البرنامج‬.‫ فالحجز قد فشل‬،‫ إذا كان كذلك‬. NULL ‫بعد ذلك ما إن كان المؤشّر يساوي‬

.( exit ‫حالا )باستعمال‬

.‫ فك ّل شيء قد عمل تماما‬،‫إذا تم ّت قراءة الأسطر السابقة‬

. wordSize ‫ بالمتغير‬3 ‫ يب ّقى أن تقوم باستبدال كل تكرار للرقم‬، main ‫هذه هي أهم التعديلات على الـ‬
: ‫مثال‬

1 for (i = 0 ; i < wordSize ; i++)
2 foundLetter[i] = 0;

252

(‫ استعمال قاموس الكلمات‬: 2) ‫التصحيح‬

. foundLetter ‫ في كل خانة من الجدول‬0 ‫هذه الشفرة تقوم بوضع القيمة‬

‫ فبدون هذا لا يمكن للدالة معرفة‬. wordSize ‫ لأضيف المتغير‬win ‫كان يفترض أن أضع نموذج الدالة‬
.‫متى توقف الحلقة التكرار ية‬

:‫ كاملا‬main.c ‫هذه هو الملف‬

1 #include <stdio.h>

2 #include <stdlib.h>

3 #include <ctype.h>

4 #include <string.h>

5 #include ”dico.h”

6 int win(int foundLetter[], int wordSize);

7 int findLetter(char letter, char secretWord[], int foundLetter[])

8 char readCharacter();

9 int main(int argc, char* argv[])
10
{

11 char letter = 0; // Stores the letter suggested by the user

12 char secretWord[100] = {0}; // The word that the user must

find

13 int *foundLetter = NULL; // Boolean table. Each box

corresponds to a letter in the secret word. 0 = letter not

found, 1 = letter found

14 int remainingTries = 10; // Counting the remaining tries (0

= dead)

15 int i = 0; // A little variable to browse the table
16 int wordSize = 0;
17 printf(”Welcome !\n\n”);
18 if (!findWord(chosenWord))
19 exit(0);
20 wordSize = strlen(secretWord);
21 foundLetter = malloc(wordSize * sizeof(int)); // We allocate

dynamically the table foundLetter ( that we ’dont know

its size in the beginning )

22
23 if (foundLetter == NULL)
24 exit(0);
25 for (i = 0 ; i < wordSize; i++)
26 foundLetter [i] = 0;
27 while (remainingTries > 0 && !win(foundLetter , wordSize))
28 {
29 printf(”\n\nYou have %ld remaining tries”,

remainingTries);

30 printf(”\’nWhats the secret word? ”);
31 for (i = 0 ; i < wordSize; i++)
32 {
33 if (foundLetter [i]) // If we have

found the letter n° i

34 printf(”%c”, secretWord[i]); // We

display it

35 else

253

Pendu‫ برمجة لعبة الـ‬.9.‫الفصل ب‬

36 printf(”*”); // Else, we display a *

for the letters that are not found

37 }
38 printf(”\nSuggest a letter : ”);
39 letter = readCharacter();
40 // If ’its not the right letter
41 if (!findLetter(letter , secretWord, foundLetter ))
42 {
43 remainingTries−−; // We decrement by

1 the remaining tries

44 }
45 }
46 if (win(foundLetter , wordSize))
47 printf(”\n\nYou win ! The secret word is : %s”,

secretWord);

48 else
49 printf(”\n\nTou lose ! The secret word is : %s”,

secretWord);

50 free(foundLetter ); // We free the allocated memory
51 return 0;
52 }
53 char readCharacter()
54 {
55 char character = 0;
56 character = getchar(); // We read the first character
57 character = toupper(character); // We uppercase the character
58 // We read other characters until we reach \n ( to erase

them )

59 while (getchar() != ’\n’) ;
60 return character; // We return the first character that we

read

61 }
62 int win(int foundLetter[], int wordSize)
63 {
64 int i = 0;
65 int playerWins= 1;
66 for (i = 0 ; i < wordSize ; i++)
67 {
68 if (foundLetter[i] == 0)
69 playerWins= 0;
70 }
71 return playerWins;
72 }
73 int findLetter(char letter, char secretWord[], int foundLetter[])
74 {
75 int i = 0;
76 int rightLetter = 0;
77 // We search for the letter in the table foundLetter
78 for (i = 0 ; secretWord[i] != ’\0’ ; i++)
79 {
80 if (letter == secretWord[i]) // If it exists

254

‫أفكار للتحسين‬ ‫{‬

‫‪81‬‬ ‫‪rightLetter = 1; // We memorize that‬‬
‫‪82‬‬ ‫‪it was the right one‬‬

‫‪83‬‬ ‫‪foundLetter[i] = 1; // We put the‬‬
‫‪correspondent value to 1 in the‬‬
‫‪table‬‬

‫‪84‬‬ ‫}‬
‫‪85‬‬ ‫}‬
‫‪86‬‬ ‫; ‪return rightLetter‬‬
‫} ‪87‬‬

‫ب‪ 4.9.‬أفكار للتحسين‬

‫تنز يل المشروع‬

‫للبدأ‪ ،‬أدعوكم لتنز يل المشروع عبر الرابط التالي‪:‬‬

‫‪https://openclassrooms.com/uploads/fr/ftp/mateo21/pendu_siteduzero.‬‬
‫‪(10 Ko) zip‬‬

‫إذا كنت تعمل على الماك أو اللينكس‪ ،‬قم بحذف الملف ‪ dico.txt‬و أنشئ واحدا ً جديدا ً‪ .‬على أي‬
‫حال فالملفات يتم حفظها بشكل مختلف على الويندوز ‪ :‬لهذا فقد تظهر لك بعض المشاكل لو استعملت المشروع‬
‫كما هو‪ .‬تأكّد من وجود كل كلمة في سطر وحدها‪ ،‬و ارجع إلى السطر بعد كتابة الكلمة الأخيرة في الملف )ليتم‬

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

‫أؤمن بأن هذا العمل كان صعبا بالنسبة للبعض من القراء‪.‬‬
‫ستجد في هذا الملف ‪ .zip‬ملفات من ‪ .h‬و ‪ .c‬كما تجد الملف ‪ .cbp‬الخاص بالمشروع‪ .‬إنه مشروع‬

‫تم إنشاؤه بالبيئة التطوير ية ‪.Code::Blocks‬‬
‫إن كنت تستعمل بيئة تطوير ية أخرى‪ ،‬فلا داعي للقلق‪ ،‬قم بإنشاء مشروع بنفسك‪ ،‬و ضع فيه يدو يا الملفات ‪.h‬‬
‫و ‪ .c‬المتواجدة في الملف ‪ . .zip‬ستجد أيضا ًالملف التنفيذي ) ‪ ( .exe‬و القاموس ) ‪.( dico.txt‬‬

‫تحسين الـ‪Pendu‬‬

‫إن مستوى شفرة اللعبة هذه‪ ،‬لابأس به‪ ،‬لدينا الآن لعبة تفتح ملفا و تأخذ منه كلمة عشوائية‪.‬‬

‫و لـكن مع ذلك سأعطيك بعض الأفكار التي يمكنك إدراجها للعبة بهدف تحسينها ‪:‬‬

‫‪255‬‬

‫الفصل ب‪ .9.‬برمجة لعبة الـ‪Pendu‬‬
‫• لحد الآن اللعبة تقترح علينا جولة واحدة‪ ،‬فسيكون من الأحسن لو نستعمل حلقة تكرار ية تسمح بلعب‬

‫جولة ثانية إذا كان اللاعب يريد ذلك !‬
‫• يمكنك أيضا ًأن تجعل اللعبة تسمح بلعب لاعبين‪ ،‬الأول يدخل الكلمة السر ية و الثاني يحاول تخمينها !‬
‫• هل ستتمكن من رسم رجل ) باستعمال الـ ‪ printf‬فقط‪ ،‬نحن في الـكونسول‪ ،‬تذكر ( يقوم بالتفاعل‬

‫مع اللاعب ؟ كأن يتأسف في حال ما إن أخطأ اللاعب في إيجاد الكلمة ؟‬
‫• يمكنك أن تطلب من اللاعب أن يختار صعوبة اللعبة‪ ،‬و حسب الصعوبة تغيّر في عدد المحاولات المسموحة‬

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

‫تطويرها و تحسينها‪ ،‬أريد منك أن تستطيع لاحقا ًبرمجة لعبة الـ‪ Pendu‬و عيناك مغمضتان !‬
‫هي ّا‪ ،‬بالتوفيق !‬

‫‪256‬‬

‫الفصل ب‪10.‬‬

‫إدخال ن ّص بشكل أكثر أمانا‬

‫إدخال النصوص في لغة الـ‪ C‬هي من أكثر الأمور حساسية‪ .‬أنت تعرف الدالة ‪ scanf‬التي تعر ّفنا عليها‬
‫في الدروس الأولى‪ .‬ستقول ‪ :‬و أ ّي الأدوات ستكون أكثر سهولة و طبيعية منها ؟ لـكن جهّز نفسك‪ ،‬بعد هذا‬

‫الدرس ستقول عنها أي شيء باستثناء ”بسيطة”‪.‬‬
‫الذين سيستعملون برنامجك هم بطبيعة الحال بشر‪ .‬فهناك منهم من يخطئ في كتابة شيء‪ ،‬بينما هناك من‬
‫يتعمّدون إرباك برنامجك بمعلومات غير منتظرة‪ .‬فإن طلبت من المستعمل ‪ :‬ما هو ع ُمرك ؟ من يضمن لك بأنه‬

‫لن يجيبك بـ‪ ”:‬إسمي فلان و أنا من البلد فلان” ؟‬
‫الهدف من هذا الدرس هو تعر يفك إلى بعض المشاكل التي يمكن أن نواجهها أثناء استعمالنا للدالة ‪، scanf‬‬

‫و تقديم دالة بديلة أكثر أمانا ًو هي ‪. fgets‬‬

‫ب‪ 1.10.‬حدود الدالة ‪scanf‬‬

‫هذه الدالة التي نستعملها جميعا ًمن الدروس الأولى في الكتاب‪ ،‬هي سلاح ذو حدين ‪:‬‬
‫• سهلة الاستعمال حينما نكون في مستوى ”مبتدئ” ‪ ،‬و لهذا السبب ع ّرفتك بها‪.‬‬
‫• لـكن الطر يقة التي تعمل بها مع ّقدة و يمكن أن تكون خطيرة في بعض الحالات‪.‬‬

‫ألا يبدو الأمر متناقضا ؟ فإن الدالة ‪ scanf‬سهلة الاستعمال و في نفس الوقت أكثر تعقيدا ً مما نتصور‪،‬‬
‫سأر يك الحدود التي يمكن لهذه الدالة أن تصل إليها و ذلك بتقديم مثالين واقعيين‪.‬‬

‫‪257‬‬

‫الفصل ب‪ .10.‬إدخال ن ّص بشكل أكثر أمانا‬

‫إدخال سلسلة محارف تحتوي على فراغات‬

‫لنفرض أننا طلبنا من المستعمل أن يقوم بإدخال سلسلة محارف في الـكونسول‪ ،‬و هو يقوم بكتابة فراغ في سلسلته ‪:‬‬

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

‫>‪2 #include <stdlib.h‬‬

‫‪3‬‬ ‫)][‪int main(int argc, char *argv‬‬
‫‪4‬‬
‫{‬

‫;}‪5 char name[20] = {0‬‬

‫;)” ? ‪6 printf(”What’s your name‬‬

‫;)‪7 scanf(”%s”, name‬‬

‫;)‪8 printf(”Ah ! Your name is %s !\n\n”, name‬‬

‫;‪9 return 0‬‬

‫} ‪10‬‬

‫‪What’s your name ? Mathieu Nebra‬‬
‫! ‪Ah ! Your name is Mathieu‬‬

‫لماذا اختفت الكلمة ”‪ ”Nebra‬؟‬

‫ذلك لأن الدالة ‪ scanf‬ٺتوقف عن القراءة حينما تصل إلى فراغ‪ ،‬أو رجوع إلى السطر أو محرف جدولة‬
‫)‪ .(tabulation‬يعني أنك غير قادر على قراءة سلسلة محرفي ّة تحتوي على فراغات‪.‬‬

‫في الواقع‪ ،‬الكلمة ”‪ ”Nebra‬لازالت مخز ّنة في الذاكرة‪ ،‬في شيء نسميه بالمتغير المؤق ّت )‪ ،(buffer‬المرة‬
‫القادمة عندما نستدعي الدالة ‪ scanf‬فهي ستقوم بقراءة الكلمة ”‪ ”Nebra‬وحدها الموجودة في المتغير‬

‫المؤقت‪.‬‬

‫يمكننا استعمال الدالة ‪ scanf‬بشكل يسمح لها بقراءة الفراغات‪ ،‬لـكن الأمر مع ّقد ج ّدا‪ .‬لمن يصرّ على‬
‫ذلك‪ ،‬يمكنك إيجاد دروس مف ّصلة على الويب‪ ،‬مثل الدرس الأجنبي المتوف ّر على هذا الرابط ‪:‬‬

‫‪http://xrenault.developpez.com/tutoriels/c/scanf/‬‬

‫;}‪1 char name[5] = {0‬‬ ‫إدخال سلسلة محارف طو يلة للغاية‬

‫يوجد مشكل آخر‪ ،‬أكثر خطورة‪ ،‬و هو تجاوز الذاكرة‪.‬‬
‫في الشفرة التي رأيناها‪ ،‬يوجد السطر التالي ‪:‬‬

‫‪258‬‬

‫حدود الدالة ‪scanf‬‬
‫ترى أنني قمت بحجز ‪ 5‬خانات من أجل الجدول المسمّى ‪ name‬الذي هو من نوع ‪ . char‬يعني أننا‬

‫قادرون على تخزين كلمة من ‪ 4‬محارف‪ ،‬بينما الحرف الأخير فهو محجوز لعلامة نهاية السلسلة ‪. \0‬‬
‫إذا نسيت ك ّل هذا فراجع درس السلاسل المحرفية‪.‬‬

‫المخطط التالي يمثل المكان الذي هو محجوز للكلمة التي ع ّرفناها ‪:‬‬

‫ماذا لو كتبنا عددا كبيرا من المحارف بالنسبة للمساحة المتوق ّعة لتخزين المتغير ؟‬

‫‪What’s your name ? Patrice‬‬
‫! ‪Ah ! Your name is Patrice‬‬

‫ستقول أن كل شيء على ما يرام لـكن الواقع أنك بصدد مواجهة أكبر كابوس لدى المبرمجـين !‬
‫لقد قمنا بـتجاوز في الذاكرة‪ ،‬هذا ما نسميه بـ‪ buffer overflow‬بالإنجليز ية‪.‬‬

‫كما ترى في المخطط التالي‪ ،‬لقد حجزت ‪ 5‬خانات لـكي تقوم باستعمال ‪ ،8‬ما الذي قامت به الدالة ‪ scanf‬؟‬
‫لقد قامت بمواصلة الكتابة في الذاكرة وكأن شيئا ًلم يحدث ! فلقد استغل ّت خانات ليس لها الحق في الكتابة فيها‪.‬‬

‫الذي جرى في الحقيقة‪ ،‬هو أن المحارف الزائدة تسببت في مسح معلومات من الذاكرة و استبدالها بهذه‬
‫المحارف‪ .‬هذا ما نسميه بالـ‪.buffer overflow‬‬

‫‪259‬‬

‫الفصل ب‪ .10.‬إدخال ن ّص بشكل أكثر أمانا‬

‫لم الأمر خطير ؟‬

‫دون الدخول في التفاصيل‪ ،‬لأنه بإمكاننا البدء في محادثة قدر ‪ 50‬صفحة و لا نتوقف أبدا ً‪ ،‬فلنقل بأنه‬
‫إن لم يقم البرنامج بالتحكم في حالات كهذه‪ ،‬فالمستعمل سيقوم بكتابة ما يحلو له و تخريب المعلومات المتواجدة‬
‫في الخانات التالية من الذاكرة‪ .‬أي أنه قادر على كتابة شفرة في تلك الخانات و برنامجك سيقوم بتشغيل تلك‬
‫الشفرات و كأنها تابعة له‪ ،‬و هذا ما نسميه بالهجوم عبر المتغير المؤقت ‪ ،buffer overflow attack‬نوع من‬

‫الهجومات المعروفة عند القراصنة‪ ،‬و لـكنه صعب التحقيق‪.‬‬
‫إذا كنت مهتما ًبهذا الموضوع‪ ،‬يمكنك قراءة المقال التالي من و يكيبيديا ) حذار‪ ،‬إن ّه مع ذلك معقد جدا ( ‪:‬‬

‫‪http://fr.wikipedia.org/wiki/D%C3%A9passement_de_tampon‬‬

‫الهدف من هذا الفصل هو تأمين قراءة البيانات و ذلك بمنع المستعمل من تجاوز الذاكرة و إحداث ‪buffer‬‬
‫‪ .overflow‬بالطبع كان بإمكاننا تعر يف جدول كبير للغاية ) ‪ 10.000‬خانة ( لـكن هذا لا يح ّل المشكل‬
‫فالشخص الذي يريد الوصول إلى الذاكرة ما عليه سوى إدخال سلسلة يتجاوز طولها ‪ 10.000‬محرف و سيعمل‬

‫هجومه كما يريد‪.‬‬
‫الشيء المحزن هو أن معظم المبرمجـين لا ينتبهون دائما لهذه الأخطاء‪ ،‬و لو أنهم قاموا بكتابة الشفرة من المرة‬

‫الأولى بشكل نظيف و صحيح‪ ،‬لما ظهرت كثير من الثغرات من التي نتح ّدث عنها اليوم‪.‬‬

‫ب‪ 2.10.‬استرجاع سلسلة محارف‬

‫توجد العديد من الدوال القياسي ّة في لغة ‪ C‬التي تسمح باسترجاع سلسلة ن ّصي ّة‪ .‬إضافة إلى الدالة ‪، scanf‬‬
‫و التي من الصعب دراستها هنا‪ ،‬لدينا ‪:‬‬

‫• ‪ : gets‬دالة تقرأ سلسلة محرفي ّة كاملة لـكنها خطيرة ج ّدا لأنها لا تعالج مشكل الـ‪.buffer overflow‬‬
‫• ‪ : fgets‬تشبه الدالة ‪ gets‬لـكنها تحمي البرنامج و ذلك بالتحكم في عدد المحارف المكتوبة في الذاكرة‪.‬‬

‫أعتقد أن الأمر مفهوم ‪ :‬على الرغم من أنها دال ّة قياسي ّة في الـ‪ gets ،C‬هي دال ّة خطيرة ج ّدا‪ .‬كل البرامج‬
‫ال ّتي تستخدمها عرضة لأن يكونوا ضحايا الـ‪.buffer overflow‬‬

‫سنرى كيف تعمل الدالة ‪ ، fgets‬و كيف نستعملها في برامجنا الخا ّصة في مكان الدالة ‪. scanf‬‬

‫الدال ّة ‪fgets‬‬

‫نموذج هذه الدالة‪ ،‬المتواجد في المكتبة ‪ stdio.h‬هو ‪:‬‬

‫‪260‬‬

‫استرجاع سلسلة محارف‬

‫;) ‪1 char *fgets( char *str, int num, FILE *stream‬‬
‫من المهم أن نفهم هذا النموذج‪ .‬معاملات الدالة هي التالية‪.‬‬

‫• ‪ : str‬مؤشّر نحو جدول في الذاكرة‪ ،‬أين ستتمكن الدالة من كتابة النص المدخل من طرف المستخدم‪.‬‬

‫• ‪ : num‬حجم الجدول ‪ str‬المرسل كمعامل أ ّول‪.‬‬

‫لاحظ أنه لو قمت بحجز جدول من ‪ ، char‬فإن الدالة ‪ fgets‬ستقرأ ‪ 9‬محارف على الأكثر ) آخر‬
‫خانة محجوزة للمحرف ‪ \0‬المشير إلى نهاية السلسلة (‪.‬‬

‫• ‪ : stream‬مؤش ّر نحو الملف الذي سنقرأ منه‪ .‬في حالتنا ”الملف المراد قراءته” هو الإدخال القياسي )‬
‫‪ ،( standard input‬أي لوحة المفاتيح‪ .‬لطلب قراءة الإدخال القياسي نرسل المؤش ّر ‪ stdin‬المعر ّف‬
‫تلقائيّا في الملفات الرأسي ّة للمكتبة القياسي ّة للـ‪ C‬ليشير إلى لوحة المفاتيح‪ .‬مع ذلك‪ ،‬يمكن استخدام ‪fgets‬‬

‫لقراءة المل ّفات‪ ،‬كما رأينا في الفصل الخاص بالمل ّفات‪.‬‬

‫الدالة ستقوم بإرجاع نفس المؤش ّر ‪ str‬للإشارة إلى إن كانت القراءة قد تمت بشكل صحيح أم لا‪ .‬يكفي‬
‫إذا أن نختبر ما إن كانت قيمة هذا المؤش ّر تساوي ‪ ، NULL‬فإن كانت كذلك‪ ،‬فهناك خطأ‪.‬‬

‫فلنجر ّب !‬

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

‫>‪2 #include <stdlib.h‬‬

‫‪3‬‬ ‫)][‪int main(int argc, char *argv‬‬
‫‪4‬‬
‫{‬

‫;]‪5 char name[10‬‬

‫;)” ? ‪6 printf(”What’s your name‬‬

‫;)‪7 fgets(name, 10, stdin‬‬

‫;)‪8 printf(”Ah ! Your name is %s !\n\n”, name‬‬

‫;‪9 return 0‬‬

‫} ‪10‬‬

‫‪What’s your name ? NEBRA‬‬
‫‪Ah ! Your name is NEBRA‬‬
‫!‬

‫الدالة تعمل بشكل جيد‪ ،‬مع تفصيل بسيط ‪ :‬عندما تضغط على زر الإدخال‪ ،‬تقوم ‪ fgets‬بالاحتفاظ‬
‫بـ ‪ \n‬الموافق‪ ،‬هذا ما يفسّر الرجوع إلى السطر بعد الكلمة ”‪ ”NEBRA‬كما يظهر في الـكونسول‪.‬‬

‫لا يمكننا أن نمنع هذه الدالة من كتابة المحرف ‪ \n‬لأن الدالة تعمل هكذا‪ .‬بالمقابل‪ ،‬هذا لا يمنع كتابتنا‬
‫لدالة خا ّصة بالإدخال تقوم نفسها باستدعاء ‪ fgets‬و حذف ذلك المحرف !‬

‫‪261‬‬

‫الفصل ب‪ .10.‬إدخال ن ّص بشكل أكثر أمانا‬

‫كتابة دالتك الخا ّصة بالإدخال باستخدام ‪fgets‬‬

‫ليس صعبا ًج ّدا أن نقوم بكتابة دالة خاصة بك تقوم ببعض التصحيحات من أجلك في ك ّل م ّرة‪.‬‬
‫سنسمّي هذه الدال ّة ‪ . read‬ستقوم بإرجاع القيمة ‪ 0‬إن كان هناك خطأ و ‪ 1‬إن لم يكن‪.‬‬

‫حذف الرجوع إلى السطر ‪\n‬‬

‫الدالة ‪ read‬تستدعي ‪ ، fgets‬إذا تم ّ ك ّل شيء على ما يرام‪ ،‬ستبحث عن المحرف ‪ \n‬بمساعدة الدالة‬

‫‪ strchr‬ال ّتي يفترض بك معرفتها‪ .‬إذا تم ّ العثور على ‪ ، \n‬فستستبدله بـ ‪ ) \0‬نهاية السلسلة ( لتجن ّب‬
‫الاحتفاظ بـ”علامة الإدخال”‪.‬‬

‫هاهي الشفرة عل ّقت عليها خطوة بخطوة ‪:‬‬

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

‫>‪2 #include <stdlib.h‬‬

‫)(‪3 #include <string.h> // Think to include string.h for strchr‬‬

‫‪4‬‬ ‫)‪int read(char *string, int length‬‬
‫‪5‬‬
‫{‬

‫‪6‬‬ ‫;‪char *inputPosition = NULL‬‬
‫‪7‬‬
‫‪// We read the text‬‬

‫? ‪8 if (fgets(string, length, stdin) != NULL) // No error‬‬

‫{‪9‬‬

‫‪10 inputPosition = strchr(string, ’\n’); // We search‬‬

‫‪11‬‬ ‫}‬ ‫”‪for the ”input‬‬
‫‪12‬‬ ‫‪else‬‬ ‫‪if (inputPosition != NULL) // If we find the \n‬‬
‫‪13‬‬ ‫{‬
‫{‬
‫‪14‬‬ ‫‪*inputPosition = ’\0’; // We replace‬‬
‫‪15‬‬ ‫}‬
‫‪16‬‬ ‫‪the character by \0‬‬
‫‪17‬‬ ‫}‬
‫‪18‬‬ ‫‪return 1; // We return 1 if there’s no error‬‬
‫‪19‬‬
‫‪20‬‬ ‫‪return 0; // We return 0 if there’s error‬‬
‫} ‪21‬‬

‫ستلاحظ أنه بالإمكان استدعاء الدالة ‪ fgets‬مباشرة داخل ‪ . if‬هذا اختصار كتابي‪ ،‬كي لا استعمل‬
‫مؤش ّرا يستقبل القيمة الم ُرجعة من الدالة ثم اختبر قيمته إن كانت ‪ NULL‬أم لا‪.‬‬

‫إنطلاقا من ‪ if‬الأول‪ ،‬أعرف هل ‪ fgets‬عملت على ما يرام أم حدث مشكل ما ) قام المستخدم‬
‫بادخال محارف أكبر من العدد المسموح به (‪.‬‬

‫إذا تم كل شيء بشكل جيد‪ ،‬سأذهب للبحث عن الـ ‪ \n‬باستعمال الدالة ‪ strchr‬ثم استبداله بالمحرف‬
‫‪ \0‬كما في الشكل التالي‪.‬‬

‫‪262‬‬

‫استرجاع سلسلة محارف‬

‫هذا المخطط يبې ّن أن السلسلة ال ّتي تمت قراءتها من طرف الدالة ‪ fgets‬هي ” ‪ ،” NEBRA\n\0‬ثم قمنا‬
‫باستبدال الـ ‪ \n‬بـ ‪ \0‬و هذا ما أعطانا ” ‪.،” NEBRA\0\0‬‬

‫ليس مشكلا أن توجد علامتا ‪ \0‬متتابعتان‪ .‬الحاسوب سيتوقف عند الإشارة الأولى و يعتبرها نهاية السلسلة‪.‬‬
‫و النتيجة ؟ حسنا‪ ،‬لقد عملت بشكل جي ّد‪.‬‬

‫)][‪1 int main(int argc, char *argv‬‬
‫{‪2‬‬
‫;]‪3 char name[10‬‬
‫;)” ? ‪4 printf(”What’s your name‬‬
‫;)‪5 read(name, 10‬‬
‫;)‪6 printf(”Ah ! Your name is %s !\n\n”, name‬‬
‫;‪7 return 0‬‬
‫}‪8‬‬

‫‪What’s your name ? NEBRA‬‬
‫! ‪Ah ! Your name is NEBRA‬‬

‫تفر يغ المتغيّر المؤق ّت‬

‫لم نصل بعد إلى نهاية الأمور المزعجة‪.‬‬
‫نحن لم نقم بتحليل الحالة التي يقوم فيها المستعمل بإدخال محارف أكثر من ما هو مسموح به !‬

‫‪What’s your name ? Jean Edouard Albert 1er‬‬
‫! ‪Ah ! Your name is Jean Edou‬‬

‫بما أن الدالة ‪ fgets‬تدعم الحماية‪ ،‬فهي توقفت عند الحرف التاسع الذي قام المستعمل بإدخاله لأنّنا حجزنا‬
‫جدولا من ‪ 10‬محارف ) يجب عدم نسيان أ ّن العاشر محجوز لإشارة نهاية السلسلة (‪ .‬المشكل هو أن بقي ّة‬
‫السلسلة ال ّتي لم تتم قراءتها‪ ”ard Albert 1er” .‬لم تختف ! و إن ّما لازالت موجودة في المتغير المؤق ّت‪ .‬هذا المتغير‬
‫المؤقت هو مكان في الذاكرة يعمل كوسيط بين لوحة المفاتيح و الجدول ال ّذي سيتم تخزين السلسلة فيه‪ .‬في الـ‪،C‬‬

‫لدينا مؤش ّر نحو المتغير المؤقت‪ ،‬و هو ‪ stdin‬الذي تكلمنا عنه قبل قليل‪.‬‬
‫أعتقد أن مخططا صغيرا سيساعد على توضيح الأمور‪.‬‬

‫‪263‬‬

‫الفصل ب‪ .10.‬إدخال ن ّص بشكل أكثر أمانا‬

‫حينما يقوم المستعمل بإدخال نص بلوحة المفاتيح‪ ،‬فإن نظام التشغيل ) ويندوز مثلا ( يقوم بنسخ النص‬
‫مباشرة في المتغير المؤق ّت ‪. stdin‬‬

‫مهمة الدالة ‪ fgets‬هي إحضار المحارف الموجودة في المتغير المؤقت ووضعها في الذاكرة التي قمت أنت‬
‫بتحديدها ) الجدول ‪.( string‬‬

‫بعد القيام بعملها‪ ،‬تمسح ما قامت بنسخه من المتغير المؤق ّت‪.‬‬

‫إذا عمل كل شيء على ما يرام‪ ،‬فالدالة ‪ fgets‬ستقوم بإفراغ كل محتوى المتغير المؤق ّت‪ ،‬أي أن هذا‬
‫الأخير سيكون فارغا ً بعد استدعاء الدالة‪ .‬لـكن في الحالة التي يقوم المستخدم بإدخال كثير من المحارف لا‬
‫يمكن أن يسعها المكان المحجوز لها‪ ،‬فإنه يتم مسح الحروف التي تمت قراءتها فقط‪ ،‬و بالتالي بعد استدعاء الدالة‬

‫‪ fgets‬فإن المتغير المؤق ّت يحتوي دائما المحارف المتب ّقية !‬

‫فلنجر ّب مع سلسلة كبيرة ‪:‬‬

‫‪1‬‬ ‫)][‪int main(int argc, char *argv‬‬
‫‪2‬‬
‫{‬

‫;]‪3 char name[10‬‬

‫;)” ? ‪4 printf(”What’s your name‬‬

‫;)‪5 read(name, 10‬‬

‫;)‪6 printf(”Ah ! Your name is %s !\n\n”, name‬‬

‫;‪7 return 0‬‬

‫}‪8‬‬

‫‪264‬‬

‫استرجاع سلسلة محارف‬

‫‪What’s your name ? Jean Edouard Albert 1er‬‬
‫! ‪Ah ! Your name is Jean Edou‬‬

‫الدالة ‪ fgets‬قامت بنسخ المحارف التسعة الأولى كما كان متوق ّعا‪ .‬المشكل هو أن المحارف المتبقية لازالت‬
‫في المتغير المؤقت !‬

‫هذا يعني أنه لو استدعينا الدالة ‪ fgets‬مرة أخرى فإنها ستقوم بقراءة ما كان متب ّقيا في المتغير المؤقت !‬

‫فلنجر ّب هذه الشفرة ‪:‬‬

‫‪1‬‬ ‫)][‪int main(int argc, char *argv‬‬
‫‪2‬‬
‫{‬

‫;]‪3 char name[10‬‬

‫;)” ? ‪4 printf(”What’s your name‬‬

‫;)‪5 read(name, 10‬‬

‫;)‪6 printf(”Ah ! Your name is %s !\n\n”, name‬‬

‫;)‪7 read(name, 10‬‬

‫;)‪8 printf(”Ah ! Your name is %s !\n\n”, name‬‬

‫;‪9 return 0‬‬

‫} ‪10‬‬

‫نحن نقوم باستدعاء الدالة ‪ read‬م ّرتين لـكنك ستلاحظ أن ّه لن يتم السماح لك بإدخال اسمك مرتين‪،‬‬
‫وذلك لأن الدالة ‪ fgets‬لن تطلب من المستخدم إدخال أ ّي ن ّص في المر ّة الثانية لأ ّنها ستجده في المتغير‬

‫المؤقت !‬

‫‪265‬‬

‫الفصل ب‪ .10.‬إدخال ن ّص بشكل أكثر أمانا‬

‫‪What’s your name ? Jean Edouard Albert 1er‬‬
‫! ‪Ah ! Your name is Jean Edou‬‬
‫! ‪Ah ! Your name is ard Alber‬‬

‫إذا قام المستعمل بإدخال محارف كثيرة‪ ،‬فإن الدالة ‪ fgets‬ستحمي البرنامج من مشكل تجاوز الذاكرة‪،‬‬
‫لـكن يبقى دائما آثار الن ّص في المتغير المؤقت‪ .‬لذا يجب تفر يغ هذا الأخير‪.‬‬

‫سنقوم إذا بتحسين عمل الدالة ‪ ، read‬و سنقوم في الحالات التي ٺتطلب ذلك باستدعاء دالة نسميها‬
‫‪ ، clearBuffer‬لـكي نتأكد من تفر يغ المتغير المؤقت في حال ما احتوى على محارف زائدة ‪:‬‬

‫)(‪1 void clearBuffer‬‬

‫{‪2‬‬

‫;‪3 int c = 0‬‬

‫)‪4 while (c != ’\n’ && c != EOF‬‬

‫{‪5‬‬

‫;)(‪6 c = getchar‬‬

‫}‪7‬‬

‫}‪8‬‬

‫‪9‬‬ ‫)‪int read(char *string, int length‬‬
‫‪10‬‬
‫{‬

‫‪11‬‬ ‫;‪char *inputPosition = NULL‬‬
‫‪12‬‬
‫)‪if (fgets(string, length, stdin) != NULL‬‬

‫{ ‪13‬‬

‫;)’‪14 inputPosition = strchr(string, ’\n‬‬

‫)‪15 if (inputPosition != NULL‬‬

‫{ ‪16‬‬

‫‪17‬‬ ‫;’‪*inputPosition = ’\0‬‬
‫‪18‬‬
‫}‬

‫‪19 else‬‬

‫{ ‪20‬‬

‫;)(‪21 clearBuffer‬‬

‫} ‪22‬‬

‫;‪23 return 1‬‬

‫} ‪24‬‬

‫‪25 else‬‬

‫{ ‪26‬‬

‫;)(‪27 clearBuffer‬‬

‫;‪28 return 0‬‬

‫} ‪29‬‬

‫} ‪30‬‬

‫الدالة ‪ read‬تستدعي الدالة ‪ clearBuffer‬في حالتين ‪:‬‬

‫• السلسلة المدخلة طو يلة جدا ً ) يمكننا أن نعرف ذلك بعدم وجود الإشارة ‪ \0‬في السلسلة المنسوخة (‬
‫• إذا حدث أي خطأ مهما كان‪ ،‬يجب تفر يغ محتوى المتغير المؤقت لأسباب حماية لـكي لا يبقى شيء هناك‪.‬‬

‫‪266‬‬

‫تحو يل سلسلة محرفي ّة إلى عدد‬

‫الدالة ‪ clearBuffer‬قصيرة لـكنها عميقة‪ .‬فهي تقرأ المتغير المؤقت محرفا ًمحرفا ًباستعمال الدالة ‪. getchar‬‬
‫هذه الدالة تقوم بإرجاع ‪ ) int‬و ليس ‪ ، char‬سوف تعرف السبب لاحقا‪ ،‬أيّا يكن (‪.‬‬

‫سنكتفي نحن باسترجاع القيمة في متغير ‪ c‬من نوع ‪ . int‬نقوم بحلقة تكرار ية مادمنا لم نقرأ بعد المحرف ‪\0‬‬
‫أو الرمز ‪ ) EOF‬نهاية الملف ( و هما يعنيان ‪ :‬لقد وصلت إلى نهاية المتغير المؤقت‪ .‬سنتوق ّف عند الوصول إلى‬

‫أحد هذين المحرفين‪.‬‬

‫يبدو عمل الدالة ‪ clearBuffer‬صعبا ً قليلا ً لـكنها تقوم بعملها‪ .‬لا تتردد في تكرار قراءة الشرح عدة‬
‫مرات من أجل الفهم الجيد‪.‬‬

‫ب‪ 3.10.‬تحو يل سلسلة محرفي ّة إلى عدد‬

‫دالتنا ‪ read‬هي فعالة و قو ي ّة الآن‪ ،‬لـكنها تجيد قراءة النصوص فقط‪ .‬ستتساءل حتما ‪” :‬لـكن كيف‬
‫نقوم باسترجاع عدد ؟”‬

‫الحقيقة أن الدالة ‪ fgets‬هي دالة مبدئية‪ .‬مع ‪ fgets‬لا يمكن قراءة سوى النصوص‪ ،‬و لـكن توجد‬
‫دوال أخرى تقوم بتحو يل النص إلى عدد‪.‬‬

‫‪ : strtol‬تحو يل سلسلة محرفي ّة إلى ‪long‬‬

‫نموذج هذه الدالة خاص نوعا ًما ‪:‬‬
‫;) ‪1 long strtol( const char *start, char **end, int base‬‬

‫الدالة ستقوم بقراءة السلسلة المحرفي ّة المرسلة إليها ) ‪ ( start‬و ستحاول تحو يلها إلى ‪ long‬باستعمال‬
‫الأساس ) ‪ ( base‬المحدد ) غالبا ً ما نستعمل الأساس ‪ ،10‬لأننا نستعمل الأرقام من ‪ 0‬إلى ‪ ،9‬و لهذا ضع‬

‫مكانه العدد ‪ .( 10‬ستقوم بإرجاع العدد الذي نجحت في قراءته‪.‬‬
‫بالنسبة لمؤشر المؤشر ‪ ، end‬فالدالة ستقوم استغلاله لإرجاع أول محرف صادفته و لم يكن رقما ً‪ .‬لـكننا لسنا‬

‫بحاجة إليه‪ ،‬فلنكتفي بوضع ‪ NULL‬مكانه لنقول أننا لا نريد استرجاعه‪.‬‬

‫على السلسلة المحرفي ّة أن تبدأ برقم‪ ،‬فبعد العدد كل شيء يتم تجاهله‪ .‬يمكن أن تكون مسبوقة بفراغات‪.‬‬
‫هذه أمثلة للفهم الجيد ‪:‬‬

‫;‪1 long i‬‬
‫‪2 i = strtol( ”148”, NULL, 10 ); // i = 148‬‬
‫‪3 i = strtol( ”148.215”, NULL, 10 ); // i = 148‬‬
‫‪4 i = strtol( ” 148.215”, NULL, 10 ); // i = 148‬‬
‫‪5 i = strtol( ” 148+34”, NULL, 10 ); // i = 148‬‬
‫‪6 i = strtol( ” 148 dead leaves”, NULL, 10 ); // i = 148‬‬
‫( ‪7 i = strtol( ” There are 148 dead leaves”, NULL, 10 ); // i = 0‬‬

‫)‪error : The string ’doesnt start with a number‬‬

‫‪267‬‬

‫الفصل ب‪ .10.‬إدخال ن ّص بشكل أكثر أمانا‬

‫كل السلاسل التي تبدأ برقم ) أو ربما بفراغات قبله ( سيتم تحو يلها إلى ‪ long‬حتى الوصول إلى محرف‬
‫غير مقبول ) نقطة‪ ،‬فاصلة‪ ،‬علامة استفهام‪ ،‬زائد‪ ،‬الخ (‪.‬‬

‫بالنسبة لسلسلة لا تبدأ بأرقام و أو بفراغات تليها أرقام‪ ،‬فلا يمكن تحو يلها و بالتالي تقوم الدالة بإرجاع‬
‫القيمة ‪.0‬‬

‫يمكننا كتابة الدالة ‪ ، readLong‬و التي تقوم باستدعاء الدالة ‪ ) read‬لقراءة النص (‪ ،‬و بعد ذلك تحو يل‬
‫النص إلى عدد ‪:‬‬

‫)(‪1 long readLong‬‬
‫{‪2‬‬
‫‪3 char textNumber[100] = {0}; // 100 boxes are sufficient‬‬
‫))‪4 if (read(textNumber, 100‬‬
‫{‪5‬‬
‫‪6 // If we read the text without problems, we convert‬‬

‫‪7‬‬ ‫}‬ ‫‪textNumber to long and we return it‬‬
‫‪8‬‬ ‫‪else‬‬ ‫;)‪return strtol(textNumber, NULL, 10‬‬
‫‪9‬‬ ‫{‬
‫‪10‬‬ ‫‪// If ’theres a problem, we return 0‬‬
‫‪11‬‬ ‫}‬ ‫;‪return 0‬‬
‫‪12‬‬
‫‪13‬‬
‫} ‪14‬‬

‫يمكنك تجريب الشفرة داخل ‪ main‬بسيط‪.‬‬

‫)][‪1 int main(int argc, char *argv‬‬
‫{‪2‬‬
‫;‪3 long age = 0‬‬
‫;)” ? ‪4 printf(”How old are you‬‬
‫;)(‪5 age = readLong‬‬
‫;)‪6 printf(”Ah ! You are %d years old !\n\n”, age‬‬
‫;‪7 return 0‬‬
‫}‪8‬‬

‫‪How old are you ? 18‬‬
‫!‪Ah ! You are 18 years old‬‬

‫‪ strtod‬تحو يل سلسلة محرفي ّة إلى ‪double‬‬

‫الدالة ‪ strtod‬مطابقة للدالة ‪ ، strtol‬الفرق الوحيد هو أنها ستحاول قراءة عدد عشر ّي و إرجاع‬
‫‪. double‬‬

‫;) ‪1 double strtod( const char *start, char **end‬‬

‫‪268‬‬

‫مل ّخص‬

‫تجد أن المعامل الثالث ‪ base‬اختفى هنا‪ ،‬بينما يبقى مؤش ّر المؤش ّر ‪ end‬ال ّذي لا يفيدنا في شيء‪.‬‬

‫على خلاف الدالة السابقة‪ ،‬فإن هذه الدالة ستأخذ في الحسبان ”النقطة” العشر ية‪ .‬عندما أقول نقطة يعني‬
‫أن الدالة لا تقبل الفاصلة ”‪ ) ”,‬يبدو أ ّنها مبرمجة من طرف ناطقين بالإنجليز ية (‪.‬‬

‫فلتقم بكتابة الدالة ‪ readDouble‬بنفسك‪ .‬إن كتابتها مماثلة للدالة ‪ ، readLong‬الاختلاف الوحيد هو‬
‫أنها ستستدعي الدالة ‪ strtod‬ثم ستقوم بإرجاع قيمة ‪. double‬‬

‫يعني أنك ستكتب التالي في الـكونسول ‪:‬‬

‫‪What’s your weight ? 67.4‬‬
‫! ‪Ah ! Your weight is 67.400000 kg‬‬

‫حاول بعد ذلك تعديل الدالة ‪ readDouble‬لتقبل الفاصلة أيضا ً كفاصل عشري‪ .‬إن الأمر بسيط ‪:‬‬
‫فقط قم باستبدال كل تكرار للمحرف ” ‪ ” ,‬بالمحرف ” ‪ ) ” .‬بالاستعانة بالدالة ‪ ،( strchr‬ثم قم ببعث‬

‫النص الجديد إلى الدالة ‪. strtod‬‬

‫مل ّخص‬

‫• الدالة ‪ scanf‬بالرغم من أنها تبدو سهلة و طبيعية إلا انها مع ّقدة و تفرض علينا بعض الحدود‪ .‬فمثلا ً‪،‬‬
‫هي لا تقبل قراءة نص يحتوي فراغات‪.‬‬

‫• نقول أننا تسببنا في الـ‪ buffer overflow‬إذا تجاوزنا المساحة المخصصة في الذاكرة‪ ،‬فمثلا ً لو قام المستخدم‬
‫بإدخال ‪ 10‬محارف و نحن قد حجزنا ‪ 5‬خانات فقط‪.‬‬

‫• الحل الأمثل هو استدعاء الدالة ‪ fgets‬لتقوم باسترجاع النص الذي ي ُدخله المستعمل‪.‬‬
‫• يجب أن تتجنب استعمال الدالة ‪ gets‬بأي ثمن لأ ّنها لا تحمي من الـ‪.buffer overflow‬‬
‫• يمكنك كتابة دالة خاصة بك‪ ،‬تقوم باستدعاء الدالة ‪ fgets‬كما فعلنا لـكيّ تح ّسن عملها‪.‬‬

‫‪269‬‬

‫الفصل ب‪ .10.‬إدخال ن ّص بشكل أكثر أمانا‬
‫‪270‬‬

‫الجزء ج‬

‫إنشاء ألعاب ‪ 2D‬في ‪SDL‬‬

‫‪271‬‬



‫الفصل ج‪1.‬‬

‫ٺثبيت الـ‪SDL‬‬

‫ابتداءا ً من الآن‪ ،‬إنتهت الدروس النظر ية ! لأننا سنمر ّ إلى مرحلة مهمّة‪ ،‬و سنستمتع بالتطبيق بالإستعانة‬
‫بمكتبة نسميها ‪.SDL‬‬

‫في الدروس السابقة كنا قد تطر ّقنا تقريبا ً لك ّل أساسيات اللغة ‪ ،C‬لـكن تبقى هناك دائما ً بعض التفاصيل‬
‫الصعبة نوعا ًما لنكتشفها‪ .‬سأقول لك بأنه يمُكن لهذا الكتاب أن يتوق ّف هنا مخـبرا إيّاك ‪” :‬نعم لقد تعل ّمت البرمجة‬
‫بلغة ‪ ،”C‬لـكني متأكّد بأن الجميع سيشاركني الرأي لو قلت بأن الم ُبرمج سيح ّس نفسه دائما ًمبتدئا ًمادام لم ”يخرج”‬

‫من الـكونسول !‬

‫الـ‪ SDL‬هي مكتبة ت ُستخدم خا ّصة لإنشاء ألعاب ثنائية الأبعاد‪ .‬سنتعر ّف في هذا الدرس على هذه المكتبة‬
‫و نتعلّم كيف نقوم بتثبيتها‪.‬‬

‫نسمي هذا النوع من المكتبات بمكتبات الطرف الثالث )‪ .(third party libraries‬يجب أن تعرف أنه هناك‬
‫نوعين من المكتبات ‪:‬‬

‫• المكتبة القياسية )‪ : (standard library‬و هي المكتبة القاعدية التي تعمل على ك ّل أنظمة التشغيل )من‬
‫هنا تم استنباط الكلمة ‪ (standard‬و هي تسمح بالقيام بأمور بسيطة كـ ‪ . printf‬هذه المكتبات يتم ّ‬

‫تسطيبها تلقائيّا عند ٺثبيتك للبيئة التطوير ية و المترجم‪.‬‬
‫خلال الجزئين الأ ّولين من هذا الكتاب‪ ،‬كنا ّقد استعملنا المكتبة القياسي ّة فقط ) ‪، stdio.h ، stdlib.h‬‬
‫‪ .(… time.h ، string.h‬لم نقم بدراستها بالتفصيل لكن ّا جرّبنا منها جزءا ً كبيرا ً‪ .‬إن كنت تريد‬
‫معرفة المزيد عن هذا النوع من المكتبات أ ْجرِ بحثا ً في ‪ ،Google‬مثلا ً بكتابة ”‪ ،”C standard library‬و‬

‫ستجد نماذج الدوال في هذه المكتبة‪ ،‬بالإضافة إلى شرح قصير حول دور ك ّل دالة‪.‬‬
‫• مكتبات الطرف الثالث )‪ :(third party libraries‬هي مكتبات لا يتم ٺثبيتها تلقائيا‪ .‬و إن ّما يجب عليك‬

‫تنز يلها من الأنترنت و ٺثبيتها بنفسك على حاسوبك‪.‬‬

‫‪273‬‬

‫الفصل ج‪ .1.‬ٺثبيت الـ‪SDL‬‬

‫على عكس المكتبات القياسية‪ ،‬التي تكون بسيطة نسبي ّا و تحتوي على عدد قليل من الدوال‪ ،‬فإنه توجد‬
‫الآلاف من مكتبات الطرف الثالث‪ ،‬و التي تمت كتابتها من طرف مبرمجـين آخرين‪ .‬بعضها جي ّدة‪ ،‬و‬
‫أخرى أقل‪ ،‬بعضها مدفوع‪ ،‬و بعضها الآخر مجاني‪ ،‬إلخ‪ .‬الأمر المثالي هو إيجاد مكتبة جي ّدة و مجانية في‬

‫نفس الوقت !‬

‫إنه لمن المستحيل أن أضع لك درسا ًيشرح كل المكتبات الموجودة‪ .‬حت ّى لو أمضيت حياتي كل ّها ‪ 24‬ساعة‬
‫‪ ،24 /‬لن أستطيع !‬

‫لذا سأق ّدم لك مكتبة واحدة فقط مكتوبة بالـ‪ C‬و مُستعملة من طرف مبرمجـين مثلك‪.‬‬
‫هذه المكتبة تدعى ‪ .SDL‬السؤال المطروح هو لماذا اخترت هذه المكتبة بالضبط ؟ ما الذي يميّزها عن باقي‬

‫المكتبات ؟‬
‫هذه أسئلة سأبدأ في الإجابة عليها إنطلاقا ًمن الآن‪.‬‬

‫ج‪ 1.1.‬لماذا نختار الـ‪ SDL‬؟‬

‫اختيار مكتبة ليس بالأمر السهل !‬

‫كما قلت لك الآن‪ ،‬توجد الآلاف من المكتبات للتنز يل‪.‬‬
‫بعضها بسيط‪ ،‬و بعضها كبير جدا ً لدرجة أن درسا ًكهذا لا يكفي أن يشرحها كل ّها !‬

‫الاختيار صعب‪ .‬لـكن ّي اخترت هذه المكتبة‪ ،‬التي هي نوعا ًما سهلة الاستعمال‪ ،‬كبداية‪ .‬ستكون هذه إذا‬
‫أ ّول مكتبة تقوم باستعمالها )إذا لم نحسب المكتبة القياسية(‪.‬‬

‫إنه من الواضح أن أغلب القر ّاء يريدون معرفة كيفية فتح نوافذ‪ ،‬إنشاء لعبة‪ ،‬إلخ‪ .‬و لـكن إن كنت تحب‬
‫الـكونسول فيمكننا الاستمرار فيها لوقت أطول‪ ،‬إذا أردت‪ ،‬لا ؟ إذا لدينا هنا بعض الفضول !‬

‫أودّ كثيرا ً أن أر يك كيف تعمل ك ّل هذه الأمور‪ ،‬لـكننا سنحاول أن نتطر ّق إليها خطوة بخطوة‪ ،‬و بالنسبة‬
‫للأعمال التطبيقية‪ ،‬فلدينا عملان تطبيقيان لهذا الجزء من الكتاب !‬

‫لقد اخترت لك مكتبة سهلة و قو ية‪ ،‬ستكون كبداية لك في تحقيق )تقريبا( أحلامك المتعل ّقة بالواجهة‬
‫الرسومية‪ ،‬و من دون تعب )حسنا ً‪ ،‬ك ّل شيء نسبيّ بالطبع !(‪.‬‬

‫الـ‪ ،SDL‬اختيار جي ّد !‬

‫سنقوم الآن بدراسة هذه المكتبة‪ .‬لماذا اخترتها هي و ليس أخرى ؟‬

‫‪274‬‬

‫لماذا نختار الـ‪ SDL‬؟‬

‫• هي مكتبة مكتوبة بلغة ‪ : C‬أي أنه بإمكان المبرمجـين أن يستعملوها في برامجهم المكتوبة بالـ‪ .C‬و كما هو‬
‫الحال بالنسبة لأغلب المكتبات المكتوبة بالـ‪ ،C‬يمكن استعمالها في لغة الـ‪ C++‬بالإضافة إلى لغات برمجية‬

‫أخرى‪.‬‬
‫• هي مكتبة حُرّة و مجانية ‪ :‬و هذا كي لا تضطر ّ لدفع أي ثمن مقابل استعمالك ما سأق ّدمه لك في بقي ّة‬
‫الكتاب‪ .‬على عكس ما قد نعتقد‪ ،‬إيجاد مكتبة جيدة و مجانية ليس أمرا ً صعبا ًكثيرا ً‪ ،‬فقد انتشرت كثيرا ً‬
‫في أيامنا هذه‪ .‬المكتبة الحرة هي ببساطة مكتبة يمكنك الحصول على الشفرة المصدر ية الخاصة بها‪ .‬في‬
‫حالتنا هذه‪ ،‬رؤ ية الشفرة ليس مُهمّا بالنسبة لنا‪ .‬لـكن كونها حرة يفتح لنا الباب من أجل ميزات أخرى‬
‫أهم ّها المداومة )أي أنه إن توقف صاحب المكتبة عن تطويرها‪ ،‬يمُكن لمبرمجـين آخرين أن يكملوا عمله(‪،‬‬

‫بالإضافة إلى مج ّاني ّتها غالبا‪ .‬هذا يعني عدم إمكانيّة اختفاء المكتبة في يوم من الأيام‪.‬‬
‫• ي ُمكنك إنشاء برامج تجار ية ذات ملـكية خاصة بفضل هذه المكتبة‪ .‬قد أكون قد تسرّعت بهذا الكلام‪،‬‬

‫لـكن ّه يجب اختيار مكتبة حرّة تمنحك الحر ي ّة الأقصى‪ .‬الحقيقة أنه يوجد نوعان من المكتبات الح ُرة ‪:‬‬
‫– المكتبات تحت رخصة ‪ : GPL‬مكتبات مجانية‪ ،‬و يمكنك رؤ ية الشفرة المصدر ية الخاصة بها‪ ،‬لـكن‬

‫بشرط أن تقوم أنت كذلك بنشر الشفرة المصدر ية الخاصة بالبرنامج الذي أنشأته باستخدامها‪.‬‬
‫– المكتبات تحت رخصة ‪ : LGPL‬مثل سابقتها‪ ،‬لـكن ليس عليك أن تنشر الشفرة المصدر ية الخاصة‬

‫بالبرنامج‪ .‬أي أنه يمكنك بها إنشاء برامج مملوكة‪.‬‬

‫بالرغم من أنه يمكنك قانونيّا عدم نشر الشفرة المصدر ية الخاصة بالبرنامج‪ ،‬إلا أنني أنصحك بذلك‪.‬‬
‫فبهذا يمكنك أن تأخذ رأي المبرمجـين الأكثر تمر ّسا ً منك‪ .‬و هذا يسمح لك بالتح ّسن‪ .‬بعد هذا‪،‬‬
‫فإن إنشاء برنامج حُر أو ذو ملـكية خاصة‪ ،‬يرجع لطبيعة تفكير كل شخص‪ .‬لن أدخل في نقاش‬

‫بخصوص هذا الموضوع‪ ،‬لـكن فلتعلم أن ك ّل النوعين له مميزاته و مساوئه‪.‬‬

‫• هي مكتبة متعددة المن ّصات )‪ : (multi-platform‬سواء كنت على الويندوز‪ ،‬الماك أو اللينكس‪ ،‬ستعمل‬
‫لديك هذه المكتبة‪ .‬و الحقيقة أن هذه نقطة قوّة يراها المبرمجون بالمكتبة ‪ :‬يمكنها أن تعمل على عدد كبير‬
‫جدا ً من أنظمة التشغيل‪ ،‬فعلى غرار الويندوز و الينكس و الماك‪ ،‬هي تشتغل أيضا ًعلى ‪،Amiga ،Atari‬‬
‫‪… Dreamcast ،Symbian‬إلخ‪ .‬أي أنه بالإمكان لبرامجك أن تعمل حتى على أجهزة ‪ Atari‬القديمة ! مع‬

‫ذلك يجب القيام ببعض التعديلات و رب ّما استخدام مترجم خاص‪ .‬لن أدخل في التفاصيل هنا‪.‬‬

‫‪275‬‬

‫الفصل ج‪ .1.‬ٺثبيت الـ‪SDL‬‬

‫• أخيرا‪ ،‬فإن هذه المكتبة تسمح لك بالقيام بالـكثير من الأمور الممتعة التي سنتعر ّف إليها من خلال الدروس‬
‫القادمة‪ .‬لا أقول أ ّن مكتبة ر ياضي ّاتيّة قادرة على ح ّل معادلات من الدرجة الرابعة ليست ممتعة‪ ،‬لـكن ّي‬

‫سأركّز على أن يكون هذا الدرس سهلا قدر الإمكان لـكيّ يحث ّك على البرمجة‪.‬‬

‫هذه المكتبة ليست مخصصة فقط لإنشاء ألعاب الفيديو‪ .‬سأعترف بأن معظم البرامج التي تمت كتابتها بهذه‬
‫المكتبة‪ ،‬هي عبارة عن ألعاب‪ ،‬لـكن هذا لا يعني أنك مجـبر لاستعمالها من أجل ذلك ‪ .‬فكما نعلم‪ ،‬ك ّل شيء‬
‫ممكن بالعمل و الاجتهاد‪ .‬كنت قد رأيت من قبل محرر نصوص تمت برمجته بالـ‪ ،SDL‬غلى الرغم من أن ّه هناك‬
‫مكتبات أخرى أحسن لهذا الغرض‪ .‬إن كنت تريد برمجة واجهة رسومية تقليدي ّة تسمح بإظهار نافذة‪ ،‬زر‪،‬‬

‫قائمة‪ ،‬إلخ‪ .‬فأنا أنصحك إذا بالتوجّه إلى المكتبة ‪.GTK+‬‬

‫الإمكانية المتاحة بالـ‪SDL‬‬

‫المكتبة ‪ SDL‬هي مكتبة منخفضة المستوى‪ .‬هل ٺتذكر أول الدروس حينما تكلّمت لك عن لغات البرمجة عالية‬
‫المستوى و لغات البرمجة منخفضة المستوى ؟ هذا ينطبق على المكتبات أيضا ً‪.‬‬

‫• المكتبات منخفضة المستوى ‪ :‬تحتوي على دوال قاعدية ج ّدا‪ .‬يوجد عدد قليل من هذه الدوال لأن ّه‬
‫يمكننا القيام بك ّل شيء بها‪ .‬و هذه الدوال لبساطتها تكون سر يعة ج ّدا‪ .‬لهذا فالبرامج المنشأة بهذا النوع‬

‫من المكتبات تكون عادة الأسرع‪.‬‬
‫• المكتبات عالية المستوى ‪ :‬تحتوي على الـكثير من الدوال التي تسمح بالقيام بالـكثير من المهام‪ .‬هذا يجعلها‬

‫أبسط من ناحية الاستخدام‪.‬‬
‫لـكن هذا النوع من المكتبات يكون عادة ”كبيرا”‪ ،‬و ليس من السهل دراستها و معرفتها بأكملها‪ .‬كما أنها‬

‫قد تكون أثقل من المكتبات منخفضة المستوى )لـك ّن هذا قد لا يكون واضحا(‪.‬‬

‫على العموم‪ ،‬لا يمكننا القول بأن ”مكتبة منخفضة المستوى هي أحسن من مكتبة عالية المستوى” أو العكس‪.‬‬
‫فك ّل منهما لها مميزات و مساوئ‪ .‬الـ‪ SDL‬التي سنقوم بدراستها‪ ،‬تنتمي إلى المكتبات منخفضة المستوى‪.‬‬

‫يجب إذا أن ٺتذكر بأن الـ‪ SDL‬تق ّدم دوالا قاعدية‪ .‬يمكنك إذا الرسم بيكسلا ببيكسل‪ ،‬رسم مستطيل أو‬
‫إظهار صور‪ .‬هذا ك ّل شيء‪ ،‬و ص ّدقني أ ّن هذا كا ٍف‪.‬‬

‫• بتحر يك صورة‪ ،‬يمكنك أن تقوم بتحر يك شخصي ّة‪.‬‬
‫• بإظهار العديد من الصور الواحدة تلو الأخرى بسرعة‪ ،‬يمكنك إنشاء تحر يك )‪.(animation‬‬

‫• بوضع العديد من الصور‪ ،‬الواحدة بجنب الأخرى‪ ،‬يكون باستطاعتك إنشاء لعبة حقيقي ّة‪.‬‬

‫‪276‬‬

‫لماذا نختار الـ‪ SDL‬؟‬
‫كمثال عن لعبة تم صنعها بالـ‪ ،SDL‬اعلم أ ّن اللعبة الشهيرة ”‪ ،”Civilisation : Call to power‬تم دعمها في‬

‫نظام اللينكس لاحقا ًباستخدام الـ‪.SDL‬‬

‫يجب أن تعلم أ ّن جودة اللعبة تعود إليك و إلى الفر يق الذي تعمل معه‪ .‬إن كان لديك مصمم موهوب‪،‬‬
‫فيمكنك صنع لعبة أجمل‪.‬‬

‫الشيء الوحيد الذي يح ّد الـ‪ SDL‬هو أنها تقتصر على الألعاب ثنائية الأبعاد‪ ،‬و لم ت ُنشأ من أجل الألعاب‬
‫ثلاثية الأبعاد‪ .‬هذه أمثلة على ألعاب يمكن تحقيقها بالـ‪) SDL‬ليست سوى قائمة صغيرة‪ ،‬ك ّل شيء ممكن مادام‬

‫ثنائيّ الأبعاد( ‪:‬‬
‫• ‪Breakout‬‬
‫• ‪Bomberman‬‬

‫• ‪Tetris‬‬
‫• ألعاب المن ّصات ‪… ،Rayman ،Sonic ،Super Mario Bros :‬‬
‫• ‪ RPG‬ثنائية الأبعاد ‪ ،Zelda :‬الأجزاء الأولى للعبة ‪ ،Final Fantasy‬إلخ‪.‬‬

‫لا يمكن وضع لائحة كاملة‪ ،‬الأمر يعود فقط للقدرة على التخي ّل‪ .‬و ص ّدقني بأنك قادر على برمجة ألعاب فائقة‬
‫الروعة‪ .‬فلقد رأيت أحد القر ّاء ينشئ تهجينا بين ‪ Breakout‬و ‪.Tetris‬‬

‫فلنعد إلى الأرض و لنمسك خيط هذا الدرس‪ .‬سنقوم الآن بتسطيب المكتبة‪ ،‬لنتم ّكن من التق ّدم في العمل‪.‬‬
‫‪277‬‬

‫الفصل ج‪ .1.‬ٺثبيت الـ‪SDL‬‬

‫ج‪ 2.1.‬تنز يل الـ‪SDL‬‬

‫الموقع الرسمي للمكتبة ‪ SDL‬سيصبح قريبا الوجهة ال ّتي نقصدها كثيرا‪ .‬هناك‪ ،‬يوجد ك ّل ما تحتاجه‪ ،‬بدء ً من‬
‫المكتبة نفسها و مرورا إلى التوثيق )‪ (Documentation‬الخاص بها‪.‬‬

‫‪http://www.libsdl.org/‬‬

‫إذهب إلى اللائحة ‪ Download‬المتواجدة على يسار الصفحة الرئيسية للموقع‪.‬‬
‫اختر النسخة الأحدث ال ّتي تجدها )‪ SDL 1.2‬عندما كتبت هذه السطور(‪.‬‬

‫صفحة التنز يل مجز ّأة إلى عدة أجزاء‪.‬‬
‫• الشفرة المصدر ية )‪ : (Source code‬هنا يمكنك تحميل الشفرة المصدر ية الخاصة بالمكتبة‪ .‬أدري أن‬
‫القراء فضوليون ليعرفوا كيف تعمل المكتبة من الداخل‪ ،‬لـك ّن هذا لن يفيدنا‪ .‬الأسوأ هو أن ّه سيقوم‬

‫بإلهائك عن هدفنا الرئيسي‪.‬‬
‫• مكتبات وقت التشغيل )‪ : (Runtime libraries‬هي الملفات التي تحتاج إلى تقديمها مع الملف التنفيذي‬
‫حين تريد أن تعطي برنامجك لشخص آخر‪ .‬بالنسبة للويندوز‪ ،‬أنا أتكلم عن الملف ‪ . SDL.dll‬هذا‬

‫الأخير يجدر به أن يتواجد إما ‪:‬‬
‫– بنفس المجل ّد الذي يحتوي الملف التنفيذي )أنا أنصحك بهذا(‪ .‬الأحسن دائما هو أن تعطي الـ‪DLL‬‬
‫مع الملف التنفيذي و تبقيهم في نفس المجلد‪ .‬إذا وضعت الـ‪ DLL‬في المجل ّد الخاص بالويندوز‪ ،‬لن‬
‫يكون عليك إلحاق الـ‪ DLL‬مع ك ّل مجل ّد يحتوي البرنامج ‪ .SDL‬و مع ذلك قد تحدث بعض المشاكل‬

‫في حال ما قمت بمسح نسخة أحدث من الـ‪.DLL‬‬
‫– في المجل ّد ‪. C:\Windows‬‬

‫• مكتبات التطوير )‪ : (Development libraries‬هي الملفات ‪) .a‬أو ‪ .lib‬بالنسبة للـ‪ (Visual‬و‬
‫الملفات ‪ .h‬التي تسمح بإنشاء برامجك ‪ .SDL‬هذه الملفات ليست مفيدة إلا بالنسبة إليك أنت فقط‬

‫المبرمج‪ .‬أي أنه ليس عليك تقديمها مع ملفات البرنامج حين تنتهي من هذا الأخير‪.‬‬

‫إذا كنت تعمل في الويندوز‪ ،‬فسأعطيك ثلاثة نسخ‪ ،‬و ذلك حسب المترجم الخاص بك ‪:‬‬

‫• ‪ : VC6‬بالنسبة للذين يستخدمون النسخ القديمة غير المجانية من ‪) Visual studio‬لا أعتقد أن هناك من‬
‫القر ّاء من لازال يستعمل هذه النسخ(‪ .‬ستجد فيها على أي حال الملفات ‪. .lib‬‬

‫• ‪ : VC8‬بالنسبة للذين يستعملون ‪ Visual Studio 2005 Express‬أو نسخة أحدث‪ ،‬ستجد فيها الملفات‬
‫‪. .lib‬‬

‫• ‪ : mingw32‬بالنسبة للذين يستعملون ‪) Code::Blocks‬ستجدون فيها إذا الملفات ‪.( .a‬‬

‫‪278‬‬

‫إنشاء مشروع ‪Windows : SDL‬‬

‫الشيء الخاص هنا‪ ،‬هو أن ”مكتبات التطوير” تحتوي كل الملفات ‪ .h‬و الملفات ‪) .a‬أو ‪( .lib‬‬
‫بالطبع‪ ،‬لـكنها تحتوي أيضا ًالملف ‪ SDL.dll‬و ملفات التوثيق الخاصة بالـ‪! SDL‬‬

‫باختصار‪ ،‬ك ّل ما عليك تحميله هو ”مكتبات التطوير”‪ ،‬فك ّل ما تحتاجه يتواجد بداخلها‪.‬‬

‫لا تخطئ في الرابط ! قم باختيار الـ‪ SDL‬في قسم ”‪ ”Development libraries‬و ليس من قسم ”‪Source‬‬
‫‪! ”code‬‬

‫ماذا هو التوثيق )‪ (Documentation‬؟‬

‫التوثيق هو قائمة تحوي اللائحة الكاملة للدوال الخاصة بمكتبة معي ّنة‪ .‬و كل هذه الملفات تكون مكتوبة‬
‫بالانجليز ية )حتى لو كان كاتبوها مبرمجـين فرنسيين(‪ .‬هذا سبب آخر يدفعك للتق ّدم في لغة ‪! Shakespeare‬‬

‫محتوى ملفات التوثيق ليس عبارة عن درس‪ ،‬بل هي عادة موجزة‪ .‬الشيء الإيجابي بالنسبة لدرس‪ ،‬هي‬
‫أ ّنها تحتوي قائمة لكل الدوال الموجودة‪ ،‬فهي إذا المرجع للمبرمج‪.‬‬

‫في كثير من الأحيان ستجد مكتبات بدون دروس تشرح كيفية عملها‪ .‬و هنا لا يبقى لك سوى التوثيق ال ّذي‬
‫نسميه عادة ”‪ ،”doc‬و يجب عليك تدبّر أمرك بهذا فقط )حت ّى لو كان هذا صعبا أحيانا عندما تبدأ من دون أي ّة‬

‫مساعدة(‪ .‬المبرمج الحقيق ّي هو من يتم ّكن من إيجاد ضال ّته في الـ”‪.”doc‬‬

‫لح ّد الآن‪ ،‬أنت لست بحاجة إلى التوثيق الخاص بالـ‪ SDL‬لأنني أنا من سيشرح لك كيفية عملها‪ .‬لـكن بما‬
‫أنني غير قادر على أن أشرح لك كل الدوال التي بها‪ ،‬ستحتاج إلى قراءة التوثيق لاحقا‪.‬‬

‫مل ّفات التوثيق توجد أصلا ًفي الحزمة ”‪ ”Development libraries‬كما سبق و ذكرت‪ ،‬لـكن بإمكانك تحميلها‬
‫وحدها من القائمة ‪. Downloadable / Documentation‬‬

‫أنصحك أن تجمع ملفات ‪ HTML‬الخاصة بالتوثيق في مجل ّد خا ّص )اسمه مثلا ً ‪ ( Doc SDL‬ثم انشاء اختصار‬
‫إلى الفهرس ‪ . index.html‬و الهدف من هذا هو الوصول إلى هذه الملفات بشكل أسرع حينما تحتاج إليها‪.‬‬

‫ج‪ 3.1.‬إنشاء مشروع ‪Windows : SDL‬‬

‫ٺثبيت مكتبة قد يكون أكثر صعوبة قليلا ًعلى ما تعوّد عليه الجميع‪ .‬هنا لا يوجد ٺثبيت تلقائيّ يطلب منك أن‬
‫تنقر ”التالي”‪” ،‬التالي”‪” ،‬التالي”‪” ،‬إنتهى”‪.‬‬

‫الحقيقة أن ٺثبيت مكتبة أمر صعب على المبتدئين‪ .‬لـكن لأقوم برفع المعنو يات فإن تسطيب مكتبة ‪SDL‬‬
‫أمر سهل جدا ً مقارنة بتسطيب مكتبات أخرى أتيحت ليّ فرصة استخدامها من قبل )هناك من يتم إعطاؤك منها‬

‫الشفرة المصدر ية فقط‪ ،‬بينما انت ٺتولى أمر الترجمة !(‪.‬‬
‫و الحقيقة أن كلمة ”ٺثبيت” ليست الملائمة هنا‪ .‬لن نقوم بتثبيت أي شيء‪ ،‬فقط نريد أن نصل إلى الـكيفية‬

‫التي ننشئ فيها مشروع ‪ SDL‬في البيئة التطوير ية الخاصة بنا‪.‬‬

‫‪279‬‬

‫الفصل ج‪ .1.‬ٺثبيت الـ‪SDL‬‬
‫ستختلف كيفية التعامل حسب البيئة التطوير ية التي تستعملها‪ .‬سأقوم بتقديم الطر يقة الخاصة بك ّل بيئة من‬

‫بيئات التطوير التي ق ّدتمها في بداية الكتاب‪ ،‬و هكذا كي يستطيع الجميع المتابعة‪.‬‬
‫سأعرض الآن كيف ننشئ مشروع ‪ SDL‬في ك ّل واحد من البيئات الثلاث السابقة‪.‬‬

‫تسطيب الـ‪ SDL‬في ‪Code::Blocks‬‬

‫استخراج ملفات الـ‪SDL‬‬
‫افتح الملف المضغوط ”‪ ”Development Libraries‬الذي قمت بتنز يله‪.‬‬
‫هذا الملف هو بامتداد ‪ .zip‬بالنسبة للـ‪ Visual‬و ‪ .tar.gz‬بالنسبة للـ ‪) mingw32‬يلزمك برنامج مثل‬
‫‪ Winrar‬او ‪ 7-Zip‬لـكي تقوم بفك الضغط عن الملفات ذات الصيغة ‪.( .tar.gz‬‬
‫الملف المضغوط يحتوي العديد من المجل ّدات الداخلية‪ ،‬و هذه هي الملفات التي تهمّنا ‪:‬‬

‫• ‪ : bin‬يحتوي الملف ‪ .dll‬الخاص بالـ‪.SDL‬‬
‫• ‪ : docs‬يحتوي الملفات التوثيقي ّة الخاصة بالـ‪.SDL‬‬
‫• ‪ : include‬يحتوي الملفات الرأسية ‪.(headers) .h‬‬
‫• ‪ : lib‬يحتوي الملفات ‪) .lib‬أو ‪ .a‬بالنسبة لـ‪(Code::Blocks‬‬
‫يجب عليك استخراج كل الملفات و المجل ّدات الداخلية ووضعها في مكان ما بالقرص الصلب لحاسوبك‪،‬‬
‫يمكنك مثلا وضعها في مجلد خاص بـ‪ SDL‬داخل مجل ّد الـ‪.Code::Blocks‬‬

‫‪280‬‬

‫إنشاء مشروع ‪Windows : SDL‬‬

‫بالنسبة لي فإن المسار هو التالي ‪:‬‬

‫‪C:\Program Files (x86)\CodeBlocks\SDL-1.2.13‬‬

‫احفظ المسار الذي به البرنامج‪ ،‬ستحتاج إليه عندما تريد تعديل إعدادات ‪ Code::Blocks‬لاحقا‪.‬‬

‫و الآن‪ ،‬علينا بالقيام بخطوة بسيطة‪ ،‬لتسهيل الأمور علينا‪ ،‬توجّه إلى المسار ‪) include/SDL‬في حالتي‪،‬‬
‫هو متواجد بـ ‪ ،( C:\Program Files (x86)\CodeBlocks\SDL-1.2.13\include\SDL‬قم‬

‫بنسخ الملفات الرأسية ‪ .h‬في المجل ّد الأب‪) ،‬أي في ‪:‬‬
‫‪.( C:\Program Files (x86)\CodeBlocks\SDL-1.2.13\include‬‬

‫ها قد تم تسطيب المكتبة‪ ،‬فلنقم الآن بتعديل إعدادات ‪.Code::Blocks‬‬

‫إنشاء مشروع ‪SDL‬‬
‫افتح ‪ Code::Blocks‬و قم بانشاء مشروع جديد‪.‬‬
‫‪281‬‬

‫الفصل ج‪ .1.‬ٺثبيت الـ‪SDL‬‬

‫عوض أن تقوم باختيار ‪ Console Application‬كما جرت العادة‪ ،‬اختر ‪.SDL project‬‬

‫النافذة الأولى لا جدوى منها‪ ،‬قم بتجاوزها بالضغط على ”التالي”‬
‫)‪.(Next‬‬

‫‪282‬‬

‫إنشاء مشروع ‪Windows : SDL‬‬

‫سي ُطلب منك أن تقوم بإدخال اسم المشروع‪ ،‬قم بذلك كالعادة ‪:‬‬

‫الآن يجب اختيار المسار الذي ثبتنا فيه المكتبة ‪:‬‬
‫‪283‬‬

‫الفصل ج‪ .1.‬ٺثبيت الـ‪SDL‬‬
‫إظغط على الزر الذي يأخذ شكل مرب ّع به ثلاث نقاط‪ ،‬ستظهر لك النافذة التالية ‪:‬‬

‫‪284‬‬

‫إنشاء مشروع ‪Windows : SDL‬‬
‫قم باختيار المسار )بالنسبة لي هو ‪.( C:\Program Files (x86)\CodeBlocks\SDL-1.2.13‬‬

‫قد تظهر لك في مكان النافذة السابقة هذه النافذة ‪:‬‬

‫إملأ الحقل‬
‫بنفس الطر يقة السابقة‪ ،‬ثم ّ اضغط على زر الخروج‪ ،‬و ستلاحظ أن المسار قد تم تسجيله كالتالي ‪:‬‬

‫‪285‬‬

‫الفصل ج‪ .1.‬ٺثبيت الـ‪SDL‬‬

‫إضغط على ‪ ،Next‬ستظهر لك نافذة اختيار المترجم‪ ،‬قم باختيار الأوضاع ‪ Realease‬أو ‪) Debug‬هذا لا‬
‫يهم(‪.‬‬

‫أخيرا إضغط على ”إنهاء” )‪ .(Finish‬سيتم إنشاء المشروع التجريبي ‪:‬‬

‫يحتوي المشروع على ملفين ‪ main.cpp‬و ملف ‪ .bmp‬قبل أن تحاول القيام بالترجمة‪ .‬يجب القيام بخطوة‬
‫أخيرة )عليك القيام بها دائما(‪ ،‬و هي نسخ الملف ‪ SDL.dll‬من ملفات المكتبة )ال ّذي يفترض أن يكون في‬
‫المسار ‪ ( C:\Program Files (x86)\CodeBlocks\SDL-1.2.13\bin\SDL.dll‬و ضعه في‬

‫المجل ّد الخاص بالمشروع‪.‬‬
‫‪286‬‬

‫إنشاء مشروع ‪Windows : SDL‬‬

‫أخرج من ‪ Code::Blocks‬و أعد الدخول إليه‪ ،‬ثم قم بترجمة البرنامج الم ُقترح مسبقا ً‪ .‬يفترض أن تظهر النافذة‬
‫‪287‬‬

‫الفصل ج‪ .1.‬ٺثبيت الـ‪SDL‬‬
‫التالية ‪:‬‬

‫إذا ظهرت لك النافذة السابقة‪ ،‬فهنيئا لك‪ ،‬المكتبة مثبتة بشكل جيد !‬
‫إن ظهرت لك الرسالة ”‪ ”The application can’t start because the file SDL.dll is missing‬أي أنه‬
‫لا يمكن تشغيل البرنامج‪ ،‬لأن ملف ‪ SDL.dll‬غير موجود‪ ،‬فهذا يعني أنك لم تقم بنسخ الملف الأخير‬

‫في ملفات المشروع كما طلبت منك !‬
‫و كما قلت‪ ،‬إن كنت تريد تسليم المشروع إلى أصدقائك‪ ،‬عليك بارفاق الملف التنفيذي ‪ .exe‬بالملف‬

‫‪ ، SDL.dll‬بينما أنت لست بحاجة إلى إعطائهم الملفات ‪ .h‬و ‪ .a‬ال ّتي لا تهم أحدا سواكم‪.‬‬
‫ملاحظات مترجمة الكتاب ‪1‬‬

‫إن لم يشتغل البرنامج و لازال المترجم يشير دائما إلى عدم وجود الملف ‪ ، SDL.dll‬فجرب نسخ هذا الأخير و‬
‫لصقه في المجلدين ‪ Debug‬و ‪ Release‬من مجل ّد المشروع‪ ،‬أي في نفس المكان الذي يتواجد به الملف التنفيذي‪.‬‬
‫أريد أن أنوّهك بأن المشروع الذي تم انشاؤه هو خاص باللغة ‪) C++‬لأنها اللغة التي يتم اختيارها تلقائيا من‬
‫بيئة التطوير‪ ،‬كون أن هذه الأخيرة تم تطويرها للعمل بلغة الـ‪ ،(C++‬سنقوم إذا بتحو يل هذا المشروع من ‪C++‬‬

‫‪ 1‬ك ّل النص التالي و لقطات الشاشة المرافقة ابتداء ً من هنا و إلى نهاية هذا القسم‪ ،‬يشرح الطر يقة ال ّتي استخدمتها مترجمة الكتاب‬
‫لتشغيل البرنامج في حالة ما لم تعمل الطر يقة السابقة )الأصلي ّة(‪ .‬هذا يعني أ ّن هذه الفقرات التالية ليست موجودة في الكتاب الفرنسي‬

‫الأصلي‪ ،‬و إن ّما هو مساهمة شخصي ّة من المترجمة‪.‬‬

‫‪288‬‬

‫إنشاء مشروع ‪Windows : SDL‬‬
‫إلى ‪ C‬ببساطة‪.‬‬

‫توجّه إلى ملفات المشروع‪ ،‬ستجد الملف ‪ main.cpp‬قم بتغيير امتداده إلى ‪. main.c‬‬

‫أدخل الآن إلى ‪ ،Code::Blocks‬ستظهر لك على الأرجح النافذة التالية ‪:‬‬

‫إظغط على الزر ”لا” )‪.(No‬‬
‫توجه إلى القائمة اليسار ية‪ ،‬و قم بالنقر باليمين على الملف ‪ main.cpp‬و اختر حذفه من المشروع ‪:‬‬

‫‪289‬‬

‫الفصل ج‪ .1.‬ٺثبيت الـ‪SDL‬‬

‫اضغط على اسم المشروع‪ ،‬و اطلب إضافة ملف جديد ‪:‬‬
‫‪290‬‬

‫إنشاء مشروع ‪Windows : SDL‬‬

‫اختر الملف ‪ main.c‬من ملفات المشروع ‪:‬‬

‫ستظهر لك نافذة أخرى‪ ،‬قم باختيار ‪ ،Next‬ثم انقر على ”موافق” )‪.(OK‬‬
‫‪291‬‬

‫الفصل ج‪ .1.‬ٺثبيت الـ‪SDL‬‬
‫أنقر باليمين مجددا على الملف ‪ main.c‬و اختر ”خصائص” )‪: (Properties‬‬

‫توجه إلى القائمة ‪ ،Advanced‬ستجد ‪ ،Compiler variable‬غي ّرها من ‪ CPP‬إلى ‪ CC‬كالتالي ‪:‬‬
‫‪292‬‬

Windows : SDL ‫إنشاء مشروع‬

: ‫ هذا ما سيبدو عليه المشروع الجديد‬OK ‫إضغط بعد ذلك على‬

: ‫ضع الشفرة التالية بدل الشفرة السابقة‬
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <SDL/SDL.h>
4 int main(int argc, char *argv[])
5{
6 SDL_Init(SDL_INIT_VIDEO);
7 SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE);
8 return EXIT_SUCCESS;
9}

293

‫الفصل ج‪ .1.‬ٺثبيت الـ‪SDL‬‬
‫و أخيرا ً‪ ،‬من القائمة العلو ية‪ ،‬اختر هدف البناء ‪. Release‬‬

‫يمكنك ترجمة البرنامج‪ ،‬ستظهر لك نافذة و تختفي فجأة‪ ،‬لا تقلق‪ ،‬سنعالج ذلك لاحقا ً‪ ،‬أنا أهن ّئك‪ ،‬كل شيء‬
‫يعمل بشكل جيد جدا‪.‬‬

‫يمكنك مسح الملف ‪ .bmp‬لأننا لسنا بحاجة إليه‪ .‬بالنسبة للملف ‪ ، main.c‬يمكنك الآن استبدال محتواه‬
‫بالشفرة التالية ‪:‬‬

‫>‪1 #include <stdlib.h‬‬

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

‫>‪3 #include <SDL/SDL.h‬‬

‫‪4‬‬ ‫)][‪int main(int argc, char *argv‬‬
‫‪5‬‬
‫{‬

‫;‪6 return 0‬‬

‫}‪7‬‬

‫إنها شفرة مبدئية‪ ،‬تشبه الشفرات التي تعوّدنا عليها )تضمين ‪ stdlib.h‬و ‪ stdio.h‬ثم ‪ .( main‬الشيء‬
‫الوحيد الذي تغيّر هو تضمين الملف ‪ . SDL.h‬إن ّه ملف رأس ّي يستكلف نفسه بتضمين كل الملفات الرأسية‬

‫الخاصة بالمكتبة ‪.SDL‬‬

‫إنشاء مشروع ‪ SDL‬في ‪Visual C++‬‬

‫استخراج ملفات الـ‪SDL‬‬

‫من الموقع الرسمي‪ ،‬قم بتنز يل آخر نسخة من المكتبة من قسم ”‪ ”Development Libraries‬و اختر نسخة ‪Visual‬‬
‫‪.C++ 2005 Service Pack 1‬‬
‫إفتح الملف ‪. .zip‬‬

‫إنه يحتوي على التوثيق )في المجلد ‪ ،( docs‬الملفات ‪) .h‬في المجلد ‪ ،( include‬و الملفات ‪) .lib‬في‬
‫المج ّلد ‪ ( lib‬المكافئة للملفات ‪ .a‬بالنسبة لمترجم ‪ .Visual‬ستجد أيضا ًالملف ‪ SDL.dll‬في المجل ّد ‪. lib‬‬

‫• انسخ الملف ‪ SDL.dll‬إلى مجل ّد المشروع‪.‬‬
‫• انسخ الملفات ‪ .lib‬إلى المجل ّد ‪ lib‬الخاص بـ‪ .Visual C++‬بالنسبة لي‪ ،‬أنا أتكلم عن المجل ّد‬

‫‪. C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib‬‬
‫• انسخ الملفات ‪ .h‬إلى المجل ّد ‪ includes‬الخاص بـ‪ .Visual C++‬أنشئ مجل ّدا ‪ SDL‬في المجلد‬

‫‪ includes‬لجمع الملفات ‪ .h‬الخاصة بالـ‪ SDL‬فيه‪ .‬بالنسبة لي‪ ،‬سأضع تلك الملفات في المجلد ‪:‬‬
‫‪. C:\Program Files (x86)\Microsoft Visual Studio 8\VC\include\SDL‬‬

‫‪294‬‬

‫إنشاء مشروع ‪Windows : SDL‬‬

‫إنشاء ‪ SDL‬مشروع جديد‬

‫في الـ ‪ Visual C++‬أنشئ مشروعا ً من نوع ‪ .Application console Win32‬سم ّيه مثلا ً ‪ testsdl‬ثم اضغط‬
‫على ”موافق”‪.‬‬

‫ستفتح نافذة مساعدة‪ .‬توجه إلى ‪ Application parameters‬و تأكد من أن الخانة ‪Empty project‬‬
‫مختارة‪.‬‬

‫لقد تم ّ إنشاء المشروع إذا‪ .‬إن ّه فارغ‪ .‬أضف إليه ملفا ً جديدا ً و ذلك بالنقر على ‪ Source files‬ثم‬
‫‪ Add‬ثم ‪: New element‬‬

‫‪295‬‬

‫الفصل ج‪ .1.‬ٺثبيت الـ‪SDL‬‬
‫حينما تفتح نافذة جديدة‪ ،‬أطلب إنشاء ملف جديد من نوع )‪ ، C++ File (.cpp‬قم بتسميته‬

‫‪ . main.c‬بوضعك للامتداد ‪ .c‬فإن الـ‪ Visual‬سيقوم بانشاء ملف ‪ C‬و ليس ‪.C++‬‬
‫أكتب )أو انسخ‪/‬أل ِصق( الشفرة المبدئية الذي وضعتها أعلاه‪ ،‬في الملف الجديد الذي أنشأته‪.‬‬

‫تخصيص مشروع ‪ SDL‬في ‪Visual C++‬‬
‫التعديل على المشروع أصعب قليلا ً مما هو الحال مع الـ‪ ،Code::Blocks‬لـكن بقليل من التركيز‪ ،‬ستتمكن من‬

‫فعله‪ .‬توجّه إلى خصائص المشروع من ‪. testsdl properties / Project‬‬
‫• في القسم ‪ Code generation / C / C++‬ع ّدل قيمة الـ ‪ Runtime Libraries‬إلى‬

‫)‪. DLL multithread (/MD‬‬
‫• في القسم ‪ Advanced / C / C++‬اختر ‪ Compilation as‬و ضع القيمة‬
‫)‪) Compile as C code (/TC‬و إلا فإن ‪ Visual‬سيترجم البرنامج كأنه ملف ‪ C++‬و ليس‬

‫كملف ‪.(C‬‬
‫• في القسم ‪ Input / Link editor‬ع ّدل قيمة الـ ‪ Additional dependencies‬لـكي تضيف‬

‫‪ SDL.lib‬و ‪. SDLmain.lib‬‬
‫• في القسم ‪ System / Link editor‬ع ّدل قيمة الـ ‪ Sub-System‬إلى الـ ‪. Windows‬‬

‫قم بالضغط على ”موافق” لحفظ التغييرات‪.‬‬
‫يمكنك الآن الترجمة و ذلك بالذهاب إلى ‪ Generate‬ثم ‪. Generate solution‬‬

‫‪296‬‬

‫إنشاء مشروع ‪(Xcode) Mac OS : SDL‬‬
‫ستجد الملف التنفيذي الذي يتواجد بمجلد المشروع )أو بمجلد داخلي يسمى ‪ ( Debug‬و لا تنس أنه على‬
‫الملف ‪ SDL.dll‬أن يتواجد في نفس المجل ّد الذي يتواجد به الملف التنفيذي‪ .‬أنقر م ّرتين على ‪ ، .exe‬إذا‬
‫سار ك ّل شيء على ما يرام‪ ،‬فلن يحصل أ ّي شيء‪ ،‬و إلّا فسيحدث خطأ إذا لم يكن الملف ‪ SDL.dll‬في‬

‫نفس المجل ّد‪.‬‬

‫ج‪ 4.1.‬إنشاء مشروع ‪(Xcode) Mac OS : SDL‬‬

‫فلتقم بتحميل النسخة ‪ 1.2‬من الـ‪ ،SDL‬و ذلك من خلال الجزء ”‪ ”Download‬أسفل يسار الموقع‪ ،‬كالتالي ‪:‬‬

‫في أسفل الصفحة ستجد قسما ًيدعى ”‪ .”Runtime Libraries‬نزّل الملف الذي يتناسب مع هندسة معالج‬
‫جهازك )‪ Intel‬أو ‪ ،(PowerPC‬هذا ما ستوضحه الصورة الموالية‪ .‬إن كنت تريد معرفة هندسة المعالج‪ ،‬يمكنك‬
‫الذهاب إلى القائمة ”‪ ”Apple‬في أعلى اليسار‪ ،‬و النقر على ”‪ .”About this Mac‬في السطر ”‪ ”Processor‬ستجد‬

‫إما ‪ Intel‬أو ‪.PowerPC‬‬
‫‪297‬‬

‫الفصل ج‪ .1.‬ٺثبيت الـ‪SDL‬‬

‫حينما يتم تحميل الملف‪ ،‬انقر عليه مرتين‪ ،‬يفترض أن يفتح لوحده‪ .‬ستجد بهذا المجل ّد مجل ّدا ‪SDL.framework‬‬
‫قم بنسخه و لصقه في المجلد ‪. /Library/Frameworks‬‬
‫إنتهى‪ ،‬المكتبة مس ّطبة الآن !‬

‫ستجد مجل ّدا آخر اسمه ‪ devel-lite‬أتركه مفتوحا‪ ،‬سنعود إليه لاحقا ً‪.‬‬
‫الآن قم بانشاء مشروع جديد ”‪ ،”Cocoa Application‬إضغط على ”‪ .”Next‬في ‪ Product Name‬قم‬
‫بتسمية المشروع )كـ”‪ ”SDL‬مثلا ً(‪ .‬و في ‪ ، Company Identifier‬ضع ما تريد )كاسم مستعار لك‬
‫مثلا(‪ .‬أترك الباقي كما هو ثم اضغط على ”‪ .”Next‬اختر أين تريد وضع المشروع‪ .‬سيتم انشاء مجل ّد بطر يقة تلقائية‬

‫و ليس عليك إنشاء واحد بنفسك ووضع ملفات المشروع بداخله‪.‬‬
‫ما إن يتم إنشاء المشروع‪ ،‬قم بالتخلص من الملفات التي لا تحتاجها ‪، AppDelegate.m ، AppDelegate.h :‬‬

‫‪ main.m ، InfoPlist.strings ، MainMenu.xib‬و ‪: Credits.rtf‬‬
‫‪298‬‬

‫إنشاء مشروع ‪(Xcode) Mac OS : SDL‬‬

‫اختر المشروع من التفرع الشجري اليساري )القسم ‪ Install SDL‬من الصورة الموالية( في الشجرة‬
‫الثانية اختر اسم مشروعك من قسم ‪ PROJECT‬و ليس من ‪: TARGETS‬‬

‫يمكنك أيضا ًتغيير الـ‪ localisation‬من ‪ English‬إلى ‪ . French‬اختر ‪ ، English‬أنقر على ‪ -‬للمسح‬
‫و على ‪ +‬لإضافة ‪ ، French‬هذا يعود إليك و لست مضطرا ً للقيام بذلك‪.‬‬

‫سنقوم الآن بتخصيص المشروع على نظام ‪ ) 32 bits‬لأن المكتبة لا تشتغل على أنظمة ‪ ،(64 bits‬و سنقوم‬
‫بإضافة المسارات من أجل الـ‪ ،frameworks‬و للملفات الرأسية أيضا ً‪ .‬إضغط على ‪ Build Settings‬ثم‬

‫‪ All‬ثم في ‪ Architectures‬انقر على ‪ 64-bit Intel‬و اختر ‪: 32-bit Intel‬‬
‫‪299‬‬

‫الفصل ج‪ .1.‬ٺثبيت الـ‪SDL‬‬

‫ما إن تفعل ذلك‪ ،‬اختر ‪ LLVM GCC 4.2‬من السطر ‪. Compiler for C/C++/Objective-C‬‬

‫اذهب إلى منطقة البحث في أعلى اليمين‪ ،‬و اكتب ”‪ ،”search paths‬يجدر بك أن تجد سطرين مهمّين بالنسبة‬
‫لنا و هما ‪ Header search paths‬و ‪ . Framework search paths‬انقر مرتين على الجهة اليمنى‬
‫للسطر ‪ Framework search paths‬أنقر على علامة ‪ +‬و أضف المسار ‪. /Library/Frameworks‬‬

‫بالنسبة للسطر ‪ Header Search paths‬أضف المسار‬
‫‪. /Library/Frameworks/SDL.framework/Headers‬‬

‫إختر الآن ”هدفك”‪ ،‬و هذه المرة من قسم ‪: TARGETS‬‬

‫توجه إلى ‪ ، Summary‬في المنطقة ‪ Application Category‬يمكنك وضع ما تشاء‪ ،‬لن يغير هذا‬
‫شيئا كبيرا ً‪ ،‬لأنه ينفع من أجل الـ‪ AppStore‬فقط‪ .‬ع ّدل السطر ‪ Main Interface‬و ضع ”‪.”SDLMain‬‬
‫بالنسبة للـ ‪ App Icon‬فاسمه يدل عليه‪ ،‬فهو يسمح لك بتحديد أيقونة لبرنامجك‪ .‬يكفي سحب ثم تحرير الصورة‬
‫الم ُراد استعمالها كأيقونة‪ .‬بالنسبة للمنطقة ‪ Linked Frameworks and Libraries‬سنقوم بإضافة‬
‫الـ‪ framework‬الخاص بنا ‪ ، SDL.framework‬أنقر على ‪ +‬في منطقة البحث ‪ ،‬أكتب ”‪ ،”SDL‬حين تجده في‬
‫القائمة‪ ،‬أنقر على ‪ ، Add‬إن لم تجده فهذا يعني أنك لم تقم بوضعه في المجل ّد المناسب ) ‪.( /Library/Frameworks‬‬

‫‪300‬‬


Click to View FlipBook Version