سربارگذاری عملگر ورودی و خروجی << >> در زبان C++


شاید گاهی لازم باشد عملکرد عملگر های ورودی و خروجی را در برنامه های خود (معمولا برنامه های کنسولی) به صورت دلخواه تغییر دهیم تا بتوانیم آنها را برای اشیاء کلاس هایمان به صورت صحیح کار ببریم. سربارگذاری عملگر های ورودی و خروجی را در این پست با یک نمونه ساده در مورد "تاریخ" (date) نشان داده شده است. به کلاس ساده زیر توجه کنید.

class date
{
public:
int day, month, year;

date (int day, int month, int year)
{
   this->day = day;
   this->month = month;
   this->year = year;
}
};

کلاس date دارای سه عضو عمومی برای روز، ماه و سال است و یک سازنده برای مقدار دهی این اعضا دارد. البته اعضای کلاس معمولا باید به صورت خصوصی تعریف شوند ولی ما در این مین مثال ساده ترین گزینه را در نظر می گیریم. سربارگذاری عملگر های ورودی و خروجی باید در بیرون کلاس صورت گیرند. در ادامه به ترتیب سربارگذاری برای عملگر ورودی و خروجی تعریف شده است. ما می خواهیم که بتوانیم تاریخ را به صورت یکجا (مثلا 22/3/1396 وارد کنیم یا در خروجی چاپ کنیم، پس باید این عملگر های را به گونه ای که مورد نظر ماست دستکاری کنیم).


istream &operator>> (istream &output, date &day)
{
  char slash;
  output >> day.day >> slash >> day.month >> slash >> day.year;
  return output;
}

ostream &operator<< (ostream &output, date day)
{
  return output << day.day << "/" << day.month << "/" << day.year;
}

عملگر << از نوع istream و عملگر >> از نوع ostream است. برای همین نوع بازگشتی توابع را از این انواع تعیین می کنیم. این توابع باید دارای دو پارامتر باشند که پارامتر اول شیئی از نوع ذکر شده برای خروجی است و پارمتر دوم شیئی از کلاس date است که دربردارنده سه عضو روز، ماه و سال است. اگر این اعضا خصوصی تعریف شده بود باید از توابع دستیابی برای دسترسی به آنها استفاده می کردیم ولی چون اینجا اعضا، عمومی هستند نیازی به این کار نیست.

تابع اول به نحوی تعریف شده است که روز، ماه و سال را یکجا از از کاربر دریافت می کند و مقدار آنها را در متغیر های عضو قرار می دهد؛ کاراکتر اسلش / به عنوان جدا کننده انها به کار رفته است همانطور که هنگام نوشتن تاریخ از آن برای جدا کردن روز، ماه و سال استفاده می کنیم. تابع دوم ساده تر از تابع اول است و تنها سه متغیر عضو را همراه با کاراکتر اسلش برای جداسازی در خروجی چاپ می کند. حالا می توانیم این این دو عملگر را برای اشیاء کلاس date به صورت مستقیم به کار ببریم و تاریخ را یکجا از ورودی دریافت یا در خروجی نمایش دهیم.  

 

سربارگذاری عملگر تساوی ( == )


این پست مثالی از سربارگذاری عملگر تساوی یا == در زبان C++ است. سربار گذاری این عملگر می تواند در داخل یا خارج از کلاس موردنظر انجام شود؛ به این معنی که تابع سربارگذاری تابع عضو کلاس باشد یا خیر. برای این مثال ما سربارگذاری را در خارج از کلاس انجام می دهیم و در فضای عمومی برنامه تابع خود را قرار می دهیم.

تفاوت سربارگذاری در داخل یا خارج از کلاس (تابع عضو یا غیر عضو) :

تفاوت اینکه تابع را در کلاس تعریف کنید یا خیر این است که هنگامی که در تابع در کلاس تعریف می شود اولا به اعضای خصوصی دسترسی دارید و دوما تابع شما تنها یک پارامتر را می پذیرد که آن عملوند طرف راست عملگر == است و عملگر this به عملوند طرف چپ == اشاره دارد. ولی تابعی که در خارج از کلاس تعریف شده باشد مانند مثال زیر نیازمند دو پارامتر است که اولی عملوند طرف چپ و دومی عملوند طرف راست == هستند.
کلاس زیر را در نظر بگیرید : (من همیشه سعی می کنم تا ساده ترین حالت ممکن را در مثال ها، عنوان کنم تا ذهن خواننده درگیر مسائل فرعی نشود)


class students
{
public:
  int num;
  string name , family;
};

students کلاسی برای ذخیره نام، نام خانوادگی و شماره یک دانش آموز است. فرض کنید دو شی یا دو دانش آموز از کلاس بالا در اختیار دارید و می خواهید یکسان بودن آنها را به صور مستقیم با عملگر == بررسی کنید. اگر این مثال را نمی پسندید می توانید کلاسی را برای تاریخ یا درامد یا هر چیز دیگری تصور کنید...

students stu1, stu2;
stu1.name = "ali"; stu2.name = "hossein";
stu1.familiy = "rahimi"; stu2.family = "rajabi";
stu1.num = 15452214; stu2.num = 15426444;

اگر بخواهید این دو دانش آموز را به صورت مستقیم با یکدیگر مقایسه کنید چون عملگر == با کلاس شما مطابقت ندارد، با پیغام خطای کامپایلر مواجه می شوید.

if (stu1 == stu2) // Error
{
  // do something
}

راه حل سربار گذاری عملگر == برای کلاس students است. تابع سربارگذاری عملگر == دارای دوپارامتر const یا "ثابت" است که در مورد آنها توضیح دادیم. نوع این بازگشتی این تابع bool یا منظقی است چون قرار است یک مقدار true یا false را برگرداند و بدنه آن (در این مثال) بررسی هر سه متغیر عضو کلاس برای دو شی ارسال شده است.

bool operator== (const students &stu1, const students &stu2)
{
     if (stu1.name == stu2.name
         && stu1.family == stu2.family
          && stu1.num == stu2.num)
     { 
        return true;
     }
    return false; 
}

یا به صورت بهتر :


bool operator== (const students &stu1, const students &stu2)
{
return (stu1.name == stu2.name
          && stu1.family == stu2.family
           && stu1.num == stu2.num);
}

حالا میتوان با این تابع، به صورت مستقیم عملگر == را برای اشیای کلاس students به کار برد. حالا که سربارگذاری عملگر == را انجام دادیم، باید بتوانیم سربارگذاری عملگر =! را به همین صورت انجام دهیم. 

جست و جو و مرتب سازی در vector

 
در زبان C++ دو تابع پیش ساخته را می توانیم برای جست و جو و مرتب سازی وکتور به کار ببریم. واضح است که استفاده از توابع پیش ساخته در بسیاری مواقع به توابع شخصی ارجحیت دارد.

مرتب سازی وکتور :
برای مرتب سازی وکتور از تابع sort استفاده می کنیم که در کتابخانه algorithm نوشته شده است و حالت کلی آن به صورت زیر است.


// #include < algorithm >

sort (Beginning, End);

تابع sort دو پارامتر دارد که ابتدا و انتهای بازه مورد نظر برای مرتب سازی را مشخص می کند. دو تابع begin و end ایندکس ابتدا و انتهای وکتور را برمی گردانند. اگر وکتور numbers را در مثال زیر در نظر بگیریم، مرتب سازی کل وکتور به صورت زیر خواهد بود.


vector < int > numbers (100);
sort (numbers.begin(), numbers.end());

با این کار کل عناصر ویکتور از کوچک به بزرگ مرتب خواهند شد. مرتب سازی می تواند از هر بازه دلخواهی صورت گیرد. برای این کار می توانید از پارامتر های begin و end مقدار دلخواه را کم یا زیاد کنید تا محدوده دلخواه شما مشخص شود. برای مثال مرتب سازی نیمه اول وکتور به صورت زیر خواهد بود.

sort (numbers.begin(), numbers.end() - 50);


جست و جو در وکتور :

جست و جو در وکتور میتواند به سادگی با یک الگوریتم جست و جوی خطی انجام شود. ولی ما در این جا از تابع find از کتابخانه استاندارد C++ استافده می کنیم که حات کلی آن به صورت زیر است و در کتابخانه algorithm نوشته شده است.


// #include < algorithm >
find (Beginnig, End, Value);

دو پارامتر اول، نقطه شروع و پایان جست و جو و پارمتر سوم مقداری است که در وکتور به دنبال آن می گردیم. برای مثال در وکتور numbers کد زیر وجود مقدار 124 را در وکتور بررسی می کند.


if (find (numbers.begin(), numbers.end(), 124) != numbers.end())
{
  cout << "found";
}
else
{
  cout << "not-found";
}

تابع find مقدار صحیح یا غلط را برنمیگرداند، در عوض مقداری از نوع iterator را برمیگرداند که ایندکس اولین خانه است که مقدار ارسال شده در آن یافته شده است. و اگر این مقدار اصلا یافته نشد حد بالا بازه جست و جو + یک ، را برمی گرداند. پس حالا که ما در کل وکتور جست و جو را انجام می دهیم، اگر جست و جو موفقیت آمیز نباشد(مقدار ارسال شده یافته نشود) ایندکس آخرین خانه وکتور + یک (numbers.end() + 1) یا اندازه ویکتور (numbers.size()) برگردانده می شود.
اگر خواسته باشید ایندکس خانه ای که یافته شده است را به دست اورید می توانید به صورت زیر عمل کنید.

int index = find (numbers.begin(), numbers.end(), 124) - numbers.begin();

در این صورت هم اگر عمل جست و جو نتیجه ای نداشته باشد، اندازه وکتور بر گردانده می شود.

 

Type Safety چیست ؟

 

type safety یا به فارسی "اطمینان نوع" قابلیت یا ویژگی یک زبان برنامه نویسی برای جلوگیری یا کاهش رخدادن خطاهای "عدم تطابق نوع" یا Type Errors در برنامه است. عدم تطابق نوع، به رفتار ناخواسته و نامطلوب یک برنامه به دلیل اختلاف در انواع داده ای در متغیر ها، ثابت ها یا توابع برنامه، گفته می شود. برای مثال رفتار کردن با یک متغیر نوع صحیح (integer) مانند یک متغیر نوع ممیز شناور (float).

یک زبان برنامه نویسی ممکن است خطاهای بالقوه را در هنگام کامپایل مشخص کند یا اطلاعات انواع را در زمان اجرا با مقدار ها بررسی کند تا خطاهای قریب الوقوع را مشخص کند یا ترکیبی از این دو نوع باشد. type safety گاهی اوقات نه به عنوان یک ویژگی زبان برنامه، بلکه به عنوان ویژگی برنامه نوشته شده یاد می شود؛ به این دلیل که برخی از زبان های برنامه نویسی امکاناتی برای برنامه نویسیان فراهم کرده اند تا برنامه نویسان بتوانند از آن در برنامه های خود استفاده کنند.


