الجمعة، 8 يوليو 2016



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


و هده الدرس الاول و الثاني





 الردوس الاولى الجزئين الاول والثاني
السلام عليكم 
كل عام وانتم بالف خير 
اخوتي الاعزاء اقدم لكم متابعة الدروس اللغة البرمجية c pp  مع الضروف الصعبة التي يمر بها البلد من تفجيرات  وانتهاكات حقوق الانسان و عدم تواجد السلطة  بعد تفجير الكرادة وتفجير كل مكان حدث فيه في بغداد والعراق عموما لكن يجب ان نكمل دراساتنا لكي يتثقف الجيل الجديد و نعرف مستقبل اولادنا لنبدأ بدروس الجديدة  


تعلم سي بلس بلس
الدرس السادس
هياكل البيانات
مساء الخير
نتناول اليوم موضوع رائع وقوي جدا من الناحية البرمجية- لقد تعلمت فيما سبق كيف تعلن عن بيانات حسب نوعها وقد كنت تعلن عنها بصورة منفصلة الآن وبنفس الطريقه سوف نعلن عنها ولكن في صورة مجمعة لتكون هيكل للبيانات وهذا الموضوع مفيد جدا في برمجه قواعد البيانات وسترى فوائد ذلك ولو اننا لم ندرس تخزين البيانات في ملفات على الاقراص حيث سنتناول ذلك في درس قادم ولكن عند تجميع البيانات في هياكل اذا قمت بتخزين الهيكل نفسه سيتم تخزين جميع عناصره دفعة واحدة دون ان تنسى اي عنصر وبالتالي يعطيك ميزة اضافيه عما لو كنت تعلن عن البيانات في صورة منفصلة كما سترى
ومثالنا اليوم عن قاعدة البيانات الافتراضية التالية سوف ندرسها بالطريقه العاديه وبطريقة هياكل البيانات لتعرف الفرق وتفهم الموضوع وفي نفس الوقت تدرك ميزات وفوائد هياكل البيانات
لنفرض ان هناك مصنع يعمل على فترتين ولكل عامل فيه سجل بيانات بالطبع لعامل الفترة الاولى والآخر لعامل الفترة الثانية ونفترض للتبسيط ان بيانات كل عامل تحتوي على اسمه ورقمه الوظيفي وراتبه اليومي حتى انه لوتغيب احدى الفترات وضع راتب يومه بالقيمة صفر حتى يتم حساب راتبه الشهري بصورة صحيحة وسيكون الاعلان عن البيانات بالصورة التاليه لنتفق عليها وفيها فائدة تكرار اشياء سبق الاشارة اليها في دروس سابقه

الصيغة
المتغير او وعاء البيانات
char [30]
اسم الموظف افترضنا انه متغير حرفي سعته 30 حرف
int
الرقم الوظيفي للموظف وهو عدد صحيح
float
الراتب اليومي للموظف وهو عدد عشري لان الراتب من المؤكد انه سيحتوي على كسور
 دعنا الآن نعلن عن هذه البيانات بالصورة العادية لنعرف الفرق
بيانات موظف الفترة الاولى
  char [30] Name1;
int  Code1;
float Wage1;
بيانات موظف الفترة الثانية

char [30] Name2;
int  Code2;
float Wage2;
  الصورة السابقه لتمثيل بيانات البرنامج مع اثنين من الموظفين يعملون لفترتين وكلما ادخلت بيانات اسم موظف الفترة الاولى سوف تستخدم المتغير Name1 وللفترة الثانية ستستخدم المتغير Name2 فماذا لو بدلت المتغيرين بالخطأ بالطبع سيحدث خلل كبير بالبرنامج دعنا نمثل ماسبق تماما بالطريقة الجديده عن طريق استخدام هياكل البيانات
استخدام هياكل البيانات
 
struct OurDataBase
{
char [30] Name;
int  Code;
float Wage;
}L1,L2;
 انظر الى الصورة السابقه كم هي مختصرة انها رائعة وانا ارى فيها اختصار مفيد ودعنا نرى كيف نصيغ ذلك بالجدول الذي تعودنا عليه للتوضيح
الصيغة
التفسير
struct
هو الامر الذي ندرسه الان ومعناه الاعلان عن هيكل بيانات
OurDataBase
اسم الهيكل سميه كما شئت
{
قوس بداية البلوك
ضع ما يحلو لك من انواع بيانات داخل البلوك
}
قوس نهاية البلوك – لاتنساه من فضلك
L1,L2;
متغيرات اختياريه ترمز لمن سيشارك في استخدام البيانات المعلنه للهيكل
 كما رأيت بالمثال لم نستخدم متغير اسم للموظف الاول وآخر للموظف الثاني بل استخدمنا متغير واحد وسوف يتشارك اي عدد حسب تصميم الهيكل في استخدام بيانات الهيكل ولنوضح ذلك
للتعبير عن اسم الموظف الاول او موظف الفترة الاولى
L1.Name
للتعبير عن اسم الموظف الثاني او موظف الفترة الثانية
L2.Name
 للتعبير عن رقم الموظف الاول او موظف الفترة الاولى
