Breakpoint

الـ breakpoint هي نقطة يضعها المبرمج عند أحد أسطر البرنامج ، تخبر الـ debugger أن يوقف البرنامج عند هذا السطر ويمكن معرفة حالة وقيمة المتغيرات عند هذا الوقت أي قبل تنفيذ الأسطر التالية؛ لها أكثر من فائدة مثلًا معرفة هل تم المرور على هذا الـ Block مثل Block الـ if ، أي هل تم تنفيذ مابداخله أو ماقيمة هذا المتغيّر في هذا الوقت من البرنامج كذلك معرفة قيم الـ Array كاملة وأيضّا معرفة قيمة العدّاد والرقم الذي توقّف عنده .

 إذا لم يقف البرنامج يعني أنه لم يمر على هذا السطر إما بسبب شرط if أو loop أو غير ذلك من الأسباب. 

إحدى طرق إضافتها في الكود : تقف عند السطر الذي تريده ، زر الفأرة الأيمن ، ثم اختيار insert break-point .

مثال :

في المثال نقرأ من المستخدم رقم ، نرسله للدالة ، الدالة تقسمه على 2 وتعيد الجزء الصحيح منه ، إذا كانت القيمة 1 فمافوق سيتم طباعة العبارة أما إذا كانت 0 ، لن يتم تنفيذ Block الـ if .

الـ Array في هذا المثال فقط حتى نرى العداد وصل إلى أي عدد ، ونرى قيم الـ Array كاملة .

#include <iostream>
#include <string>
using namespace std;

int fun(int num)
{
 return num / 2;

}
void main()
{
 //Breakpoint Example

 int num;
 cout << " Enter num: ";
 cin >> num;

 int Array[5];
 for (int i = 0; i < 5; i++)
 Array[i] = num *i;

 if (fun(num))
 {
 cout << "The number is greater than or equal 2" << endl;
 }
 system("pause");
}

قمت بوضع الـ breakpoint في السطر رقم 23 

أدخلت الرقم 3 ، في الأسفل نرى  قيم المتغيرات .

1 2 3 4 6 7 8

 

أدخلت رقم 1 ، ولم يحدث شيء لأن البرنامج لم يدخل الـ if أي لم يمر على الـ breakpoint.

GUI الواجهة الرسومية

خطوات أساسية لبدء مشروع c++ بواجهة رسومية.

1- إنشاء مشروع واجهة رسومية “الشرح على بيئة تطوير Visual Studio 2013 , Professional”.

مشروع جديد (New Project)

مشروع جديد

 


Visual C++

C++


CRL

CLR


CRL Empty Project

Empty

 


 تسمية المشروع ثم OK

اسم المشروع

 


2- إنشاء أول نافذة : ممكن أن تتم بأكثر من طريقة ، سأكتفي بواحدة

Source File >> ثم زر الفأرة اليمين

Source File


ADD – New item

Add-New item


UI

UI


Widows Form

Widows form


 النتيجة بعد ضغط زر ADD

MyForm


3- فتح صفحة الأكواد التي يتم العمل داخلها 

النقر مرتين على النافذة يفتح ملف .h وهذه الطريقة لكل بقية المكونات الأزرار وغيرها 

نقر


الكود  يظهر بهذا الشكل ، وهذه إحدى الطرق

كود


4- إظها صندوق الأدوات لاستخدامها ، مثل الأزرار Buttons و مربع النص TextBox … الخ

View

عرض


ToolBox

صندوق الأدوات

ToolBox


5- إظهار مربع خصائص المكون  الذي يحوي اسم المكون والخط ووقت الظهور ..الخ، مثل خصائص النافذة .

 في الوضع الافتراضي يكون موجود في الزاوية اليمنى في الأسفل؛ ولكن إن لم يظهر لك :

الزر الأيمن على النافذة – خصائص 

زر أيمن

 


ستظهر على الجانب الأيمن ، قم بتثبيتها حتى تكون ظاهرة دائمًا في أسفل الركن الأيمن

خصائص

تثبيت الخصائص الخصائص ، النتيجة


6- إضافة Label والكتابة فيه .

من صندوق الأدوات ToolBox أختار Label ثم أسحبه إلى داخل النافذة .

ToolBox

Label


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

الكتابة

Text

 

Hello World

 

تغيير حجم الخط

Font Size

 

النتيجة

Font Size Result


7- إضافة Button وبرمجته .

بنفس طريقة الـ label  نضيف الزر ، وننقر عليه مرتين لفتح صفحة الكود ، وتغيير خصائص الزر مثل اسمه الظاهر بمثل طريقة الـ label عن طريق مربع الخصائص.

Button Button2 Code of Button


سنقوم ببرمجة الزر ، بحيث عند ضغطه ينقلنا لنافذة أخرى 

*تحتاج بدايةً أن تُنشِئ نافذة جديدة بنفس طريقة النافذة الأولى .

أولًا : عمل include للنافذة الجديدة في النافذة الأولى

#include "MyForm1.h"

include Form 1 include Form 2