ساختار vector در زبان C++


در زبان برنامه نویسی C++ ، وکتور (vector) ساختاری است که به شما اجازه می دهد چندین مقدار یا ارزش را تحت یک نام ذخیره و استفاده کنید؛ بر خلاف متغیر ها که تنها اجازه ذخیره یک مقدار تحت یک نام را می دهند. وکتور را میتوانید مانند آرایه تصور کنید که دارای خانه هایی مشخص و پشت سر هم است و در هر کدام از انها می تواند یک مقدار ذخیره شود و برای دسترسی به این خانه ها از ایندکس آنها که از صفر شروع می شود، استفاده می شود.
تعریف یک وکتور :
پیش از هر کاری، برای استفاده از این ساختار باید کتابخانه vector را به برنامه خود اضافه کنید. حالت کلی تعریف وکتور به صورت زیر است :


// add vector lib to program
#include

// declaration
vector < TYPE > NAME;

خط بالا یک وکتور را به کلی ترین حالت ممکن تعریف می کند. پس تعریف به این صورت است که پس از کلمه vector در بین دو علامت < > ، نوع داده ای وکتور اعلان می شود و پس از آن نام وکتور مشخص می شود.
برای مثال کد زیر را در نظر بگیرید که وکتوری به نام numbers از نوع int یا صحیح تعریف می کند که در طول پست برای ذکر مثال از آن استفاده می کنیم.


vector < int > numbers;

مشخص کردن تعداد خانه ها یا عناصر وکتور در هنگام تعریف :

vector < TYPE > NAME (SIZE);

در این صورت وکتوری با تعداد عناصر یا خانه های مشخص شده به صورت SIZE ایجاد می شود و به عبارت دیگر اندازه وکتور به تعداد مشخص شده محدود می شود.

تعیین مقدار اولیه یا پیشفرض عناصر وکتور در هنگام تعریف :

vector < TYPE > NAME (SIZE , Default_Value);

در این صورت وکتوری با اندازه مشخص شده ایجاد می شود که عناصر آن همگی به صورت پیشفرض دارای مقدار تعریف شده Default_Value هستند.

دسترسی و مقدار دهی به عناصر وکتور :
برای دسترسی به عناصر وکتور از ایندکس یا شماره خانه هر عنصر استفاده می کنیم. برای مثال برای وکتور numbers مقدار دهی یا خواندن سه عنصر اول به صورت زیر خواهد بود.

numbers[0] = 100;
numbers[1] = 200;
numbers[2] = 300;
..........
cout << numbers[0];
cout << numbers[1];
cout << numbers[2];


مقدار دهی با استفاده از تابع push_back :
تابع push_back مقدار ارسال شده را در اولین خانه در دسترس (خالی) وکتور قرار می دهد. بنابراین اگر برای اولین بار از این تابع استفاده کنیم مقدار ارسال شده در خانه اول ( ایندکس 0 ) وکتور قرار می گیرد. (چون وکتور تا به حال مقدار دهی نشده باشد) و برای بار های بعد مقدار ارسال شده در خانه های بعدی قرار خواهند گرفت. فرض کنید خط زیر را برای وکتور numbers به کار ببریم :

numbers.push_back (400);

در این صورت مقدار 400 در خانه چهارم این وکتور قرار می گیرد چون سه خانه اول قبلا (در کد های بالا) اشغال شده بوده اند و خانه چهارم اولین خانه ی در دسترس برای ذخیره این مقدار است.

حذف اخرین عنصر وکتور با استفاده از تابع pop_back :
تابع pop_back آخرین خانه اشغال شده وکتور را خدف (خالی) می کند. ولی دقت کنید که مقدار این خانه را بر نمی گرداند. برای مثال کد زیر، مقدار 400 را از خانه چهارم وکتور numbers حذف می کند.

numbers.pop_back();