L1.Code
  للتعبير عن رقم الموظف الثاني او موظف الفترة الثانية
L2.Code
  للتعبير عن الراتب اليومي للموظف الاول او موظف الفترة الاولى
L1.Wage
 للتعبير عن الراتب اليومي للموظف الثاني او موظف الفترة الثانية
L2.Wage
 هل رأيت كم هي بسيطة ربما احتوى هيكل البيانات على مائة متغير مثلا سوف تخزنهم وتسترجعهم بمنتهى السرعة كما سترى فيما بعد ويمكن ايصبح تدوال البيانات السابقة داخل البرنامج سواء بالادخال من مستخدم البرنامج او بالتخصيص كما يلي
L1.Name = “Mohamad Hasan”;
L1.Code = 120;
L1.Wage = 13.50;

L2.Name = “Ahamd Ali”;
L2.Code = 270;
L2.Wage = 0;
بالطبع هذه فكرة برنامج ويمكن اضافة المزيد من التحسينات من خلال تحليل البيانات فمثلا جمع المتغير L1.Wage لمدة شهر سوف يعطيك راتبه الشهر وجمع القيم التي تساوي صفر للمتغير L1.Wage لمدة شهر سوف يعطيك عدد ايام غيابه خلال الشهر وهذا يبقى دور تحليل البيانات لاستخلاص نتائج ومخرجات – المثال السابق كان لتوضيح الفكرة فقط.   









الدرس السابع
  المصفوفات
مساء الخير
المصفوفات من الادوات الهامة في لغات البرمجة لتخزين قيم عددية او حرفية تحت نفس الاسم بمعنى آخر دعنا نرى المثال التالي لتخزين عدد
int A;
 A=5;
في هذا المثال لم نستطع ان نخزن في المتغير المعلن عنه وهو عدد صحيح سوى قيمة واحدة فقط ولو حاولت (بالطبع تتفق معي في هذا ) تخزين قيمة اخرى فسوف تلغي القيمة الاولى لتحل محلها القيمة الجديده تقوم المصفوفات بعلاج هذه المشكلة مثال لذلك.
int A[50];
اعلن عن مصفوفة اعداد صحيحة تستطيع تخزين خمسون عدد صحيح كما يلي
 A[0] = 5;
A[1] = 10;
.
A[49] = 300;
مع ملاحظة ان التعبير التالي سوف يعتبر خطأ جسيم مع لغة سي++
A[50] = 200;
رغم ان المصفوفة تتسع ل 50 رقم الا ان المصفوفة تبدء من العنصر A[0] وتنتهي بالعنصر A[49]  وبذلك يكون مجموع العناصر 50 كما طلبت شاملا الرقم صفر وفي لغة سي++ دائما نبدء العد من صفر وليس من 1
  ويمكن ان تكون المصفوفة ذات اتجاهين مثل
15 65 33 44
1  0  11 22
33 52 11 17 
18 25 14 41
  لتمثل بلغة سي ++ كما يلي
 int A[4][4];
  حيث يكون العدد 44 المظلل بالاحمر هو
A[0][0] = 44;
 
ويكون العدد 18 المظلل بالاخضر هو
A[3][3] = 18;
  وافضل طريقة لتعبئة وتخصيص قيم لمصفوفة وللتعامل مع المصفوفات بصفة عامة هي عمل looping  باستخدام for  او غيرها كما سبق ووضحنا ذلك وكمثال  لملئ المصفوفة التالية بالقيمة صفر

int A[100];
int I;
for (I = 0 ; I < 100 ; I++)
{
A[I] = 0;
}
بالطبع الدوران السابق يغير قيمة العداد من صفر الى 99 ووضعنا داخل البلوك تخصيص لعناصر المصفوفة وبدلا من وضع قيمة عددية لتشير لعنصر بالمصفوفة وضعنا رمز العداد حيث انه سوف يتغير مع الدوران الذي يحدث وبالتالي تتخصص القيم حسب الترتيب
  ولتخصيص القيم صفر مثلا لمصفوفه ذات اتجاهين
int A[10][10] , I , J;
for (I = 0 ; I < 10 ; I++)
{
for (J = 0 ; J < 10 ; J++)
{
A[I][J] = 0;
}
}
بوضع دورتين واحدة تدور على الصفوف حتى تنهيها وتعود لتغير الصف وهكذا كما سبق وتعلمت 


  ولنا في المصفوفات مآرب أخرى
  لاتحتوي لغة سي ++ على تعريف ثابت وداخلي للمتغيرات الحرفية ولذلك يتم تلافي ذلك باستخدام المصفوفات ربما يعترض واحد من المتابعين لهذه الدروس بأن الامر char يقوم بذلك نعم هو كذلك ولكنه يعرف المتغير على انه حرف واحد فقط ونحن سنتحايل عليه بالمصفوفات كما يلي