ثانيًا : كتابة هذا الكود داخل دالة الـ button  ، ومن مسميّات الدوال في الكود والتعليقات الموجودة بإمكانك فهم الكود .

// creat a new form of MyForm1
  MyForm1^ frm = gcnew MyForm1();
  this->Hide(); //Hide MyForm "The Start Form"
  frm->ShowDialog(); // Show MyForm1

Button Code 1 Button Code 2


8- في النافذة الأخرى سنضع 2 من الأزرار  واحد Exit يخرج من البرنامج والآخر  Restart ويعيد تشغيل البرنامج من البداية .

البداية مع Exit .

 //Exit Button
 Application::Exit();

ExitExit Button

زر إعادة التشغيل 

 //Start Again Button
 Application::Restart();

Restart

 


9- تشغيل البرنامج 

عند عمل build سيظهر لك هذا الخطأ ، سببه هو أنه يجب أن تعيّن Main Form وهي تقابل Main Function نقطة بداية البرنامج .

Error 1 error LNK1561: entry point must be defined 

الحل:

أولًا : أفتح ملف cpp للنافذة الأولى ، موجود في الناحية اليمنى ؛ ثم أكتب بداخله هذا الكود ، وأكتب اسم مشروعك بدل كلمة “اسم المشروع الموجودة” 

using namespace System;
using namespace System::Windows::Forms;

[STAThread]
void Main(array<String^>^ args)
{
 Application::EnableVisualStyles();
 Application::SetCompatibleTextRenderingDefault(false);

اسم المشروع::MyForm form;
 Application::Run(%form);
}

مكان ملف cpp في الجانب الأيمن
Cpp Place

الكود

Codeثانيًا : أذهب إلى خصائص المشروع وأتبع الآتي 

Properties>>Configuration Properties->Linker->System
Select Windows (/SUBSYSTEM:WINDOWS) for SubSystem.
Advanced->Entry Point, type in Main >>hit OK.

Project FolderخصائصConfLinkerSystemW-subsAdvancedMainOK

أعمل Build مرة أخرى ثم Run ستجد أن البرنامج يعمل معك .

في هذا المثال لم أقم بتغيير أسماء النوافذ التي يقترحها البرنامج مثل MyForm ، لذلك عندما تغيّر أسماءها قد لاتعمل معك بعض أكوادي لاختلاف المسميّات ، وأنا أقترح عليك أن لاتغيّر الأسماء بالنسبة لي كانت تسبب مشاكل في الربط .

 

هناك اختلافات عند العمل مع visual studio 2008 ، بإمكانك مراسلتي إذا كنت تعمل على هذه النسخة ؛ كذلك لدّي مشروع  أتممته مع مجموعتي في الجامعة بواجهة رسومية يحوي LinkedList و Stack و Queue بإمكانك مراسلتي أيضًا إذا أحتجت مساعدة قد يكون لدي إجابة أو مررت على نفس الخطأ ؛ أنا أكتب هذا الكلام لأنني رأيت خلال تطوير مشاريع الواجهة الرسومية بالـ c++ أن المصادر شحيحة جدًّا ، لذلك لاأحب أن يواجه غيري صعوبات قد أكون اعرف لها حلًّا .

القراءة والكتابة في Text file

-أكتب برنامج يكتب في text file ثم يقرأ ماتمت كتابته .

الحل:

#include <iostream>
#include <fstream> //must include
#include <string>
using namespace std;

int main()
{

 int num;
/*---------------Write------------------------*/
 ofstream myfile("example.txt"); //create a text file automatically
 if (myfile.is_open())
 {
 //write on a text file
 myfile << "This is a line.\n";
 myfile << "This is another line.\n";

 //read data from user then write it on the file
 cout << "Enter a number: ";
 cin >> num;
 myfile << num;
 myfile.close();
 }
 else cout << "Unable to open file";

/*---------------Read------------------------*/
 string line;
 ifstream Read("example.txt" , ios::in);
 if (Read.is_open())
 {
 while (getline(Read,line))
 {
 cout << line << '\n';
 }
 Read.close();
 }
 else cout << "Unable to open file";

 system("pause");
 return 0;
}

-مايتم كتابته يبقى في الملف بعد الـ run ولكن عند عمل run مرة أخرى يكتب على البيانات السابقة .

– مكان الملف النصّي :

 المستندات documents

بيئة التطوير مثلًا visual studio

ملف المشاريع projects 

 ملف المشروع الذي أنشاته ، ثم بداخله ستجد ملف يحمل نفس اسم المشروع ستجد بداخله هذا الـ text file .

 

Template Class

أنشِئ Class :

اسمه: Addition

المتغيرات : elem1 ,elem2

يحوي : parameterized constructor و دالة لحساب مجموع العنصرين  و دالة لطباعة محتوى  .

-أجعل هذا الـ class يستقبل أي نوع من البيانات ، بمعنى يمكنه جمع أي عددين سواءً int أو double أو أي نوع آخر .

الحل:

جعل الـ class يستقبل أي نوع من البيانات يعني استخدام مفهوم template .