برنامه محاسبه معکوس ماتریس n * n ( زبان C# )


در پست های قبل نحوه به دست آوردن معکوس یا واران یک ماتریس 3 در 3 یا بیشتر و همچنین شروط آن را یادآوری کردیم. در این پست هم برای کسانی که مانند من علاقه دارند برنامه محاسبه را خودشان به صورت دلخواه بنویسند، نکاتی را توضیح خواهیم داد. هدف اصلی من از این چند پست، افزایش مهارت در برنامه نویسی با بهانه تعیین معکوس یا واران یک ماتریس بود که سوژه خوبی برای برنامه نویسی در سطوح مقدماتی است؛ در این میان یک یادآوری هم از دروس دوران دبیرستان شد. در انتهای پست نیز میتوانید نسخه ای از برنامه ای که من برای این چند پست نوشته ام را داشته باشید. که به احتمال زیاد بدون مشکل نخواهد بود.

اولین کار برای محاسبه معکوس ماتریس به دست آوردن ماتریس الحاقی است. ماتریس الحاقی ماتریسی هم مرتبه ماتریس ورودی است که درایه های آن از انجام 3 عملیات زیر به دست می آید :

1 : هر درایه برابر است با کهاد ماتریس نسبت به سطر و ستون آن درایه.
2 : درایه های ماتریس با شرط اینکه، "اگر سطر + ستون درایه یا i+ j فرد بود" تغییر علامت می یابند.
3 : درایه های نسبت به قطر اصلی جابه جا می شوند. مانند اینکه قطر اصلی را محور تقارن ماتریس در نظر بگیریم.
برای دو تغییر اول فرمول زیر استفاده می شود و ماتریسی که از این اعمال این دو تغییر به دست می یابد را ماتریس همسازه گفته می شود.


A i, j = (-1) ᴵ + ᴶ x | M i ,j |


من تابع محاسبه ماتریس همسازه را اینگونه نوشته ام :


private double[,] Hamsaze(double[,] matrix)
{
int Size = (int)Math.Sqrt(matrix.Length);
double[,] result = new double[Size, Size];
for (int i = 0; i < Size; i++)
{
   for (int j = 0; j < Size; j++)
   {
      result[i, j] = Math.Pow(-1, (i+1 + j+1)) * Determinant(Kehad(matrix, i, j));
   }
}
return result;
}


در این تابع دو تابع دیگر به نام Determinant و Kehad را مشاهده می کنید. که از نامشان پیداست خروجی انها چیست.
تابع دترمیان :

private double Determinant(double[,] matrix)
{
double determinant = 0;
int Size = (int)Math.Sqrt(matrix.Length);
if (Size == 1)
{
   return matrix[0, 0];
}
else if (Size == 2)
{
   return (matrix[0, 0] * matrix[1, 1] - matrix[0, 1] * matrix[1, 0]);
}
else
{
  for (int i = 0; i < Size; i++)
     determinant += (int)Math.Pow(-1, (i + 1) + 1) * matrix[0, i] * Determinant(Kehad(matrix, 0, i));
}
return determinant;
}


تابع کهاد :


private double[,] Kehad(double[,] matrix, int ROW, int COL)
{
int Size = (int) Math.Sqrt(matrix.Length);
double[,] result = new double[Size - 1, Size - 1];
int x = -1, y = 0;
for (int i = 0; i < Size; i++)
{
   if (i == ROW)
   continue;
   x++;
   y = 0;
    for (int j = 0; j < Size; j++)
    {
      if (j == COL)
      continue;
      result[x, y++] = matrix[i, j];
    }
}
return result;
}

تابعی که برای اعمال تغییر سوم (به همراه دو تغییر اول) به کار برده ام Adjugate نام دارد و کاری که می کند، جابه جا کردن درایه های ماتریس همسازه نسبت به قطر اصلی آن است.

private double[,] Adjugate(double[,] matrix, int row, int col)
{
// first step
matrix = Hamsaze(matrix);

//second step
double temp = 0;
for (int i = 0; i < row; i++)
   {
    for (int j = i - 1; j >= 0; j--)
    {
      temp = matrix[j, i];
      matrix[j, i] = matrix[i, j];
      matrix[i, j] = temp;
    } 
   }  
return matrix;
}

با به دست آوردن ماتریس الحاقی تنها کاری که باید بکنیم این است که معکوس دترمینان ماتریس ورودی را در ماتریس الحاقی ضرب کنیم. این کار ساده است چون تنها باید این عدد را در تک تک درایه های ماتریس الحاقی ضرب کنیم. برای مثال ضرب یک عدد در ماتریس می تواند با کد زیر انجام شود. (البته واضح است که در تمام توابع بالا و تابع زیر سطر و ستون ماتریس یا row و col با یکدیگر برابر خواهد بود چون مربعی بودن ماتریس، پیش شرط وجود این مشتقات است.)  

فرمول محاسبه ماتریس معکوس : 

Inv(matrix) = 1 / Determinant(matrix)  x  Adjugate-matrix

ضرب یک عدد در ماتریس :

number : عدد مورد نظر

for (int i = 0; i < row; i++)
   for (int j = 0; j < col; j++)
   {
      matrix[i, j] *= number;
   }

در پایان می توانید از لینک زیر برنامه ی ساده ای که برای محاسبه معکوس ماتریس در محیط دات نت نوشته ام را دانلود و تست کنید. البته باید آخرین نسخه دات نت را برای اجرای این برنامه داشته باشید.

Effective Memory Clock چیست ؟


Effective Memory Clock یا "فرکانس موثر حافظه"، نقطه ی مقابل Real Memory Clock یا "فرکانس واقعی حافظه"، به فرکانس کلی یک حافظه تصادفی (RAM) گفته می شود که از ضرب فرکانس واقعی، در تعداد واحد های انتقال یافته اطلاعات در هر چرخه (کلاک) به دست می آید. برای مثال در رم های DDR - Double Data Rate فرکانس موثر از ضرب فرکانس واقعی در 2 به دست می آید چون این حافظه ها در هر چرخه می توانند دو واحد اطلاعات را انتقال دهند و یا در حافظه های QDR - Quad Data Rate فرکانس موثر از ضرب فرکانس واقعی در 4 به دست می آید چون این حافظه ها در هر چرخه 4 واحد اطلاعات را منتقل می کنند.    



کاربرد دوگانه ی عملگر های & و * در زبان C++


شاید قبلا در مورد کاربرد دوگانه عملگر های & و * در زبان برنامه نویسی C++ صحبت کرده باشم ولی این پست یک یاداوری در مورد این دو عملگر است. این دو عملگر می توانند به صورت پیشوند یا پسوند به کار روند و در این صورت عملکرد های متفاوتی خواند داشت.


عملگر & به صورت پسوند نوع: (یا پیشوند متغیر در هنگام اعلان)
در این صورت، & برای تعریف یک نام مستعار یا تعریف یک پارمتر از نوع ارجاع به کار می رود. در زیر مثالی از موضوع را مشاهده می کنید.


تعریف یک نام مستعار برای یک متغیر :
int num = 100;
int& mirror = num;  // or :  int  &mirror = num; 

تعریف یک پارمتر به صورت ارجاع :
void Function (int& Parameter1);



عملگر & به صورت پشوند متغیر :
در این صورت این عملگر آدرس متغیر موردنظر را بر می گرداند. در زیر مثالی از این موضوع را مشاهد می کنید.



بازگرداندن آدرس یک متغیر :
int num = 100;
cout << & num;


عملگر * به صورت پسوند نوع : (یا پیشوند متغیر در هنگام اعلان) 

در این صورت این عملگر برای تعریف یک اشاره گر به کار می رود. در زیر مثالی از این موضوع را مشاهد می کنید.


تعریف یک اشاره گر :
int num = 100;
int* ptr = & num;  // or : int *ptr = & num;


عملگر * به صورت پشوند متغیر :
در این صورت این عملگر مقدار متغری که اشاره گر به آن اشاره می کند. برای مثال اشاره گری که در بالا تعریف کردیم را در نظر بگیرید.


بازگرداندن مقدار متغیری که اشاره گر به آن اشاره دارد :
cout << * ptr;


 

ایجاد و راه اندازی Event

همانطور که قبلا گفتیم، عملیات اطلاع رسانی یا سیگنالیگ یک Event (رخداد) شامل یک دلیگیت (Delegate) میشود و دلیگیت، در بردارنده ی اشاره گر هایی به توابعی است که بایستی در هنگام رخ دادن Event فراخوانی شوند. اکثر Event هایی که ما به آنها سرو کار داریم مربوط به کنترل های برنامه مانند دکمه ها، منو ها و تکست باکس ها و ... مربوط می شوند و هنگامی رخ می دهند که کاربر با انها تعاملی داشته باشد؛ اما  Event ها را  همچنین میتوان در کد های برنامه ایجاد و راه اندازی کرد.
یک Event عضوی از یک کلاس ارجاع (Reference) است که به وسلیه ی کلمه Event و نام کلاس دلیگیت، تعریف می شود. در زیر نمونه ی ساده ای از تعریف Event را مشاهده می کنید.

public delegate void HANDLER();


// Class with an event member
public ref class EventClass
{
public:
// declaring the event
event HANDLER^ EVENT;

// Function to trigger event
void TriggerEvent()
{
   EVENT();
}
};

   

کلاس EventClass دارای یک Event وهله ای (instance) به نام EVENT است که با استفاده از دلیگیت HANDLER تعریف شده است و با آن در ارتباط است. و تابع عمومی TriggerEnevt مسئول راه اندازی این Event و در این مثال، بدون پارامتر است. هنگامی که EVENT راه اندازی می شود، میتواند توابعی که در لیست دلیگیت هستند را فراخوانی کند و همچنین نوع خروجی تعریف شده آن را داشته باشد. همینطور که می بینید راه اندازی Event مشابه فراخوانی دلیگیت است. برای جواب دادن به این Event میتوان کلاسی مشابه زیر ایجاد کرد :


public ref class AnswerClass

{
public:
void answer()
{
   Console::WriteLine("Event triggered");
}
};

کلاس AnswerClass دارای یک تابع عمومی به نام answer است که می تواند برای جواب دادن به Event به کار رود به این خاطر که دارای پارمتر ها و نوع بازگشتی یکسان با دلیگیت تعریف شده ما است.(در این مثال برای سهولت، هر دو بدون پارامتر و نوع بازگشتی هستند). 

به کار گیری Event :
قبل از اینکه بتوانیم از این تابع استافده کنیم باید یک شی از کلاس EventClass ایجاد کنیم. خط اول کد زیر این کار را انجام می دهد. بعد از اینکار میتوانیم این تابع را برای مدیریت Event خود ثبت کنیم.


EventClass^ obj = gcnew EventClass;

AnswerClass^ answer = gcnew AnswerClass;
obj -> EVENT += gcnew HANDLER(answer, & AnswerClass::answer);
obj ->TriggerEvent();

خط دوم کد بالا یک شی از کلاس AnswerClass ایجاد می کند، چون تابع answer یک تابع وهله ای (غیر استاتیک) است و سپس در خط بعد نمونه ای (وهله ای) از دلیگیت HANDLER را به همراه تابع مدیریت کننده خود را به Event تعریف شده در کلاس EventClass اضافه می کنیم؛ به عبارت دیگر تابع answer را برای Event خود ثبت می کنیم. در خط بعد با استفاده از تابع TriggerEvent آن را راه اندازی می کنیم. با فراخوانی این تابع، EVENT راه اندازی می شود و نتیجه ی آن، فراخوانی تابع answer است و در نتیجه عبارت "Event triggerd" در خروجی چاپ می شود.

منبع : Ivor Horton's beginnig visual C++ 2010

دلیگیت های آزاد - Unbound Delegates


در پست های قبل دلیگیت هایی که تعریف کردیم از نوع "دلیگیت های محدود" یا Bound Delegates بودند، زیرا آنها مجموعه ی ثابتی از توابع را در لیست فراخوانی خود داشتند. یک دلیگیت "نامحدود" یا "آزاد" به تابعی وهله ای (Instance) اشاره می کند که دارای لیست پارامتر مشخص شده و نوع بازگشتی برای یک نوع شی مشخص شده است. بنابراین یک دلیگیت یکسان میتواند برای فراخوانی توابع وهله ای برای هر شی مشخص شده به کار رود. در زیر نمونه ای از تعریف یک دلیگیت آزاد را مشاهده می کنید.

public delegate void HANDLER (HandlerClass^ , int value);

اولین آرگومان نوع اشاره گر this را مشخص می کند، برای اینکه یک دلیگیت از نوع HANDLER بتواند یک تابع وهله ای (غیر استاتیک) را فراخوانی کند. این تابع باید یک آرگومان از نوع int و نوع بازگشتی void داشته باشد. بنابراین یک دلیگیت از نوع HANDLER تنها میتواند یک تابع برای یک شی از کلاس HandlerClass را فراخوانی کند ولی برای هر شی از این نوع. این ممکن است کمی محدود کننده به نظر برسد ولی در بسیار مفید خواهد بود. فرض کنید HandlerClass ساختاری مشابه زیر دارد ...

ref class HandlerClass
{public:
// constructors ...
....
// functions
void Function1 (...)
{// do something}
void Function2 (...)
{// do something}
...
}

میتوان یک دلیگیت از نوع HANDLER را به صورت زیر ایجاد کرد:

HANDLER^ handler = gcnew HANDLER (&HandlerClass::Function1);

هنگامی که یک دلیگیت آزاد را فراخوانی می کنید، اولین آرگومان، شی مشخص کننده ی توابعی از لیست است که باید فراخوانی شوند و آرگومان های بعدی، آرگومان های آن توابع هستند. برای مثال شاید بخواهید دلیگیت handler را به صورت زیر فراخوانی کنید.

HandlerClass^ obj = gcnew HandlerClass ("parameters");
handler (obj, "value");

اولین آرگومان یک هندل به شی کلاس HandlerCalss است که شما با ارسال پارامتر ها به سازنده کلاس، ایجاد کردید که تعداد آنها بسته به تعریف سازنده است. دومین ارگومان مقداری است که به تابع موردنظر ارسال می کنید.
دلیگیت های آزاد را نیز میتوان با استفاده از عملگر های + و - در یکدیگر ادغام یا از یکدیگر تفکیک کرد. برای مثال بالا فرض کنید که بخواهید تابع دیگری از کلاس را به لیست دلیگیت اضافه کنید. با استفاده از عملگر + این کار به صورت زیر امکان پذیر است.

handler += gcnew HANDLER (&HandlerClass::Function2);

عملگر های + و - در delegate


عملگر + به نحوی برای delegate سربارگذاری شده است تا لیست توابع دو delegate را در یک شی delegate ترکیب کند. برای مثال کلاس زیر را در نظر بگیرید که دارای دو تابع عضو است.


class HandlerClass
{public:
 static void Func1()
 {
   Console::WriteLine("First function called\n");
 }
 static void Func2()
 {
   Console::WriteLine("Second function called\n");
 }
};


همچنین delegate را به صورت زیر تعریف کرده ایم :

public delegate void HANDLER ();


حالا یک بار delegate را با تابع اول (Func1) تعریف می کنیم و آن را فراخوانی می کنیم.


HANDLER^ handler = gcnew HANDLER (HandlerClass::Func1);
handler();

چون تابع اول تنها تابع در لیست فراخووانی delegate است، خروجی به صورت زیر خواهد بود :

"First function called"

حالا با استفاده از عملگر + تابع دوم را به لیست توابع delegate اضافه می کنیم.

handler += gcnew HANDLER(HandlerClass::Func2);

الان متغیر handler به دلیگیتی اشاره دارد که دو تابع را در لیست توابع خود دارد. البته این دستور یک delegate جدید ایجاد می کند. حالا دوباره آن را فراخوانی می کنیم. 

handler();

حالا این خروجی را خواهید گرفت :

"First function called"
"Second function called"

هر دو تابعی که که در لیست دلیگیت وجود دارند به ترتیبی که در آن قرار گرفته اند فراخوانی می شوند.
عملگر - نیز عملکردی مشابه عملکرد + دارد، البته واضح است که اینبار توابع مشخص شده به صورت ارگومان، از لیست توابع delegate خذف می شوند. برای مثال دستور زیر تابع Func2 را از لیست handler حذف می کند.

handler -= gcnew HANDLER(HandlerClass::Func2);

در برنامه نویسی با فناوری Windows Forms بسیار از این دو عملگر برای ایجاد و به کار گیری Event های مختلف استفاده می شود.

ISOCPP مسئول تدوین استاندارد های C++


C++ زبان بزرگ و مهمی در دنیای کامپیوتر است. همه ما این را می دانیم و به آن معترف هستیم و می دانیم بدون آن شاید دنیای کامپیوتر به شکل امروزی نبود. اکثر قریب به اتفاق زبان های برنامه نویسی جدید از C و C++ تاثیر گرفته اند و دنیای کامپیوتر بر این دو زبان بنا شده است. پس همینگونه که واضح است یکپارچه سازی و ارتقای C++ امری بسیار مهم و بزرگ است، چون هنوز هم بسیاری از شرکت ها به این زبان وابسته اند و روی آن سرمایه گذاری می کنند. امروزه زبان C++ تحت تسلط هیچ شرکتی نیست و استاندارد سازی آن توسط ISO صورت می گیرد. ISOCPP موسسه ای نا سودبر است که جهت تدوین استاندارد های این زبان و ارتقای آن تشکیل شده است و در راس افراد حاضر در آن، خالق این زبان، آقای بیارنه استراستروپ قرار دارد. تا قبل از سال 2011 آخرین استاندارد کلی C++ در سال 1998 به تصویب رسید و از آن موقع به بعد استاندارد دیگری برای این زبان تدوین نگردید، تا در سال 2011 که استاندارد کلی دیگری برای C++ به تصویب رسید و آن را به نام C++11 می شناسیم. به همت ISOCPP دو استاندارد جدید این زبان برای سال 2014 و 2017 برنامه زیری شده اند، که از این دو، استاندارد 2017 ، استاندارد کلی بعدی برای C++ خواهد بود.



از دیگر اهدف ISOCPP ، شفاف سازی و امکان مشارکت علاقه مندان در پروسه تدوین استاندارد است. در سایت ISOCPP.org میتوانید به اطلاعات بسیاری در مورد C++ استاندارد دسترسی داشته باشید شامل آموزش ها، اخبار، ویدئو ها و لینک های مرتبط می شود. بد نیست این را هم بدانید که این بنیان توسط شرکت های بزرگی همچون ماکروسافت، گوگل، اینتل و ... حمایت مالی می شود ولی این شرکت ها حق رای در استاندارد سازی ندارند و صرفا از این بنیان حمایت می کنند، چون منافعشان به زبان C++ وابسته و مرتبط است.  

Delegate چیست ؟ (C++)  


در زبان برنامه نویسی سی پلاس پلاس، Event یک عضو از کلاس است که به یک شی اجازه اطلاع رسانی هنگام رخ دادن اتفاق خاص را می دهد، و علمیات اطلاع رسانی یا سیگنالینگ شامل یک Delegate (نماینده) می شود که امکان عکس العمل به Event را فراهم می آورد. برای مثال یک کلیک موس یک event به حساب می آید و شیئی که از این event سرچشمه می گیرد می تواند با فراخوانی یک یا چند تابع، رخ دادن این event را اطلاع رسانی کند؛ یک delegate میتواند ابزار دسترسی به توابعی که مسئول این event هستند را ارائه کند. 
ایده delegate بسیار ساده است - یک شی که یک یا چند اشاره گر به تابعی که دارای یک لیست پارامتر و نوع خروجی است، را در بر می گیرد. این تابع که delegate به آن اشاره می کند، Event را مدیریت می کند. پس delegate در C++/CLI تقریبا عملکرد مشابهی نسبت به "اشاره گر به تابع" در C++ استاندراد دارد.

تعریف delegate :

تعریف delegate ، مشابه تعریف تابع است که در ابتدای آن از کلمه delegate استفاده شده باشد. اما در اصل دو چیز در آن تعریف می شود: نام نوع ارجاع برای شی delegate و لیست پارامتر ها و نوع خروجی تابعی که می تواند همراه با delegate به کار رود. نوع ارجاع یک delegate ، کلاس System::Delegate را به عنوان کلاس پایه در اختیار دارد، پس همیشه از این کلاس مشتق خواهد شد. در زیر نمونه ای از تعریف delegate آمده است.

public delegate void HANDLER(int value);

این خط یک HANDLER از نوع ارجاع delegate تعریف می کند که نوعش از System::Delegate مشتق شده است و یک شی از آن می تواند حاوی اشاره گری به یک یا چند تابع با یک پارامتر ورودی int و نوع خروجی void (بدون نوع خروجی) داشته باشد. تابعی که delegate به آن اشاره می کند میتواند Static یا Instance باشد.

ایجاد delegate :

حالا که delegate را تعریف کردیم میتوانیم اشیاء delegate از این نوع ایجاد کنیم. ما میتوانیم دو تابع سازنده داشته باشیم که اولی، یک و دیگری، دو پارامتر را می پذیرد. پارامتری که برای سازنده delegate با یک پارامتر استفاده می شود باید یک تابع static عضو کلاس یا یک تابع عمومی باشد. تابعی که به عنوان پارامتر تعریف می کنید باید دارای پارامتر ها و نوع خروجی یکسان با انواع تعریف شده در delegate باشد. برای مثال کلاس زیر را در نظر بگیرید.


class HandlerClass
{public:
static void Sample(int num)
{
  Console::WriteLine(L"Function called with value {0}", num);
}

};

تابع Sample از کلاس بالا را به عنوان تابع مدیریت کننده ی Event به کار می بریم. این تابع دارای یک پارامتر ار نوع int و نوع خروجی void است درست مانند آنچه در delegate تعریف کرده ایم. البته نیازی نیست این تابع در کلاس باشد و هر تابعی متواند این مسئولیت را قبول کند. در زیر از این تابع برای ایجاد delegate استفاده می کنیم.


HANDLER^ handler = gcnew HANDLER (HandlerClass::Sample);


شی handler ، آدرس تابع استاتیک Sample در کلاس HandlerClass را در بردارد. اگر شما delegate را فراخوانی کنید، این تابع را فراخوانی کرده اید. این فراخوانی را می توان به صورت زیر انجام داد.


handler - > Invoke("parameter");

یا به صورت  :

handler ("parameter");

این دستور باعث فراخوانی توابعی می شود که در لیست فراخوانی delegate قرار دارند که در این مثال تنها تابع Sample می باشد. پس خروجی به صورت زیر خواهد بود. (فرض کنید مقدار 100 را به عنوان پارامتر به delegate ارسال کرده ایم)


(عبارت زیر در خروجی چاپ می شود)
Function called with value 100

در پست های بعدی به سراغ ادامه ی بحث delegate در C++ می رویم.
   style=

برنامه ماتریس همسازه (C#)


ماتریس همسازه را در پست های قبل توضیح دادیم، یک برنامه ی ساده به زبان سی شارپ در این پست برای شما قرارداده ام تا بتوانید ماتریس همسازه یک ماتریس را با آن به دست آورید. نوشتن برنامه برای ماتریس همسازه ساده است، در پست های قبل نحوه ی به دست آوردن دترمینان یک ماتریس مربعی را به شما نشان دادم و برای یادآوری می توانید به این پست مراجعه کنید. برای شروع یک بار نحوه محاسبه ماتریس کهاد را به شما نشان می دهم. روشی که من برای به دست آوردن ماتریس کهاد از آن استفاده می کنم به صورت زیر است.


private float[,] Kehad (float[,] matrix, int ROW, int COL)
{
int Size = (int) Math.Sqrt(matrix.Length);
float[,] result = new float[Size - 1, Size - 1];
int x = -1, y = 0;
for (int i = 0; i < Size; i++)
{
   if (i == ROW)
   continue;
   x++;
   y = 0;
   for (int j = 0; j < Size; j++)
    {
         if (j == COL)
           continue;

        result[x, y++] = matrix[i, j];
    }
}
return result;
}

نوع خروجی تابع بالا یک ماتریس (آرایه) از نوع float است و ROW و COL سطر و ستونی هستند که قرار است از ماتریس حذف شوند. این تابع تنها ماتریس داده شده را در ماتریس خروجی کپی می کند؛ ولی هنگامی که به سطر و ستون مشخص شده برسد آن سطر یا ستون را نادیده می گیرد. این کار با دستور continue انجام می شود.
فرمول محاسبه هسازه ماتریس به صورت زیر است :


A i, j = (-1) ᴵ + ᴶ x | M i ,j |

پیاده سازی این فرمول در زبان سی شارپ می تواند به صورت زیر باشد :



private float[,] Hamsaze (float[,] matrix)
{
int Size = (int)Math.Sqrt(matrix.Length);
float[,] result = new float[Size, Size];
for (int i = 0; i < Size; i++)
{
   for (int j = 0; j < Size; j++)
   {
     result[i, j] = (float) Math.Pow(-1, (i+1 + j+1)) * Determinant(Kehad(matrix, i, j));
   }
}
return result;
}

خروجی تابع بالا نیز یک ماتریس از نوع float است و ورودی آن، ماتریس اصلی است. در تابع بالا برای تک تک درایه های ماتریس اصلی همسازه محاسبه می شود و تابع Determinant دتر مینان ماتریس (های) ارسال شده را محاسبه می کند که قبلا در موردش توضیح داده بودیم. برای آزمایش می توانید از برنامه زیر استفاده کنید، البته برای اجرای آن نیاز به فریمورک .Net نسخه 4.5 دارید.




پدر زبان سی شارپ، Anders Hejlsberg

Anders Hejlsberg یک برنامه نویس و مهندس نرم افزار برجسته دانمارکی است که در طراحی و توسعه چند زبان برنامه نویسی محبوب و موفق شرکت داشته است. او طراح و خالق زبان توربو پاسکال و طراح ارشد زبان دلفی بوده است و هم اکنون در شرکت ماکروسافت به عنوان طراح ارشد زبان سی شارپ و توسعه دهنده ی زبان TypeScript فعالیت می کند. در سال 2001 جایزه "ممتازی در برنامه نویسی" از مجله Dr. Dobb's به وی اهدا شد. او را به عنوان پدر زبان C# می شناسند.

برنامه ی ضرب بولی ماتریس به زبان C++


در پست های قبل برنامه ای برای ضرب دو ماتریس بولی (ماتریس هایی که درایه های آنها تنها 0 و 1 هستند) به زبان C# (سی شارپ) قرار داده بودم که مثل اینکه خیلی مورد علاقه دوستان قرار گرفته بود. در این پست تقریبا برنامه مشابهی به زبان C++/CLI رو در برای شما قرار دادم که می توانید برای "ضرب معمولی ماتریس" و "ضرب بولین ماتریس" به کار ببرید. البته برای استفاده از این برنامه باید فریمورک .Net نسخه ی 4.5 را در کامپیوترتان داشته باشد.

تبدیل صریح یا cast در C++


از دستورات "تبدیل صریح" (explicit conversion) که cast نیز نامیده می شود، برای مجبور کردن کامپایلر به تبدیل انواع در زبان C++ استفاده می شود. انواع مختلفی بز دستور cast وجود دارند که یک به یک به انها می پردازیم. برای شکل دادن مقدار یک عبارت به یک نوع دلخواه به صورت زیر عمل می کنیم.


static_cast < "new type" > ("old type" or "expression");

کلمه ی static_cast در بیان می کند که cast به صورت ایستا یا static بررسی خواهد شد. به این معنی که هنگامی که برنامه ی شما کامپایل شد، دیگر در هنگام اجرا، بررسی نخواهد شد که آیا این دستور cast برای اعمال مطمئن هست یا خیر. نتیجه این دستور، تبدیل متغیر یا نتیجه ی یک عبارت (عبارت کوتاه و ساده یا عبارت پیچیده) به نوع اعلام شده در داخل علامت < > می باشد. 
در هنگام کار با کلاس ها با dynamic_cast کار خواهید کرد، که در آن تبدیلات به صورت پویا یا dynamic (در حال اجرای برنامه) بررسی و چک خواهند شد.
نوع بعدی تبدیل صریح، const_cast نام دارد که برای از بین بردن "ثابت بودن" یک ثابت یا یک عبارت به کار می رود.
reinterpret_cast و safe_cast نیز انواع دیگری از این دستورات هستند که در پست های بعدی به سراغ آنها می رویم.

وراثت در C++ (مقدمات)


در زبان برنامه نویسی C++ هنگامی که کلاسی را بر اساس کلاس موجود دیگری تعریف می کنید، به کلاس جدید، "کلاس وارث" یا به انگلیسی Derived Class و به کلاس اولیه، "کلاس پایه" یا Base Class گفته می شود. کلاس های وارث به طور خودکار داری تمام داده ها و (با کمی محدودیت) تمام توابع عضو کلاس پایه هستند و به قول معروف این اعضا را به ارث می برند. البته کلاس پایه نیز همچنان دارای این اعضا خواهد بود و کلاس پایه هم می تواند علاوه بر این اعضا دارای اعضای اختصاصی خود باشد.
توابعی که از کلاس پایه برای کلاس وارث، اختصاص نمیابد، "توابع سازنده"، "تابع نابودگر" و توابعی هستند که عملگر جایگزینی ( = ) را سربارگذاری می کنند. دلیل آن هم این است که هر کلاس دارای توابع سازنده و نابودگر خاص خود است. برای مثال تمامی کلاس هایی که در محیط دات نت (تحت CLR ) تعریف می کنید به طور خودکار وارثی از کلاس Base Object Class هستند حال انکه بخواهید اینطور باشد یا نه؛ و البته همین کلاس ها نیز می توانند کلاس پایه برای کلاس های دیگر باشند.
نحوه ی تعریف یک کلاس وارث مشابه کلاس های دیگر است و تنها تفاوت ان با یک پلاس معمولی مجزا در این است که پس از نام آن، نام کلاس پایه ذکر می شود. در زیر مثالی ساده برای این مورد آورد شده است.


کلاس پایه :

class parent
{public:
  bool flag;
  string str;
}

کلاس وارث :

class child : parent
{public:
  float f;
  short int si;
}

در بالا، parent یک کلاس پایه و child یک کلاس وارث می باشد. به این معنی که داده های عضو کلاس parent (که شامل str و flag هستند) برای کلاس child نیز قابل استفاده هستند. برای مثال می توان به صورت زیر به متغیر عضو flag در کلاس دسترسی پیدا کرد.


child obj;
obj.flag = true;

البته نه به همین سرعت ! باید دقت داشته باشید "وراثت" به طور پیشفرض به صورت "خصوصی" یا private صورت میگیرد و هنگامی که وراثت به صورت خصوصی تعریف شود نمی توان به داده های عضو به ارث گذاشته شده، در خارج از کلاس دسترسی پیدا کرد و اگر بخواهید دستور بالا را به کار ببرید با خطای کامپایلر موجه خواهید شد که جمله ی بالا را به شما می گوید! برای تعریف وراثت کلاس به صورت "عمومی" یا public تنها کافی است قبل از نام کلاس پایه، کلمه ی public را اضافه کنید تا بتونید به اعضای داده ی به ارث گذاشته شده، در خارج از کلاس دسترسی داشته باشید.


class child : public parent;    

افزودن یک ستون به DataGridView (به صورت هوشمند)

DataGridView یکی از ابزار های ورودی و خروجی در محیط دات نت و مناسب برای نمایش آرایه ها،جدول ها، ماتریس ها و ... است. در این پست یک روش برای ایجاد یک ستون به صورت هوشمند به شما نشان خواهم داد. در ابزار DataGridView اگر کاربر مقدار یکی از سلول های سطر آخر DataGridView را تغییر دهد، به طور خودکار یک سطر دیگر به DataGridView اضافه می شود، به این دلیل که شاید کاربر بخواهد سطر های بعدی را نیز پر کند. نمی دانم برای ستون ها هم چنین گزینه ای به طور پیشفرض وجود دارد یا خیر ولی در این پست یک روش برای ایجاد این قابلیت به DataGridView به شما معرفی می کنم. اضافه کردن سطر و ستون به وسیله ی کد، با استفاده از تابع Add انجام می شود و در زیر مثالی برای آن آورده شده است :

اضافه کردن یک سطر :
DataGridView_Name.Rows.Add();
اضافه کردن یک ستون :
DataGridView_Name.Columns.Add("Column_Name", "Header_Name");


حالا اگر بخواهیم وقتی که کاربر یکی از سلول های های ستون آخر را پر کرد یک ستون به DataGridView اضافه شود می توانیم از یک Event به نام CellBeginEdit استفاده کنیم. برای این کار باید یک Event در قسمت Form Designer پروژه به DataGridView خود اضافه کنید و یک تابع برای اضافه کردن ستون ایجاد کنید. در زیر مثالی از هر دو آورده شده است :

تعریف Event :

this.dataGridView_Name.CellBeginEdit += new System.Windows.Forms.DataGridViewCellCancelEventHandler(this.AutoAddColumn);


تعریف تابع AutoAddColumn :

private void AutoAddColumn(object sender, EventArgs e)
{
   // add a column to datagrid
   if (dataGridView_Name.CurrentCell.ColumnIndex == dataGridView_Name.ColumnCount - 1)
   {
      DataGridView_Name.Columns.Add("Column_Name", "Header_Name");
   }
}

با استفاده از CellBeginEdit ، هنگامی که یک سلول ویرایش می شود تابع AutoAddColumn اجرا می شود و اگر این سلول جزء سلول های آخرین ستون DataGridView باشد، با استفاده از تابع Add یک ستون به ستون های موجود آن اضافه می شود.   

برنامه محاسبه دترمینان ماتریس n*n

در این پست برنامه محاسبه دترمینان یک ماتریس مربعی دلخواه را برای شما گذاشته ام که خودم با زبان سی شارپ نوشته ام ولی نمیتوانم بگویم که کاملا بدون ایراد است ! 
اگر نمی دانید که دترمینان یک ماتریس n*n چگونه محاسبه میشود یا مانند من یادتان رفته است، می توانید به سایت الگوریتمستان (algorithmha.ir) مراجعه کنید که در آن به طور کامل طریقه ی محاسبه دترمینان توضیح داده شده است. 
واضح است که مهمترین بخش نوشتن این برنامه محاسبه ی دترمینان ماتریس است که با بسط ماتریس روی یک سطر یا ستون این کار صورت می گیرد. و برای این کار باید از یک تابع بازگشتی استفاده کنید. البته این تابع می تواند شکل های مختلفی داشته باشد. در ادامه روشی که برای نوشتن این تابع استفاده کرده ام را توضیح می دهم. برای این کار به یک تابع دیگر نیز احتیاج دارید که "ماتریس کهاد" ماتریس اولیه را محاسبه کند. نوشتن این تابع ساده است و تنها کافی است سطر و ستون گفته شده را از ماتریس حذف کنیم و مابقی درایه ها را به ماتریس حاصل انتقال دهیم.
می دانید که ماتریس را به صورت یک آرایه ی دو بعدی در نظر می گیریم. یک بار دیگر در نظر داشته باشید که برای نوشتن این برنامه باید ابتدا به طور کامل با مقدمات ریاضی آن اشنا باشید تا بتوانید آنها را در زبان بررنامه نویسی پیاده کنید. کد زیر را نگاه کنید. این کد من برای تعیین دترمینان ماتریس مربعی n*n است.



private float Determinant(float[,] matrix)
{
float determinant = 0;
int Size = sqrt(matrix.Length);
if (Size == 1)
{
   return matrix[0, 0];
}
else if (Size == 2)
{
   return (matrix[0, 0] * matrix[1, 1] - matrix[0, 1] * matrix[1, 0]);
}
else
{
   for (int i = 0; i < Size; i++)
   determinant += power(-1, (i+1)+1) * matrix[0,i] * Determinant(Kehad(matrix, 0, i));
}
return determinant;
}


تابع بالا کمی احمقانه به نظر می رسد، دلیلش هم تازه کار بودن من است ولی کاری که میخواهیم انجام دهیم را انجام می دهد. به طور خلاصه در تابع بالا اینقدر ماتریس را کوچک می کنیم تا به یک ماتریس دو در دو (2*2) برسیم و وقتی به آن رسیدیم هم که دترمینان از از "تفاضل حاصلضرب درایه های قطر اصلی از حاصلضرب قطر فرعی" به دست می آید و همه هم آن را می دانیم. این روش "بسط لاپلاس" نامیده می شود و در سایت الگوریتمستان کاملا توضیح داده شده است. 

نکات دیگری که در تابع بالا باید توضیح دهم یکی متغیر Size است که از جذر طول آرایه به دست می آید و همان تعداد سطر یا ستون ماتریس است. چون ماتریس "مربعی" است با محاسبه جذر طول آن (تعداد درایه های آن)، تعداد ستون ها یا سطر هایش مشخص می شود. (شاید روش بهتری هم برای اینکار باشد) اما بهر حال. در مورد تابع Kehad هم که گفتم که تابعی است که ماتریس "کهاد" یا mirror ماتریس اولیه را محاسبه می کند. تنها نکته ی اساسی تابع Determinant شاید "بازگشتی" بودن آن باشد که بدون استفاده از این شیوه شاید نتوان دترمینان ماتریس را محاسبه کرد. تابع Determinant خود را فراخوانی می کند ولی با هر بار فراخوانی، ماتریس کهاد کاتریس دور قبل به ان ارسال میشود و این چنین است که دترمینان یک ماتریس n*n محسابه می شود. در بالا ماتریس بر روی سطر اول (i == 0) بسط داده می شود. (پارامتر های دوم و سوم تابع کهاد، سطر و ستونی هستند که قرار است از ماتریس حذف شوند).
برنامه زیر که در آن از همین تابع استفاده شده است را می توانید برای محاسبه ی دترمینان ماتریس ها استفاده کنید ولی یادتان باشد که برای استفاده از آن باید .Net Framework روی کامپیوترتان نصب باشد. اگر به سورس برنامه احتیاج داشتید کافی است در قسمت نظرات مطرح کنید تا آن را برای شما قرار دهم. اگر برنامه مشکل دارد در بخش نظرات مطرح کنید تا بنده هم از آن مطلع شوم.

 لینک 1

لینک 2

نحوه ی محاسبه ی دترمینان ماتریس

تفاوت بین TextBox و Rich TextBox

textbox یا به فارسی "جعبه متن" یکی از اساسی ترین ابزار هایی ورودی و خروجی اطلاعات دربرنامه نویسی ویزوال به حساب می آید. به شخصه تا به حال همیشه برای برنامه های ساده ای که نوشته ام از textbox های معمولی استفاده کرده ام ولی همیشه می خواستم بدانم که قابلیت های Rich textbox نسبت به textbox های معمولی چیست. این بود که به پس از مطالعه چند سایت در اینترنت تصمیم گرفتم که این پست را بزنم و ترجمه مطالبی که خوانده ام به اشتراک بگذارم. در زیر تفاوت های یک textbox معمولی با Rich textbox را مشاهد می کنید. در حقیقت مزایای Rich textbox ها را مشاهد می کنید.

Rich Textbox ها به شما امکان می دهند تا متن را فرمت بندی کنید. برای مثال رنگ یا فونت متن را تغییر دهید، یا URL ها را تشخیص دهید. به علاوه میتوانید متن انتخاب شده را تشخیص و تغییر دهید، در متن، تصویر درج کنید. البته در تکست باکس های معمولی نیز می توانید فونت و رنگ متن را تغییر دهید ولی تنها می توانید یک فونت برای کل متن داشته باشید؛ همچنین میتوانید انتخاب کنید که کل متن به حالت Bold یا UnderLine یا ... در آید ولی این انتخاب به کل متن تحمیل می شود ولی در RTB ها شما میتوانید مانند WordPad ویندوز عمل کنید و بسته به نیازتان قسمت های مختلف متن را ویرایش کنید. همچنین RTB ها قابلیت نمایش جدول را دارند و می توانید با انها فایل های RTF را باز یا ذخیره کنید. 

برنامه های Notepad (مشابه Textbox) و Wordpad (مشابه Rich Textbox) در ویندوز مثال خوبی برای این دو ابزار برنامه نویسی هستند. اگر با این دو برنامه کار کرده باشید میتوانید تفاوت های TB و RTB را متوجه شوید.  

کلاس BigInteger

کلاس BigInteger در محیط دات نت برای کار با اعداد بزرگ خارج از محدوده ی انواع استاندارد مانند int و long ایجاد شده است. این کلاس دارای مشخصات و توابع زیادی است که همه ی آنها را می توانید در صفحه ی زیر مشاهده کنید.

http://msdn.microsoft.com/en-us/library/system.numerics.biginteger.aspx

این کلاس در فایل Numerics قرار دارد و برای استفاده از آن ابتدا باید پروژه ی خود را به آن ارجاع دهید و سپس آن را فراخوانی کنید. برای اضافه کردن این فایل به برنامه خود بر روی نام پروژه کلیک راست کرده و گزینه ی Add Reference (یا  C++ : Reference) را انتخاب کنید. سپس از درون لیست Assemblies نام System.Numerics را پیدا کرده و تیک آن را بزنید و پنجره فعلی را OK کنید. با این کار ارجاعی به این فایل در برنامه ایجاد می شود. حالا برای استفاده از این کلاس آن را با دستور Using به برنامه الحاق کنید : 

C# : using System.Numerics;

C++ : using namespace System::Numerics;

حالا کلاس BigInteger در برنامه قابل استفاده است. برای مثال :

BigInteger big = 1216845972115566256;

توابع در زبان پاسکال - Functions


توابع در زبان پاسکال برنامه های فرعی یا تکه برنامه هایی هستند که وظیفه ی خاصی بر عهده دارند. معمولا مقادیر یا اطلاعاتی را به عنوان ورودی دریافت می کنند و اعمال خاصی را روی آنها انجام می دهند. ورودی توابع همان پارامتر هایی است که هنگام استفاده از تابع یا به اصطلاح "فراخوانی" تابع به آن ارسال می کنیم و خروجی تابع (در صورت وجود) مقدار یا اطلاعاتی است که توسط "نام تابع" به برنامه بازگزدانده می شود. پس از ذکر شکل کلی توابع در زبان پاسکال به چند نکته در مورد آنها اشاره می کنیم.


function "NAME" ( "Parameters" ) : "TYPE";
Begin
/* function body */
End;

شکل کلی تابه به این صورت است که پس از کلمه کلیدی Function ، نام تابع آورده می شود و پس از آن پارامتر های تابع (نام به همراه نوع) و پس از آن نوع تابع ("TYPE") که مشخص کننده ی نوع خروجی آن است، آورده می شود و پس از آن بدنه ی تابع که کد های اجرا شونده تابع هست، در یک بلوک شامل Begin و End قرار می گیرد. حالا ذکر چند نکته در مورد توابع :

- توابع تنها یک مقدار را به برنامه باز می گردانند و این کار به وسیله قرار دادن مقدار خروجی در نام تابع صورت می گیرد.
- تابع می تواند بدون بارامتر باشد؛ برای اینکار کل پرانتز پارامتر های تابع، حذف می شود و فراخوانی تابع تنها با ذکر نام تابع در برنامه صورت می گیرد.
- تمام پارمتر های تابع از نوع مقداری یا صوری باشد. چون قرار نیست پارامتر های به برنامه اصلی بازگزدانده شوند.
- می توان آرایه ها، رکورد ها و مجموعه ها را به عنوان پارمتر تابع تعریف کرد. برای ارسال این انواع بع تابع باید آنها را در قسمت type تعریف کنید و سپس متغیر هایی از نوع آن ایجاد کردذه و آنها را به تابع ارسال کنید. به صورت مستقیم نمیتوان اینکار را انجام داد.
- یک تابع میتواند خود را فراخوانی کند. به این معنی که در داخل بدنه ی تابع، تابع فراخوانی شده باشد. به این گونه توابع، توابع بازگشتی می گویند.
- توابع در انتهای قسمت تعریف برنامه اصلی (Var) تعریف می شوند.
- نام توابع مقدار خروجی تابع را در بردارد. پس میتوان تابع را در دستور خروجی یا جایگزینی استفاده کرد.
- در تعریف توابع حتما باید نوع تابع را مشخص کنید؛ تابع بدون نوع وجود ندارد.
- یک تابع را می توان در درون یک تابع دیگر استفاده کرد ولی نمیتوان تک تابع را در درون یک تابع دیگر تعریف کرد. به عبارت دیگر در پاسکال "توابع تودرتو" وجود ندارند.

برای مثال در زیر تابعی به نام fact ، فاکتوریل یک عدد ارسالی را محاسبه می کند.

function fact (num : integer) : longint;
var
i , f : integer;
Begin
f := 1;
for i := 1 to num Do
f := f * i;
fact := f;
End;

در تابع یالا با قرار دادن مقدار متغیر f در نام برنامه، مقدار فاکتوریل محاسبه شده به برنامه اصلی فرستاده می شود. برای به کار بردن این تابع در برنامه کافی است نام تابع را به همراه یک پارمتر از نوع integer ذکر کنیم. مانند زیر : (مقدار 24320 در خروجی چاپ می شود)

writeln ( fact (10) );

روال ها در زبان پاسکال - Procedures


روال ها (Procedures) و توابع (Functions) دو قابلیت تقریبا مشابه در زبان برنامه نویسی پاسکال هستند. هر دو به عنوان برنامه های فرعی به حساب می آید و هدفشان انجام یک "وظیفه ی محول شده" و کاهش کد نویسی و افزایش بهره وری در تولید نرم افزار است . بسیاری از زبان های برنامه نویسی از این ویژگی پشتیبانی می کنند؛ حالا شاید با نام های متفاوت. درست مانند توابع در ریاضیات، توابع در برنامه نویسی مقادیر یا اطلاعاتی را دریافت می کنند و عملیات خاصی را روی آن انجام می دهند و نتیجه را بر می گردانند. البته توابع در برنامه نویسی، می توانند هیچ مقداری را دریافت نکنند یا هیچ مقداری را به برنامه اصلی برنگردانند و فقط یک کار خاص (برای مثال نوشتن یک پیام خوشامد گویی) را انجام دهند. این چیزی است که شما به عنوان برنامه نویس آن را تعیین می کنید که عملکرد توابع شما چه چیزی باشد. در یک پست نمی توان تمام و کمال در مورد توابع و روال ها صحبت کرد ولی تا جایی که بشود در این پست نکات استفاده و ساخت توابع و روال در برنامه توضیح داده می شود. درست مانند بسیاری از زبان های دیگر، در پاسکال هم می توان از توابع از پیش ساخته شده استفاده کرد و هم توابع جدید و سفارشی تولید کرد. استفاده کردن از توابع و روال های از پیش ساخته شده، کار دشواری نیست و با جست و جو در اینترنت یا کتاب های برنامه نویسی پاسکال به لیست تمام توابع و کاربرد آنها دسترسی پیدا کرد. هدف ما در این پست بیشتر توابع و روال های دستساز برنامه نویس است. پست را با معرفی روال ها ادامه می دهیم و در پست های بعدی به سراغ توابع می رویم.

روال ها :
روال ها برنامه های فرعی هستند که می توانند اطلاعاتی از برنامه اصلی دریافت کنند و کار های خواصی روی آنها انجام دهند و نتیجه را به برنامه اصلی (برنامه فراخوانی کننده) بازگردانند. به استفاده کردن از یک روال یا تابع در برنامه، "فراخوانی" روال یا تابع می گویند. شکل کلی روال ها در پاسکال این گونه است :

Procedure NAME (Parameters);
begin
/* code */
end;

شکل کلی روال ها را در پاسکال دیدید. استفاده از کلمه ی کلیدی Procedure ، آوردن نام روال و پارامتر های آن درون پرانتز؛ سپس بدنه ی روال که در آن کد های روال برای اجرا نوشته می شود. خط اول، عنوان روال نام دارد و بدنه ی تابع بین دو کلمه ی begin و end قرار می گیرد. حالا وارد جزئیات می شویم، ابتدا پارامتر های روال. پارامتر های روال همان متغیر هایی هستند که به روال ارسال می شوند تا در روال اعمالی رو آنها صورت گیرد. این پارمتر ها به دو شیوه به روال ارسال می شوند که به "پارمتر های صوری" و "پارمتر های واقعی" معروف هستند.
(در زبان C++ این قضیه "ارسال از طریق آدرس" و "ارسال از طریق مقدار" نامیده می شود.) حالا این یعنی چه ؟
پارمتر های صوری به پارمتر هایی گفته می شود که فقط قابلیت "ارسال" به روال را دارند و از روال به برنامه ی اصلی بازگشت داده نمی شوند. به این معنی که هر بلایی که در روال سر آنها در آورید، در برنامه اصلی مقدار آنها محفوظ باقی ماند. البته این به این معنی نیست که آنها در روال هم غیر قابل تغییر باشند. پارامتر های صوری به شیوه ی زیر اعلام می شوند.

NAME : TYPE

پارمتر های واقعی آن دسته از پارامتر هایی هستند که نتیجه ی آنها از روال به برنامه ی اصلی برمی گردد. یعنی اگر در روال دچار تغییر شوند در کل برنامه دچار تغییر می شوند. برای مشخص کردن چنین متغیر هایی تنها کلمه Var را قبل از نام آنها می آوریم.

Var NAME : TYPE

حالا یک مثال در مورد روال ها :

Procedure Sample (i : integer; j : real; Var a : integer; Var b : real);
begin
/* do something with i , j , a, b */
end;

در بالا روالی به نام Sample تعریف شده است که دارای 4 پارامتر است که دو تای آنها صوری و دو تای دیگر واقعی هستند. پارامتر های i و j که بدون کلمه ی var تعریف شده اند پارامتر های صوری هستند و پاارمتر های a و b که با کلمه ی Var تعریف شده اند، پارامتر های واقعی هستند. پس هر تغییری که در روال بر روی پارمتر های i و j رخ دهد بر روی مقادیر آنها در برنامه اصلی بی تاثیر خواهد بود. یعنی اگر در هنگام فراخوانی روال مقادیر آنها به ترتیب 10 و 15.5 بوده باشد، پس از پایان کار روال هم این مقادیر یکسان خواهند بود. حالا کلا منظور از فراخوانی چیست ؟
فراخوانی روال به معنی استفاده از روال در برنامه است. روال ها در قسمت Var (تعریف متغیر ها) برنامه تعریف می شوند و پس از ان در برنامه ی اصلی استفاده می شوند. با استفاده از نام روال، آن را در برنامه فراخوانی می کنیم و سپس پارامتر های آن را به ترتیب داخل پرانتز می آوریم.

NAME (parameters);

برای مثال بالا استفاده از روال به صورت زیر خواهد بود.

x , y : integer;
r , l : real;
Sample (x , r , y , l);

چون روال Sample دارای 4 پارامتر بود، در هنگام استفاده از روال هم باید 4 پارمتر به روال ارسال شود. ترتیب پارمتر ها باید به درستی رعایت شود چون هر پارمتر ممکن است دارای نوع خاصی باشد و در هنگام فراخوانی، پارمتر های ارسال شده "به ترتیب" (به صورت متناظر) با پارمتر های تعریف شده در روال مچ می شوند. یعنی در مثال بالا :

x -----> i
r -----> a
y -----> j
l -----> b

پس اگر ترتیب پارامتر ها به هم بخورد، نتایج برنامه تغییر می کند یا ممکن است کامپایلر از شما خطا بگیرد چون نوع پارامتر ها را رعایت نکرده اید. حالا چند نکته در مورد روال ها :

- روال ها می توانند بدون پارمتر هم تعریف شوند. برای این کار باید کلا پرانتز را روال حذف کرد و در هنگام فراخوانی هم تنها نام روال آورده می شود.
- نتایج روال از طریق پارمتر های (واقعی) روال به برنامه برگشت داده می شود و راه دیگری برای این کار وجود ندارد. یعنی اگر میخواهید نتیجه ای را به برنامه ی اصلی برگردانید باید اطلاعات را در پارامتر های واقعی ذخیره کنید.
- در هنگام استفاده از روال باید به ترتیب و نوع پارمتر های تعریف شده در روال دقت کنید تا مشکلی در اجرای و کامپایل برنامه پیش نیاید.
- در بدنه ی روال ها نیز میتوانید هر نوع متغیری را تعریف کنید. این متغیر ها به متغیر های "محلی" معروف هستند و تنها در داخل روال معتبر هستند و پس از پایان کار روال از حافظه پاک می شوند.
- پارمتر های صوری را پارامتر های "ورودی" و پارمتر های واقعی را پارامتر های "ورودی-خروجی" می نامند.
- میتوان در داخل یک روال، روال دیگری را تعریف کرد ولی برنامه ی اصلی نمیتواند به صورت مستقیم به آن روال (روال دوم) دسترسی داشته باشد. به این گونه روال ها ، روال های تودرتو گفته می شود.
- روال های یک برنامه قابلیت دسترسی به روال های قبلی خود را دارند. یعنی برای استفاده از یک روال باید روال از قبل تعریف شده باشد.
- اگر میخواهید روالی را در روال دیگر استفاده کنید ولی آن را پس از روال دوم تعریف کرده اید باید ابتدا آن روال را در بالای برنامه با استفاده از کلمه ی کلیدی forward اعلان کنید. در این حالت تنها عنوان روال (بدون بدنه) را ذکر کنید و پس از آن کلمه ی forward را ذکر کنید.
- روال ها دارای نوع خروجی نیستند.
- روال ها در قسمت انتهایی بخش تعاریف برنامه، تعریف می شوند و پارامتر های آنها می تواند هر چیزی باشد از انواع ساده تا آرایه، رکورد یا مجموعه
- برای ارسال رکورد و آرایه به روال باید آنها را در type تعریف کرد و سپس متغیر هایی از نوع ایجاد کرد و سپس آن متغیر ها را به روال ارسال کرد.

C++ Class Template


در مورد template ها در گذشته صحبت کردیم و استفاده از انها در توابع توضیح داده شد، حالا در این پست در مورد آوردن این ویژگی به کلاس ها توضیح می دهیم. استفاده از کلاس های template انعطاف پذیری کلاس را افزایش و کد نویسی را کاهش می دهد. در زیر با ارائه یک مثال، پیاده سازی کلی یک کلاس template را نشان می دهیم.


template < class T >
class Class_Name
{
public:
Class_Name (T "Variable_Name")
{
   // code
}
T test (T "Variable_Name")
{
   // code
}
private:
T "Variable_Name";
};

در بالا یک کلاس به صورت template تعریف کرده ایم که یک "سازنده" و یک تابع عضو دارد. قبل از هر چیز توضیح چند چیز ضروری است.
T در مثال بالا تنها یک نام است و هیچ گونه مشکلی برای تعریف نام دلخواه خود نخواهید داشت. T در واقع یک TypeName است (یک "نوع" است) است که در اینده، هنگام ایجاد یک شی از این کلاس تعریف خواهد شد.
مثال بالا تنها نمونه ساده ای از تعریف یک کلاس template است و هیچ مانعی برای برای ایجاد دهها سازنده، تابع و متغیر عضو با استفاده از نوع T وجود ندارد و همچنین مانعی برای تعریف یک کلاس با چندین TypeName نیست. برای مثال می توانید کلاس را با سه typename تعریف کنید که در هنگام ایجاد شی از کلاس به ترتیب، تعریف خواهند شد.

template < class T, class T2, class T3 >

سه نوع T ، T2 و T3 میتوانند در هر کجای کلاس به کار روند و متغیر هایی از نوع آنها تعریف کرد. البته واضح است که کلاس های مدیریت شده نمی توانند متغیر های مدیریت نشده داشته باشند، پس باید در باره ی انتخاب انواع اندیشید.

ایجاد یک شی از کلاس : همانطور که تعریف و قوانین کلاس بالا، مشابه کلاس های معمولی است، تعریف یک شیاز کلاس نیز مشابه کلاس های معمولی است با این تفاوت که باید Type Name هایی که در template تعریف کرده اید را هنگام ایجاد شی از کلاس، مشخص کنید. در زیر حالت کلی تعریف یک شی از کلاس آمده است :


Class_Name < type > Object_Name;

یا (به صورت یک اشاره گر) :

Class_Name < type > * Object_Name = new Class_Name < type > () ;


اگر کلاس شما حاوی چند type name باشد، باید آنها را به ترتیب مشخص کنید.

Class_Name < type1, type2, type3 , ... > Object_Name;

تعریف توابع در بیرون کلاس نیز مشابه کلاس های معمولی و به صورا زیر است :

template < class T >
Class_Name < T >::Function_Name (T "Variable_Name", other variables...)
{
// code
}

در بالا نمونه یک تابع بدون نوع بازگشتی آمده است که در بیرون کلاس تعریف شده است. البته این تابع باید قبلا در کلاس اعلان شده باشد.

در زیر هم نمونه یک template class را مشاهد می کنید که دارای چند تابع عضو و سازنده و type name است.

template < class T, class T2, class T3 > 
class Sample
{
public:
Sample ()
{
// code
}
Sample (T ipt)
{
// code
}
~Sample()
{
// code
}
// Function declaration
void someFunc ();

T somFunc2 (T r)
{
return r;
}
private:
T j;
T2 k;
T someFunc3 (T3 p)
{
// code
}
};

حلقه ی for each و Renge-Based for در C++


در زبان C++ حلقه ی for دارای دو نسخه ی ساده شده برای کارهای خاص می باشد. این دو نسخه حلقه ی for each و range-based for هستند که غالبا برای پیمایش ترتیبی و کامل یک آرایه به کار می روند.

for each :
حالت کلی حلقه ی for each به صورت زیر است :


for each ("VARIABLE" in "ARRAY")
{
// code
}

کد بالا را چنین می شود بیان کرد: "برای هر عنصر از نوع VARIABLE در آرایه فلان، دستورات زیر را انجام بده".برای مثال اگر Sample را یک آرایه از اعداد صحیح در نظر بگیریم، حلقه ی for each به صورت زیر در می آید : 

for each (int I in Sample)
{
// do something
}

توجه به چند نکته زیر در به کار بردن این حلقه اهمیت دارد.
- متغیری شمارش حلقه (در اینجا I ) می تواند در بیرون حلقه هم تعریف شده باشد و نیازی نیست حتما در خود حلقه تعریف شود.
- در این حلقه برخلاف حلقه ی for معمولی نمی توان شمارنده را دستکاری کرد ولی آرایه قابل دستکاری است.
- میتوان شمارنده را به صورت auto تعریف کرد تا کامپایلر به صورت خودکار نوع آن را نسبت به آرایه ارسالی تعریف کند.
- در زبان C# حلقه ی for each نحو یکسانی دارد، البته نام حلقه در C#، بدون فاصله (foreach) است.

Range-Based for :
حالت کلی این حلقه به صورت زیر است :

for ("VARIABLE" : "ARRAY")
{
// code
}

مثال بالا برای در حلقه ی Range-Based به صورت زیر خواهد بود :

for (int I : Sample)
{
// do something
}


این حلقه نیز مانند حلقه ی قبلی بیان یکسانی دارد و قواعد آن نیز مشابه حلقه ی for each است؛ با این تفاوت که متغیر شمارش حلقه در این جا باید حتما در خود حلقه تعریف شود. استفاده از این دو حلقه در بسیاری مواقع بهتر از حلقه ی for یا While است، ولی کاراییشان مسلما کمتر و دستتان در استفاده از آنها بسته تر است.  

Properties در C++/CLI و C#


اگر برنامه نویس زبان های C++ یا C# هستید حتما با "مشخصات" یا properties کلاس ها کار کرده اید. چه هنگام استفاده از کلاس های از پیش نوشته شده .Net یا کلاس هایی که خود مینویسید. حداقل از field ها استفاده کرده اید. برنامه نویسی بدون استفاده از آنها محال است! field ها همان متغیر های کلاس شما هستند که وقتی به صورت "عمومی یا Public آنها را تعریف می کنید به مشابه (نه دقیقا) مشخصات (Properties) رفتار می کنند. استفاده از فیلد ها و property ها بسیار حیاتی و اساسی است. چطور میشود که یک فایل یا آرایه در اختیار داشته باشید و نخواهید نام، طول یا حجمش را بدانید؟ یا چطور میشود یک مشتری داشته باشید در صورتی که نام، آدرس یا شماره تلفن آو را ندانید ؟ property ها همانطور که از نامشان برمیآید خواص یک شیء هستند و در مورد آن شیء توضیح می دهند.

در این پست کمی بیشتر با Properties در زبان C# یا C++ آشنا می شویم. مثال های این پست به زبان C# هستند ولی در زبان C++/CLI نیز نحو تقریبا مشابه است. حالت کلی تعریف یک property به شکل زیر است :


public/private TYPE Property_Name
{
   get
   {
      // Code
   }

   set
   {
      // code 
   }
}



public" و "private نوع دسترسی به property را مشخص می کنند. "TYPE" نوع property و "Property_Name" واضخا نام آن است. در داخل بلوک اصلی دو بلوک به نام های Set و Get وجود دارد که به setter (قرار دهنده) و Getter (گیرنده) معروف هستند.
کد های بلوک Get هنگامی که کاربر قصد دریافت اطلاعات Property را دارد، اجرا می شوند. و کد های بلوک Set برای ثبت تغییرات و نوشتن در Property به کار می رود. این کد ها میتوانند هر چیزی باشند. از یک عملیات انتصاب ساده تا محاسبات پیچیده... که واضحا بستگی به نیاز شما دارد. اگر property شما نیازی به دستکاری شدن ندارد میتوانید کل بلوک Set را حذف کنید. در این صورت property شما "فقط خواندنی" یا read-only خواهد بود. مسلما برخی از مشخصاتی که در طول برنامه نویسی به آنها سر و کار داریم هم باید این گونه باشند. معمولا در بلوک Get با استفاده از دستور return مقداری که قرار است به برنامه بازگشت داده شود، را بازمیگردانند و در بلوک Set ، عملیات انتصاب عنوان می شود. ولی بسته به نیاز شما هر کدی میتواند در آنها استفاده شود.
پس کلا هدف این کارها چه بوده است ؟ property ها نقش دریافت کننده و فرستنده ی مقادیر را دارند. در setter مقادیر را دریافت می کنید و عملیات دلخواه را روی آنها انجام می دهید و در getter انها را به برنامه برمیگردانید. معمولا property ها به صورت "عمومی" (public) تعریف می شوند (تا توسط کاربر کلاس قابل دسترسی باشند) و مقادیر خود را در فیلد های خصوصی ذخیره می کنند. برخی از مواقع شاید این کار مزیتی نداشته باشد و کار به صورت مستقیم با فیلد ها هم کارتان را راه بیندازد؛ ولی در بسیاری از مواقع، استفاده از property ها مزایای خود را نمایان می کند. مانند پنهان سازی اطلاعات. در اخر می توان property ها را در یک جمله تعریف کرد : "راهی برای درسترسی به اطلاعات." شاید تا همین جا برای این پست کافی باشد، در پست های بعدی به جزئیات در مورد مشخصات کلاس اشاره می کنیم.

مرتب سازی صدفی - ShellSort


مرتب سازی صدفی یا مرتب سازی لایه ای یا Shell Sort یک الگوریتم مرتب سازی درجا و مقایسه ای، مناسب برای ساختار های داده ی آرایه ای نه چندان طولانی است. البته این الگوریتم در مقایسه با برخی از الگوریتم های دیگری مانند، مرتب سازی درجی، مرتب سازی انتخابی یا مرتب سازی حبابی سرعت بهتری دارد. درک این الگوریتم بسیار ساده است و درنتیجه پیاده سازی آن در زبان های برنامه نویسی هم زیاد مشکل نیست. 
الگوریتم :
فرض کنید لیستی از اعداد یا اسامی در اختیار دارید؛ در این الگوریتم ابتدا عناصری که بیشترین فاصله (از نظر محل قرار گیری) از هم را دارند با یکدیگر مقایسه میشوند. به نوعی که انگار آنها در یک لیسن جداگانه قرار دارند. سپس این فاصله در دور بعدی مرتب سازی کمتر می شود و دوباره روند ادامه پیدا می کند.

دور اول :
فرض لیستی با 12 عدد در اختیار دارید. ابتدا عناصری که 6 خانه از هم فاصله دارند (12 تقسیم بر 2) با یکدیگر مقایسه می شوند و در صورت نیاز جابه جا می شوند. یعنی عنصر اول با عنصر هفتم، هنصر دوم با عنصر هشتم، عنصر سوم با عنصر نهم و به همین ترتیب عنصر ششم با عنصر دوازدهم. در خلال این مقایسات عنصری که در حال حاضر جابه جا شده است با عنصر 6 خانه ی قبل نیز مقایسه میشود و در صورت نیاز تعویض می شود.

دور دوم تا دور آخر :
در مرحله ی بعد فاصله ها را نصف می کنیم (6 تقسیم بر 2) سپس دوباره از ابتدای لیست دوباره با توجه به فاصله ی کنونی لیست را مرتب مکنیم. عنصر اول با عنصر چهارم، عنصر دوم با عنصر پنجم و به همین ترتیب تا آخر. دو باره مانند قبل عنصری که در حال حاضر تعویض شده است با عناصر قبلی (به تعداد فاصله) هم مقایسه می شوند. این روند ادامه پیدا می کند تا فاصله ها به 1 یا صفر برسد و لیست مرتب شود. به احتمال زیاد توضیح این الگوریتم کمی گیج کننده است، انیمیشین زیر این الگوریتم را بسیار واضح توضیح می دهد.

تکه برنامه زیر یک پیاده سازی غیر موثر این الگوریتم در زبان C# است :
list : ارایه ای نامرتب برای مرتب سازی.
Gap : فاصله ی مرتب سازی در هر دور.
swap : تابعی برای جابه جایی دو عنصر از لیست.



int[] list = new int[] {-1, -5, 1, 92, -8, 14, -7, 29, 22, 18, 10,
                              2, 32, 0, 41, 4, 8, 6, 5, 9, 41, 23, -9};

int Gap = list.Length / 2;

while (Gap > 0)
{
for (int i = 0; i + Gap < list.Length; i++)
{
if (list[i] > list[i + Gap])
{

  swap(ref list[i], ref list[i + Gap]);

  for (int j = i; j - Gap >= 0; j--)

     {

if (list[j] < list[j - Gap])
{
   swap(ref list[j], ref list[j - Gap]);
}
else
{
   break;
}

   }

}

}

Gap = Gap / 2;
}
  

ایجاد پروژه ی C++ Windows Forms در Visual Studio 2012 (روش دوم)


در Visual Studio 2012 به طور پیشفرض گزینه ی C++ Windows Forms وجود ندارد (حذف شده است)؛ با انجام مراحل زیر میتوانید این گزینه را به قسمت "ایجاد پروژه ی جدید" بازگردانید.


گام 1 :

این فایل ها را دانلود کنید.

لینک دوم.


گام 2 :
به مسیر زیر رفته و از فایل های موجود Backup بگیرید. (یک پوشه ایجاد کنید و فایل های موجود را در آن کپی کنید).
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcprojects\vcNET

گام 3 :
فایل هایی که دانلود کرده اید را در این پوشه (مسیر بالا) کپی کنید.

گام 4 :
ویژوال استدیو را باز کنید و به قسمت New Project - > Visual C++ - > CLR بروید. در صورت درست انجام دادن مراحل بالا باید گزینه ی Windows Forms را در میان گزینه های موجود مشاهد کنید.

گام 5 :

یک پروژه ی Windows Forms ایجاد کنید و ببینید همه چیز درست کار می کند یا نه !

منبع : http://www.abouthack.com/

پست اصلی : http://www.abouthack.com/articles/programming/c-plus-plus/windows-forms-application-in-visual-c-2012.html  

نکات برنامه نویسی به زبان پاسکال (قسمت دوم)


در زبان پاسکال :

- داده های شمارشی (Enum) به ترتیب از 0 شماره گذاری می شوند و از این طریق قابل دسترس هستند.
- متغیر های داده های شمارشی را نمیتوان مستقیما با دستور Read یا Write به کار برد.

- یک مجموعه حداکثر می تواند 256 عضو داشته باشد؛ پس نمیتوان انها را از نوع integer یا real یا انواع گسترده دیگر انتخاب کرد.

- جابه جایی و تکرار در مجموعه ها بی تاثیر است.

- در پاسکال عملیات اجماع، اشتراک و تفاضل بر روی مجموعه ها قابل انجام است و اینکار به ترتیب با عملگر های + ، * و - انجام می شود.

- "رکورد" ها در زبان پاسکال در نقش "ساختار" ها یا "کلاس" ها در زبان C++ یا C شارپ هستند. کلمه ی End ، انتهای فیلد های یک رکورد را مشخص می کند.

- فیلد های یک رکورد نمیتوانند از نوع همان رکورد باشند ولی میتوانند از نوع یک رکورد دیگر باشند. برای دسترسی به فیلد های یک رکورد از عملگر ( . ) استفاده می شود.

- یک رکورد برای ارسال به تابع، باید در قسمت type تعریف شده باشد.

- تعداد تکرار یک الگوریتم (مجموع تعداد تکرار حلقه ها) مرتبه ی الگوریتم را تعیین میکند. هر چه مرتبه و پیچیدگی یک الگوریتم کمتر باشد سرعت اجرای بهتری دارد.

- توابع تنها میتوانند یک مقدار را برگشت دهند و نوع بازگشتی آنها نمیتواند از نوع رکورد یا آرایه باشد.

- متغیر های بولین قابلیت خوانده شدن از ورودی را نداردند. مقدار "True" بزرگتر مساوی "False" است.

True > False

- کلمات کلیدی زبان پاسکال را نمیتوان برای نامگذاری ها به کار برد؛ ولی نام توابع و روال ها و ... میتوانند برای نام گذاری استفاده شوند. در این صورت عملکرد اصلی انها لغو خواهد شد؛ ولی این کار توصیه نمی شود.