char  Q;
Q = ‘A’;
عرفنا المتغير Q على انه حرف وبالتالي لانستطيع تخزين فيه سوى القيمة A  فاءذا طلبت طباعة قيمة المتغير Q سيقوم البرنامج بطبع الحرف A  فماذا لو اننا نريد تخزين عدة حروف تمثل اسم شخص اذا علينا بمصفوفة حروف كما يلي
char Q[40];
Q = “Mohamad Hasan”;
هل رأيت كيف تغلبنا على ذلك اعتمد الصيغة السابقة مؤقتا حتى الوصول لدرس يعطيك مزايا اكثر وشرح اوضح للمتغيرات الحرفية اننا لن نتأخر كثيرا عليك فهو الدرس القادم 





تعلم سي بلس بلس
الدرس الثامن
  المتغيرات الحرفية
مساء الخير
  لقد تحدثنا في الدرس السابق عن تخزين الحروف في مصفوفات وألان سوف نعيد ما قلناه بشئ من التفصيل لنأخذ مثال مشابه لما سبق تماما
char A[50];
سوف تتذكر الآن ماقلناه بأن المصفوفة السابقة تقوم بتخزين اسم او مجموعة حروف عددها 50 حرف شاملا المسافات التي بين الاسماء فعند ضغطك على قضيب المسافات يعتبر حرف ولكنه ليس له شكل لينتج المسافة بين الكلمات المهم ان المجموع 50 حرف تبدء المصفوفة من صفر الى 49 كما قلنا سابقا ان مصفوفات سي++ تبدء من صفر وليس من واحدد ولذلك الاعداد من صفر الى 49 هي 50 عدد وبالتالي عدد الحرف المخزنة هي 50 حرف كما سبق وطلبت وتم تلبية طلبك كل ذلك قلناه سابقا ولكن دعني اضيف بأن عدد الحروف التي سوف تدخلها سوف تكون 49 فقط وليس 50 لان سي++ تضيف في نهاية المتغير الحرف رقم 50 من عندها وهو الحرف \0 وهو يعني نهاية المتغير الحرفي ليعرف نظام التشغيل بأن هذه هي نهاية المتغير ولا يوجد شئ بعدها والرمز السابق يطلق عليه NULL character
وخلاصة القول ان تعلن عن المصفوفة بعدد يزيد بواحد عن سعتها المدخلة
لا تتضايق مما تفعلة سي++ من اضافة رمز على حسابك الخاص في نهاية المتغير انك تفعل ذلك وانا ايضا افعل ذلك فعند كتابة فقرة مكونة من حروف نضع نقطة في نهاية الكلام لنفيد القارئ بأن الكلام انتهى – أليس كذلك
استخدام المؤشرات للاعلان عن متغيرات الحروف
  يمكنك ايضا ان تعلن عن المتغير الحرفي باستخدام المؤشرات وهو درس كان يجب ان اشرحة ضمن الدروس السابقة ولكني رأيت ان اتركه للنهاية مع انه من المفترض ان يكون في البداية ولكن لصعوبته قليلا تلافيت وضع امثلة تحتوى مؤاشرات ما أمكن في البداية انتظارا لشرحة – يمكنك ان تعلن عن متغير حرفي بهذه الطريقة
char *A;
  وهذه طريقة اخرى للاعلان عن متغيرات حرفية تحتوي مميزات اكبر
 A = new char [50];
  ولنأخذ طريقة صياغة الامر السابق بجدولنا المعتاد

الصيغة
الشرح
A
اسم المصفوفة المفترض
=
لابد ان توضع لتون الصيغة صحيحة
New
من اوامر اللغة للاعلان عن متغير جديد
char
نوع المصفوفة (حروف)
[50];
قوسين بينهم سعة المصفوفة
 
والجديد في الصيغة السابقة هو انك بعد ان تنتهي من جميع العمليات الخاصة بالمصفوفة السابقة يمكن ان تلغيها ولذلك لتفريغ المساحة الخاصة بها من الذاكرة وهذه هي سي++ القوية جدا وذلك بالصيغة التالية
 
delete  [A] ;
ادخال المتغيرات الحرفية
  بالطبع ليس عندك مشكلة الآن في ادخال المتغيرات الحرفية باستخدام cin  ولكن لزم هنا التنويه بأن هذا الامر بالفعل سوف يدخل الحروف ولكنه سوف يتوقف عن الادخال عند الضغط على قضيب المسافة فلو انك تريد ادخال الاسم Mohamad Hasan الى متغير حرفي سوف يستقبل الاسم Mohamad  وعند ضغطك على قضيب المسافة لادخال بقية الاسم Hasan
حينها سوف يتوقف ولا يقبل الا الجزء الاول من الاسم وعليه استخدام احد عناصر فئة cin والفئات سوف نشرحها في درس قادم وهو
cin.getline (A,50,’\n’);
وصيغتة كما يلي
الصيغة
الشرح
cin.getline
الامر المشتق من cin
(
قوس احتواء البارامترات
A
اسم المصفوفة السابق الاعلان عنها
,
فاصلة بين بارامترين
50
طول او عدد الحروف المتوقع ادخالها
,
فاصلة بين بارامترين
‘\n’
معناه سطر جديد بعد المتغير ويمكنك اهمال هذا البارامتر
);
قوس نهاية احتواء البارامترات والفاصلة المنقوطة لانها ادخال الصيغة كلها
  مزيدا من الدوال التي تتعامل مع المتغيرات الحرفية
  انها عدد من الدوال للمقارنة بين الحروف والتعامل معها كما سيلي شرحه