//main.cpp
#include <iostream>
using namespace std;
#include <string>

template <typename T>
class Addition
{

 T elem1;
 T elem2;

public:

 Addition(T val1, T val2);
 T calc();
 void print();

};


template <typename T> Addition<T>::Addition(T val1, T val2)
{
 elem1 = val1;
 elem2 = val2;
}

template <typename T> T Addition<T>::calc()
{
 return elem1 + elem2;
}

template <typename T> void Addition<T>::print()
{
 cout << "Result is: " << calc() << endl;

}

void main()
{
 Addition<int> ADD1st(9, 8);

 cout << "int type| ";
 ADD1st.print();

 Addition<double> ADD2nd(1.2 , 6.2);
 cout << "double type| ";
 ADD2nd.print();

 Addition<string> ADD3rd("HE", "llo");
 cout << "string type| ";
 ADD3rd.print();

 system("pause");
}

 

Operator Overloading

أنشِئ Class :

اسمهFraction

المتغيرات numerator , denominator

يحوي : default constructor و  set & get و  overloading functions للعمليات التالية :

جمع ، أقل من ، ضرب >> as global functions .

قسمة ، إسناد “=”  >> as member functions .

قراءة وطباعة .

-في main قم باختبار كل الـ operator overloading functions .

الحل:

مفهوم operator overloading هو أن نعيد تعريف الـ built-in operator حتى نتمكن من تطبيقها على الـ objects كأن نجمع 2 objects أو نضربهما ..الخ .

نلاحظ في السؤال أنه لم يتم التوضيح بالنسة لعملية القراءة cin والطباعة cout ماإذا كانت member or global لأنها في الواقع لايمكن ان تكون سوى global أي friend .

-يجب أن نراعي في الحل قوانين ضرب وجمع وقسمة ومقارنة الكسور .

 

//.h
#include <iostream>
using namespace std;

class Fraction
{
private:
 int numerator;
 int denominator;

public:
 Fraction(){ numerator = 0; denominator = 0; }

 void setNumerator(int num)
 {
 numerator = num;
 }
 void setDenominator(int num)
 {
 denominator = num;
 }
 int getNumerator()
 {
 return numerator;
 }
 int getDenominator()
 {
 return denominator;
 }

 //global means (friend) "optional"
 friend Fraction operator +(Fraction &obj1, Fraction &obj2);
 friend bool operator < (Fraction &obj1, Fraction &obj2);
 friend Fraction operator *(Fraction &obj1, Fraction &obj2);

 //member function "optional"
 void operator = (Fraction &obj);
 Fraction operator /(Fraction &obj);

 //must be friend
 friend ostream& operator << (ostream& outs, const Fraction& ob);
 friend istream& operator>>(istream& inc, Fraction& ob);

};
-----------------------------------------------------------
//.cpp
#include "Fraction.h"
#include <iostream>
using namespace std;

Fraction operator +(Fraction &obj1, Fraction &obj2)
{
 Fraction obj3;
 obj3.denominator = obj1.denominator * obj2.denominator;
 obj3.numerator = (obj1.numerator*obj2.denominator) + (obj2.numerator*obj1.denominator);
 return obj3;
}

bool operator < (Fraction &obj1, Fraction &obj2)
{
 if ((obj1.numerator / obj1.denominator) < (obj2.numerator / obj2.denominator))

 return true;

 else return false;
}

Fraction operator *(Fraction &obj1, Fraction &obj2)
{
 Fraction obj3;
 obj3.denominator = obj1.denominator*obj2.denominator;
 obj3.numerator = obj1.numerator*obj2.numerator;
 return obj3;
}

void Fraction::operator = (Fraction &obj)
{
 numerator = obj.numerator;
 denominator = obj.denominator;
}

Fraction Fraction::operator/(Fraction &obj)
{
 Fraction obj3;
 obj3.denominator = denominator*obj.numerator;
 obj3.numerator = numerator*obj.denominator;
 return obj3;
}

ostream& operator << (ostream& outs, const Fraction& ob)
{
 outs << "The result is: ";
 outs << ob.numerator << "/" << ob.denominator << endl;
 return outs;
}

istream& operator >> (istream& inc, Fraction& ob)
{
 cout << "Enter the number numerator: ";
 inc >> ob.numerator;
 cout << "Enter the number denominator: ";
 inc >> ob.denominator;
 return inc;
}
---------------------------------------------------
//main.cpp
#include <iostream>
using namespace std;
#include "Fraction.h"
int main() {

 Fraction f1, f2;

 cin >> f1;
 cin >> f2;

 cout << " << operator:\n";
 cout << f1 << f2;

 cout << " + operator: ";
 Fraction f3 = (f1 + f2);
 cout << f3;

 cout << " < operator: ";
 cout << (f1<f2) << endl;

 cout << " * operator: ";
 Fraction f4 = f1*f2;
 cout << f4;

 cout << " = operator: ";
 Fraction f5 = f1;
 cout << f5;

 cout << " / operator: ";
 cout << (f1 / f2);



 system("pause");
 return 0;
}