char  Name1 [30] = “MOHAMAD HASAN”;
 char  Name2 [30] = “mohamad hasan”;
 int  L;
 L = strcmp (Name1 , Name2);
الدالة strcmp  تقارن بين متغيرين حرفيين مع الاخذ في الاعتبار حالة الحروف الصغيرة والكبيرة فالحرف A  بالنسبة لها غير الحرف a  وتعيد قيمة عدد صحيح يخزن في المتغير الصحيح L  كما يلي
 
القيمة المعادة
الشرح
اصغر من الصفر
عندما يكون الاسم الاول اصغر من الثاني
تساوي صفر
عندما يتساوى الاسمان
اكبر من الصفر
عندما يكون الاسم الاول اكبر من الثاني
 ربما يسأل احدكم سؤال ما معنى ان يكون اسم اكبر من اسم حيث ان اسم يساوي اسم هو شئ مفهوم اي تطبق الحروف فما معنى ان يكون اكبر او اصغر نعم ربما يهمك فقط عملية التساوى كأن تدخل كلمة سر يتم مقارنتها مع كلمة اخرى مخزنة داخل الحاسب للتعرف على الشخص  اما حالة ان يكون الاسم اكبر او اصغر فهي نادرة الاستخدام وتستخدم فقط في ترتيب الاسماء ابجديا ومعنى اكبر ان يكون ترتيب الحروف في جدول اسكي  للاسم الاكبر يلي ترتب الحروف للمتغير الاصغر .
في المثال السابق لن تكون قيمة L  تساوي صفر رغم ان الحروف واحدة للاسمين ولكن مرة حروف صغيرة ومرة حروف كبيرة ولكن هناك الدالة التالية التي لاتهتم بحالة الحروف

char  Name1 [30] = “MOHAMAD HASAN”;
 char  Name2 [30] = “mohamad hasan”;
 int  L;
 L = strcmpi (Name1 , Name2);

هذه الدالة strcmpi  سوف تعطي قيمة = صفر لان الاسمين متساويين وهي لاتهتم بحالة الحروف
الحاق متغير حرفي بآخر strcat
 
char  Name1 [30] = “Mohamad”;
 char  Name2 [30] = “Hasan”;
 int  L;
strcat (Name1 , Name2);
تقوم الدالة بالحاق الاسم الثاني بالاول ليصبح الاسم الثاني عبارة عن الاسمين مدموجين وتكون النتيجة ان المتغير الثاني Name2 بعد العملية السابقة يصبح حاملا القيمة
Mohamad Hasan
 
تحويل الحروف الصغيرة الى كبيرة strupr
 
char  Name [30] = “mohamad hasan”;
strupr (Name);
بعد العملية السابقة يتحول المتغير Name  الى MOHAMAD HASAN
تحويل الحروف الكبيرة الى صغيرة strlwr
 
char  Name [30] = “MOHAMAD HASAN”;
strlwr (Name);
 بعد العملية السابقة يتحول المتغير Name  الى mohamad hasan

قياس طول متغير حرفي strlen
char  Name [30] = “MOHAMAD HASAN”;
int L;
L = strlen (Name);
بعد العملية السابقة سيتم قياس طول المتغير الحرفي او عدد حروفه ويوضع كعدد بالمتغير L  حيث سبق الاعلان عنه كعدد صحيح
واليك مثال يشمل كل ما سبق شرحه
#include    //For cout
#include      //For many of the string functions
int main()
{
  char name[50];            //Declare variables
  char lastname[50];        //This could have been declared on the last line  
cout<<"Please enter your name: ";   //Tell the user what to do
  cin.getline(name, 50, '\n');      //Use gets to input strings with spaces
// or just to get strings after the user presses enter
 
  if(!strcmpi("Mohamad", name)) //The ! means not,strcmpi returns 0 for
  {                               //equal strings
    cout<<"That's my name too."< //Tell the userif its my name
 
  }
  else                              //else is used to keep it from always
    {                             //outputting this line
     cout<<"That's not my name." 
  }

   cout<<"What is your name in uppercase..."<
  strupr(name);                   //strupr converts the string to uppercase
  cout<
  cout<<"And, your name in lowercase..."<
  strlwr(name);                    //strlwr converts the string to lowercase
  cout<
  cout<<"Your name is "<
//the length of the string
  cout<<"Enter your last name:";
  gets(lastname);               //lastname is also a string
  strcat(name, " ");              //We want to space the two names apart
  strcat(name, lastname);      //Now we put them together, we a space in
//the middle
  cout<<"Your full name is "<//Outputting it all...
  return 0;



الدرس التاسع
الملفات
 
مساء الخير
 
في هذا الدرس سوف نتعرض لتخزين البيانات واسترجاعها من الملفات بالطبع مافائدة ادخال كم كبير من البيانات اذا لم نستطع تخزينها واسترجاعها ان اوامر الحفظ بالبرامج التي تستخدمها من اهم الاوامر التي تستخدمها وان امر فتح ملف ماهي الا عملية استرجاع لبيانات سبق حفظها بملف وهذا هو موضوعنا اليوم.
عندنا اليوم فئتين هامتين للعمليتين السابق ذكرهما ألا وهما الحفظ والاسترجاع وبالاضافة الى الفئتين سيكون بصحبتنا الملف fstream.h كرأس ملف للتعريفات الخاصة بالفئتين
الفئة الاولى ifstream
ستتولى هذه الفئة القراءة من الملفات اي عملية استرجاع البيانات او فتح الملفات
 
الفئة الثانية ofstream
ستتولى هذه الفئة الكتابة في الملفات اي عملية حفظ البيانات
 
ولنأخذ مثال للتوضيح
ifstream  MyFile (“mydata.txt”);

ولنرى طريقة صياغة الامر بالجدول المعتاد
الصيغة
الشرح
ifstream
اسم الفئة الخاصة بفتح الملفات
MyFile
بارامتر اختياري تختاره لاستدعاء دوال الفئة
(mydata.txt”);
بين قوسين وعلامتي اقتباس تضح اسم الملف المراد فتحه ولايغيب عنك انه يجب ان يكون ملف موجود على القرص
 
يستخدم البارامتر الاختياري لاستدعاء دوال الفئة سواء لفتح او اغلاق الملف وكل ملف يفتح سواء للكتابة او القراءة لابد ان يغلق بعد تمام العملية واذا نسيت ذلك فتأكد من ضياع بياناتك وهذا يحدث كثيرا عند اغلاق الكومبيوتر بغير الطريقه الصحيحة حينها تكون البرامج قد قامت بفتح ملفات ولم تغلقها لانك اغلقت الجهاز حينها تحدث اخطاء ويقوم نظام تشغيل الوندوز باستدعاء scandisk للتصحيح هذه المشكلة
 
MyFile.close();
البارامتر السابق تعريفه للفئة يقوم باستدعاء احد الدوال الهامه وهي دالة اغلاق الملف كما ذكرنا لك سابقا واليك مثال كامل لعمليات الحفظ والاسترجاع لتتضح الصورة امامك كاملة.
 
 
 
#include
#include


int main()
{
  char str[10];           
  ofstream svfile("example.txt");
  svfile<<"I want to save this line of data as an example";
  svfile.close();                          
             
  ifstream rdfile("example.txt");
  rdfile>>str;   
  cout<
  rdfile.close();   
}
تم الاعلان عن معاملين افتراضيين هما svfile ليعمل مع الفئة ofstream  لتخزين البيانات والمتمثلة تخزين العبارة I want to save this line of data as an example
بعد ذلك استخدم معامل الفئة لاغلاق الملف بالدالة close
  والمعامل الثاني rdfile ليعمل مع الفئة ifstream لقراءة البيانات من الملفات وبالتحديد الملف المذكور example.txt ثم تحميل البيانات الى متغير حرفي سبق الاعلان عنه واستخدام معامل الفئة لاغلاق الملف
 
المشكلة الواجب التنبيه عليها انه مع الفئة ofstream  واذكرك بأنها هي التي تحفظ الملفات ان الملف الذي اعطيتها اسمه اذا لم يكن موجود فسوف ينشأ اما اذا كان موجود فسوف يلغى مابداخله وهذه مشكله فربما انك تفتح ملف موجود وتريد اضافة بيانات له او تعديل بيانات فيه ولذلك يجب اعطاء وتمرير بارامترات للدالة المستخدمة كما يلي
 
Flag
Function
ios::app
Opens an output file for appending.
ios::ate
Opens an existing file (either input or output) and seeks the end.
ios::in
Opens an input file. Use ios::in as an open_mode for an ofstream file to prevent truncating an existing file.
ios::out
Opens an output file. When you use ios::out for an ofstream object without ios::app, ios::ate, or ios::in, ios::trunc is implied.
ios::nocreate
Opens a file only if it already exists; otherwise the operation fails.
ios::noreplace
Opens a file only if it does not exist; otherwise the operation fails.
ios::trunc
Opens a file and deletes the old file (if it already exists).
ios::binary
Opens a file in binary mode (default is text mode).


ifstream svfile("mydata.txt", ios::nocreate); 





الدرس العاشر
 اوامر بدء التشغيل
مساء الخير
لايوجد برامج قابلة للتشغيل على نظام تشغيل دوس سوى الملفات ذات الامتداد .bat و.com و .exe  ومع نظام وندوز نفس الامتدادات ماعدا .com الذي اختفى مع وندوز ولكن ربما يعترض البعض بأنهم تحت نظام وندوز يستطيعون تشغيل معظم الامتدادات مثل ملف ذو امتداد .doc اي ملف ميكروسوفت ورد بمجرد النقر على ايكونة الملف فكيف يتم ذلك وهل يتعارض ذلك مع ماقلناه سابقا.
بالطبع يتعارض ذلك مع ما قلناه سابقا وهي عبارة عن عملية وهمية حيث يتعرف نظام التشغيل على نوعية الملفات وامتدادها لكل برنامج ويسجل ذلك في قواعد بياناته حتى ان نظام التشغيل يعطي كمثال ايكون البرنامج للملفات التي ينتجها البرنامج كأن يأخذ ملف خطاب قمت بكتابته تحت ميكروسوفت ورد نفس ايكون برنامج ميكروسوفت ورد فمبجرد النقر على الملف يقوم النظام بالبحث في بياناته المسجلة ليعرف البرنامج الذي يتبعه هذا الملف ليقوم بتشغيله وتغذيته مبدئيا باسم الملف الذي تم النقر عليه وهذه العملية تسمى ب command line وهي موضوع دراستنا اليوم
لنقوم بعمل تطوير للدالة الرئيسيه لبرنامج ليتقبل اوامر عند بدء تشغيله
int main(int argc, char * argv[])
 
الصيغة
الشرح
int argc
متغير عدد صحيح يشير الى عدد الاوامر المضافة عند بدء التشغيل وذلك بعد اسم البرنامج
char * argv[]
كما ترى مصفوفة متغيرات حرفية تشمل عدة اوامر تخزن في المصفوفة ويفصل بينهما مسافات وتذكر مت نكرره دائما عناصر المصفوفات تبدء بالعنصر رقم صفر في لغة سي++
 
لاتضع قيمة للمتغير argc سيقوم البرنامج بتخصيص هذه القيمة ولكن داخل البرنامج اذا كشفت عن قيمة المتغير وكانت تساوي صفر وكانت رغبتك ان يدخل مستخدم البرنامج اسماء للبرنامج ليعمل عليها فيمكنك حينئذ ان توقف تشغيل البرنامج وتعطيه رسالة تحذير او خطأ بأنه لم يفعل المطلوب هل عرفت الآن فائدة هذا المتغير
اما المصفوفة argv فهي تحتوي المتغير الاول في العنصر argv[0]  والثاني في المتغير سيكون بعنصر المصفوفة argv[1] وهكذا
مثال
 
Myprog.exe mydatafile.txt
سيكون Myprog.exe  هو البرنامج و mydatafile.txt هو الامر المخزن في المصفوفه argv[0]
ويمكنك ايضا ان تضيف المسار الموجود فيه الملف المراد تحميله دون ان يعتبر ذلك امر اضافي مثل
 
Myprog.exe c:\myfolder\mydatafile.txt
  ولايكون دائما سطر الاوامر او البيانات المبدئية هي اسماء ملفات بل يمكن ان تكون ارقام يعمل عليها البرنامج عند بدء تشغيله مع الاخذ في الاعتبار ان تدخل في صورة حروف ويتم استخدام اوامر اللغة في تحويله الى ارقام يمكن العمل عليها
   








الدرس الحادي عشر
 الفئات
مساء الخير
 الفئات تميز لغة سي++ وتعطيها ادوات قوية جدا فقد تقوم بعملها انت والكثير منها يأتي اليك جاهزا لتسهيل عملك واظهار برامجك في شكل جيد بقدر ماساعدت مطوري البرامج بقدر ماجعلتهم دائمي الاطلاع على ماهو جديد منها وعودة دائمة الى كتب اللغة الصادرة من الشركات مثل بورلاند وميكروسوفت والبرمجة تحت الوندوز ماهي الا فئات عديدة تورث صفاتها الى برامجك لتعمل تحت الوندوز ربما يكون هذا رد على من يقول اننا ندرس اللغة تحت الدوس انها مقدمة وعودة الى موضوعنا فالفئات تشبه الى حد كبير هياكل البيانات التى سبق وشرحناها في درس سابق ولكن يمكن ان يكون احد اعضائها دالة تعمل معها ويمكن ان تورث احدى الفئات صفاتها الى فئة اخرى واليك الشكل العام للفئة  وستكون الفئة التي سننشئها تحت اسم MyExample
 #include
 class MyExample //Standard way of defining the class
{
 public:
     //This means that all of the functions below this(and any variables)
     //are accessible to the rest of the program.
     //NOTE: That is a colon, NOT a semicolon...
 MyExample(); //Constructor
 ~MyExample(); //Destructor
  void setspeed(int p);
 int readspeed();
     //These functions will be defined outside of the class
protected:
//This means that all the variables under this, until a new type of
//restriction is placed, will only be accessible to other functions in     // the class.  NOTE: That is a colon, NOT a semicolon...
 int processorspeed;
};    //Do Not forget the trailing semi-colon
 MyExample::MyExample()
{    //Constructors can accept arguments, but this one does not
  processorspeed = 0;
          //Initializes it to zero
}
 MyExample::~MyExample()
{         //Destructors do not accept arguments
}
 //The destructor does not need to do anything.
 void MyExample::setspeed(int p)
{       //To define a function outside put the name of the function
     //after the return type and then two colons, and then the name
     //of the function.
  processorspeed = p;
}
  int MyExample::readspeed() 
{    //The two colons simply tell the compiler that the function is part
     //of the clas
  return processorspeed;
}
 
int main()
{
  MyExample compute; 
      //To create an 'instance' of the class, simply treat it like you would
      //a structure.  (An instance is simply when you create an actual object
      //from the class, as opposed to having the definition of the class)
  compute.setspeed(100);
      //To call functions in the class, you put the name of the instance,
      //a period, and then the function name.
  cout<
      //See above note.
  return 0;
}

الشرح

لقد بدئنا بالسطور التالية
#include

class MyExample //Standard way of defining the class
{
 public:

الامر calss للاعلان عن فئة يليه اسم الفئة وهو اختياري وتذكره جيدا فسوف تلتزم به فيما بعد في صياغة باقي هيكل الفئة ثم قوس لبداية بلوك الفئة ثم الامر public: وهو بالطبع يعنى عام وكل متغير او دالة تعلن بعده معناها يمكن استخدامها في بقية اجزاء البرنامج يلي ذلك الاعلان عن باني الفئة وهي دالة تنفذ آليا بمجرد بداية عمل الفئة وصيغتها كما يلي
MyExample(); //Constructor
  اسمها ليس اختياريا ولكن عليك الالتزام باسم الفئة التي انشأتها ويوضع تحت هذه الدالة كما سيلي تفصيله ما تحتاج من تخصيص لمتغيرات عند بداية البرنامج
يلي ذلك هادم الفئة وهي دالة تستدى ايضا آليا عند انتهاء عمل الفئة ويمكن ان تضع فيها اوامر لتحرير الذاكرة مثلا من متغيرات تم تخصيصها او تهمل وضع اي شئ فيها حسب فكرة البرنامج وتكون بنفس اسم الفئة يسبقها العلامة ~  كما بالصيغة التالية
 
~MyExample(); //Destructor

كل ما سبق كان تحت الامر public: كما تتذكر ثم تحته ايضا فنحن لم ننهي العمل معه بعد وضعنا اعلان عن دالتين عامتين هما
void setspeed(int p);
 int readspeed();
ثم دخلنا بعد ذلك الى الامر protected:  ومعناه كل ما سيعلن عنه بعد ذلك لا يستخدم الا في الدوال اعضاء الفئة ولا يستخدم في باقي اجزاء البرنامج وكان ذلك في الصورة التالية
protected:

int processorspeed;
}
ثم انتهى الهيكل العام للفئة بقوس اغلاق البلوك ليبدء العمل في بناء الدوال المعلنه فكلها كانت اعلانات ولن يكون شكل الدالة بالطريقه السابق شرحها في درس الدوال لانها كانت دوال عامة ولكن ستأخذ شكل آخر لتعرف الكومبايلر انها تنتمي للفئة المعلنة وليس غيرها وستكون دالة الباني او باني الفئة اول دالة سننشئها هنا كما يلي
 
MyExample::MyExample()
{   
  processorspeed = 0;
}
بدء الاعلان عن الدالة بوضع اسم الفئة ثم اسم الدالة وبالطبع اسم الفئة واسم الدالة شئ واحد كما اتفقنا ان باني الفئة يأخذ اسم الفئة كفرض عليك ثم وضعنا قيمة ابتدائية للمتغير processorspeed تساوي صفر انتهازا لفرصة ان هذه الدالة اول ما ينفذ عند العمل على الفئة
  ثم بناء دالة هادم الفئة وكما سبق شرحة هو ايضا اسم الفئة يسبقها العلامة ~ وهي اخر دالة تنفذ وذلك كما يلي
MyExample::~MyExample()
{         //Destructors do not accept arguments
}
لم نضع فيها شئ لعدم حاجتنا لذلك ثم بناء باقي الدوال اعضاء الفئة وسوف نرى فيها شكل الاعلان عن دالة عضو لفئة
 
void MyExample::setspeed(int p)
{
  processorspeed = p;
}
 
لقد كان الاعلان عن الدالة داخل هيكل الفئة بالصورة التي تعودنا عليها وهي
void setspeed(int p);
 
عبارة عن دالة لاتعيد قيمة بناء على الامر void ثم اسم الدالة وبين القوسين القيمة التي ستمرر للدالة وهنا عبارة عن تمرير عدد صحيح للدالة كل ذلك سبق ان شرحناه ولكن الجديد هنا هو عنوان الدالة عند أنشائها كان كما يلي
 
void MyExample::setspeed(int p)

void
نوع الدالة
MyExample
اسم الفئة التي تنتمي لها
::
زوجين من نقطتين فوق بعضهما
setspeed
اسم الدالة
(int p)
القيم الممرة للدالة

سوف اوفر عليك جهد التفكير في ذلك ضع نفس الاعلان عن الدالة كما هو وبعد نوع الدالة وقبل اسمها ضع اسم الفئة يليها نقتطتين وهذه امثلة
الاعلان داخل الفئة
شكل الاعلان في تعريف وبناء الدالة
void seeme (void)
voidItsCalssName::seeme (void)
int seeme (void)
int ItsCalssName:: seeme (void)
float seeme (void)
float ItsCalssName:: seeme (void)
void seeme (int a)
void ItsCalssName:: seeme (int a)
void seeme (float a)
void ItsCalssName::seeme (float a)
int seeme (float a)
int ItsCalssName:: seeme (float a)
كان ذلك على فرض ان اسم الفئة التابع لها هو ItsCalssName والذي يناظر معنا MyExample
 ثم تم بعد ذلك بناء باقي الدوال او الدالة الباقية كما يلي
int MyExample::readspeed() 
{   
  return processorspeed;
}
  تم الانتهاء من بناء الفئة ودوالها حسب فكرة البرنامج ثم دخلنا الى الدالة الرئيسية بالبرنامج وأي برنامج آخر لنستدعي الفئة ونراها كيف تعمل
int main()
{
  MyExample compute; 
    
  compute.setspeed(100);
  cout<
      //See above note.
  return 0;
}
 
لاستدعاء الفئة يجب ان نعطيها حدث او معامل مثل هياكل البيانات تماما فقد سبق ودرسنا ذلك وهو متغير اختياري نستخدمه لاستدعاء دوال الفئة وهنا افترضناه compute
والاعلان عنه يكون باسم الفئة ثم هو اي المتغير الافتراضي كما يلي
 
  MyExample compute; 
  بعد ان اخترت اسم المعامل اصبح فرضنا عليك عدم تغييره ولاستدعاء دالة ضع اسم المعامل يليه نقطة والدالة المطلوبة تماما كما كان في هياكل البيانات
  compute.setspeed(100);
استدعينا الدالة setspeed والمعلن عنها داخل الفئة بالشكل التالي للتذكره
void setspeed(int p);

وبالتالي مررنا اليها قيمة عددية وهي 100  وهل لاحظت شئ لقد استدعينا دالة عضو للفئة خارج فئة كيف ذلك – نعم لقد وضعناها تحت بند public وقد قلنا عما يندرج تحته اقصد الامر public  ان دواله يمكن استخدامها في اي مكان وهي دوال عامة
تم تمرير القيمة 100 للدالة setspeed فبدء استدعاء باني الفئة ليخصص للمتغير القيمة صفر وبعد ذلك استعيت الدالة المطلوبة حيث يوجد بداخلها امر لتخصيص القيمة المررة للمتغير processorspeed وداخل الدالة الرئيسة للبرنامج تم استدعاء دالة عامة من دوال الفئة وهي الدالة readspeed وهي تعيد قيمة المتغير processorspeed وذلك لطباعتها وهي 100 ايضا لتريك ان متغيرات الفئة مرئية بالنسبة لباقي الفئات دون الحاجة لاعادة الاعلان عنها داخل كل دالة من دوال الفئة.
ولبيان عمل باني الدالة لتعرف حقيقته دعنا نعدل البرنامج السابق وسوف اضع لون اصفر على التعديل الطفيف الذي سوف اجريه وسيكون على الصورة التالية
 
#include

class Computer //Standard way of defining the class
{
 public:
     //This means that all of the functions below this(and any variables)
     //are accessible to the rest of the program.
     //NOTE: That is a colon, NOT a semicolon...

Computer();
     //Constructor
 ~Computer();
     //Destructor
 void setspeed(int p);
 int readspeed();
          //These functions will be defined outside of the class
protected:
   //This means that all the variables under this, until a new type of
   //restriction is placed, will only be accessible to other functions in the
   //class.  NOTE: That is a colon, NOT a semicolon...
int processorspeed;
};       

   //Do Not forget the trailing semi-colon

Computer::Computer()
{    //Constructors can accept arguments, but this one does not
  processorspeed = 17;
          //Initializes it to zero
}

Computer::~Computer()
{         //Destructors do not accept arguments

}

//The destructor does not need to do anything.

void Computer::setspeed(int p)
{       //To define a function outside put the name of the function
     //after the return type and then two colons, and then the name
     //of the function.
  processorspeed = p * processorspeed;
}

int Computer::readspeed() 
{    //The two colons simply tell the compiler that the function is part
     //of the clas
  return processorspeed;
}
 int main()
{
  Computer compute; 
      //To create an 'instance' of the class, simply treat it like you would
      //a structure.  (An instance is simply when you create an actual object
      //from the class, as opposed to having the definition of the class)
  compute.setspeed(100);
      //To call functions in the class, you put the name of the instance,
      //a period, and then the function name.
  cout<
      //See above note.
  return 0;
}
لقد وضعت في باني الفئة القيمة 17 بدلا من صفر للمتغير processorspeed وقمت بتعديل الدالة setspeed  لكي تكون قيمة المتغير عبارة عن قيمته السابقة اي التي سبق تخصيصها في الباني لانه اول ما يستدعى وتضرب هذه القيمة في القيمة الممررة بالمعادلة التالية
  processorspeed = p * processorspeed;


اي ان القيمة الجديدة تساوي القيمة القديمة اي 17  مضروبة في القيمة p التي ستمرر للدالة لتصبح قيمة processorspeed  = 17*100 اي 1700
اذا نفذت البرنامج سوف تعيد الدالة readspeed قيمة المتغير الجديدة 1700 وبالتالي اتضحت امامك فائدة باني الفئة ولك مني كل تحية