پرچمداران
-
در همه بخش ها
- همه بخش ها
- فایل
- دیدگاه فایل
- نقد و بررسی فایل
- مقالات
- مقاله دیدگاه
- مقاله نقد و بررسی
- صفحات استاتیک
- صفحه دیدگاه
- صفحه نقد و بررسی
- کتابخانهها
- کتابخانه دیدگاه
- کتابخانه نقد و بررسی
- رویداد
- دیدگاه های رویداد
- بازبینی رویدادها
- تصاویر
- دیدگاه های تصویر
- نقد های تصویر
- آلبوم ها
- نظر های آلبوم
- نقد های آلبوم
- پست ها
- نوشتههای وبلاگ
- دیدگاه های وبلاگ
- بروزرسانی وضعیت
- پاسخ های دیدگاه ها
-
تاریخ سفارشی
-
همه زمان ها
4 خرداد 1397 - 31 فروردین 1403
-
سال
31 فروردین 1402 - 31 فروردین 1403
-
ماه
1 فروردین 1403 - 31 فروردین 1403
-
هفته
25 فروردین 1403 - 31 فروردین 1403
-
امروز
1 اردیبهشت 1403 - 31 فروردین 1403
-
تاریخ سفارشی
چهارشنبه, 3 مهر 1398
-
همه زمان ها
مطالب محبوب
در حال نمایش مطالب دارای بیشترین امتیاز از زمان چهارشنبه, 3 مهر 1398 در همه بخش ها
-
9 امتیازهنگامیکه شما برای اولین بار از C به CPP مهاجرت می کنید، یا اصلا برنامه نویسی را قصد دارید با CPP شروع کنید، با مفاهیم متعددی روبرو خواهید شد که شاید برای شما جالب باشند که بدانید، این ایده ها چطور شکل گرفتند، چطور به CPP افزوده شدند و اهمیت آن ها در عمل (هنگام برنامه نویسی و توسعه نرم افزار) چیست. در این پست وبلاگی IOStream، به این خواهیم پرداخت که ایده Overloading و Template و Auto Deduction چطور از CPP سر در آوردند. همانطور که شما ممکن است تجربه کرده باشید، هنگامیکه برنامه نویسی و توسعه نرم افزاری را با C شروع می کنید، برنامه شما چیزی بیش از یک مجموعه بی انتها از توابع و استراکچرها و متغیرها و اشاره گرها و ... نخواهند بود. از همین روی شما مجبور هستید مبتنی بر ایده مهندسی نرم افزار و پارادیم برنامه نویسی ساخت یافته، برای هر کاری یک تابع منحصربفرد پیاده سازی کنید. این تابع باید از هر لحاظی از قبیل نام، نوع ورودی ها، نوع خروجی و حتی نوع عملکرد منحصربفرد باشد تا بتواند یک کار را به شکل صحیح کنترل کند که همین مسئله می تواند در پیاده سازی برخی نرم افزارها، انسان را در جهنم داغ و سوزان قرار بدهد. مثلا پیاده سازی یک برنامه محاسباتی مانند ماشین حساب که ممکن است با انواع داده های محاسباتی مانند عدد صحیح (Integer) و عدد اعشاری (Float) رو به رو شود. از همین روی فرض کنید، ما قرار است یک عمل محاسباتی مانند جمع از برنامه ماشین حساب را پیاده سازی کنیم. برای اینکه برنامه به شکل صحیحی کار کند، باید عمل جمع یا همان Add برای انواع داده های موجود از قبیل عدد صحیح و اعشاری پیاده سازی شود. اگر شما این کار را انجام ندهید، برنامه شما به شکل صحیحی کار نخواهد کرد (یعنی نتایج اشتباه ممکن است برای ما تولید کند). در تصویر زیر، نمونه این برنامه و توابع مرتبط با آن پیاده سازی شده است: #include <stdio.h> int AddInt(int arg_a, int arg_b) { return arg_a + arg_b; } float AddFloat(float arg_a, float arg_b) { return arg_a + arg_b; } double AddDouble(double arg_a, double arg_b) { return arg_a + arg_b; } int main(int argc, const char* argv[]) { int result_int = AddInt(1, 2); float result_float = AddFloat(10.02f, 21.23f); double result_double = AddDouble(9.0, 24.3); printf("Result Integer: %d", result_int); printf("Result Float: %f", result_float); printf("Result Double: %lf", result_double); return 0; } به برنامه بالا دقت کنید. ما سه تا تابع Add با نام های منحصربفرد داریم که سه نوع داده مجزا را به عنوان ورودی دریافت می کنند، سه نوع نتیجه مجزا بازگشت می دهند، اگرچه پیاده سازی آن ها کاملا مشابه هم دیگر است و تفاوتی در پیاده سازی این سه تابع وجود ندارد. ولی به هر صورت، اگر به خروجی دیزاسمبلی برنامه مشاهده کنید، دلیل این مسئله را متوجه خواهید شد که چرا هنگام برنامه نویسی با زبان C، به نام های منحصربفرد نیاز است، چون اگر توابع نام های مشابه با هم داشته باشند، لینکر نمی تواند به دلیل تداخل نام (Name Conflict)، آدرس آن ها را محاسبه یا اصطلاحا Resolve کند. همانطور که در تصویر بالا خروجی دیزاسمبلی برنامه Add را مشاهده می کنید، اگر توابع نام مشابه داشتند، در هنگام فراخوانی (Call) تابع Add تداخل رخ می داد، چون دینامیک لودر سیستم عامل دقیقا نمی داند که کدام تابع را باید فراخوانی کند. برای همین نیاز است وقتی برنامه نوشته می شود، نام توابع در سطح کدهای اسمبلی و ماشین منحصر بفرد باشد. به هر صورت، به نظر شما آیا راهی وجود دارد که ما پیاده سازی این نوع توابع را ساده تر کنیم یا حداقل بار نامگذاری آن ها را از روی دوش توسعه دهنده و برنامه نویس برداریم؟ بله امکان این کار وجود دارد. مهندسان CPP با افزودن ویژگی Overloading و Name Mangling یا همان بحث Decoration مشکل برنامه نویسان در پیاده سازی توابع با نام های منحصربفرد را حل کردند (البته کاربردهای دیگر هم دارد که فعلا برای بحث ما اهمیت ندارند). ویژگی اورلودینگ در CPP به ما اجازه خواهد داد یک تابع با عنوان Add پیاده سازی کنیم که تفاوت آن ها فقط در نوع ورودی و نوع خروجی است. به عنوان مثال، در قسمت زیر، کد برنامه Add را مشاهده می کنید که با قواعد CPP بازنویسی شده است. #include <iostream> int Add(int arg_a, int arg_b) { return arg_a + arg_b; } float Add(float arg_a, float arg_b) { return arg_a + arg_b; } double Add(double arg_a, double arg_b) { return arg_a + arg_b; } int main(int argc, const char* argv[]) { int result_int = Add(1, 2); float result_float = Add(10.02f, 21.23f); double result_double = Add(9.0, 24.3); std::cout << "Result Integer: " << result_int << std::endl; std::cout << "Result Float: " << result_float << std::endl; std::cout << "Result Double: " << result_double << std::endl; return 0; } همانطور که مشاهده می کنید، ما اکنون سه تابع با نام Add داریم. ولی شاید سوال پرسیده شود که چطور لینکر متوجه تفاوت این توابع با یکدیگر می شود درحالیکه هر سه دارای یک نام واحد هستند. اینجاست که مسئله Name Mangling یا همان Decoration نام آبجکت ها در CPP مطرح می شود. اگر شما برنامه مذکور را دیزاسمبل کنید، متوجه تفاوت کد منبع (Source-code) و کد ماشین/اسمبلی (Machine/Assembly-code) خواهید شد. همانطور که در خروجی دیزاسمبلی برنامه اکنون مشاهده می کنید، توابع اگرچه در سطح کد منبع دارای نام مشابه با یکدیگر بودند، اما بعد کامپایل نام آن ها به شکل بالا تبدیل می شود. به این شیوه نام گذاری Name Mangling یا Decoration گویند که قواعد خاصی در هر کامپایلر برای آن وجود دارد. این ویژگی موجب می شود در ادامه لینکر بتواند تمیز بین انواع توابع Add شود. به عنوان مثال، تابع نامگذاری شده با عنوان j__?Add@YAHH@Z تابعی است که به نوعی از تابع Add اشاره دارد که ورودی هایی از نوع عدد صحیح دریافت می کند. این شیوه نامگذاری خلاصه موجب خواهد شد لینکر بتواند به سادگی بین توابع تمایز قائل شود. با این حال هنوز یک مشکل باقی است، و آن هم تکرار مجدد یک پیاده سازی برای هر تابع است. به نظر شما آیا راهی وجود دارد که ما از پیاده سازی مجدد توابعی که ساختار مشابه برای انواع ورودی ها دارند، جلوگیری کنیم؟ باید بگوییم، بله. این امکان برای شما به عنوان توسعه دهنده CPP در نظر گرفته شده است. ویژگی که اکنون به عنوان Templateها در مباحث Metaprogramming یا Generic Programming استفاده می شود، ایجاد شده است تا این مشکل را اساساً برای ما رفع کند. با استفاده از این ویژگی کافی است، طرح یا الگوی یک تابع را پیاده سازی کنید، تا در ادامه خود کامپایلر مبتنی بر ورودی هایی که به الگو عبور می دهید، در Backend، یک نمونه تابع Overload شده مبتنی بر آن الگو برای نوع داده شما ایجاد کند. #include <iostream> template <typename Type> Type Add(Type arg_a, Type arg_b) { return arg_a + arg_b; } int main(int argc, const char* argv[]) { int result_int = Add(1, 2); float result_float = Add(10.02f, 21.23f); double result_double = Add(9.0, 24.3); std::cout << "Result Integer: " << result_int << std::endl; std::cout << "Result Float: " << result_float << std::endl; std::cout << "Result Double: " << result_double << std::endl; return 0; } به عنوان مثال، در بالا تابع Add را مشاهده می کنید که نوع داده ورودی این تابع و حتی نوع خروجی آن مشخص نشده است و در قالب Typename به کامپایلر معرفی شده است. این یک الگو برای تابع Add است. کامپایلر اکنون می تواند مبتنی بر ورودی هایی که به تابع هنگام فراخوانی یا اصطلاحا Initialization عبور می دهیم، یک نمونه تابع Overload شده از آن الگو ایجاد کند و در ادامه آن را برای استفاده در محیط Runtime فراخوانی کند. حال اگر برنامه بالا را دیزاسمبل کنید، مشاهده خواهید کرد که کامپایلر از همان قاعده Overloading استفاده کرده است تا نمونه ای از تابع Add متناسب با نوع ورودی هایش ایجاد کند. هنوز می توان برنامه نویسی با CPP را جذاب تر و البته ساده تر کرد، اما چطور؟ همانطور که در قطعه کد بالا مشاهده می کنید، هنوز ما باید خود تشخیص دهیم که نوع خروجی تابع قرار است به چه شکل باشد. این مورد خیلی مواقع مشکل ساز خواهد بود. برای حل این مسئله، در CPP مبحثی در نظر گرفته شده است که آن را به عنوان Auto Deduction می شناسیم که سطح هوشمندی کامپایلر CPP را بالاتر می برد. در این ویژگی خود کامپایلر است که مشخص می کند نوع یک متغیر مبتنی بر خروجی که به آن تخصیص داده می شود، چیست. به عنوان مثال، شما می توانید برنامه بالا را به شکل زیر بازنویسی کنید: #include <iostream> template <typename Type> auto Add(Type arg_a, Type arg_b) { return arg_a + arg_b; } int main(int argc, const char* argv[]) { auto result_int = Add(1, 2); auto result_float = Add(10.02f, 21.23f); auto result_double = Add(9.0, 24.3); std::cout << "Result Integer: " << result_int << std::endl; std::cout << "Result Float: " << result_float << std::endl; std::cout << "Result Double: " << result_double << std::endl; return 0; } با استفاده از ویژگی Auto Deduction و کلیدواژه Auto در برنامه، خود کامپایلر در ادامه مشخص خواهد کرد که تابع Add چه نوع خروجی دارد و همچنین نوع متغیرها برای ذخیره سازی خروجی Add چه باید باشد. به عبارتی اکنون تابع Add هم Value و هم Data type را مشخص می کند که این موجب می شود برنامه نویسی با CPP خیلی ساده تر از گذشته شود. حال اگر به نمونه برنامه آخر نگاه کنید و آن را با نمونه C مقایسه کنید، متوجه خواهید شد که CPP چقدر کار را برای ما ساده تر کرده است. در این پست به هر صورت، قصد داشتم به شما نشان دهم که نحوه تحول CPP به صورت گام به گام چطور بوده است و البته اینکه پشت هر ویژگی در CPP چه منطق کلی وجود دارد. امیدوارم این مقاله برای شما مفید بوده باشد. نمونه انگلیسی این مقاله را می توانید در این آدرس (لینک) مطالعه کنید. میلاد کهساری الهادی
-
8 امتیازبا سلام و درود، همانطور که میدانید ویژگیهای اخیر در استانداردهای ۱۷ و ۲۰ بسیار عظیم و کاربردی هستند. هدف ما در مرجع آیاواستریم این است که با توجه به بهروزرسانیهای زبان سیپلاسپلاس مهمترین مواردی که نیاز است معرفی کنیم. بنابراین در این بخش به یکی از کاربردیترین موارد مرتبط در استاندارد ۱۷ با عنوان صفتهای ویژه اشاره میشود که در ادامه به تعریف هر یک از آنها میپردازیم. با توجه به استانداردهای ۱۱ و ۱۴ که در آن صفتهایی همچون [[deprecated]] و [[noreturn]] معرفی شدهاند که وظیفهٔ آن به ترتیب نمایش وضعیت منسوخ شدن یک عملکرد و یا وضعیت بازگشتی یک تابع از نوع void است. چنین صفاتی میتوانند در زمان اعلان و تعریف متغیرها و یا توابع مورد استفاده قرار گیرند. به عنوان مثال اگر کدی به صورت زیر داشته باشیم: [[deprecated]] void print(const std::string &message) { std::cout << message << std::endl; } در صورتی که تابع print در بخشی از برنامه مورد استفاده قرار بگیرد، پیغامی از سمت کامپایلر از نوع اخطار (warning) ساطع میشود، مبنی بر آن که تابع مربوطه به عنوان منسوخ شده یاد شده است. warning: 'print' is deprecated این ویژگی میتواند در ساخت و توسعهٔ کتابخانهها، موتورها، چهارچوب (فریمورک) و برنامههایی که قرار است دیگر برنامهنویسان از آنها استفاده کنند بسیار میتواند کاربردی باشد؛ چرا که با اعمال چنین خاصیتهایی در کدهای شما برای توسعهدهندگان یادآوری خواهد شد که کد مربوطه در نسخهٔ جدید یا نسخههای بعدی امکان حذف و یا تغییر را خواهد داشت. #include <iostream> #include <string> [[deprecated]] void print(const std::string &message) { std::cout << message << std::endl; } int main() { print("Hello, World!"); return 0; } در مثال بالا اخطار پیشفرض از سمت کامپایلر ساطع میشود، اما در بعضی از مواقع لازم است پیغام سفارشی جهت راهنمایی بیشتر کاربر اعمال شود که در این صورت صفت میتواند پیغام از نوع رشته را دریافت و در هنگام ساطع شدن، آن را نمایش دهد. برای این کار کافی است متن مورد نظر را به صورت زیر در صفت خود تعیین کنیم. [[deprecated("Use printView with print instead, this function will be removed in the next release")]] برای مثال یک تابع جایگزین و بهینه شده را به صورت زیر در نظر بگیرید، کامپالر اخطار مروبطه و سفارشی شده را نسبت به آن ساطع خواهد کرد. #include <iostream> #include <string> [[deprecated]] void print(const std::string &message) { std::cout << message << std::endl; } void printView(std::string_view message) { std::cout << message << std::endl; } int main() { printView("Hello, World!"); return 0; } همچنین در رابطه با صفت [[noreturn]] که در استاندارد ۱۱ معرفی شده است، باید در نظر داشت این صفت جهت بهینهسازی کامپایلر در رابطه با تولید هشدارهای بهتر و همچنین اعلام اینکه تابع مربوطه قابل دسترسی نیست مورد استفاده قرار میگیرد. مثال: #include <iostream> [[noreturn]] void myFunction() { std::cout << "Hello, World!" << std::endl; throw "error"; } void print() { std::cout << "Print Now!"; } int main() { myFunction(); print(); return 0; } در کد فوق، در زمان همگردانی (کامپایل) پیغام زیر ساطع میشود: warning: code will never be executed بنابراین در زمان اجرا تابع print(); اجرا نخواهد شد، زیرا به عنوان یک کد غیر قابل دسترس بعد از myFunction توسط کامپایلر یاد میشود. چرا که این امر اجازه میدهد تا کامپایلر بهینهسازیهای مختلفی را انجام دهد - نیازی به ذخیرهسازی و بازیابی هرگونه حالتهای ناپایدار در اطراف صدا زننده (Caller) نیست. بنابراین میتواند کدهای غیر قابل دسترس را از بین ببرد. با توجه به نیازهای این چنینی، در استاندارد ۱۷ صفتهای جدیدتر و کاربردیتری نیز ارائه شده است که به معرفی هر یک از آنها در بخش اول از این مقاله میپردازیم. صفتهای معرفی شده در استاندارد 1z یا همان ۱۷ به صورت زیر هستند: [[fallthrough]] [[maybe_unused]] [[nodiscard]] معرفی صفت [[fallthrough]] به طور معمول در برنامهنویسی، هر وقت که مرحلهٔ مربوط به case در دستور switch به انتهای خود میرسد، کد مربوطِ به دستورِ case بعدی اجرا خواهد شد. طبیعتاً عبارت break میتواند از این امر جلوگیری کند. اما از آنجایی که این رفتار را به اصطلاح fall-through میشناسیم، ممکن است در صورت عدم معرفی اشکالاتی را فراهم کند، در این حالت چندین کامپایلر و ابزارهای آنالیز کننده خطای مرتبط به آن را هشدار میدهند تا کاربر در جریان قرار بگیرد. با توجه به این موضوع که ممکن است بعضاً این مورد چشم پوشی شود، در سیپلاسپلاس ۱۷ به بعد یک صفت استاندارد معرفی شد تا توسعهدهنده بتواند با قرار دادن آن در مکان سقوط (fall-through) به کامپایلر اعلام کند که هشداری در آن بخش لازم نیست. کامپایلرها میتوانند هشدارهای مطمئنی را در زمانی که یک عبارت case بدون اجرای دستور break به انتهای خود میرسند و یا سقوط (fall-through) میکند، حداقل با یک جملهٔ مربوطِ به آن را ساطع کند. برای مثال به کد زیر توجه کنید: #include <iostream> int main() { int number { 2017 }; int standard = {0}; switch(number) { case 2011: case 2014: case 2017: std::cout << "Using modern C++" << std::endl; case 1998: case 2003: standard = number; } return 0; } در کد فوق، در زمان اجرای دستور case سوم با مقدار ۲۰۱۷، کامپایلر هشداری به صورت زیر را اعمال خواهد کرد. warning: unannotated fall-through between switch labels در این حالت برای از بین بردن (چشمپوشی کردن) از این خطا در صورتی که نیاز نباشد موارد دیگر مورد بررسی قرار بگیرد قرار دادن دستور break بعد از آن میتواند منطقی باشد. اما با توجه به انتظاری که میرود تا دستورات بدون توقف بین آنها اجرا شود، قراردادن دستور [[fallthrough]]; بعد از آن میتواند راه حل بسیار مناسبی باشد. #include <iostream> int main() { int number { 2017 }; int standard = {0}; switch(number) { case 2011: case 2014: case 2017: std::cout << "Using modern C++" << std::endl; [[fallthrough]]; // > No warning case 1998: case 2003: standard = number; } return 0; } در این حالت، کامپایلر بدون ساطع کردن خطا آن را همگردانی خواهد کرد. معرفی صفت [[maybe_unused]] صفت [[maybe_unused]] برای نشان دادن کد ایجاد شدهای است که ممکن است از منطق قطعی استفاده نکند. این مورد ممکن است اغلب در لینک شدن با پیشپردازندهها مورد استفاده قرار بگیرد یا نگیرد. از آنجایی که کامپایلر (همگردانها) میتوانند نسبت به متغیرهای بلا استفاده هشدار ساطع کنند، این صفت روش بسیار خوبی برای سرکوب آنها خواهد بود. استفاده از این ویژگی میتواند در بخشهای مهمی مفید باشد، فرض کنید کتابخانهای نوشتهایم که قرار است به صورت چند-سکویی دارای ویژگیهای یکسان در بسترهای مختلف باشد. برای مثال ساخت یک فایل در مسیر مشخصی از سیستمعامل مورد نظر جهت اعمال تنظیمات نرمافزار. namespace FileSystem::Configuration { [[maybe_unused]] std::string createWindowsConfigFilePath(const std::string &relativePath); [[maybe_unused]] std::string createMacOSConfigFilePath(const std::string &relativePath); [[maybe_unused]] std::string createLinuxConfigFilePath(const std::string &relativePath); [[maybe_unused]] std::string createiOSConfigFilePath(const std::string &relativePath); [[maybe_unused]] std::string createAndroidConfigFilePath(const std::string &relativePath); } به کد بالا توجه کنید، در صورتی که شما در محیط کدنویسی در حال استفاده از یک دستور مورد نظر از بین دستورات بالا هستید، طبیعتاً کامپایلر به بقیهٔ دستوراتی که از آنها استفاده نمیکنید پیغامی مبنی بر آن که دستور مربوطه بلااستفاده مانده است را ساطع میکند. جهت جلوگیری از این هشدارها کافی است صفت [[maybe_unused]] را قبل از آنها اعمال کنید. معرفی صفت [[nodiscard]] در صورتی که از [[nodiscard]] استفاده شود، کامپایلر میتواند درک کند توابعی که مقدار بازگشتی دارند نمیتوانند مقدار بازگشت داده شدهٔ آنها را دور انداخت و یا از آنها در زمان صدا زدن صرف نظر کرد. بنابراین با تعریف این صفت در توابع از نوع بازگشتی میتوان پیغامی به صورت زیر را ساطع کند. مثال: #include <iostream> [[nodiscard]] int myFunction() { return 17; } int main() { myFunction(); return 0; } در مثال فوق تابع myFunction در زمان فراخوانی که مقدار بازگشتی آن بی نتیجه مانده است از سمت کامپایلر هشدار مورد نظر را دریافت خواهد کرد. این پیغام در صورتی که مقدار بازگشتی تابع به متغیری از هم نوعِ خودش ارسال شود، ساطع نخواهد شد. #include <iostream> [[nodiscard]] int myFunction() { return 17; } int main() { int func; func = myFunction(); return 0; }
-
7 امتیاز
نگارش ۱.۳.۸
2,350 دریافت
دنیای خود را چگونه با کیوت بسازیم!؟ با توجه به توسعهٔ روزافزون فناوری، دنیای نرمافزاری همگام با آن با سرعت بسیار زیادی در حال پیشرفت و توسعه است. ما برای رسیدن به این مسیر باید به فکر تولید و توسعهٔ محصول با کیفیت همراه با اقدامات کلیدی باشیم تا این محصول هماهنگ با استانداردهای جهانی باشد. برای این امر نیاز است تا این استانداردها را بررسی و در درون پروژههای خود مورد استفاده قرار دهیم. کیوت به عنوان یک چهارچوب قدرتمند یکی از بهترین و پیشتازترین ابزارهای موجود در دنیای برنامهنویسی است که با تمرکز بر روی مباحث تولید محصولی اساساً بر پایهٔ تجربهکاربری و رابطکاربریِ پیشرفته همراه با پشتیبانی از قدرتمندترین زبان برنامهنویسی، نتیجهای مطلوب را در مسیر توسعهٔ محصول نرمافزاری شما فراهم میکند. توجه داشته باشید برنامهنویسی صرفاً نوشتن کد منطقی و برقراری ارتباط با دادهها و حل مسائل مربوط به آن نیست! علاوه بر حل مشکل، برقراری ارتباط با احساسات کاربر و ایجاد یک تجربه و تعامل خوب بسیار مهم است. باید توجه داشت که زمان، هزینه، سرعت و کیفیت همه باهم مهم هستند و برای به حداکثر رساندن درجه کیفیت هر یک از این مولفهها باید از بهترین روشهای ممکن استفاده کرد که شامل مواردی همچون چند-سکویی، ابری، تجربهکاربری، رابطکاربری، رابطهای برنامهنویسی، کتابخانهها و غیره... میباشند و برای رسیدن به آنها کافی است یک زبان مهم و پایه همراه با چند زبان فرعی و فناوریهای مرتبط با یکدیگر را به عنوان ابزار در اختیار داشته باشیم. آخرین اعتبار تخفیفات ویژه به مناسبتهای اخیر به پایان رسیده است. نکتهٔ بسیار مهم: این کتاب به صورت رسمی در کتابخانهٔ ملی ثبت شده است، بنابراین هرگونه چاپ، تکثیر و به اشتراکگذاری این کتاب پیگیرد قانونی دارد. توجه: دریافت نسخههای بهروزرسانی شده تنها از این صفحه برای کسانی که حداقل یک بار آن را تهیه کردهاند امکانپذیر است. نوع این کتاب الکترونیکی است، بعد از پرداخت میتوانید بر روی دکمهٔ دریافت فایل در همین صفحه کلیک کرده و آن را دریافت نمایید. در صورتی که درگاه پرداختی با مشکل مواجه شده باشد، میتوانید به شماره کارت ۶۱۰۴۳۳۷۸۸۴۵۳۳۳۴۸ (بانک ملت) واریز و آن را به آدرس kambiz.ceo@gmail.com و یا شناسهٔ تلگرامی @Kambiz_Asadzadeh اطلاع دهید تا تأیید شود. از تاریخ ۲۶ آذر ۱۴۰۲ دریافت این کتاب بدون پرداخت هزینه توسط نویسنده تأیید میشود، شما میتوانید بعد از مطالعه هزینهٔ آن را بپردازید. در صورتی که از شما اطلاعات آدرس مکانی پرسیده شد، میتوانید آنها را وارد نکنید. * تمامی حقوق مادی و معنوی این کتاب متعلق به مولف و ناشر مولف (کامبیز اسدزاده) میباشد و هرگونه کپی برداری از آن پیگرد قانونی خواهد داشت. توجه : در داشتن هر گونه انتقاد و پیشنهاد در رابطه با این کتاب با آدرس شخصی نویسنده (kambiz.ceo@gmail.com) مکاتبه نمایید. نکته : این کتاب در روزهای خاص ممکن است شامل تخفیف قرار بگیرد. نکته دوم : کسانی که این کتاب را یک بار خریداری میکنند نسخهٔ بهروزرسانی شده آن را به صورت رایگان میتوانند دریافت کنند. برخی از درخواستها در کتاب مقدماتی به صورت زیر بودند: آموزش پیشرفته در رابطه با QML و آشنایی با آن آموزش برقراری ارتباط بین ++C و QML به صورت بکاند و فرانتاند آموزش کار با کنترلها و نحوهٔ سفارشی سازی پروژه آموزش برقراری ارتباط با پایگاه داده و فناوری های مرتبط با آن آموزش نحوهٔ پیکربندی کیتها، کامپایلر و ... آموزش نحوه توسعه برنامه بر روی بسترهای مختلف از جمله اندروید، آیاواس و ... و درخواستهای دیگر... بنابراین بر اساس این درخواستها و محتوایی که نیاز می باشد بعد از جلد مقدماتی با آنها آشنا باشید را در این نسخه فراهم کرده ایم. نکته از نظر من در رابطه با محتوا: کتابخانه کیوت شامل مباحث بسیار زیادی است که میتوان از هزاران صفحه محتوای آموزشی تولید کرد. اما در این محتوای آموزشی من تنها به مواردی اشاره کردهام که لازمهٔ کار هستند و در پروژهها میبایست اطلاعات لازم در رابطه با آنها داشته باشید. سرفصل ها و محتوا چه چیزهایی هستند؟ محتوای کتاب طبق آخرین استاندارد کتابخانه بر پایه نسخه ۵.۸ به بالا میباشد. محتوای آن به نسخه ۵.۹ و حتی ۵.۱۳ بهروزرسانی شده است. همچنین ویژگی های و موارد مهمی که در نسخه ۵.۹ و ۵.۱۰ موجود هستند در این کتاب به آنها اشاره شده است. سر فصلهای نهایی و تایید شده کتاب: فصل اول مقدمه بر زبان ++C برخی از قابلیتها ساختار برنامه در ++C کتابخانهها فرق بین C و ++C ویژگیهای معرفی شده در ++C ویرایشهای ۱۱ ٬ ۱۴ و ۱۷ کامپایلرهای ++C و وضعیت آنها ساختار اسناد ++C در پروژه کاربرد این زبان در کجاست؟ استانداردهای زبان مقدمه کیوت (Qt) معرفی کیوت (Qt) ۵.۹ آشنایی با محیط توسعه، نصب و راه اندازی همراه با پیکربندی کیت (Kit) در آن نصب و راه اندازی محیط Qt پیکربندی کیتها در macOS پیکربندی کیتها در Linux پیکربندی کیتها در Windows معرفی محیط توسعه کیوت کرِیتور (Qt Creator) نسخه 4 پیکربندی و تنظیمات مربوط به ساخت برای پلتفرمهای مختلف معرفی مجوز های Qt و نحوه استفاده از مناسبترین مجوز لوگوهای نشانگر ساخته شده با Qt پشتیبانی از انواع پلتفرمها پشتیبانی از انواع معماری ها شرایط و قوانین لازم جهت انتشار اپلیکیشن در فروشگاه iTunes یا همان (Apple Store) شرایط و قوانین لازم جهت انتشار اپلیکیشن در فروشگاهWindows Store شرایط و قوانین لازم جهت انتشار اپلیکیشن در فروشگاه Google Play شرایط و قوانین اختصاصی برنامه تحت Qt جهت انتشار و پذیرش در فروشگاه های مرتبط فصل دوم معرفی فناوری Qt Quick ویرایش 2 معرفی زبان کیو اِم اِل (QML) ویرایش 2 آشنایی با سبک - سینتَکس (Syntax) زبان QML روش اعلام یا اظهار یک شیء در QML اشیاء فرزند (Child-Object) در QML سبک و روش اعمال اظهار نظر (Comment) در QML صفت های اشیاء در QML پشتیبانی از جاوا اسکریپت (JavaScript) و ترکیب آن با QML روش استفاده از جاوا اسکریپت در سند QML روش های ترکیب ++C و استفاده از آن در سند QML فصل سوم معرفی انواع پروژه ها تحت فناوری کیوت کوئیک (Qt Quick) معرفی پروژه از نوع Qt Widget Application معرفی پروژه از نوع Qt Console Application معرفی پروژه از نوع Qt Quick Application معرفی پروژه از نوع Qt Quick Controls 2 Application معرفی پروژه از نوع Qt Quick Controls Application معرفی پروژه از نوع Qt Quick Canvas 3D Application معرفی پروژه از نوع Qt Quick Labs Controls Application آغاز ایجاد پروژه تحت C++ و Qt Quick ساده ترین برنامه معرفی کلاس QGuiApplication معرفی کلاس QQmlApplicationEngine معرفی کلاس QCoreApplication معرفی تابع exect در پروژه فصل چهارم انواع کنترل ها، منو ها و دیگر آبجکت ها معرفی انواع QML پایه در فناوری Qt Quick نوع date نوع color نوع font نوع matrix4x4 نوع point نوع quaternion نوع rect نوع size نوع vector2d نوع vector3d نوع vector4d معرفی انواع اشیاء QML در فناوری Qt Quick معرفی Accessible معرفی AnchorAnimation معرفی AnchorChanges معرفی AnchorImage معرفی AnimatedSprite معرفی Animation معرفی AnimationController معرفی Animator معرفی Behavior معرفی BorderImage معرفی Contex2D معرفی Canvas معرفی CanvasGradient معرفی CanvasImageData معرفی CanvasPixelArray معرفی CanvasColorAnimation معرفی Column معرفی DoubleValidator معرفی Drag معرفی DragEvent معرفی DropArea معرفی EnterKey معرفی Flickable معرفی Flipable معرفی Flow معرفی FocusScope معرفی FontLoader معرفی FontMeteric معرفی Gradient معرفی GridMesh معرفی GridView معرفی Image معرفی IntValidator معرفی Item معرفی ItemGraResult معرفی KeyEvent معرفی KeyNavigation معرفی Keys معرفی LayoutMirror معرفی ListView معرفی Loader معرفی MouseArea معرفی MouseEvent معرفی MultiPointTouchArea معرفی NumberAnimation معرفی OpacityAnimator معرفی ParallelAnimation معرفی GraphicInfo معرفی ParentAnimation معرفی ParentChange معرفی Path معرفی PathAnimation معرفی PathView معرفی PauseAnimation معرفی PropertyAction معرفی PropertyChanges معرفی Rectangle معرفی RegExpValidator معرفی Repeater معرفی Rotation معرفی RotationAnimation معرفی RotationAnimator معرفی Row معرفی Scale معرفی ScaleAnimator معرفی SecuentialAnimation معرفی ShaderEffect معرفی ShaderEffectSource معرفی Shortcut معرفی SmoothedAnimation معرفی SpringAnimation فصل پنجم معرفی انواع کنترل های 2 Qt Quick Controls کنترل AbstractButton کنترل ApplicationWindow کنترل BusyIndicator کنترل Button کنترل ButtonGroup کنترل CheckBox کنترل CheckDelegate کنترل ComboBox کنترل Container کنترل Control کنترل Dial کنترل Drawer کنترل Frame کنترل GroupBox کنترل ItemDelegate کنترل Label کنترل Menu کنترل MenuItem کنترل Page کنترل PageIndicator کنترل Pane کنترل Popup کنترل ProgressBar کنترل RadioButton کنترل RadioDelegate کنترل RangeSlider کنترل ScrollBar کنترل ScrollIndigator کنترل Slider کنترل SprinBox کنترل StackView کنترل SwipeDelegate کنترل SwipeView کنترل Switch کنترل SwitchDelegate کنترل TabBar کنترل TabButton کنترل TextArea کنترل TextField کنترل ToolBar کنترل ToolButton کنترل ToolTip کنترل Thumbler فصل ششم معرفی Qt Quick Dialog (دیالوگ های انتخاب رنگ، فایل، فونت و پیغام) معرفی Color Dialog معرفی Font Dialog معرفی File Dialog معرفی Message Dialog معرفی Qt Quick Layouts معرفی Column Layout معرفی Grid Layout معرفی Row Layout معرفی Stack Layout معرفی Qt Quick Control Styles (سبک و استایل نویسی کنترل ها – سفارشی سازی) واکنش گرایی و پاسخ دهی محتوای وب در اپلیکیشن با Qt WebEngine محتوای چند رسانه ای در کیوت QMultimedia محتوای چند رسانه ای در کیوت QMultimedia پخش صوت ظبط صدا در فایل پخش ویدیو کار با دوربین فصل هفتم معرفی و پیکربندی کار با بانک اطلاعاتی (دیتابیس) کار با بانک اطلاعاتی و ارتباط آن بین C++ و QML معرفی و کار با XML معرفی و کار با JSON معرفی و کار با QSetting سفارشی سازی فایل .pro پروژه فصل هشتم مقایسه انواع حالت های کامپایل Debug و Release نحوه افزودن دیگر کتابخانه های C++ در محیط Qt Creator و استفاده همراه با کتابخانه Qt فرق بین کامپایل استاتیک و داینامیک نحوه خروجی گرفتن / گسترش (Deployment) در Qt پیکربندی و انتشار برنامه در پلتفرم ویندوز (Windows) پیکربندی و انتشار برنامه در پلتفرم مک (macOS) پیکربندی و انتشار برنامه در پلتفرم لینوکس (Linux) پیکربندی و انتشار برنامه در پلتفرمهای iPhone و iPad (iOS) پیکربندی و انتشار برنامه در پلتفرم اندروید (Android) معرفی ابزار کیوبس (QBS) به روز رسانی کیوت بدون دریافت فایل نصبی آفلاین اهداف و چشمانداز فنی کیوت ۶ پیشنهادات و ملاحظات در عملکرد و کارآیی (جدید)رایگان
-
7 امتیازبا سلام، با توجه به سوالات مکرر برخی از کاربران و خصوصاً دانشجویان جدید، تصمیم گرفته شد تا توضیحاتی دربارهٔ نحوهٔ یادگیری برنامهنویسی با سیپلاسپلاس بیان شود. قبل از هر چیز لازم است بدانید، سیپلاسپلاس یک زبان برنامهنویسی کاملاً تخصصی مهندسی است. بنابراین یادگیری آن طبیعتاً نیاز به تلاش، تحمل و پشتکار کافی در مقابل چالشهای آن خواهد داشت. مقدمه در حال حاضر بیش از سه دهه است که از ساخت و معرفی زبان برنامهنویسی ++C میگذرد. در رابطه با آن که هدف از ایجاد این زبان چه چیزی بوده و مزایای آن نسبت به زبانهای دیگر چه چیزی است (چرا موتور مخفی جهان مدرن امروزی است) را میتوانید در این مقاله مطالعه کنید. اما بسیاری از افراد علاقهمند به زبانهای برنامهنویسی تمایل بسیاری دارند تا در برنامهنویسی با این زبان به درجه مطلوب و درواقع (حرفهای) برسند. قبل از هر چیز باید مواردی را در نظر داشته باشیم که یاد گیری زبانهای برنامهنویسی به خودی خود کافی نیست! مخصوصاً زبانهای C و ++C مستلزم پیشنیازهای تخصصی بسیاری هستند که در روند تولید، توسعه، تجزیه و تحلیل لایههای مختلف مهم است. آیا زبان سیپلاسپلاس در حال توسعه است؟ به جرأت میتوانم بگویم که سیپلاسپلاس به عنوان پیشتاز زبانهای برنامهنویسی با سرعت بسیار زیادی در حال گسترش و توسعهٔ خود است. بهتر است بدانید این زبان از شیوهٔ نسخهنگاری معمولی بهره نمیبرند، بلکه از «استاندارد» (ISO/IEC) که کمیتهٔ استانداردسازی آن را تأیید و نهایی میکند بهره میبرد. بنابراین، بر اساس استانداردی پیش میرود که پیشنویسهها و بهبودهای آن تماماً با حفظ (پشتیبانی از عقبگرد) قابل توجه است. همانطور که در تصویر مربوطه میبینید، سیپلاسپلاس در آخرین بهروز رسانی، به نقشهٔ توسعهٔ خود در سالهای بعد نیز اشاره کرده است که در قالب استانداردهای ۲۳، ۲۶ و ۲۹ از الآن یاد شدهاند. چیزی که در هیچ زبانی در وضعیت فعلی به صورت نقشهٔ راه از توسعه آنها نمیتوان دید! این خود یک نکتهٔ بسیار مثبت است که تیم (کمیته) استانداردسازی این زبان کاملاً این اطمینان را میدهد که این زبان نسبت به نیاز و آینده در حال به روز بوده، است و خواهد بود. لازم است بدانید، استانداردهای فعلی، ۱۷ و ۲۰ و بعد ۲۳ به عنوان یک نسل انقلابی و جهش یافته از سیپلاسپلاس یاد میشوند، اگر شما تجربهٔ نوینی از برنامهنویسی را میطلبید، بهتر است به استاندارد ۲۰ خوشآمدگویی کنید که در کنار کارآیی بسیار عالی، یک نحو و سبک بسیار ساده و روان در اختیار توسعهدهنده قرار میدهد. در ادامه ما به سوالاتی که معمولاً توسط تازهکاران پرسیده شده است پاسخ دادهایم: ابعاد علمی و اقتصادی کار با ++C در ایران متاسفانه اکثر ما ملتی هستیم، تَنبَل و حاضر برای لُقمهٔ آماده! بنابراین بازار کار در ایران به گونهای است که بیشتر شرکتها و افراد توسعه دهنده به سراغ زبانهای سادهتر و در دسترستر (بی دردسر) میروند. غافل از آن که یک برنامهٔ تولید شده توسط سی++ بسیار سریع، جذاب، قدرتمند و انعطافپذیرتر است. همهٔ بحث در اینجا تمام نمیشود، چرا که شاید در سالهای اخیر وضعیت تقریباً فرق کرده و به کمک اطلاع رسانیهای اساتید و دوستان حرفهای، ما در این زمینه این اطلاعرسانی به خوبی صورت گرفته و توسعه دهندهها از قابلیتها پنهان این زبان آگاه شدهاند و میدانند که سیپلاسپلاس به عنوان یک زبان بسیار کاربردی در زمینههای مختلف جایگاه ویژهای دارد. شرکتها و گروههای برنامهنویسی بسیاری به دنبال برنامهنویسهای سی++ هستند که این امر نشان دهندهٔ این است که نسبت به سالهای گذشته پیشرفت و آگاهی جامعهٔ برنامهنویسی در این حوزه منطقیتر و بهتر شده است. من بارها در مورد بحث محدودیتهای سختافزاری، مشکلات و محدودیتهای پیش و روی قانون مور، مسائل مربوط به انرژی سبز و غیره صحبت کردهام. و اکنون زمان آن رسیده است که بیشتر در این باره فکر کنید که واقعاً چه ابزارهایی آیندهٔ بهتر و موثرتری در پیشرفت صنایع خواهند داشت. بنابراین، بهتر است قبل از هرچیز در نظر داشته باشید که هدف از این تاپیک، این نیست که اثبات کنیم یک زبان نسبت به زبان دیگر برتری دارد. هدف اصلی من این است به واقعیتهایی اشاره کنم که غیر منطقی نیستند. چرا که واقعاً کارفرمایانی وجود دارند که نیازمند به برنامهنویسانی هستند که تخصص خوبی در زبانهای برنامهنویسی دیگری مانند ++C دارند. همه چیز در زبانهای سطحبالاتر خلاصه نشده است! توجه داشته باشید که هدف از این توضیحات چنین نیست که بعد از خواندن این مطالب زبان برنامهنویسی مورد علاقهٔ خود را کنار گذاشته و به سمت سی++ بروید، خیر! یا مقصود آن نیست که با دیدن و شنیدن پیچ و خمهای آن از یادگیری آن منصرف شوید. من بارها گفتهام، تمامی زبانها به عنوان ابزارهای کاری شما در یک جعبهٔ ابزار هستند و هر زبانی حوزهٔ کاربردی خودش را دارد. بنابراین قبل از اینکه شما تصمیم بگیرید که چه زبانی را یاد خواهید گرفت باید حوزهٔ کاری وعلاقهٔ خودتان را مشخص کنید سپس وارد تحقیق و بحث و نظر خواهی راجع به آن زبان نمایید. مقایسهٔ زبان طبق این قانون کاملاً کار اشتباه و بچهگانه است و به هیچ عنوان در مورد یک زبان برنامهنویسی گاردِ تعصبی نگیرید. متاسفانه به خاطر تفکرات اشتباه و معرفیهای غیر منطقی و غیرعلمی برنامهنویسان کشور ما که ممکن است حتی خودِ شما هم چنین تصور کنید، در رابطه با سایر زبانها مانند سی++ بسیاری از کارفرمایان نیازمند چنین برنامهنویسانی هستند که در کشور ما واقعاً نیاز است. توجه داشته باشید که انتخاب درست این نیست که چون همه سراغ زبانهای پر مخاطبتری میروند و چون تمامی آگهیها استخدامی مرتبط با آنها است پس فقط باید آنها را یاد گرفت! خیر چنین تفکری اشتباه است و ضربهٔ بسیار بزرگی در صنعت و دانش آیندهٔ جامعهٔ تخصصی هر کشوری که به این شکل پیش میرود خواهد زد، چرا که ما باید طبق مسیر و سرعتی که دنیا در حال جهش است، خود را هماهنگ و بهروز کنیم. نکاتی در این میان وجود دارد که باید به آنها اشاره کرد: متاسفانه در کشور ما بسیاری از برنامهنویسان چه مبتدی چه حرفهای اینطور تصور میکنند که تولید محصول نرمافزاری یعنی برنامهنویسی یک نرمافزار که قرار است به بانک اطلاعاتی متصل شده و کارهایی مانند ثبت و ویرایش اطلاعات و در نهایت گزارش گیری و دیگر عملیات ممکن را انجام دهد! این تفکر به شدت اشتباه است! الآن دیگر سیستم نرمافزاری، معماریها و سبک و سیاقهای ساختوساز فرق کرده است. مبتنی بودن بر خدمات متمرکز، غیرمتمرکز و دیگر فناوریها بسیار مهم است. توجه کنید که بزرگترین و معروفترین فناوریها مطرح جهانی معمولاً به واسطهٔ این زبان طراحی میشوند، مانند، سیستمعاملها، نرمافزارها، زیرساختها و حتی بلاکچین و بیتکوین که خالی از لطف نیستند. بسیاری از بانکها و شرکتهای صنعتی و اقتصادی مهم کشور نیازمند برنامهنویسان سی++ هستند تا بتوانند در بحث بانکی برای توسعه دستگاههای پرداخت مانند Pos و ATM از این زبان و برنامهنویسان بهره ببرند. در صنایع بزرگ خودرو سازی و دیگر موارد نرمافزارهای مورد نیاز است تا با سرعت بسیار و بدون محدودی پلتفرمی پاسخگوی یک چرخهٔ تولید باشند تا بتواند زیرساختها و رابطهای یک شرکت بزرگ را مدیریت و آن را بهینه کند. در بسیاری از حوزههای صنعتی کشور شرکتهای غولپیکر در زمینهٔ تولیدات انبوه و سنگین که توسط ماشینآلات صورت میگیرد به دنبال برنامهنویسان سی و سی++ هستند که ممکن است به صورت معرف یا آشنا با آنها مواجه و استخدام شوید. شرکتهای سختافزاری و استارتآپهایی که در حوزهٔ الکترونیک و سختافزار فعالیت میکنند به دنبال برنامهنویسیان سی++ هستند تا بتوانند در حوزهٔ کاری خود اهداف خود را توسعه و شما را به عنوان مهرهای مفید پیش ببرند. شرکتهای توسعهدهندهٔ موبایل و خطوط تولیدی تلفنهای همراه داخلی گسترش یافته و به شدت نیازمند برنامهنویسان سی++ هستند که برخی از آنها مبادلات بینالمللی نیز دارند. در بخش حوزهٔ شهر سازی، مدیرت شهر و همچنین راهداری شرکتهایی هستند که برای تولید سیستمهای مدیریتی مانند مدیریت راهها و ترددهای خودرو و یا مدیریت ترافیک و موارد این چنینی به دنبال برنامهنویسان سی++ هستند. بسیاری از شرکتها و حتی تیمهای توسعه بر روی پلتفرمهای iOS و Android به صورت تخصصی سفارشی سازی و حتی ساخت و توسعهٔ اپلیکیشنهای ایرانی تمرکز دارند که جدیداً به لطف آگاهی از فریموُرکهایی مانند Qt به سمت این حوزه آمده و نیازمند سی++ کاران هستند. شرکتهای بازیسازی کشور ما که این سالها با پیشرفتهای خوبی مواجه شدهاند به دنبال برنامهنویسان سی++ هستند که بتوانند در این صنعت برای فرهنگسازی و توسعه صنعت بازی سازی جلو بروند. بسیاری از شرکتهای پنهان وجود دارد که به صورت بسیار مخفیانه در صنایع سهبعدی و پیشرفته در حال فعالیت هستند که محصولات خود را نه در ایران بلکه در خارج از آن آمریکا و دیگر کشورهای اروپایی به فروش میرسانند که به سفارش آنها بوده است. با دید سطحی به این مسائل نباید نگاه کنید، اگر آگهیهای استخدامی نمیبینید به خاطر این است که این زبان کار کُن می خواهد نه تَنبل! بنابراین شما باید به سراغ آن بروید چرا که بسیاری از شرکتهای بینالمللی فعالیتهای بزرگی انجام میدهند که هیچوقت از آنها خبر ندارید و به صورت کاملاً سفارشی و حساسیت کامل به دنبال برنامهنویسان این زبان هستند (چون میدانند یک سی++ کار هدفمند و با دید بازتری به توسعه نگاه میکند). چنین شرکتها معمولاً استخدام را به صورت رابطهای انجام میدهند و تعداشان هم کم نیست. ما میدانیم که شاید شما با دیدگاه اینکه حتماً باید نرمافزارهای کاربردی تولید کنید به قضیه نگاه میکنید، خوشبختانه فریمورک کیوت به قدری قدرتمند و پُخته شده است که میتوان هر محصول کاربردی در هر زمینهای را تولید کرد که از کارایی بسیار بهتری نسبت به دات نت بهرهمند است. در حوزهٔ امنیت، شبکه و موارد این چنینی شرکتهای بزرگ و Ispها نیازمند این زبان هستند. البته دلایل بسیاری وجود دارد که موجب میشود شرکتها از روی ناچاری به سراغ برنامهنویسان دیگر بروند، که من شخصاً آن را تجربه کرده ام ! در بسیاری از پروژهها که به عنوان مشاور فنی در آنها شرکت کرده بودیم متوجه آن شدیم شرکتها به خاطر عدم وجود برنامهنویس سی++ برای ادامهٔ چرخهٔ تولید خود مجبوراً سراغ برنامهنویسهای دیگر زبانها میروند. این امر به خاطر این است که واقعاً درصد تعداد برنامهنویسان این زبان نسبت به زبانهای دیگر به خاطر (راحت طلبی) و شاید عدم آگاهی از این زبان دور هستند. یکی از نکتههایی که اخیراً جالب بوده است، آن است که شما به واسطهٔ سیپلاسپلاس میتوانید حتی وبسایتهای مورد نیاز خود را بسازید! یک سیستم چند-منظوره طراحی کنید که در حوزههای قابل استفاده باشد. برخی از هماهنگیهایی که این زبان خود را به بهروز رسانیهای بسیار سریع در فناوری وفق داده است، پشتیبانی از ساختارهای چند-سکویی و کاملاً بومی با کارآیی بالا است که در حوزههای موبایل، دسکتاپ و وب میتوانید آن را مورد استفاده قرار دهید. از فناوریهای مربوط به فریمورکهای طراحی گرفته، تا امکان ساختوساز در قالب وباسمبلی، بلاکچین و دیگر موارد. یک نکتهٔ بسیار مهم که طی این سالها تجربه کردهام، این است که خیلی از شرکتها و خدمات دهندهها با این که در جریان مزایای این زبان هستند، مجبوراً به خاطر عدم وجود متخصص کافی از ابزارهای دیگر برای توسعهٔ کار خود استفاده میکنند. هرچند مشکلات این زبان تا به الآن شفاف شده است، اما بهروز رسانیها و توسعههای پی در پی آن موجب بهبودهای بسیار چشمگیری در آن نیز شدهاست. برخی از سوالاتی که علاقهمندان به این حوزه میپرسند در ادامه آمده است: من یک دانشجو هستم و رشتهٔ تحصیلی من کامپیوتر است، به برنامهنویسی با ++C علاقه دارم از کجا باید شروع کنم؟ اگر شما به قصدِ حرفهای شدن دنبال یادگیری این زبان هستید، همانطور که اشارهای شد مباحث پیش نیاز برای یادگیری این زبان مهم هستند و برای درک هرچه بیشتر این زبان بهتر است دانش خوبی در زمینهٔ تجزیه و تحلیل رفتار کامپایلر داشته باشید. علاوه بر این برای آشنایی با کامپایلر رفتار سیستمعامل و واکنشهای کامپایلری در سیستمعاملهای متفاوت بسیار مهم است. به عنوان مثال کامپایلر GCC بر روی ایستگاههای یونیکس تعبیه شده و برای خود قوانین و استانداردهایی را دارد. در کنار آن کامپایلر MSVC نوعی کامپایلر اختصاصی تحت ویندوز است که متناسب با ساختار و معماری ویندوز رفتار میکند. در نگاه اول آشنایی با آنها شاید الزامی به نظر نرسد، چرا که شما صرفاً به سمت یادگیری زبان، نحو (سینتکس)، ویژگیها، کتابخانهٔ پیشفرض و هستهٔ آن میپردازید. اما در بُعد ساخت و ساز یک محصول عالی اطلاعات شما در زمینههای مختلف لازم است کافی باشد. من یک دانشجو هستم اما متاسفانه رشتهٔ تحصیلی من کامپیوتر نیست، به برنامهنویسی با ++C علاقه دارم از کجا باید شروع کنم؟ این کار کمی دشوار است، در مرحلهٔ اول پیشنهاد ما این است که سراغ زبانهای برنامهنویسی دیگری بروید که نیازی نداشته باشد شما درگیر درک کامپایلر یا رفتارهای سیستمعاملی شوید. اما به هر حال اگر شما به هر نحوی میخواهید این زبان را یاد بگیرید چارهٔ کار تلاش مستمر و حوصله است. متاسفانه سیپلاسپلاس ذاتی مرموز دارد و آن این است که اگر بتوانید به آن مسلط شوید یک زبان با وفا و قدرتمندی خواهد بود که در هر زمینهای به نیازهای شما پاسخگو خواهد شد. اما اگر به هر دلیلی نتوانید با این زبان دوست شوید به طور بسیار مرموزی اعصابتان را به هم خواهد ریخت ? که البته طبیعی است چون سی++ تحت کامپایلرهای خود دستِ برنامهنویس را آزاد گذاشته و شما هستید که انتخاب میکنید کُد شما به چه شیوهای با توجه به هدف چگونه عمل کند. چقدر زمان لازم است تا من این زبان برنامهنویسی را یاد بگیرم؟ با توجه به ساختار زبان و رفتارهای کامپایلر میتوان گفت به قدری دامنهٔ سی++ گسترده است که تنها راه حل ممکن برای رسیدن به یک وضعیت مطلوب از دانش مرتبط با آن باید زمان مشخصی در نظر گرفته شود. ممکن است شما بتوانید در بازهٔ ۱ الی ۳ ماه مباحث مقدماتی این زبان را درک کنید. اما توجه داشته باشید پیشنیازات آن نیز نیازمند تحقیق، تجربه عملی و نتیجهگیری تئوری و علمی هستند. با توجه به اینکه شما (سریع، هوشمند با گیرایی بالا باشید) میتوانید در کمتر از ۶ ماه به یک پایداری تقریباً قابل قبول در حد مقدماتی این زبان برسید. استاندارد زبان را درک کنید و نحوهٔ برقراری ارتباط با کتابخانههای پیشفرض STL و غیره را تجربه کنید. برای کسب دانش و افزایش آن به میزان متوسط و به بالا نیازمند تلاش بسیار بیشتری خواهید بود که باید در قالب پروژههای عملی و واقعی صورت گیرد. متاسفانه سی++ به دلیل گسترده بودن چنان پیچیدگیهایی را دارد که تنها میتوان در موقع برنامهنویسی به صورت عملی (بر روی پروژههای واقعی) آن را تجربه کرد. آیا ارزش دارد من این زبان را یاد بگیرم؟ فرصت من کم است و میخواهم سریعاً به درآمدزایی برسم در همین ابتدا به شما میگویم که اگر صرفاً به درآمدزایی سریع فکر میکنید، سیپلاسپلاس گزینهٔ مناسبی برای این رویا نیست! اگر شما به عنوان یک برنامهنویس متوسط و به بالا به این زبان تسلط دارید، و حداقل میتوانید با یکی از کتابخانههای خوب آن ارتباط برقرار کنید، وقت آن است که با کتابخانههای قدرتمند این زبان وارد عمل شوید. کتابخانههایی مانند Boost، Poco، Qt و غیره از سری کتابخانههایی میباشد که امکانات بسیاری را در اختیار شما علاقهمندان این زبان قرار میدهند تا بتوانید در کمترین زمان ممکن به نیازهای خود دسترسی داشته و آن را پیاده سازی کنید. همهٔ آنها در ساخت و توسعهٔ محصول به شما کمک میکنند. فراموش نکنید که بارها گفتهام به زبانها، کتابخانهها و فناوریها به عنوان ابزار در داخل جعبهابزار خود بنگرید. توجه داشته باشید که لازمهٔ طراحی و توسعه یک محصول مفید (قابل قبول) در قالب MVP (کمینه محصول پذیرفتنی) مستلزم داشتن دانش طراحی محصول نیز میباشد. اما همه چیز اینگونه خلاصه نشده است و شما برای اینکه بتوانید یک محصول واقعاً قابل قبول را پیاده سازی کنید مسلماً باید آن را مجهز به قابلیتهای دیگری مانند منابع ذخیره داده و یا سرویسها و ماژولهایی کنید که بتواند به عنوان یک محصول کاربردی روی آن حساب کرد. آیا صرفاً با دانستن زبانهای برنامهنویسی و تسلط بر آن میتواند یک محصول استاندارد و سطح جهانی را به طور کامل تولید کرد؟ نظر من قطعاً خیر است! اگر شما واقعاً با دیدگاه یک سازنده، یک تولید کننده و مهندس تمام عیار در ذهن خود رویا پروری میکنید، در این صورت باید بدانید همه چیز در زبان خلاصه نمیشود! از نظر من حداقل مواردی که (به طور خیلی خیلی خلاصه و محدود) نیاز است تا یک متخصص بتواند پاسخگوی تصمیمگیری نقشهٔ توسعهٔ یک محصول برای مشتری در ابعاد مختلف و سطوح متفاوت از حوزههای موجود در قالب اصولی باشد به صورت زیر است که فرد یا یک تیم باید به آنها اشراف کافی داشته باشد: ۱- آشنا مبانی کامپیوتر که امر طبیعی (شامل درک و فهم مسائل و نحوهٔ حلشون متناسب با پلتفرم اجرایی محصول) ۲- آشنا به ساختار نوع محصول استاندارد در یک حوزه مثل: وب، آیاواس، اندروید یا دسکتاپهای مختلف مثل لینوکس، مک و ویندوز، اینترنت اشیاء و دیگر موارد. ۳- آشنا به فلسفهٔ بکاند و فرانتاند یا ترکیبی از این دو به همراه ابزارهای مناسب. ۴- آشنا به اصول طراحی UI/UX به عنوان یک نیاز و یک فاکتور مهم در ساخت محصولی که وابسته به عملکرد کاربر دارد و در حوزهٔ فرانتاند مهم و کاربردی هست. ۵- آشنا به اصول SOLID و امثالش مهم هستند. ۶- آشنا اصول برنامهریزی ساخت بانک اطلاعاتی، اینکه از چه بانک اطلاعاتیای استفاده کنی و چرا؟ ۷- آشنا به ارتباطات دادهای، جداول و ارتباط بین فیلدها، جداول و روشهای درست تبادل اطلاعات مابینی دادهها. ۸- آشنا و تسلط کافی به یک محیط توسعه و ادغام ابزارها و محیط طراحی برای هدف. ۹- آشنا به معماری ساختار و رابطهای برنامهنویسی (Api) ۱۰- آشنا به استانداردهای Http، درک و مدیریت درخواست، پاسخها و ... ۱۱- آشنا به الگوهای طراحی برنامهنویسی (DP) ۱۲- آشنا به روشهای نگهداری و آزمایش نرمافزار و کدها به خصوص درک مبحث Fault tolerance. ۱۳- آشنا به روشهای اطمینانسازی و ایمنسازی پردازشهای داخلی نرمافزار برای جلوگیری یا دشوار سازی نفوز و خرابکاری. ۱۴- آشنا به روشها و معماریهای احراز هویت و نحوهٔ ادغامش با نرمافزار مثل:JWT, OAuth, AWS و غیره... ۱۵- آشنا به نوع پارادایمهای زبان برنامهنویسی، در قالبهای (دستوری) Imperative و (اعلانی) Declarative مثل OOP، functional و دیگر موارد. ۱۶- آشنا به سبک معماری نرمافزاری (Microservice یا مثلاً Monolith) مزایا و معایب آنها. ۱۷- آشنا به سبک معماری طراحی مانند MVC در طراحی بدنهٔ محصول. ۱۸- آشنا به سبک و الگوهای طراحی ساختاری در بکاند مانند Builder، Abstract، Factory و غیره. ۱۹- آشنا به ساختار یک زبان (در صورتی که میخواهید جوابگوی مسائلِ پیش آمده باشید) کالبدشکافی زیرپوستی و عمیق یک زبان مهم است. ۲۰- آشنا و درک کامپایلرها و مفسرها، تفاوتها و شیوههای عملکردیشون نسبت به کدهای بهینه شده و عادی. ۲۱- آشنا و درک مدلهای مختلفی از سیستمهای توزیع شده مثل IaaS، PaaS، SaaS یا FaaS. ۲۲- آشنا به ابزارهای ساخت و فرآیند کاری اونها مثل CMake، NMake، QMake و غیره. ۲۳- آشنا به روشهای مدیریت وابستگیهای نرمافزار و ابزارهای لازم برای بستهبندی بهتر خروجی. ۲۴- آشنا به روشهای کدنویسی قابل آزمایش (Unit Test) و استفاده از ابزارهایی مثل CTest, GTest, Catch2 و غیره. ۲۵- آشنا به توسعهٔ آزمون محور (Test Driven- Development) ۲۶- آشنا به گامها و شرایط نسخهنگاری و مراحل توسعهٔ نرمافزار (SDP) ۲۷- آشنا به روشهای امنیت در کد و توسعه به شیوههای بررسی از طریق Fuzz-Test، Sanitizer، آنالیزرهای پویا و ایستا و غیره... ۲۸-آشنا به قوائد طراحی بر پایهٔ خدمات مبتدی بر معماری ابری برای خدمات پیامی، وبسرویسها، پردازش و غیره. ۲۹- در سطوح وب آشنا به مکانیزم شاخص بندی، فاکتورهای SEO و شیوههای درست بهبود صفحات وب. ۳۰- آشنا به روشهای به کار گیری و پیادهسازی ثبت کنندهٔ وقایع در دل محصول و روشهای بازخورد برای توسعهٔ بهتر به همراه مانیتورینگ، نظارت و تریسینگ. ۳۱- در شرایط لزوم آشنا به نحوهٔ به کار گیری و دلیل استفاده از فناوریهایی مثل Redis، Memcached و غیره. ۳۲- آشنا و درک صحیح از مفاهیم همزمانی (Concurrency) و روشهای به کار گیری آن نسبت به زبان برنامهنویسی و شرایط مناسب استفاده. ۳۳- آشنا به سبک و قوائد و ساختار زبانهای برنامهنویسی و فرآیند ساخت و ترجمه. ۳۴- و تا صدها گزینهٔ دیگر که میتوان در این بخش لیست کرد که اگر انتخاب شما زبانهای نزدیک به سیستم باشد این داستان در ادامهٔ این توضیحات سر به فلک خواهد کشید. با توجه به این موارد اگر بخواهید محصولی را بسازید که طبق استاندارد آن را توسعه و تولید کنید که در بستر سیپلاسپلاس شکل میگیرد، باید ابزارها و موارد پیشنهادی زیر را در اختیار داشته باشید و کار با آنها را تا حد نیاز بدانید: یک محیط توسعه یکپارچهٔ نرمافزار مانند Qt Creator، Xcode یا Visual Studio (پیشنهاد ما Qt Creator است) این محیط به عنوان IDE نیز یاد میشود. پلتفرم توسعه (سیستمعاملی) که قرار است محیط توسعهٔ یکپارچه خود را بر روی آن نصب و شروع به برنامهنویسی کنید را مشخص نمایید. اگر شما کاربر ویندوز هستید باید محیط توسعهٔ یکپارچهٔ شما مجهز به کامپایلر MSVC و یا نسخهٔ پورت شدهٔ GCC یعنی MinGW باشد. اگر شما کاربر مکاواِس هستید به صورت پیشفرض با نصب محیط توسعه کامپایلر Clang بر روی آن تعبیه خواهد شد. البته میتوانید به صورت سفارشی از کامپایلر GCC نیز استفاده کنید. در صورتی که کاربر لینوکس هستید کامپایلر GCC به صورت پیشفرض بر روی محیط توسعهی شما تعبیه خواهد شد. آشنا به دستورات ترمینال و یا کنسول در سیستمعاملهای لینوکس، مک و ویندوز در ساخت و سازهای دستوری مفید هستند و نیاز است آنها را بدانید. آشنا به Git و دستورات مربوط به آن در نگهداری و به اشتراکگذاری مخازن پروژه میتواند برای شما سودمند باشد. بر اساس پیشنها جهت محیط توسعه کتابخانهٔ Qt نیز پیشنهاد میشود (دلیل آن این است که این کتابخانه به شما کمک میکند تا بتوانید رابط کاربری نرمافزار (محصول) خود را پیاده سازی کنید). اگر هدف شما طراحی یک محصول استانداردی است که از شکل و ظاهر آنچنانی برخوردارد نیست بهتر است از ماژولهای پیشفرض Qt مانند Qt Widget برای طراحی آن استفاده کنید. این کار بسیار ساده است و نیازی برای داشتن دانش در رابطه با حوزههای JavaScript و QML ندارد. البته میتوانید با ترکیب CSS طراحی رابط کاربری برنامهٔ خود را بهبود ببخشید. بعد از این موارد نیاز است که شما هدف توسعهٔ خود را مشخص کنید، اینکه میخواهید توسعه دهندهٔ چه پلتفرمی باشید؟ تولید کننده برنامههای دسکتاپ بر روی ویندوز؟ یا لینوکس و مک؟ یا همهٔ آنها؟ خوشبختانه با توجه به قابلیتهای ذاتی سی++ و کیوت شما میتوانید برنامهٔ خود را تنها با داشتن محیط توسعهٔ خود بر روی پلتفرم مورد نظر خود کامپایل و خروجی بگیرید (البته به شرط اینکه از سرویسهای اختصاصی سیستمعاملی) استفاده نکرده باشید. البته دقت کنید اگر شما توسعهدهندهٔ اختصاصی برای فقط یک سیستمعامل خواهید بود، در این صورت نیازی به یادگیری مفاهیم یا رابطهای اختصاصی برنامهنویسی یک پلتفرم دیگر نخواهید بود. اگر مشتاق آن هستید که برای پلتفرمهای موبایل مانند آیاواس یا اندروید برنامه تولید کنید، موضوع کمی گستردهتر خواهد شد و حتماً باید ملزوماتی که در ابتدای مقاله به آن اشاره شده است را در نظر داشته باشید. برای مثال تولید یک نرمافزار iOS مستلزم آن است که شما علاوه بر داشتن دانش سی++ در رابطه با معماری و ساختار و همچنین قوانین، قوائد و ساختار نرمافزارهای مرتبط با اپل راداشته باشید. در Android نیز این چنین است. اگر شما تازه کار هستید پیشنهاد میکنیم هدف خود را فعلاً محدود بر یک پلتفرم خاص کنید، حتماً نیاز نیست اطلاعات خود را کامل و سپس اقدام کنید. برای مثال توسعه محصول بر روی ویندوز برای آغاز کار بسیار مناسب است و شما صرفاً بر روی این پلتفرم متمرکز خواهید بود. در نهایت شما محصول خود را با آزمایش وخطاهای بسیاری میتوانید تولید و با توجه به مستنداتی که در همین مرجع ارائه شده اس مستقر و برای کاربر نهایی ارائه کنید. برای اینکه بدانید مزایای این زبان در چیست و چه کتابخانههایی میتوانند مفید باشد و برخی از سوالات احتمالی که ممکن است به ذهن شما برسد این بخش را مطالعه کنید. برای نحوهٔ شروع کار با Qt این بخش را مطالعه کنید. جهت نحوهٔ نصب و راه اندازی محیط توسعه این بخش را مطالعه کنید. منابع فارسی یا زبان اصلی؟ پاسخ این سوأل بدون شک راحت است! زبان انگلیسی، زبان علم است، بنابراین هر آنچه که شما در زبانهای بومی و غیر انگلیسی مطالبه میکنید، ممکن است با محدودیتهای شدیدی مواجه شوید. بنابراین برای یادگیری محتوای علمی به شدت توصیه میشود به کمک مراجع انگلیسی آن را بیاموزید! من زبانم ضعیف هست، آیا باید به زبان انگلیسی تسلط کافی داشه باشم تا بتوانم زبانهای برنامهنویسی را یاد بگیرم؟ این یکی از سوألهای بسیار پر تکرار است که بارها با آن مواجه میشویم! در پاسخ باید صادقانه بگویم، شما به حداقلهای زبان انگلیسی واقعاً نیاز دارید! در حد این که متنهای عادی را بخوانید، آنها را متوجه باشید و بر اساس نگارش معنای صحیح جمله و واژهها را درک کنید. رفته رفته به آن عادت خواهید کرد و در آن نیز حرفهای خواهید شد. اما فراموش نکنید که زبانآموزی در کنار برنامهنویسی از لزومات است. در مورد واژههای تخصصی هم نگران نباشید، معمولاً واژههایی که معنای آنها را مابین جملات و کتابها نمیدانید، در مراجع و یا پانویسهای آنها تعریف میکنند. بسیاری از واژهها در قالب یک روش، مفهوم یا اصطلاح عنوان میشوند و شما باید به دنبال تعریف کامل آن باشید. به عنوان مثل، اصطلاح RAII در سیپلاسپلاس که به برخی از آنها در این بخش اشاره کردهام. من سن پایینی ندارم، آیا برای شروع کردن برای یادگیری سیپلاسپلاس دیر است؟ شاید من تجربهٔ سنیِ کافی، نسبت به کسانی که این سوأل را میپرسند نداشته باشم، اما نسبت به تجربهای که در مهندسی کامپیوتر و به خصوص ساختوساز و توسعهٔ محصولات نرمافزاری دارم، میتوانم به جرأت بگویم که این یک دغدغهٔ ذهنیای به حساب میآید که شاید در قالب و جنسِ ترسِ بیهوده از دست دادن زمان را به خود بگیرید. اما واقعیت آن است، تا زمانی که شما شروع نکنید، بله نمیتوانید! اما نکتهای که مد نظرم است بدانید، این است که در انتخاب زبانها، به خصوصی یادگیری سیپلاسپلاس، بهتر است بخشی از هدف و استعدادی که به آن دارید را هدف قرار دهید، (هدف مشخص و شفافی داشته باشید) چون خاصیت این زبان در چند-منظوره بودن آن است، و ممکن است شما را وسوسهٔ خود در همهٔ جوانب کند! که این باعث میشود شما هرگز به یک نقطهٔ شروع نرسید. به عنوان مثال، برای شروع بهتر است یک حوزه را انتخاب کنید و پیشبرورید، مانند: برنامهنویسی و طراحی اپلیکیشن در سیستمعامل ویندوز. یا برنامهنویسی در حوزهٔ موبایل، وب، بازیسازی، امبدها (سیستمهای درونسازی شده) و غیره... این بستگی به سلیقهٔ شما و نوع نیازی که در بازار میبینید خواهد داشت. در زیر منابعی را معرفی میکنم که به رایگان یا با کمترین هزینه میتوانید به آنها دسترسی داشته باشید: منابع استاندارد و رسمی زبان سیپلاسپلاس: https://en.cppreference.com https://isocpp.org برای یادگیری در سطوح مقدماتی وبسایتهای زیر پیشنهادات مناسبی هستند: https://www.geeksforgeeks.org/references-in-c http://www.cplusplus.com/reference https://www.tutorialspoint.com/cplusplus/cpp_references.htm https://www.learncpp.com در صورتی که میخواهید در حالت بسیار ساده، تصویری و در قالب برگههای تقلب به ویژگیهای زبان و کتابخانههای آن بپردازید، وبسایت زیر یک نمونه بسیار مناسب است: https://hackingcpp.com توجه کنید که خیلی از مباحث در وبسایتها ذکر نمیشود، نیاز است بعضی از کتابها را در نظر بگیرید و آنها را عمیقاً مطالعه کنید، بنابراین برای مطالعه به ترتیب سطح مقدماتی و پیشرفته را در زیر عنوان میکنم: Beginning C++ Programming Beginning C++20 A Tour of C++ The C++ Programming Language C++ Primer Programming: Principles and Practice Using C++ کتابهای معرفی شده به استانداردهای ۱۱، ۱۴، ۱۷ و ۲۰ اشاره میکنند. کتابهای پیشنهادی برای سطح پیشرفته: Effective C++ Professional C++ C++ Templates: The Complete Guide – Second Edition Modern C++ Programming Cookbook Hands-On System Programming with C++۱۷ C++ High Performance Optimized C++ در صورتی که نیاز به کسب دانش بیشتر در حوزهٔ سطح پایین، سختافزار، معماری و ساختارهای نرمافزاری دارید کتابهای زیر بسیار مفید هستند: Computer Organization & Design RISC-V / ARM / MIPS / x86 Software Architecture with C++ در صورتی که تجربیات و نوشتههای خودم رو در این باره نیاز دارید به صورت زیر دستهبندی کردم که به ترتیب پیشنهاد میکنم مطالعشون کنید: اگر به دنبال مشاورهها، منابع یا مقالات و توصیههای فارسی یا انگلیسی من هستید، پیشنهاد میکنم در همین وبسایت، یوتیوب، گیتهاب و یا کانال تلگرامی من ملحق بشید. من هر جا که باشم، با شناسهٔ KambizAsadzadeh اگر در حد توانم باشد شما را راهنمایی خواهم کرد.
-
6 امتیازسلام و درود خدمت دوستان عزیز، همانطور که میدانید مهمترین و شاید بزرگترین سوال در حوزهٔ برنامهنویسی این است که من باید کدام زبان برنامهنویسی را انتخاب کنم؟! واقعیت امر این است که این سوال همیشه از سمت علاقهمندان مطرح شده است اما هیچگاه یک پاسخ اساسی در مورد آن ارائه نشده است. البته اساتید و برنامهنویسان حرفهای به خوبی میدانند که زبانهای برنامهنویسی به عنوان ابزارهای کمک کار ما کاربرد دارند و به هیچ عنوان نمیتوان یک زبان را به عنوان اولین و آخرین انتخاب در نظر گرفت، اما شناخت در مورد آنها کمک بسیاری در انتخاب ابزارهای مناسب خواهد کرد. در این پُست من قصد دارم در رابطه با انتخاب یک زبان برنامهنویسی بر اساس نیاز و علایق صحبت کنم تا شما عزیزان بتوانید به یک نتیجهٔ مطلوب برسید. بنابراین، قبل از هر چیز این بسیار مهم است که بدانیم یک زبان برنامهنویسی چیست! و چرا باید از آن استفاده کنیم؟! اجازه دهید نگاهی به دلیل استفاده از زبان برنامهنویسی داشته باشیم، چرا از زبان برنامهنویسی استفاده میکنیم؟ به برقراری ارتباط با یکدیگر فکر کنید، انسان برای برقراری ارتباط با همنوعان نیاز به ابزاری به نام زبان دارد که عناصر اساسی آن حروف است. برای مثال حروف خ-ا-ن-ه با ترکیب شدن به خانه تبدیل شده و شما میتوانید آن را درک کنید و این کدی است که شما توسط آن با جهان بیرون خود ارتباط برقرار میکنید. ممکن است کدهای شما توسط یک زبان دیگر مانند زبان انگلیسی ساخته شود، برای مثال h-o-m-e حرفی است که که نتیجهٔ آن Home خواهد بود. در کشور ما معمولاً زبان مادری هریک از ما فارسی، ترکی (آذربایجانی)، عربی، کردی، لُری و دیگر موارد هستند که به صورت بومی آن را فرا میگیریم و با تسلط بسیاری از آن استفاده کرده و منظور همنوعان خود را درک میکنیم. در بحث کامپیوتر، استفاده از زبان انسانی تا حدی کاربرد دارد که فقط خود انسان آن را درک خواهد کرد نه ماشین! چرا که زبان بومی و اصلی کامپیوتر (ماشین) ۰ و ۱ است نه کاراکتر و حرف! ماشینها برای برقراری ارتباط و درک منظور انسان از واحد ۰ و ۱ استفاده میکنند که مجموعهای از آنها به عنوان دستورالعملهای مشخصی برای کامپیوتر قابل درک است. مغز کامپیوتر یعنی واحد پردازشگر مرکزی (CPU) به عنوان پردازندهٔ مرکزی تمامی دادههای شما را در قالب ۰ و ۱ شناسایی میکند و آنها را درک خواهد کرد. بنابراین زبان بومی ماشین بر خلاف انتظار برای انسان بسیار دشوار است و اگر به فکر این باشید که بخواهید از طریق آن با کامپیوتر ارتباط برقرار کنید شما یک دیوانهٔ تمام عیار بشمار خواهید آمد! اجازه دهید منظورم را سادهتر کنم، کامپیوتر منظور شما را از home درک نخواهد کرد! اما اگر به آن بگویید 01101000 01101111 01101101 01100101 مسلماً خواهد فهمید که منظور شما از آن یعنی home است! حالا اگر منظور شما سلام دنیا باشد باید به کامپیوتر بگویید 01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111 01110010 01101100 01100100 و همینطور برای برقراری ارتباط بیشتر باید هزاران، میلیونها و میلیاردها ۰ و ۱ را با اصول زبان ماشین در کنار هم قرار دهید تا شاید بتوانید یک دستورالعمل ساده برای انجام یک کار را به آن انتقال دهید! احمقانست نه؟! وقت و زمان برای ما انسانها بسیار با ارزش است و مسلماً به هدر دادن آن به این روش هرچند دانش بسیار بالایی از مهندسی کامپیوتر میطلبد اما حتی اگر شما یک دانشمند هم باشید بکار گیری این روش دیوانگی محض است! ما که کامپیوتر نیستیم! ما انسانیم! ساختار کامپیوتر بسیار شبیه به ساختار انسان است، همانطور که خالق انسان، خداوند یکتا او را آفرید به آن نیز هوش و قدرتِ تفکر داد تا بتواند بر اساس آن رشد کرده و در مسیر پیشرفت قدم بردارد، انسان نیز از دانستههای خود برای ساختههایش استفاده میکند. کامپیوترها به عنوان ابزارهای ساخت دست بشر دارای ساختار بسیار ساده ولی در عین حال بسیار پیچیده هستند که انسان برای برنامهریزی آن نیاز به ابزارهایی دارد (ابزارهایی برای ایجاد دستورات قابل درک برای ماشین). ابزارهای برنامهریزی برای کامپیوتر همانطور که اشاره شد، کامپیوترها هیچ درکی از کدهایی که انسان مینویسد ندارند! بنابراین ما نیاز به ابزاری داریم تا منظور خود را برای درک کامپیوتر ارائه دهیم. حال آن ابزار میتواند یک مفسر (Interpreter) باشد یا یک کامپایلر (Compiler) ! هر دوی این ابزارها وظیفهٔ دریافت زبان سطح بالا (نزدیک به زبان انسان) و تبدیل (ترجمهٔ آن) به زبان ماشین است. با تفاوت اینکه مفسرها کدهای نوشته شده را خط به خط تفسیر کرده و آنها را برای پردازنده اجرا میکند، در حالی که کامپایلر تمامی کدها را به شیء و هر شیء را به کد باینری یکجا ترجمه کرده و هرجا که نیاز بود آنها توسط پردازنده اجرا میشوند. به بیان سادهتر فرض کنید قرار است به زبان روسی صحبت کنید، شما دو روش خواهید داشت: صحبت کردن به زبان روسی به صورت مستقیم استخدام یک مترجم، صحبت با مترجم و ترج گفتههای شما توسط مترجم به طرف مقابل برخی از مزایا و معایب کامپایلر و مفسر نسبت به یکدیگر نکته ۱: مفسرها کدهای نوشته شده را به صورت خط به خط تفسیر و ترجمه میکند اما کامپایلرها آنها را یکجا ترجمه میکند که دارای یک خروجی مانند یک فایل اجرایی است. نکته ۲: برنامهٔ تولید شده تحت کامپایلر توسط سخت افزار (ماشین واقعی) اجرا میشود در صورتی که برنامهٔ تولید شده با مفسر توسط نرمافزار (ماشین مجازی) اجرا میشود. نکته ۳: کامپایلرها عملیات بهینهسازی یا همان (Optimization) را در آخرین مرحله از کامپایل (ترجمه) انجام میدهند، در صورتی که مفسرها عملیات بهینه سازی را در زمان تبدیل انجام میدهند. نکته ۴: سرعت اجرای کدهای کامپایل شده بسیار بیشتر از کدهای تفسیر شده است. برای مثال اگر حلقهای را در نظر داشته باشید که قرار است ۱۰ بار اجرا شود، آن حلقه در حالت مفسر ۱۰ بار تفسیر شده و ۱۰ بار توسط پردازنده اجرا خواهد شد! در حالی که در حال کامپایل شده حلقه یک بار ترجمه میشود و نتیجهٔ آن یک بار توسط پردازنده در زمان نیاز اجرا میشود! این بسیار مهم است و در پردازشهای بسیار بزرگ سرعت برنامههای کامپایل شده به شدت بالاتر از تفسیر شدهها است. نکته ۵: کدهای تولید شده توسط مفسر سطح بالاتری نسبت به کدهای تولید شده توسط کامپایلر دارند در واقع آنها تقریباً قابل خواندن هستند اما کدهای تولید شده توسط کامپایلر غیر قابل خواندن است. نکته ۶: امنیت برنامههای کامپایل شده و همچنین دسترسی به منابع کد آنها از امنیت بیشتری نسبت به برنامههای تحت مفسر دارند. نکته ۷: برنامههای تفسیر شده وابستگی خاصی به سیستمعامل ندارند و در هر جایی که برنامهٔ تفسیر کننده موجود باشد اجرا خواهند شد، در صورتی که برنامههای کامپایل شده برای هر نوع سیستمعامل متفاوت باید مجدداً کامپایل شود که البته برای اجرای آن نیازی به نصب بودن کامپایلر بر روی سیستمعامل نیست. نکته ۸: کامپایلر کد برنامه را به صورت کامل به کُد ماشین ترجمه میکند، بنابراین زمان اجرای آن بسیار کم تر است و انتخاب بسیار خوبی برای دوستداران سرعت است. نکته ۹: استفاده از زبانهای مفسری برای توسعهدهندگان مبتدی آسانتر از نوع کامپایلری میباشد بنابراین یادگیری و استفاده از این نوع زبانها نسبتاً سریعتر و راحتتر از نوع کامپایلری است. فرایند توسعهٔ نرمافزار در این فرایند کامپایلر برنامه را میسازد سپس همه دستورات زبان را از نظر صحت تجزیه و تحلیل میکند و اگر دستوری غلط باشد، اخطار میدهد. در صورتی که خطایی وجود نداشته باشد همهٔ کدها را به کد ماشین تبدیل میکند که در نهایت فایلهای مختلفی را به برنامه اجرایی اضافه میکند و در نهایت برنامه را اجرا میکند. در حالی که مفسر برنامه را میسازد اما، فرایند افزودن فایل اجرایی به برنامه یا تولید کدهای ماشین وجود ندارد بلکه دستورات کد منبع خط به خط در حین زمان اجرا یا به اصطلاح Run-time اجرا میکند. کدام زبان در چه حوزهای کاربرد دارد؟ با توجه به تعاریف بالا نوبت آن رسیده است تا زبان برنامهنویسی مورد نظر خود را بر اساس نیاز و قابلیتهایی که آن در اختیار توسعهدهنده قرار میدهد انتخاب کرد. حوزههای کاربردی زبانهای برنامهنویسی متناسب با کاربرد و رسالت آنها مشخص میشود، به طور کلی زبانهای برنامهنویسی را بهتر است به دو دستهٔ اصلی و فرعی جدا کنیم. در دستهٔ اصلی زبانهایی که پایه و اساس کتابخانهها، نرمافزارهای عظیم، انجینها و همچنین خود زبانهای برنامهنویسی میباشند را زبان مادر و اصلی و تمامی زبانهایی که به عنوانی جهتِ مکمل سازی و یا محصول نوع سوم برای اهداف تجاری ساخته شدهاند را فرعی میگوییم. زبانهای اصلی و مادر: C و ++C زبانهای اصلی و فرعی: Python, Java, Delphi, C#, Swift, Objective-C, Php, Rust, JavaScript زبانهای مکمل رابط کاربری: JavaScript, CSS, Xaml, Xhtml, Html, QML زبانهای مکمل بسترهای بلاکچین: C++, Rust و Solidity درنظر داشته باشید کتابخانهها و برنامههای اساسی و پایه که بخش اعظمی از آنها توسط زبانهای سی++ و سی نوشته میشوند در صورت نیاز برای زبانهای دیگر نیز قابل استفاده هستند. به عنوان مثال سیستمعاملها، نرمافزارهای عظیم، انجینهای بازیسازی، کتابخانههای پرکاربرد و مهم همهٔ آنها توسط زبانهای اصلی توسعه یافتهاند اما در صورت نیاز میتواند از کتابخانههای نوشته شده توسط زبانهای اصلی در زبانهای فرعی نیز استفاده کرد. شاید اینطور به نظر برسد که اگر با زبانهای اصلی هر کاری میتوان انجام داد، پس چرا زبانهای دیگر را مورد استفاده قرار میدهیم؟! جواب سوال این است که زبانهای اصلی و مهم نیاز به دانش بسیار از لحاظ معماری سیستمعامل، کامپایلر و دیگر شاخههای علوم کامپیوتر هستند و نحوِ کُدنویسی در آنها نسبت به زبانهای دیگر مانند جاوا، پایتون، سیشارپ و غیره دشوارتر است. بنابراین ممکن است انتخاب اول برنامهنویسان مبتدی نباشند اما کاربرد آنها جنریک (عمومی) است. اشاره به کاربرد زبانهای محبوب در حوزههای مختلف: توسعهٔ زیرساختها: C, C++, Rust, Go توسعهٔ وبسایت: C++, Java, Php, JavaScript, C#, Ruby, Python توسعهٔ نرمافزارهای موبایل: , C++, Java, C#, Objective-C, Swift, JavaScript, Kotlin توسعهٔ نرمافزارهای دسکتاپ: C/C++, Java, Delphi, VB.Net, C#, JavaScript, Objective-C توسعهٔ نرمافزارهای اِمبِد: C/C++, Python توسعهی بازیهای کامپیوتری: ++C و #C توسعهٔ هوش مصنوعی: C++, Python, R, Prolog, Java, Haskell, AIML توسعهٔ رابطکاربری: JavaScript, QML, XAML نکتهٔ قابل توجهی از کاربرد زبانهای اصلی در این است که خود آنها وابستهٔ زبان برنامهنویسی و محدود بر یک حوزه نیستند و به اصطلاح زبان مادر بشمار میآیند که و در تمامی حوزهها کاربرد دارند. کاربرد در صنایع و حوزههای مختلف بر اساس ویژگیهایی که یک زبان برنامهنویسی ارائه میدهد بسیار مهم است. برای مثال Python, R, Prolog و غیره در حوزهٔ هوش مصنوعی و بیگ دیتا بسیار سادهتر به کمک توسعه دهندگان میآید. در توسعهٔ وبسایت زبانهای برنامهنویسی Node.JS, Php, C#, Asp.Net محبوبیت بیشتری دارند. اما میتوان با توجه به این پست وبسایتهای بسیار سریع و بهینهای را توسعه داد که بی شک نیاز به دانش بسیار بالایی دارد و بهتر است در اهداف خاص از آن استفاده شود. در حوزهٔ موبایل در پلتفرم iOS دو زبان Swift و Objective-C به عنوان زبان اصلی پلتفرمهای iOS, tvOS و watchOS به شمار میآیند. در حوزهٔ اندروید (Android) زبانهای Java و Kotlin به عنوان انتخابهای اول توسعهدهندگان مطرح میشند در صورتی که بسیاری از کتابخانههای اندروید تحت C و ++C توسعه یافته و حتی میتواند با استفاده از ++C اپلیکیشن و بازیهای بسیار سریعتری را تولید کرد. در حوزههای صنایع بازیسازی زبانهایی مانند #C نیز کاربرد دارند، اما ترجیح اول و اصلی در این حوزه بکارگیری ++C است چرا که هیچ زبانی به جز آن نهایت سرعت را ارائه نخواهد داد. آمارها و محبوبیتها سالانه طبق گزارش بسیاری از مراجع نمودارها و آمارهایی در رابطه با ایندکس شدن زبانهای برنامهنویسی ارائه میشود که نمونهای از آنها TIOBE است. متاسفانه باید گفت مقایسهٔ چنین مراجع بر اساس ویژگیهایی که در بالا توضیح دادیم صورت نمیگیرد و صرفاً بر اساس محبوبیت بین کاربران گزارش داده میشوند. برتری زبان نسب به زبان دیگر بر اساس چنین آمارهایی اشتباه بوده و توسط آن نمیتوان یک زبان را به عنوان انتخاب اول در نظر گرفت. همچنین اگر دقت کنید مقایسهٔ زبانهای برنامهنویسی اسکریپتی با کامپایلری و همچنین زبانهایی مانند SQL در بین آنها وجود دارد که از لحاظ منطقی درست نیست چرا که کاربرد زبانها با یکدیگر متفاوت بوده و ملاک آماری این مراجع فقط استقبال کاربران است. تعاریف و هِدایتهای اشتباه به سمت یک زبان برنامهنویسی متاسفانه مشاهده میشود که در بسیاری از گروهها و سایتهای برنامهنویسی چندین زبان برنامهنویسی را به عنوان بهترین انتخاب معرفی میکنند و دلیل انتخاب آنها را مشاهدهٔ رتبههای آن بر اساس ایندکسهای برخی از مراجع و یا طرفداری بعضی از شرکتها و تعصبات بی هدف است! باید در نظر داشته باشید قدرت و ویژگیهای یک زبان ربطی به محبوبیت آن ندارد. اگر احساس میکنید شرکتها تقاضای متخصص زبان برنامهنویسی خاصی را دارد که تکرار میشود به آن معنی نیست که زبانهای برنامهنویسی دیگر در حال منسوخ شدن یا کنار گذاشتن هستند. ارزش زبان ملاک برتری آن است نه محبوبیتش! به عنوان مثال اگر JavaScript رتبهٔ اول از نظر محبوبیت را دارد به آن معنا نیست که Php در حال منسوخ شدن است! هر زبانی کاربرد خودش را نسبت به اهداف و ویژگیهای خود دارد. آیا زبان ماشین منسوخ شده است؟! خیر! این چه سوالیه!!؟ چنین افکار بیهوده را از ذهن خود بیرون بریزید! تمامی زبانهای کامپایلری به جز نوعهای مفسری در نهایت کدهایشان توسط کامپایلر به زبان ماشین یعنی assembly تبدیل میکنند. مثال زیر کد ++C است: int main() { } خروجی آن به زبان ماشین (Assembly) در کامپایلر GCC به صورت زیر خواهد بود: main: push rbp mov rbp, rsp mov eax, 0 pop rbp ret انتخاب چند-سکویی پیشنهاد میشود یا خیر؟ لازم بذکر است که بدانید، ابزارهای چند-سکوی بسیاری وجود دارند که به شما اجازه میدهند بدون داشتن دانش آنچنانی در رابطه با زبانهای برنامهنویسی متعددِ مخصوص سکوهای هدف محصول خود را توسعه دهید. برخی از آنها عبارتند از Xamarin و یا React Native که متاسفانه به دلیل ساختار نامطلوب تبدیل کدهای نوشته شده نتیجهٔ نهایی آنها آنچنان خوب مانند محصولات واقعی زبان بومی نیستند چرا که کدهای آن مستقم به زبان ماشین ترجمه نمیشوند. اما این بسیار مهم است که بدانید ابزارهای بومی چند-سکویی واقعی انتخاب بهتری برای این امر بشمار میآیند که معروفترین آنها Qt است که به صورت بومی بدون اُفت کیفیت محصول نهایی به شما اجازهٔ توسعه محصول در سکوهای مختلف را میدهد که مسلماً دانش بسیار بالایی از سی++ را میطلبد. در نتیجه اگر به دنبال محصول با کیفیت در حوزهٔ چند-سکویی هستید باید دانش بالایی از ++C داشته باشید. نکته: در نظر داشته باشید زبانهای کامپایلری خود به دو دسته نیز تقسیم میشوند که برخی از آنها به صورت مستقیم کدهای نوشته شده را به کد ماشین ترجمه میکنند و برخی از آنها کد نوشته شده را به یک زبان میانی تبدیل و سپس آن را توسط برنامهٔ مجازی برای ماشین برنامهریزی مینمایند. بهتر است توجه داشته آنها مزایا و معایبی نیز خواهند داشت. زبانهای کامپایلری در دو دستهی بومی (Native) و مجازی (Virtual) کامپایل از نوع بومی روشی است که کدهای نوشته شده را به صورت مستقیم به کُد ماشین ترجمه میکند. کامپایل از نوع مجازی روشی است که کدهای نوشته شده را ابتدا به کُدمیانی (کدمشترک یا همان بایت کُد - Byte Code) در جاوا و زبان میانی (CIL) در Net. تبدیل میکند که خودِ آن شبیه به کُد ماشین است. در این فرایند کد مربوطه توسط کامپایلر مخصوص یعنی JIT (کامپایلری از نوع Just-In-Time) در زمان اجرا توسط سیستمعامل، به دستورالعملهای قابل فهم برای پردازنده تفسیر و اجرا میشود (که این فرایند شبیه به فرایند عملکرد اجرایی مفسرها است). زبانهای بومی (زبانهایی که کد آنها به کد ماشین به صورت مستقیم توسط کامپایلر قبل از اجرای آنها توسط سیستمعامل، ترجمه میشوند که به اصطلاح ahead-of-time (جلوتر از زمان) یا همان AOT نام دارد) مانند: C, C++, Rust, Haskell, Clean, Swift, Go, Fortran, D زبانهای مجازی (زبانهایی که کد آنها توسط یک رابط میانی به زبان مشترک ترجمه میشود) : Java و #C مزایا و معایب زبانهای کامپایلری از نوع کلاس بومی (Native) از سرعت بسیار بالایی برخوردار هستند (دلیل آن ترجمهٔ مستقیم کدها به کد ماشین است) در مقابل بزرگترین مزیتی که زبانهای نوع کلاس مجازی (Byte Code) دارند به خاطر وجود یک برنامهٔ واسط جهت شبیهسازی کدهای ترجمه شده به کد قابل فهم برای پردازنده، اجرا شدن آنها در هر پلتفرم بدون کامپایل مجدد امکان پذیر است که البته این ویژگی خود نیازمند نصب بودن JVM بر روی پلتفرم مربوطه میباشد. در نوع بومی برای اجرا در هر پلتفرم لازم است سورس کدها را برای پلتفرم مقصد کامپایل کنید که نیازی به وجود ماشین مجازی مانند JVM یا برنامهٔ خاصی ندارد. سریعترین زبان برنامهنویسی کدام است؟ شاید پاسخ به این سوال به گونهای تعصبی به نظر برسد، اما واقعیت این است که باید حقیقت را پذیرفت! با توجه به دلایلی که به نوع زبانهای کامپایلری آورده شده است مشخص است که سریعترین نوع زبانهای برنامهنویسی باید در دستهٔ شاخهٔ کامپایلری و کلاس Native قرار گرفته باشند چرا که در این مبحث زبانها کامپایلری (مجازی) و مفسری حرفی برای گفتن ندارند. جهت تثبیت آن مستنداتی از بنچمارکها در این بخش آورده شدهاست. حقیقت این است ++C در بدترین حالت ممکن بدون بهینهسازی کدها و فلگهای خاص حداقل ۲ تا ۴ برابر سریعتر از زبانهای کامپایلری دیگر است! تلخترین حقیقت نیز این خواهد بود که ++C حداقل ۱۰۰ تا ۲۰۰ برابر سریعتر از زبانهای مفسری است! با توجه به تجربیات شخصی در صورتی که نوع کامپایلر Clang باشد سرعت کدها به چند برابر از این نیز خواهد رسید! همچنین باید در نظر بگیرید اگر کدهای شما خارج از اصول استاندارد زبان باشد ممکن است نتایج آن به تساوی و حتی پایینترین حالت ممکن برسد. سخن آخر، برای انتخاب زبان برنامهنویسی و به دست آوردن مهارت در آن و در نهایت تبدیل دانش به یک محصول نرمافزاری، بهتر است بر اساس نوع (کامپایلری یا مفسری بودن)، اهمیت سرعت، ویژگیهای آن و کاربردش در حوزههای مختلف تصمیم بگیرید نه بر اساس تعصب و علاقه. دقت کنید که زبانهای برنامهنویسی ابزارهای برنامهنویسی بوده و هرچقدر جعبه ابزار شما کامل باشد توانایی و مهارت شما در توسعهٔ حوزههای مختلف بیشتر خواهد بود. در صورتی که میخواهید در رابطه با انواع روشهای کامپایل و تفاوتهای کامپایل Native، Cross Compile و JIT آشنا شوید، پیشنها میشود مقاله زیر را مطالعه فرمایید.
-
6 امتیازاصطلاحاتی که بهتر است در مورد C++ مدرن بدانید! داشتم به این فکر میکردم که برخی از مبتدیان برنامهنویسی به خصوص کسانی که به سراغ زبانهایی مثل سی++ میروند معمولاً مستقیم وارد کد نویسی میشوند و به این گمان که آغاز برنامهنویسی یعنی نوشتن یک کد با خروجی «سلام، دنیا»! دریغ از آن که بعضی از موارد مانند «معرفی کامپایلر و انواع آن» و حتی «ساختار برنامههای نوشته شده تحت سیپلاسپلاس» و یا حتی «مدیریت حافظه» را در نظر بگیرند! من معمولاً در مقالات و آموزشهای خودم به این اشاره میکنم که قبل از هر چیز باید با ساختار برنامههای نوشته شدهٔ یک زبان آشنا شد و سپس به بررسی موارد دیگر مانند نحو زبان و یا دیگر ویژگیهای آن. بنابراین، یکی از خطرناکترین عواملی که موجب خونریزی داخلی یک نرمافزار در برنامههای نوشته شده توسط برنامهنویس درC++ میشود عدم مدیریت حافظهٔ اختصاص یافته است که باید بعد از اختصاص یافتن حافظه در زمان معین آن را آزادسازی کند. در صورتی که این کار صورت نگیرد عمل Memory Leak (نَشتِ حافظه) رخ داده است. بسیاری از علاقهمندان بر این باورند که چون سی++ دارای GC یا همان Garbage Collector (زبالهروب) نیست که البته صحیح است! سی++ دارای GC نیست و این امر محدودیت یا نکته ضعف آن هم نیست! سی++ همه چیز را آزادانه در اختیار برنامهنویس قرار میدهد تا خود در زمان مناسب روش مدیریت حافظه را انتخاب کند. در علوم رایانه بازیافت حافظه یا زبالهروبی نوعی مدیریت حافظهٔ خودکار است که عمل مدیریت حافظههای اختصاص یافته شده را به دست میگیرد و اکثر زبانهای برنامهنویسی مانند #C، جاوا و دیگر موارد مشابه به آن مجهز به این ویژگی هستند که البته وجود چنین ابزارهایی میتواند توهمی را ایجاد کند مبنی بر آن که دیگر نیازی به مدیریت منابع نیست، اما در بعضی موارد مدیریت منابع هنوز یک الزام است چرا که منابع آزاد شده هنوز هم دلیل بر نشتِ حافظه هستند. این نشت حافظه زمانی اتفاق میافتد که اشیاء هنوز قابل دسترس از طرف اشیاءای که زنده هستند اما هرگز مورد استفادهٔ دوباره قرار نمیگیرند اتفاق بیافتد. در بسیاری از زبانهای برنامهنویسی این ویژگی وجود دارد که طبیعتاً مدیریت توسط GC راه حل بسیار خوب و بی نقصی نیست. اما با توجه به عدم وجود GC در سی++ اکثراً با روشهای دستی برای مدیریت حافظه میپردازند که رایجترین روش آن استفاده از عمل new و delete در اختصاص دادن و آزادسازی حافظه است. بسیاری از ما با سی++ در دانشگاه و یا دروس مرتبط با مفاهیم اولیه برنامهنویسی آشنا شده ایم، اما معمولاً مفاهیم مربوطه برای نسلهای قبلی و منسوخ شدهٔ این زبان است. بهتر است در نظر داشته باشید که برنامهنویسی مدرن یعنی پیروی از اصول و قوانین جدیدی که در تکامل یافتن یک زبان به کار گرفته میشود. RAII : Resource Acquisition is initialization بنابراین، باید در نظر گرفت مدیریت حافظه از استاندارد ۱۱ به بعد این زبان به روشهای بسیار مدرنتری هوشمند سازی شده است. یکی از بهترین تکنیکهای موجود در هستهٔ زبان اصطلاح Raiiاست. الگوی RAII مخفف «Resource Acquisition is initialization» که به عنوان یک اصطلاح در برنامهنویسی مطرح میشود به صورت یک تکنیک (کنترل تخصیص منابع و آزادسازی آنها) یکی از ویژگیهای اصلی در سیپلاسپلاس است. با قرار دادن چنین کدی دیگر نیاز به فراخوانی آن کد توسط برنامهنویس در مخرب (ویرانگر) نیست و کامپایلر خود این کار را انجام میدهد. به طور کلی این الگو هر شیء را مجبور میسازد تا در زمان مواجه با رفتارهای ناهنجار خود را پاکسازی کند. به طور کلی هنگامی که شما یک شیء را مقداردهی اولیه میکنید، قبل از انجام آن باید منابع مورد نیاز آن را تأمین کنید (در سازنده). هنگامی که یک شیء از محدوده خارج میشود، هر منبعی را که مورد استفاده قرار داده است باید آزاد کند (در مخرب - ویرانگر). نکات کلیدی هرگز نباید یک شیء به حالت نیمه آماده یا نیمه از بین رفته وجود داشته باشد! وقتی که یک شیء ساخته میشود، آن شیء باید در حالت آماده باش برای استفاده باشد. وقتی یک شیء از محدوده خارج میشود، باید منابع اختصاص یافتهٔ خود را در حافظه آزاد کند (کاربر مجبور به انجام کار دیگری نیست). آیا RAII عنوان بدی برای مفهوم این تکنیک است! از نظر خالق سیپلاسپلاس نام بهتر میتواند به صورت زیر باشد: مدیریت منابع مبتنی بر حوزه (محدوده یا دامنه) : Scope Based Resource Management چیزی که تکنیک RAII را نقض میکند چیست؟ اشارهگرهای خام و تخصیص حافظه فراخوانی با کلمهٔ کلیدی new برای دست آوردن یا اختصاص دادن منبع (حافظه). فراخوانی با کلمهٔ کلیدی delete برای آزادسازی منبع (حافظه). اما این مورد به صورت خودکار بعد از خروج از محدوده توسط اشارهگرها صورت نمیگیرد. void rawPtrFn() { // acquire memory resourceNode* n = newNode; // manually release memory delete n; } بنابراین در صورتی که برنامهنویس استفاده از کلمهٔ کلیدی delete را برای آزادسازی حافظه فراموش کند (نشتِ حافظه) رخ میدهد. این عمل کافی است تا تکنیک RAII را نقض کنیم. void UseRawPointer() { // Using a raw pointer -- not recommended. Song* pSong = new Song(L"Nothing on You", L"Kambiz Asadzadeh"); // Use pSong... // Don't forget to delete! delete pSong; } بنابراین، راه حل RAII برای این امر در چیست؟ کلاسی داشته باشید که : حافظه را هنگام مقداردهی اولیه تخصیص دهد. حافظه را هنگام فراخوانی مخرب (ویرانگر) آزاد کند. دسترسی به اشارهگرهای زیرین را امکانپذیر کند. اشارهگرهای هوشمند (Smart Pointers) یک اشارهگر هوشمند یک شیء به سبکِ RAII است که تضمین میکند یک اشارهگر در هر زمانی که مناسب باشد حافظهٔ اختصاص یافته شده را آزاد میکند. به عنوان یک قاعده، برنامههای نوشته شده در سیپلاسپلاس مدرن (پیشرفته) هرگز نباید از اشارهگرهای خام (Raw) برای مدیریت حافظهٔ پویا (مشترک) استفاده کنند. برنابراین، در برنامههای مدرن سی++ به ندرت باید از کلمهٔ کلیدی delete جهت آزادسازی حافظه استفاده کرد. در واقع انجام این روش موجب جلوگیری از نشت حافظه است. این ویژگی اساساً مدیریت حافظهٔ خودکار را ارائه میدهد. زمانی که یک اشارهگر هوشمند دیگر استفاده نمیشود (زمانی که از محدودهٔ خود خارج میشود) حافظهٔ مورد نظر خود را به طور خودکار آزاد میکند.توجه داشته باشید که اشارهگرهای سنتی با عنوان اشارهگرهای خام (Raw Pointer) شناخته میشوند. اشارهگرهای هوشمند را میتواند یک شکل کلی از GC در نظر گرفت؛ نوعی مدیریت خودکار وقتی که دیگر توسط برنامه مورد استفاده قرار نمیگیرند حافظهٔ اختصاص یافتهٔ آن شیء به طور خودکار حذف میشود. در استاندارد ۱۱ سیپلاسپلاس سه نوع اشارهگر هوشمند معرفی شده است که همهٔ آنها در فایل سرآیند <memory> از کتابخانهٔ استاندارد STL معرفی شدهاند. کلاس std::unique_ptr یک اشارهگر هوشمند که دارای یک منبع تخصیص حافظهٔ پویا است. این شیء دارای یک اشارهگر به حافظهٔ پشته است، بنابراین نمیتوان آن را کپی کرد. تنها میتوان آن را جابجا (move) و مبادله کرد. خارج از این بیشتر مانند یک اشارهگر عادی رفتار میکند. { std::unique_ptr<Person> person(new Person("Kambiz")); if (person != nullptr) person->SetLastName("Asadzadeh"); if (person) DoSomethingWith(*person); } اگر دقت کنید، اپراتورهای -> و * اطمینان میدهد که unique_ptr میتواند اکثر اوقات شبیه به یک اشارهگر خام (Raw Pointer) استفاده شود. کاربردهای معمول از unique_ptr که باعث میشود از آن را به یک ابزار واقعی و ضروری تبدیل کند به صورت زیر است: آنها را میتوان با خیال راحت در داخل یک ظرف (Container) ذخیره کرد. هنگامی که به عنوان متغیرهای عضو کلاس دیگر استفاده میشوند، نیاز به حذف صریح در مخرب را از بین میبرند. در واقع نیازی نیست در مخرب کلاس خود شیءای را که حافظهای را به خود اختصاص داده است به صورت دستی آزاد کنید. علاوه بر این، موجب جلوگیری تولید خطاهای احتمالی از طرف کپی عضوها برای اشیاءای که باید حافظهٔ پویا داشته باشد در کامپایلر نیز میشود. آنها امنترین و توصیه شدهترین روشهایی برای انتقال مالکیت انحصاری، یا بازگشت به یک unique_ptr از یک تابع که شیء ای را در پشته ساخته است و یا با انتقال یکی از آنها به عنوان آرگومانی که در تابع میتواند به عنوان مالکیت بیشتر پذیرفته شود. در هر دو مورد، std::move به طور کلی باید مورد استفاده قرار بگیرد، و این انتقال مالکیت را به صورت صریح بیان میکند. انتقال مالکیت از قبل تعیین شده از طرف توابع امضاء شده معلوم میشود. از نشت حافطه جلوگیری میکند. همچنین، یک شیء unique_ptr میتواند حافظهٔ اختصاص داده شده را با استفاده از new[] مدیریت کند: { std::unique_ptr<int[]> array(new int[123]); DoSomethingWith(array.get()); } به طور معمول توصیه میشود که برای ساخت یک unique_ptr از std::make_unique() استفاده شود. کلاس std::shared_ptr شامل یک اشارهگری است که دارای یک منبع تخصیص حافظهٔ پویا با تفاوت اینکه میتواند چندین شیء را به صورت اشتراکی از یک منبع مشترک ردیابی کند. در واقع هنگامی که موجودیتهای متعددی همان شیء اختصاص یافته شده به حافظه را به اشتراک میگذارند، البته این وضعیت همیشه مشهود نبوده و یا ممکن است آن را به یک مالک واحدی اتخصاص دهید. این اشاره گر های هوشمند، شمارندهای از یک رشتهٔ ایمن(thread-safe) برای منبع حافظهٔ مشترک حفظ میکند و در زمانی که تعداد مرجع آن به صفر رسید، حذف میشود. در واقع این زمانی رخ میدهد که آخرین شیء مشترک از آن حذف شود. تابع use_count() نیز تعداد مراجع را بر میگرداند. همچنین مشابه unique_ptr این شیء یعنی shared_ptr میتواند آرایههای پویا را مدیریت کند که این ویژگی از استاندارد ۱۷ به بعد ممکن شده است. چندین شیء از shared_ptr ممکن است دارای همان شیء باشند. اگر یکی از موارد زیر اتفاق بیفتد، شیء از بین رفته و حافظهٔ آن آزاد میشود: آخرین بازمانده از شیء shared_ptr از بین رفته باشد. آخرین بازماندهٔ شیٔ shared_ptr که دارای یک اشارهگر از طریق اپراتور = و یا reset() است تعیین میشود. آنچه که shared_ptr را از unique_ptr متمایز میکند آن است که آنها میتوانند کپی شوند: { auto age = std::make_shared<int>(30); auto aliasAge = age; age.reset(); } کلاسstd::weak_ptr مانند std::shared_ptr است اما با تفاوت آن که شمارندهٔ آن افزایش نمییابد و اختیار شیء را به دست نمیگیرد. درواقع، بعضی اوقات نیاز است هنگام ساخت مخازنی از اشیاءای که به اشتراک گذاشته شدهاند بدانید آن شیء وجود دارد یا خیر. کاربرد آن نیز همراه با shared_ptr معتبر است و اطلاعاتی در بارهٔ اشیائی که توسط shared_ptr به دست گرفته است ارائه میکند. چند مثال در بارهٔ اشارهگرهای هوشمند: { std::unique_ptr<int> p(new int); // شیء p قابل استفاده در داخل حوزه است. } // در این بخش که خارج از دامنهٔ اشارهگر است حافظهٔ اختصاص یافته آزاد میشود. همانطور که مشخص است یک شیء که تحت اشارهگر هوشمند مورد استفاده قرار میگیرد تا زمانی که خارج از حوزهٔ خود قرار نگیرد قابل استفاده خواهد بود. نمونه کد پایین مثالی از نحوهٔ نمونه سازی تحت اشارهگرهای هوشمند است. void UseSmartPointer() { // Declare a smart pointer on stack and pass it the raw pointer. unique_ptr<Song> song2(new Song(L"Nothing on You", L"Kambiz Asadzadeh")); // Use song2... wstring s = song2->duration_; //... } // song2 is deleted automatically here.
-
6 امتیازمراحل ساخت برنامه در زبان سیپلاسپلاس پیش نویس ۰.۶ قبل از هر چیز به اینفوگرافی زیر توجه کنید که مراحل ساخت برنامه در سیپلاسپلاس را نشان میدهد. مقدمهای بر همگردانی (کامپایل) و اتصال (لینک کردن) این سند مرور مختصری در رابطه با مراحل را برای شما فراهم میکند تا به شما در درک دستورات مختلف برای تبدیل و اجرای برنامهٔ خودتان کمک کند. تبدیل مجموعهای از فایلهای منبع و هدر در سیپلاسپلاس به یک فایل خروجی و اجرایی در چندین گام (به طور معمول در چهار گام) پیشپردازنده (Preprocessors)، کامپایل و گردآوری (Compilation)، اسمبلر (Assmbler) و پیوند دهنده (Linker) تقسیم میشود. قبل از هر چیز اگر در محیط توسعهٔ Qt Creator داخل فایل .pro مقدار زیر را وارد کنید، تا بتوانید فایلهای ساخته شدهٔ موقت در زمان کامپایل را مشاهده کنید. QMAKE_CXXFLAGS += -save-temps این دستور اجازهٔ آن را خواهد داد تا فایلهایی با پسوند .ii و .s در شاخهٔ بیلد پروژه تولید شوند که در ادامه به آنها اشاره شده است. تعریف پیشپردازنده پیشپردازندهها (Preprocessors) درواقع دستوراتی هستند که اجازه میدهند تا کامپایلر قبل از آغاز کردن مراحل کامپایل دستوراتی را دریافت کند. پیشپردازندهها توسط هشتگ (#) مشخص میشوند این نماد در سی++ مشخص میکند که دستور فوق از نوع پیشپردازنده میباشد که نتیجهٔ آن در قالب ماکرو (Macro) در دسترس خواهد بود. برای مثال ماکروی __DATE__ توسط پیشپردازندهها از قبل تعریف شده است که مقدار تاریخ و زمان را بازگشت میدهد. بنابراین هرکجا که از آن استفاده شود کامپایلر آن را جایگزین متن خواهد کرد. در شکل زیر مرحلهای که از پیشپردازندهها استفاده میشود آمده است: پیشپردازنده، کامپایل (گردآوری کردن)، لینک (پیوند کردن) و ساخت برنامه اجرایی فرایند تبدیل مجموعهای از فایلهای متنی هِدر و سورس سی++ را «ساخت» یا همان Building میگویند. از آنجایی که ممکن است کُد پروژه در بسیاری از فایلها هدر و سورس سی++ توسعه و گسترش یابدمراحل ساخت در چند گام کوچک صورت میگیرد. یکی از رایجترین موارد در مراحل گردآوری (ترجمهٔ یک کد سیپلاسپلاس به دستورالعملهای قابل فهم ماشین) است. اما گامهای دیگری نیز وجود دارد، پیشپردازنده و لینک (پیوندها) این بخش به طور خلاصه توضیح میدهد که چه اتفاقی در هر یک از مراحل رُخ میدهد. یک کامپایلر یک برنامهٔ خاص است که پردازش اظهارات (دستورات) نوشته شده در یک زبان برنامهنویسی خاص را به یک زبان ماشین که قابل فهم برای پردازنده میباشد تبدیل کند. به طور معمول یک برنامهنویس با استفاده از یک ویرایشگر که به محیط توسعهٔ یکپارچهٔ نرمافزار (IDE) مشهور است توسط زبان برنامهنویسی مانند ++C دستورات (اظهارات) را مینویسد. فایل ایجاد شده با نام (filename.cpp در زبان برنامهنویسی سیپلاسپلاس) شامل محتوایی است که معمولاً به عنوان دستورات برنامهنویسی سطح بالا نامیده میشود. سپس برنامهنویس کامپایلرِ مناسب برای زبان برنامهنویسی مانند سی++ را اجرا میکند و نام فایلهایی که حاوی دستورات هستند را برای کامپایل مشخص میکند که این انتخاب و مشخص سازی توسط IDE به راحتی قابل مدیریت است. پس از آن، کار کامپایلر این است که فایلهای منبع .cpp را جمع آوری کرده و پیشپردازندهها را بررسی کند تا دستورات احتمالی را اجرا نماید که نتیجهٔ این مرحله در فایلی با پسوند .ii ر قالب filename.ii تولید میشود که در این فرایند نیز خط به خط کُدهای موجود در آنها را بررسی میکند تا خطاهای احتمالی نحو (سینتکس - Syntax) بررسی میشود و آنها را به طور ترتیبی به دستورالعملهای سطح ماشین تبدیل کند. توجه داشته باشید که هر نوع پردازندهٔ کامپیوتر دارای مجموعهای از دستورالعملهایِ ماشین خودش است. بنابراین کامپایلر تنها برای سی++ نیست، بلکه برای اهداف و مقاصد خاص هر پلتفرم است. پس کدهایی که توسط پیشپردازنده سیپلاسپلاس به زبان اسمبلی برای معماری مورد نظر در پلتفرم مقصدترجمه شدهاند نتایج آن در فایلی با پسوند .ss در قالب filename.ss قابل نمایش هستند که در حالت عادی قابل رویت نیست. توجه داشته باشید که باید در این مرحله باید مشخص شود برنامه قرار است توسط چه نوع پردازندهای تحتِ چه نوع معماری مونتاژ (اسمبل) شود. برای مثال پردازندهها با انواع معماریهای مختلف وجود دارند که برخی از آنها به صورت x86-x64، x64، ARMv7، aarch64 غیره ... میباشند. شکل یک (کامپایل یک فایل منبع ++C) مرحلهٔ سوم را در نظر داشته باشید که عمل کامپایل فایل سیپلاسپلاس در دو مرحله قبلی یک فایل اجرایی را تولید نمیکند. برنامهای که توصیف شده است، احتمالاً توابعی را در رابطهای برنامهنویسی (API) و یا توابع ریاضی یا توابع مرتبط با I/O را فراخوانی کند که ممکن است شامل فایلهای هدر مانند iostream یا fstream و حتی ماژولهای دیگری که در زبان تعبیه شدهاند را داشته باشد که فایل تولید شده توسط کامپایلر در این مرحله یک فایل شیء نامیده میشود که با پسوند .o به صورت filename.o تولید خواهد شد که علاوه بر دستورالعملهای تبدیل شده به کد ماشین، شامل توابع و دستورالعملهای خارجی نیز میباشد. هرچند در این مرحله دستورات تبدیل به دستورالعملهای قابل فهم توسط پردازنده شدهاند اما فعلاً قابل اجرا نیستند چرا که باید این توابع خارجی افزوده شده را به آن لینک کرد که در مرحلهٔ بعد یعنی مرحلهٔ چهارم اتفاق میافتد. در نهایت مرحلهٔ چهارم فایل با پسوند .o که شامل کدهای تولید شده توسط کامپایلر به زبان ماشین است که پردازندهها میتوانند این دستورات را درک کنند که همراه با کدهای تولید شدهٔ هر کتابخانهٔ دیگری که مورد نیاز است توسط لینکر (لینک شده) و در نهایت جهت تولید یک فایل اجرایی مورد استفاده قرار میگیرند که نوع آن فایل از نوع اجرایی یا در واقع Executable File خواهد بود. شرح کامل فرایند ساخت فایل اجرایی اکثر پروژهها دارای مجموعهای از فایلهای هدر سی++ هستند، که امکان ماژولار شدن در آن را فراهم میکند و مجموعهای از آن میتواند به عنوان بخشهای کوچکی از برنامه محسوب شوند. برای ساخت چنین پروژههایی هر فایل سیپلاسپلاس باید کامپایل شود و سپس فایلهای ساخته شده در قالب شیء (آبجکت) باید همراه توابع و کتابخانههای دیگر لینک (پیوند) شوند. البته هر گام از مراحل کامپایل شامل یک مرحله پیشپردازنده است که دستورالعمل # عمل تغییرات و اصلاحیهها را در فایل متن اعمال میکند. شکل زیر فرایند ساخت چند فایل به صورت همزمان را نشان میدهد: در ادامهٔ این مقاله، مطلبی مرتبط با تنظیمات بیشتر از کامپایلر آمده است که میتوانید آن را مورد مطالعه قرار دهید.
-
5 امتیازاگرچه که زبان برنامهنویسی سیپلاسپلاس به عنوان یک زبان بسیار قدرتمند و قدیمی شناخته شده است، اما کتابخانهٔ استاندارد و پیشفرض آن برخی از موارد واقعاً مهم را به تازگی تعبیه کرده است. ویژگیهایی که در زبانهایی مثل جاوا و یا سیشارپ داتنت سالهاست وجود دارند. به هر حال این ویژگیها در سی++ ۱۷ موجود شدهاند و این یک بهبود و پیشرفت بسیار خوب است. برای مثال ما الآن فایلسیستم استانداردی را در اختیار داریم. این ویژگی به عنوان یک کتابخانه، امکان برای انجام عملیات بر روی سیستمفایلها و اجزای آنها مانند، مسیرها، فایلها و پوشهها را فراهم میکند. کتابخانهٔ فایلسیستم در فایل سرآیند <filesystem> قرار گرفته است که توسط فضای نام مخصوص خود std::filesystem قابل فراخوانی است. به مثال زیر توجه کنید: namespace fs = std::filesystem; استفاده از این کتابخانه بسیار ساده و کاربردی است، بنابراین اگر بخواهیم به سادگی مسیری از یک ریشه را به دست آوریم، کد آن به صورت زیر خواهد بود: #include <iostream> #include <filesystem> namespace fs = std::filesystem; int main() { fs::path p = fs::current_path(); std::cout << "The current path " << p << " decomposes into:\n" << "root name " << p.root_name() << '\n' << "root directory " << p.root_directory() << '\n' << "relative path " << p.relative_path() << '\n'; } فراخوانی کتابخانه، نمونهسازی از کلاس current_path و سپس چاپ نام، ریشه و مسیر مربوطهٔ آن صورت گرفته است. بنابراین این کتابخانه دارای کلاسهای زیر است که توضیح و کاربرد هر کدام را آوردهایم: کلاس path، این کلاس امکان کار با مسیرها را فراهم میکند، در واقع برای نمایش یا مشاهدهٔ یک مسیر از این کلاس استفاده خواهیم کرد. کلاس filesystem_error یک شیء استثناء در اثر سربارگذاری بیشاز حد کتابخانهٔ فایلسیستم ایجاد میکند، در واقع برای مدیریت خطاها کاربردی خواهد بود. کلاس directory_entry برای کنترل ورودی یک مسیر استفاده میشود، برای مثال بررسی وجود یا عدم وجود در زیر مجموعههای این کلاس امکانپذیر است. کلاس directory_iterator یک تکرار کننده از محتوای یک مسیر (دایرکتوری) را ارائه میکند. کلاس recursive_directory_iterator یک تکرار کننده از محتوایت یک مسیر یا زیر مسیرهای آن را ارائه میکند. کلاس file_status نوع فایل و مجوزهای آن را ارائه میکند. کلاس space_info اطلاعات مربوط به فضای آزاد و موجود در سیستمفایل را ارائه میکند. کلاس file_type اطلاعات مربوط به نوع فایل را ارائه میکند. کلاس perms مجوزهای سیستمفایل را شناسایی میکند. کلاس perm_options معانی هر یک از عملیات مرتبط با مجوزها را ارائه میکند. کلاس copy_options معانی عملیات کپی را مشخص میکند. کلاس directory_options معانی عملیات مربوط به مسیر (دایرکتوری) را مشخص میکند. کلاس file_time_type مقادیر زمانی مربوط به فایل را ارائه میکند. هر یک از کلاسهای فوق دارای متدها و توابعی هستند که در مدیریت فایلسیستم بسیار کاربردی و مفید خواهد بود. در کلاس path شما میتوانید با متدهای مفیدی کار کنید، برای مثال کد زیر پسوند یک فایل موجود که در مسیر به آن اشاره میشود را، در صورت وجود ارائه خواهد کرد. fs::path("/foo/bar.txt").extension(); اگر مسیر فوق دارای فایل ذکر شده باشد، مقدار برگشتی آن .txt خواهد بود. و یا اگر نیاز باشد نام فایل را ارائه کند کافی است از متد file_name آن استفاده کنید! به مثالهای زیر توجه کنید: #include <iostream> #include <filesystem> namespace fs = std::filesystem; int main() { std::cout << fs::path("/foo/bar.txt").filename() << '\n' << fs::path("/foo/.bar").filename() << '\n' << fs::path("/foo/bar/").filename() << '\n' << fs::path("/foo/.").filename() << '\n' << fs::path("/foo/..").filename() << '\n' << fs::path(".").filename() << '\n' << fs::path("..").filename() << '\n' << fs::path("/").filename() << '\n' << fs::path("//host").filename() << '\n'; } همچنین جهت مدیریت خطا و دریافت یک کد یا پیغام خطا به کد زیر توجه کنید: try { cout << fs::file_size("path&file"); } catch (fs::filesystem_error &e) { cout << "Error Message = " << e.what() << " with Code : " << e.code(); } در صورتی که خطایی رخ دهد، کد خطا ساطع خواهد شد، جهت نمایش پیام خطا از تابع what و دریافت کد خطا از تابع code استفاده میشود. این مقاله ادامه دارد...
-
5 امتیازمعرفی سیاههی تغییرات (Change Log) سیاههی تغییرات (changelog یا CHANGELOG) اشاره به یک سیاهه یا تاریخچهی تغییراتی دارد که در یک پروژه همانند یک وبسایت اینترنتی یا یک پروژه نرمافزاری اعمال میشوند. یک پروندهی سیاههی تغییرات شامل یک لیستی است از تغییرات قابل توجه برای هر نسخه از یک پروژه. این تغییرات عموماً به عنوان اصلاحات باگها، قابلیتهای جدید و ... در این سیاهه نوشته میشوند. برخی از پروژههای متنباز فایل سیاههی تغییرات را در دایرکتوری سطح بالای کدهای منبع پروژه خود قرار میدهند. هرچند که قرارداد متعارف نامگذاری این فایل ChangeLog است، این فایل گاهی اوقات به صورت CHANGES یا HISTORY هم نامگذاری میشود (باید توجه داشت که NEWS فایل متفاوتی است که تغییرات بوقوع پیوسته از یک نسخه به نسخه دیگر در آن نوشته میشود، نه تغییراتی که از یک کامیت به کامیتی دیگر اتفاق افتادهاند). برخی از نگهدارندههای پروژهها پسوند .txt را هم به انتهای این فایل اضافه میکنند. برخی از سیستمهای نسخهبندی قادر به تولید کردن اطلاعاتی هستند که مناسب قرارگرفتن در یک فایل سیاههی تغییرات است. چرا باید از سیاههی تغییرات جهت حفظ تغییرات استفاده شود؟ برای اینکه کاربران و مشارکت کنندگان به راحتی بدانند که دقیقاً چه تغییرات قابل توجهی بین هر نسخهی انتشار یافته و دیگر نسخهها ایجاد شده است، بهتر است از این اصول پیروی شود. چه کسانی به سیاههی تغییرات نیاز دارند؟ چه مصرفکنندگان و چه توسعهدهندگان، کاربران نهایی نرمافزار، انسانهایی هستند که به آنچه در نرمافزار تغییر پیدا میکند اهمیت میدهند؛ هنگامی که نرمافزار تغییر پیدا میکند، مردم میخواهند بدانند که چرا و چطور این تغییرات اعمال شده است. بنابراین استفاده از این قالب علاوه بر ارائهی ارزشی در بحث تجربهکاربری، در روند توسعه اهمیت بسیاری دارد. چطور میتوانم یک سیاههی تغییرات خوب ایجاد کنم؟ راهنمای اصول سیاههی تغییرات برای انسانها هستند نه ماشین. برای هر کدام از نسخهها باید یک مدخل وجود داشته باشد. انواع مشابه تغییرات باید دستهبندی شوند. نسخهها و بخشها باید پیوند پذیر باشند. آخرین نسخه اول میآید. تاریخ عرضهی هر کدام از نسخهها، نمایش داده میشود. از استاندارد و اصول نسخهبندی معنایی استفاده و آن را رعایت کنید. انواع تغییرات Added برای امکانات جدید. Changed برای تغییر در عملکرد موجود. Deprecated برای امکاناتی که به زودی حذف میشوند. Removed برای امکانات حذف شده. Fixed برای هر نوع رفع خطا. Security در صورت وجود هرگونه آسیبپذیری امنیتی. برای ردیابی تغییرات آتی یک بخش با عنوان Unreleased در بالا نگهدارید، این کار دو هدف دارد: مردم میتوانند ببیند که در نسخههای آینده چه تغییراتی را میتوان انتظار داشت. در زمان انتشار، میتوانید تغییرات بخش Unreleased را به بخش نسخهی جدید منتقل کنید. آیا استانداردی برای سیاههی تغییرات وجود دارد؟ حقیقتاً خیر، هرچند سبکی از گنو و همچنین بخشی از فایل خبر گنو به این مورد اشاره دارند، اما اینها ناکافی میباشند. نام فایل سیاههی تغییرات چه باید باشد؟ میتوانید آن را CHANGELOG.md بنامید. برخی از پروژهها از HISTORY، NEWS و یا RELEASES استفاده میکنند. هرچند مهم نیست که نام فایل نهایی این روند چه چیزی باشد، اما طوری باید باشد که کاربر متوجه هدف فایل تغییرات باشد. یک مثال از قالب صحیح از سیاههی تغییرات # Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ## [1.0.0] - 2017-06-20 ### Added - New visual identity by [@tylerfortune8](https://github.com/tylerfortune8). - Version navigation. - Links to latest released version in previous versions. - "Why keep a changelog?" section. - "Who needs a changelog?" section. - "How do I make a changelog?" section. - "Frequently Asked Questions" section. - New "Guiding Principles" sub-section to "How do I make a changelog?". - Simplified and Traditional Chinese translations from [@tianshuo](https://github.com/tianshuo). - German translation from [@mpbzh](https://github.com/mpbzh) & [@Art4](https://github.com/Art4). - Italian translation from [@azkidenz](https://github.com/azkidenz). - Swedish translation from [@magol](https://github.com/magol). - Turkish translation from [@karalamalar](https://github.com/karalamalar). - French translation from [@zapashcanon](https://github.com/zapashcanon). - Brazilian Portugese translation from [@Webysther](https://github.com/Webysther). - Polish translation from [@amielucha](https://github.com/amielucha) & [@m-aciek](https://github.com/m-aciek). - Russian translation from [@aishek](https://github.com/aishek). - Czech translation from [@h4vry](https://github.com/h4vry). - Slovak translation from [@jkostolansky](https://github.com/jkostolansky). - Korean translation from [@pierceh89](https://github.com/pierceh89). - Croatian translation from [@porx](https://github.com/porx). - Persian translation from [@Hameds](https://github.com/Hameds). - Ukrainian translation from [@osadchyi-s](https://github.com/osadchyi-s). ### Changed - Start using "changelog" over "change log" since it's the common usage. - Start versioning based on the current English version at 0.3.0 to help translation authors keep things up-to-date. - Rewrite "What makes unicorns cry?" section. - Rewrite "Ignoring Deprecations" sub-section to clarify the ideal scenario. - Improve "Commit log diffs" sub-section to further argument against them. - Merge "Why can’t people just use a git log diff?" with "Commit log diffs" - Fix typos in Simplified Chinese and Traditional Chinese translations. - Fix typos in Brazilian Portuguese translation. - Fix typos in Turkish translation. - Fix typos in Czech translation. - Fix typos in Swedish translation. - Improve phrasing in French translation. - Fix phrasing and spelling in German translation. ### Removed - Section about "changelog" vs "CHANGELOG". ## [0.3.0] - 2015-12-03 ### Added - RU translation from [@aishek](https://github.com/aishek). - pt-BR translation from [@tallesl](https://github.com/tallesl). - es-ES translation from [@ZeliosAriex](https://github.com/ZeliosAriex). ## [0.2.0] - 2015-10-06 ### Changed - Remove exclusionary mentions of "open source" since this project can benefit both "open" and "closed" source projects equally. ## [0.1.0] - 2015-10-06 ### Added - Answer "Should you ever rewrite a change log?". ### Changed - Improve argument against commit logs. - Start following [SemVer](https://semver.org) properly. ## [0.0.8] - 2015-02-17 ### Changed - Update year to match in every README example. - Reluctantly stop making fun of Brits only, since most of the world writes dates in a strange way. ### Fixed - Fix typos in recent README changes. - Update outdated unreleased diff link. ## [0.0.7] - 2015-02-16 ### Added - Link, and make it obvious that date format is ISO 8601. ### Changed - Clarified the section on "Is there a standard change log format?". ### Fixed - Fix Markdown links to tag comparison URL with footnote-style links. ## [0.0.6] - 2014-12-12 ### Added - README section on "yanked" releases. ## [0.0.5] - 2014-08-09 ### Added - Markdown links to version tags on release headings. - Unreleased section to gather unreleased changes and encourage note keeping prior to releases. ## [0.0.4] - 2014-08-09 ### Added - Better explanation of the difference between the file ("CHANGELOG") and its function "the change log". ### Changed - Refer to a "change log" instead of a "CHANGELOG" throughout the site to differentiate between the file and the purpose of the file — the logging of changes. ### Removed - Remove empty sections from CHANGELOG, they occupy too much space and create too much noise in the file. People will have to assume that the missing sections were intentionally left out because they contained no notable changes. ## [0.0.3] - 2014-08-09 ### Added - "Why should I care?" section mentioning The Changelog podcast. ## [0.0.2] - 2014-07-10 ### Added - Explanation of the recommended reverse chronological release ordering. ## [0.0.1] - 2014-05-31 ### Added - This CHANGELOG file to hopefully serve as an evolving example of a standardized open source project CHANGELOG. - CNAME file to enable GitHub Pages custom domain - README now contains answers to common questions about CHANGELOGs - Good examples and basic guidelines, including proper date formatting. - Counter-examples: "What makes unicorns cry?" [Unreleased]: https://github.com/olivierlacan/keep-a-changelog/compare/v1.0.0...HEAD [1.0.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.3.0...v1.0.0 [0.3.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.2.0...v0.3.0 [0.2.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.8...v0.1.0 [0.0.8]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.7...v0.0.8 [0.0.7]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.6...v0.0.7 [0.0.6]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.5...v0.0.6 [0.0.5]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.4...v0.0.5 [0.0.4]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.3...v0.0.4 [0.0.3]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.2...v0.0.3 [0.0.2]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.1...v0.0.2 [0.0.1]: https://github.com/olivierlacan/keep-a-changelog/releases/tag/v0.0.1
-
5 امتیازخلاصه تعریفی از زبان برنامه نویسی سیپلاسپلاس (++C) با توجه به پیشرفت و توسعهٔ زبانهای برنامهنویسی، به ویژه ظهور زبانهای جدید که جهت حل مشکلات زبانهای موجود و یا با هدف ایجاد انقلاب و یا سهولت برنامهنویسی، یکی از سوألاتی که مدام به ذهن میآید این است که چه زبانی را باید انتخاب کرد که از لحاظ بُعد علمی، اقتصادی و فنی بهترین انتخاب باشد تا با یک خیال راحت به یادگیری آن بپردازیم. در این مقاله به مزایای این زبان نسبت به دیگر زبانها و همچنین چشماندازی از آیندهٔ زبان اشاره شده است؛ سیپلاسپلاس به عنوان قدرتمندترین زبان برنامهنویسی تا به کنون است که به جرأت میتوان گفت به عنوان یک زبان برنامهنویسیِ غالب بر دیگر زبانهای برنامهنویسی لقب «هیولای زبانهای برنامهنویسی» را به خود اختصاص میدهد. با توجه به ساختار و نقشهٔ راه توسعهٔ خود، هنوز هم به عنوان یکی از پر طرفدارترین و پر کاربردترین زبانهای برنامهنویسی ساخت دست بشر به شمار میرود. آیا تا به حال فکر کردهاید که یک جهان پیشرفتهٔ متکی به فناوری امروز، وابستهٔ چه چیزهایی است و موتور نامرئی آن چیست؟ اخیراً دانشمند بزرگ، همچنین سازندهٔ زبان سی++ «بیارنه استراس تروپ» در یک سخنرانی ۱ دقیقهای به معرفی موتور نامرئی جهان پرداخته است که در این لینک میتوانید از زبان او بشنوید. سیپلاسپلاس با قابلیتهای انواع داده ایستا، نوشتار آزاد، چندمدلی، معمولاً زبان ترجمه شده با پشتیبانی از برنامهنویسی ساختیافته، برنامهنویسی شیءگرا، برنامهنویسی جنریک است. C++ به همراه جد خود C از پرطرفدارترین زبانهای برنامهنویسی تجاری هستند بنا بر این در زیر فلسفهای از این زبان را بیان می کنیم: زبان ++C طراحی شدهاست تا یک زبان عمومی با کنترل نوع ایستا و همانند C قابل حمل و پربازده باشد. زبان ++C طراحی شدهاست تا مستقیماً و بصورت جامع از چندین شیوه برنامهنویسی (برنامهنویسی ساختیافته، برنامهنویسی شیگرا، انتزاع داده، و برنامهنویسی جنریک) زبان ++C طراحی شده است تا به برنامهنویس امکان انتخاب دهد حتی اگر این انتخاب اشتباه باشد. زبان ++C طراحی شده است تا حداکثر تطابق با C وجود داشته باشد و یک انتقال راحت از C را ممکن سازد. زبان ++C از بکاربردن ویژگیهای خاص که مانع از عمومی شدن است خودداری مینماید. زبان ++C از ویژگیهایی که بکار برده نمیشوند استفاده نمیکند. زبان ++C طراحی شدهاست تا بدون یک محیط پیچیده عمل نماید. زبان ++C مورد انتخاب برای ساخت نرمافزارهایی با کارآیی بالا است که به طور «مستقیم» به منابع یا تجهیزات و ابزارهای سیستمعامل دسترسی دارند. بنابراین علاوه بر ویژگی سطحِ بالای این زبان شما را قادر میسازد تا به سطوح پایینتر از یک سیستمعامل دسترسی داشته باشید و این امر موجب میشود از قدرت بسیار بالایی در برنامهنویسی بهره ببرید ، لذا در مقایسه با سایر زبانهای برنامهنویسی شما باید از جزئیات بیشتری اطلاع داشته باشید تا بتوانید برنامهٔ فوق حرفهای خود را تولید کنید. کتابخانهها چه چیزی هستند و در این زبان چگونه است؟ به مجموعههای یکپارچهای از کلاسهای پیاده سازی شده (به صورت فایلهای سرآیند با پیاده سازیهای کد یا اشیای زبان ماشین) که برای برنامهنویسی به کار میروند، یک کتابخانه C++ گفته میشود و یکی از ویژگیهای بارز آن تولید و دسترسی به کتابخانههای بیشمار است. لیستی از این کتابخانههای همراه با توضیحات در لینک زیر آمده است : A list of open source C++ libraries - cppreference.com لیست کامل انواع کامپایلرها : List of compilers - Wikipedia ویژگیهای جدید در ویرایش ۱۱، ۱۴، ۱۷ و ۲۰ چیست؟ زبان C++11 (معروف به C++0x) یک نسخه استاندارد از زبان ++C است که در ۱۲ آگوست ۲۰۱۱ منتشر و توسط ISO جایگزین C++03 شد این نسخه دارای نشان ISO/IEC 14882:2011 می باشد و در تاریخ ۱۸ آگوست ۲۰۱۴ نسخه جدید آن یعنی C++14 منتشر و جایگزین C++11 شد. امکانات اضافه شده به هسته C++ : یکی از وظایف کمیته استاندارد سازی توسعه هسته زبان است.در توسعه فعلی چندین بخش از زبان بهبود یافته که شامل چندنخی (multithreading) ، پشتیبانی از برنامهنویسی عمومی، مقدار دهی اولیه یکنواخت و پیشرفت عملکرد میباشد. ویژگیهای هسته زبان و تغییرات آن به چهار بخش کلی دسته بندی شداند: 1. پیشرفت در عملکرد زمان اجرا (Run-Time) 2. پیشرفت در عملکرد زمان ساخت (Build-Time) 3. پیشرفت در ویژگی ها (قابلیت استفاده) 4. و قابلیت های جدید ویرایش C++ 14 بر روی اشکالزدائی و بهبودهای جزیی استاندارد قبلی یعنی C++11 تمرکز کرده است؛ این زبان در تاریخ ۱۵ می ۲۰۱۳ منتشر و در ۱۵ آگوست ۲۰۱۴ بعد از رای گیری و انجام تغییراتی جزئی استاندارد این زبان منتشر شد. بدلیل این که عموماً تاریخ انتشار این زبان بطور قابل ملاحظهای دیر هنگام بوده است به C++14 گاهی C++1y نیز گفته میشود. همانند استاندارد C++11 که به آن C++0x گفته میشده و قرار بر این بوده که قبل از ۲۰۱۰ منتشر شود (البته تا سال ۲۰۱۱ انتشار به تعویق افتاد). گرچه تمامی کامپایلرها درحال کاربروی C++14 هستند اما هنوز تمامی آن ها از C++14 پشتیبانی نمیکنند. در C++11 و C++14 توابع جدیدی به هسته اصلی زبان و کتابخانه استاندارد آن اضافه شده است که شامل بسیاری از کتابخانههای C++TR1 به استثنای کتابخانهٔ توابع ریاضی ویژه میباشد. ویژگیهای اضافه شده کتابخانه در ویرایش ۱۱ std::move std::forward std::to_string type traits smart pointers std::chrono tuples std::tie std::array unordered containers std::make_shared memory model ویژگیهای اضافه شده به زبان در ویرایش ۱۱ move semantics variadic templates rvalue references initializer lists static assertions auto lambda expressions decltype template aliases nullptr strongly-typed enums attributes constexpr delegating constructors user-defined literals explicit virtual overrides final specifier default functions deleted functions range-based for loops special member functions for move semantics converting constructors explicit conversion functions inline-namespaces non-static data member initializers right angle brackets ویژگیهای اضافه شده به کتابخانه در ویرایش ۱۴ user-defined literals for standard library types compile-time integer sequences std::make_unique ویژگیهای اضافه شده به زبان در ویرایش ۱۴ binary literals generic lambda expressions lambda capture initializers return type deduction decltype(auto) relaxing constraints on constexpr functions variable templates ویژکیهای اضافه شده به کتابخانه در ویرایش ۱۷ std::variant std::optional std::any std::string_view std::invoke std::apply splicing for maps and sets ویژگیهای اضافه شده به زبان در ویرایش ۱۷ template argument deduction for class templates declaring non-type template parameters with auto folding expressions new rules for auto deduction from braced-init-list constexpr lambda lambda capture this by value inline variables nested namespaces structured bindings selection statements with initializer constexpr if utf-8 character literals direct-list-initialization of enums ویژگیهای اضافه شده به زبان در ویرایش ۲۰ concepts designated initializers (based on the C99 feature) [=, this] as a lambda capture template parameter lists on lambdas three-way comparison using the "spaceship operator", operator <=> initialization of an additional variable within a range-based for statement lambdas in unevaluated contexts default constructible and assignable stateless lambdas allow pack expansions in lambda init-capture string literals as template parameters atomic smart pointers (such as std::atomic<shared_ptr<T>> and std::atomic<weak_ptr<T>>) removing the need for typename in certain circumstances new standard attributes [[no_unique_address]] [[likely]] and [[unlikely]] calendar and time-zone additions to <chrono> std::span, providing a view to a contiguous array (analogous to std::string_view but span can mutate the referenced sequence) <version> header feature test macros bit-casting of object representations, with less verbosity than memcpy() and more ability to exploit compiler internals conditional explicit, allowing the explicit modifier to be contingent on a boolean expression constexpr virtual functions ranges (The One Ranges Proposal) concept terse syntax constexpr union, try and catch dynamic_cast and typeid, std::pointer_traits various constexpr library bits immediate functions using the new consteval keyword signed integers are now defined to be represented using two's complement (signed integer overflow remains undefined behavior) a revised memory model coroutines – already experimentally supported in Clang 5 modules – experimentally supported in Clang 5 and Visual Studio 2015 Update 1 as well as GCC various improvements to structured bindings (interaction with lambda captures, static and thread_local storage duration) contracts have been removed (see list of features deferred to a later standard) use of comma operator in subscript expressions has been deprecated constexpr additions (trivial default initialization, unevaluated inline-assembly) using scoped enums various changes to the spaceship-operator DR: minor changes to modules constinit keyword changes to concepts (removal of -> Type return-type-requirements) (most of) volatile has been deprecated DR: [[nodiscard]] effects on constructors The new standard library concepts will not use PascalCase (rather standard_case, as rest of standard library) text formatting (chrono integration, corner case fixes) bit operations constexpr INVOKE math constants consistency additions to atomics (std::atomic_ref<T>, std::atomic<std::shared_ptr<T>>) add the spaceship (<=>) operator to the standard library header units for the standard library synchronization facilities (merged from: Efficient atomic waiting and semaphores, latches and barriers, Improving atomic_flag, Don't Make C++ Unimplementable On Small CPUs) std::source_location constexpr containers (std::string, std::vector) std::stop_token and joining thread (std::jthread) Many new keywords added (and the new "spaceship operator", operator <=>), such as concept, constinit, consteval, co_await, co_return, co_yield, requires (plus changed meaning for export), and char8_t. And explicit can take an expression since C++20. (Most of) the use for the volatile keyword has been deprecated. C++ has added a number of attributes over the years, including new in C++20, [[likely]] and [[unlikely]]; and [[no_unique_address]]. etc... کتابخانههای استاندارد چیست و در نسخههای جدید چگونه در دسترس هستند؟ در زبان برنامهنویسی ++C کتابخانهٔ استاندارد سی++ مجموعهای از کلاسها و رویهها است که در هسته زبان نوشته شدهاند و قسمتی از استاندارد ISO سی++ میباشند. در سال ۱۹۹۸ استاندارد ++C شامل دو بخش هسته زبان و کتابخانه استاندارد ++C است. این کتابخانه شامل بیشتر بخشهای STL و کتابخانه استاندارد C است. بیشتر کتابخانههای ++C در استاندارد وجود ندارند و یا استفاده از تعریف قابلیت پیوند کتابخانهها را میتوان در زبانهایی مانند فرترن، C، پاسکال، بیسیک نوشته شوند. البته با توجه به ویژگیهای کامپایلر مشخص خواهد شد که کدام زبان را میتوان استفاده نمود. کتابخانهٔ استاندارد ++C شامل کتابخانه استاندارد C با یک سری تغییرات برای بهبود عملکرد است. بخش بزرگ بعدی این کتابخانه STL است. STL شامل ابزار بسیار قدرتمندی مانند نگهدارندهها (مانند vector و list)، تکرارکنندهها (اشارهگرهای عمومی شده) برای شبیهسازی دسترسی مانند آرایه الگوریتمهایی برای جستجو و مرتبسازی در آنها وجود دارند. نقشهها (نقشههای چندگانه) (آرایه شرکتپذیر) و مجموعهها (مجموعههای چندگانه) واسطهای عمومی فراهم میسازند. در نتیجه با استفاده از قالب تابع، الگوریتمهای جنریک با هر نگهدارنده و دارای تکرارکننده عمل نماید. همانند C ویژگیهای کتابخانه را میتوان با استفاده از شبه دستور include# شامل یک سرآیند استاندارد اضافه نمود. C دارای ۶۹ کتابخانه استاندارد است که ۱۹ تا از آنها نامناسب تشخیص داده شدهاند. استفاده از کتابخانهٔ استاندارد - مانندstd::vector یا std::string به جای آرایههای C موجب ایجاد برنامههای مطمئن تر شده است. STL در آغاز محصولی جداگانه از HP و سپس SGL پیش از ادغام در کتابخانه استاندارد ++C بودهاست. استاندارد عبارت STL را بکار نمیبرد بلکه آن را بخشی از کتابخانه میداند اما مردم هنوز هم آن را برای جداسازی بخشهای مختلف کتابخانه با این نام بکار میبرند. (جریانهای ورودی/خروجی، جهانیسازی، تشخیص، زیرمجموعه کتابخانه C) بیشتر کامپایلرها کتابخانه استاندارد و STL را پیادهسازی مینماید. پیادهسازیهای مستقلی نیز همانند STLport نیر وجود دارند. پروژههای دیگر نیز پیادهسازیهای خود را از STL با توجه به اهداف خود بوجود میآورند. روش جدیدی جناب بیجارن در نظر گرفته که کتابخانه های استاندارد ++C علاوه بر اینکه توسط خود کامپایلرها در دسترس و قابل استفاده هستش بلکه توسط کتابخانه STL و Boost نیز می توان دسترسی به مجموع عظیمی از کتابخانه ها استاندارد ISO داشت. ساختار فایلها در این زبان چگونه است؟ در رابطه با ساختار برنامه های نوشته شده توسط ++C بدانید که منظور از ساختار در اینجا انواع فایل های موجود در زبان سیپلاسپلاس است، در این رابطه باید اینگونه اشاره کنیم که در این زبان ما می توانیم از فایل های زیر برای برنامه نویسی استفاده کنیم. فایل با پسوند .c این فایل منبعی برای کد هایی از نوع زبان C هستند. فایل با پسوند .c++ منبعی برای کد هایی از نوع زبان C و ++C هستند ضعف این نوع فایل در قابل حمل نبودن و عدم شناسایی توسط فایل سیستم ها می باشد. فایل با پسوند .cxx منبعی برای کد هایی از نوع زبان C و ++C هستند با تفاوت اینکه نسبت به فایل .c++ قابل حمل تر است. فایل با پسوند .cpp منبعی برای کد هایی از نوع زبان C و ++C هستند یعنی در هر دو نیز قابل استفاده می باشند. این پسوند با تمامی سیستم ها سازگاری دارد و بسیار رایج است. فایل با پسوند .hxx معمولا فایل با عنوان (هدر/سرصفحه) یاد می شوند و معمولا فقط حاوی اعلان ها میباشند. فایل با پسوند .hpp معمولا فایل با عنوان (هدر/سرصفحه) یاد می شوند و معمولا فقط حاوی اعلان ها میباشند. این فرمت توسط مارس دیجیتال استفاده می شود. همچنین بورلند و دیگر کامپایلر های سی++ از آن پشتیبانی میکنند. ممکن است در این فایل متغیر ها، ثوابت و توایعی که در فایل منبع اصلی به آن ها اشاره شده است اعلام شود. فایل با پسوند .h معمولا فایل با عنوان (هدر/سر صفحه) یاد میشوند و معمولا فقط حاوی اعلان ها میباشند این نوع بسیار رایج است و تقریبا با تمامی سیستم ها سازگاری دارد. فایل با پسوند .hh در این زبان: فایل با عنوان (هدر/سر صفحه) یاد می شوند و معمولا فقط حاوی اعلان ها میباشند. فایل با پسوند .h++ در این زبان: این نوع فایل ها معمولا فایل با عنوان (هدر/سرصفحه) یاد میشوند و معمولاً فقط حاوی اعلان ها میباشند. ضعف این نوع فایل در قابل حمل نبودن و عدم شناسایی توسط فایل سیستم ها میباشد. فایل با پسوند .ixx در استانداردهای جدید جهت تعریف سند ماژول (اختصاصاً برای کامپایلرهای MSVC) معرفی شده است. همچنین فایل با پسوندهای cppm، ccm، mxx، cxxm و c++m به عنوان پسوندهای جدیدی در رابطه با خاصیت ماژول از استانداردهای جدید برای کامپایلرهای مدرن هستند. یک فایل سرآیند با پسوند (.h, .hpp و ...) میتواند شامل محتوای زیر باشد: تعریف کلاس تعریف توابع درون خطی (Inline) اعلام تابع اعلام شیء مثال: #ifndef CPPFILES_H #define CPPFILES_H extern int status; class CPPFiles { public: CPPFiles(); void myFunction(); inline int safe(int i); }; #endif // CPPFILES_H یک فایل منبع - سورس با پسوند (.c, .hpp، .cxx و ...) میتواند شامل محتوای زیر باشد: تعریف کلاس تعریف توابع اعلام شیء مثال : #include "cppfiles.h" int status = 1; CPPFiles::CPPFiles() { } void CPPFiles::myFunction() { //Do somthing... } int CPPFiles::safe(/*@Param*/) { return /*Somthing...*/; } انواع فایل هایی که به آنها اشاره شد بسیار است ولی متناسب با محبویت و پشتیبانی کامپایلر ها از این فایل ها در این زبان برای انتخاب آنها مهم است بنا بر این در طی آموزش و تمامی مراحل ما فقط از فایل های .h برای هدر و فایل های .cpp برای منابع استفاده خواهیم کرد. چرا و چه زمانی باید از فایل های hpp. و چه زمانی از فایل های cpp. استفاده کنیم؟ توجه داشته باشید که سیپلاسپلاس از تمامی پسوند فایلهای مذکور پشتیبانی میکند، معمولاً استفاده از فایلهای hpp و h جهت اعلان و تعریفهای اولیهٔ کدها مناسب است و در زمان تعریف کامل عملکرد کد مورد نظر فایل با پسوند cpp پیشنهاد میشود. هرچند استفادهٔ غیر استاندارد نیز پشتیبانی میشود اما باید توجه داشت جهت حفظ ساختار استاندارد روشهای اصولی منطقی و صحیح هستند. کاربرد این زبان در کجاست؟ معمولاً تمامی برنامهها و نرمافزارهایی که به صورت روزمره در زندگی مدرن امروزی مشاهده میکنیم بدون شک توسط زبان های اساسی نوشته شدهاند. به عنوان مثال انواع صنایع موجود در کشورها از قبیل صنعت خودروسازی، صنعت فضایی، سیستمهای معماری و بانکی ، تجهیزات مدرن و سختافزارهای رباتیک، سیستمهای کامپیوتری و یا کنسول هایبازی ، سیستمهای خانگی و یا هوش مصنوعی، تجهیزات مجهز به انواع حسگرها، پزشکی، فضایی، زبانهای برنامهنویسی، سیستمعاملها و بسیاری از موارد دیگری که میتوان نام برد بدون شک توسط این زبان پیاده سازی شدهاند. چگونه C++ میتواند در لایه های زیرین (سطح پایین) و بالا (سطح بالا) مورد استفاده قرار بگیرد؟ به نقل از سازندهٔ آن، این زبان هر دو ویژگی سطح بالا و سطح پایین را ارائه میکند. سیپلاسپلاس دارای بخشهای سطح پایین است، مانند اشارهگرها، آرایهها و کستها. این ویژگیها تقریباً مشابه همان ویژگی C هستند که ارائه شده است و برای کار با کارهای سختافزاری ضروری هستند. بنابراین اگر میخواهید به امکانات سطح پایین زبان دسترسی داشته باشید، بله سیپلاسپلاس مجموعهای از این امکانات را در اختیار شما قرار میدهد. با این حال، اگر نمیخواهید از ویژگیهای سطح پایین استفاده کنید، نیازی به استفاده از آنها به صورت مستقیم در این زبان نیست. در عوض میتوانید از امکانات سطح بالا از جمله کتابخانههای آن را مورد استفاده قرار دهید. به عنوان مثال اگر نمیخواهید از اشارهگرها و آرایهها استفاده کنید میتوانید از رشتهها و نگهدارندههای استاندارد استفاده کنید که به مراتب گزینههای بهتری هستند. آیا سیستم عامل ها و نرم افزار های مطرح دنیا توسط این زبان نوشته شده اند؟ دلیل آن چیست؟ همانگونه که مشخص است بسیاری از سیستم عامل ها از ابتدا توسط خانواده اسمبل ، C نوشته شده اند که به صورت زیر به تعدادی از آن ها اشاره میکنیم: DragonFlyBSD,FreeBSD,OpenBSD,NetBSD HP-UX Centos,Debian,Fedora,OpenSUSE,RedHat,Ubuntu OSX,iOS,Darwin OracleSolaris,OpenIndiana Cygwin Android Windows Phone BlackBerry WindowsXP,Vista,7,8,10 دلیل آن که از زبان هایی مانند C و ++C برای نوشتن سیستمعامل استفاده میشود قابلیت های مهم آن است به عنوان مثال: کارآیی بالا ، مستقل از سکو، زبان پاسه و غالب بودن و عدم وابستگی آن به زبان های دیگر، ارتباط با سختافزار و تمامی دیوایسها، مدیریت هوشمندانه و همچنین برنامهنویسی آزادانه ، دسترسی به لیست عظیمی از کتابخانهها که میتوان توسط آن ها هر چیزی را که در رویاهای خود به آن فکر میکنید در واقعیت خلق کنید. انواع سخت افزارهایی که این زبان پشتیبانی میکند: زبان برنامهنویسی سیپلاسپلاس با استفاده از کامپایلرهای قدرتمندی چون GCC، Clang و غیره، طیف گستردهای از سختافزارها و معماریها را پشتیبانی میکند. مدل ماشین هایی که پشتیبانی میشود : PowerPC , Oracle,Fujitsu,Sun, IBM,Freescale , AMD,Intel مدل پردازندهها: Athlon,Atom,Core,Core2,Corei3/i5/i7,Opteron,Pentium,Phenom,Sempron,Turion,etc Itanium,Itanium2,Itanium29000/9100/9300,etc PowerPC,POWER1/2/3/4/5/6/7,G1,G2,G3,G4,G5,etc UltraSPARCI/II/III/IV/T1/T2,SPARCT3/T4,etc کاربرد این زبان در زمینه وب چگونه است؟ در این زمینه معمولاً به دلیل وجود چهارچوبها و زبانهای سادهتری نسبت به سی++ در حوزهٔ وب مانند Php و غیره...، معمولاً فرصت نشده است تا به شناخت کتابخانهها و مزایای این زبان در این حوزه پرداخته شود. با توجه به توسعههای اخیر صنعت وب دانشمندان به این نتیجه رسیدهاند که جهت افزایش کارایی در زمینهٔ وب و از بین بردن محدودیتهای وابسته به مرورگرهای اینترنتی، از فناوریهای بهتری مانند wasm نیز پرده برداری شود که در این فناوری سی++ گزینهٔ پشت پردهای از این فناوری محسوب میشود که اجازه میدهد با اجرای کدها و دسترسی به رابطهای برنامهنویسی پیشرفته یک دنیای جدیدی از فناوری وب را ارائه کند. این فناوری با عنوان Web Assembly شناخته میشود که اجازه میدهد برنامههای نوشته شده توسط سی++ در مرورگر به عنوان یک پلتفرم جدید اجرا شوند. البته این تنها روش نیست، سی++ به لطف کتابخانههای عظیم خودش قادر است هر چیزی را در اختیار برنامهنویس قرار دهد. به عنوان مثال دسترسی به کتابخانههای عظیم Qt، Wt این امکان را فراهم میکنند که به راحتی یک سیستم ابر پیشرفتهٔ تحت وب را به کمک این زبان پیاده سازی کنید که هیچ نوع سیستم موجود در وب قابل رقابت و مقایسه با ویژگیها و نتایج خارقالعادهٔ آن نخواهد داشت. در مثال زیر یک سیستم مدیریت محتوا به صورت آزمایشی پیاده سازی شده است که میتوانید نتایج خارقالعادهٔ آن را مشاهده کنید. همچنین توجه کنید که این تنها کاربرد سی++ در وب نیست، حقیقت آن است که وبسایتهای بزرگی همچون فیسبوک، گوگل و غیره هستهٔ وبسایتهای خود را توسط این زبان توسعه دادهاند که دلایل آنها مصرف بهینهٔ تجهیزان سختافزاری و دسترسی به ویژگیهای سیستمی بسیار زیاد و امنیت بسیار بالا است. احتمالاً در رابطه با موتور قدرتمند v8 Engine شنیدهاید، این یک موتور اساسی برای محصولات گوگل است که کاملاً تحت سی++ توسعه یافته است. برخی از محیطهای برنامهنویسی مانند Node.JS تحت آن قدرت گرفتهاند. برخی از محصولات اساسی و معروف که بخش عمده و یا به صورت کامل توسط سیپلاسپلاس نوشته شدهاند (این لیست تنها شامل برجستهترین محصولات است) : سیستمعاملها ویندوز مکینتاش لینوکس آیاواس اندروید مرورگرها اُپرا فایرفاکس گوگل کروم مایکروسافت اِدج اپل سافاری نرمافزارهای کاربردی و مهندسی تمامی محصولات قدرتمند Adobe مانند فوتوشاپ، افترافکت و غیره... تمامی محصولات Autodesk مانند Maya، 3dsMax و Autocad مجازیسازها مانند Virtual Box و VMware محصولات مایکروسافت مانند Visual Studio و Office محصولات اپل مانند iTunes، Xcode و غیره... بازیها و صنایع مرتبط توسعهٔ کنسولهای بازی Playstation و Xbox اکثر بازیهای خارقالعاده در سطح AAA پیامرسانها تلگرام اسکایپ موتورهای دیتابیس مانند MySQL و غیره... کتابخانهها و ابزارهای پیشرفتهٔ توسعه ابزارهای مرتبط با فناوریهای روز مانند Blockchain و غیره... زبانهای برنامهنویسی مانند Swift و غیره... راهاندازها و ابزارهای قدرتمند AMD، Intel و NVIDIA Geforce و پلتفرمهایی مانند Cuda. و هزاران و میلیونها ابزار و برنامههایی که در زندگی روزمره با آنها سرو کار داریم. اشاره ای بر انواع موتور های دیتابیس که توسط ++C پشتیبانی میشوند : SQL NoSQL SQLite MySQL Sybase Adaptive Server SQL Server Oracle PostgreSQL IBASE : Borland IBM DB2 متأسفانه به دلیل عدم اطلاع و شناخت کافی از حقایق این زبان، توصیه برای یادگیری زبانهایی مانند Java و #C و مشابه آنها ممکن است بر اساس علاقههای فردی و تعصب باشد. بنابراین توصیه میشود حتماً در مورد تفاوتهای ساختاری و مزایای زبانها حتماً تحقیق شود. چگونه باید طراحی رابط کاربری را انجام دهیم؟ برای طراحی رابط گرافیکی ابتدا باید ذهن خود را از محیط VS و همچنین کنسول کنار بکشید لذا برای این کار کتابخانه های مخصوصی در نظر گرفته شده است به صورت زیر: FLTK nana WxWidgets OWLNext GTK+ glibmm gtkmm goocanvasmm libglademm libgnomecanvasmm webkitgtk flowcanvas evince Qt libdbusmenu-qt توسط این کتابخانه های میتوان محیطهای کاربری را فراهم ساخت. در این میان دو کتابخانهٔ wxWidgets و Qt بسیار قدرتمند عمل کردهاند که بین این دو نیز Qt با قدرت بسیار زیادی از رقیب خود یعنی wxWidgets پیشی گرفته است و معمولاً پروژههایی که در آن رابطکاربری خلاقانه (Creative) و مدرن مطرح است حرف از Qt به گوش میرسد (کیوت یک چهارچوب جامع جهت طراحی رابطهای کاربری قدرتمند است). پیشنهادات ما استفاده از مقالات خارجی و منابع رسمی میباشد: http://en.cppreference.com/w Learn C++ https://www.learn-cpp.org Learn C++ (Introduction and Tutorials to C++ Programming) http://www.cplusplus.com نگاهی به کاربرد این زبان در بین فناوریهای جدید! سیپلاسپلاس همچنین به عنوان یکی از قدرتمندترین و محبوبترین زبانهای برنامهنویسی در دنیای فناوری شناخته میشود و در صنعت بلاکچین نیز یک قدرت غالب است. زبان شیءگرایی برای توسعه بلاکچین مناسب است، زیرا از همان اصول کپسولهسازی، انتزاع، چندریختی و مخفی کردن دادهها استفاده میکند. به عنوان مثال بلاکچین از ویرایشهای ناخواسته از دادهها جولوگیری میکند که به عنوان یکی از چهار زبان برنامهنویسی آینده دار میتوان به آن اشاره کرد. همچنین توجه داشته باشید که فناوریهای دیگری مانند مباحث Cross-Platform و رشد بسیار شدید فناوری IoT این زبان به عنوان یک زبان پیشتاز در این حوزه است که در کنار بسیاری از کاربردهای اساسی خود میتوان به عنوان یک ابزار اساسی و کاربردی به آن در آیندهای که از همین حالا شروع شده است اشاره داشت. آیا با ++C میتوان برنامههای موبایلی مانند Android , iOS و غیره را تولید کرد؟ پاسخ، بله! متأسفانه این مورد هم مانند حوزهٔ وب به خاطر عدم شناخت و تبلیغات کافی از ذهن بسیاری از افراد به یک گزینهٔ بی اهمیت تبدیل شده است، اما با توجه به رشد روز افزون و ایجاد ابزارهای ضعیف، نیاز به شناخت این زبان و ابزارهای واقعی و قدرتمند آن الزامی شده است. برای مثال در حوزهٔ موبایل ابزارهایی مانند Xamarin و یا Flutter این روزها سرو صدای بسیاری کردهاند، اما واقعیت این است، آنها هیچگاه نتیجهٔ واقعی و مشابه به زبانهای پیشفرض پلتفرمهای توسعه را ندارند و نخواهند داشت. فناوری چند-سکویی به معنای واقعی تنها در ابزارهایی مانند Qt Framework و سی++ خلاصه میشود که به شما اجازهٔ تولید و توسعهٔ کدهای خود را به صورت بومی در پلتفرم هدف فراهم میکند. پیشنهاد ما در رابطه نحوه شروع برای یادگیری و آشنایی با زبان و انواع کتابخانه ها به صورت زیر است: قبل از هر چیز هدف خود را در رابطه با منابع مشخص نمایید، اگر زبان انگلیسی شما خوب است میتوانید در همین قدم اول از منابع رسمی و استاندارد که بی نقص هستند استفاده کنید. سعی کنید اگر قرار است این زبان را یاد بگیرید عملا با آن درگیر شوید. از مقدمات برنامه نویسی شروع کنید و حتما در رابطه با تاریخچه زبان و اهداف آن تحقیق کنید. شرکت و سازمان های بزرگ و موفق را الگو قرار دهید. اگر هدف شما سریع رسیدن به پول بدون در نظر داشتن کیفیت و اهداف بزرگ از پروژه هستش به هیچ عنوان سراغ این زبان نروید زیرا C++ برنامه نویس مشتاق به حرفهای شدن را میطلبد نه برنامهنویس راحت طلب. حتماً سیپلاسپلاس مدرن را بیآموزید. استانداردهای مدرن شامل نسخههای ۱۱، ۱۴، ۱۷ و ۲۰ هستند. برای استفاده و کار با کتابخانههای این زبان بهتر است کتابخانههای پیشفرض STL را به خوبی یاد بگیرید. برای توسعه هرچه بیشتر پروژه و استفاده از انواع قابلیتها توسط این زبان میبایست از کتابخانههای دیگر استفاده کنیم که در این میان در رابطه با بخش طراحی و رابط کاربریQt، GTK, MFC, SDL , wxWidgetsمناسب است که پیشنهاد ما در میان این لیست (Qt) خواهد بود که تحت آن میتوان مدرنترین طراحی ها را خلق نمود. برای کار با شبکه کتابخانههای Curl, Poco, Qt, RakNet, ReplicaNet, SDL موجود هستند و در بین اینها Curl بهترین گزینه میتواند باشد. برای کار با 3D بعدی کتابخانه مخصوص OpenGL یا باز همان Qt را که بر پایه موتور OpenGL است پیشنهاد میکنیم و یا میتوانید از کتابخانه های مخصوص DirectX و OpenGL و حتی نسخههای توسعهٔافته به نام Vulkan را به صورت تخصصی استفاده یاد بگیرید. در رابطه با 2D نیز از OpenGL، Direct2D, GDI و GDI+ میتوان استفاده کرد. در مورد Sound از کتابخانه های مطرح OpenAL, Fmod و Bass استفاده کنید. در مورد بحث فیزیک کتابخانه های Nvidia Physix, Nvidia Apex, Bullet, Box2D, ODE, Open Dynamics در رابطه با هوش مصنوعی کتابخانه های OpenAI, FEAR, OpenSteer, PathLib مطرح هستند. برای کار با پردازش تصویری OpenCV, OpenNI پیشنهاد میشود. برای کار با پردازش موازی OpenCL, OpenML, CUDA مناسب است. برای اسکریپت نویسی Lua, LuaPlus, Phyton برای کار با ورودی ها از OpenInput, Qt, SDL, SFML میتوان استفاده کرد. برای بازی سازی کتابخانه های Unreal Engine, OGRE, Irrlicht, KGE مناسب هستند که در بین اینها Unreal Engine بسیار قدرتمند عمل میکند. برای طراحی و اجرای وب سایت کتابخانه های WebKit, ClearSilver, Teng مناسب هستند. برای توسعهٔ ابزارهای مرتبط با فناوری بلاکچین، میتوان به کتابخانههای قدرتمند و خارقالعادهای به نام EOS اشاره کرد. لازم بذکر است اینها نمونهای از کتابخانههای بیشمار سی++ هستند و میتوان به کتابخانههای بسیاری اشاره کرد که خارج از گنجایش این مقاله است. منابع فارسی برای یادگیری سیپلاسپلاس مدرن چیست؟ متأسفانه منابع فارسی برای این زبان معمولاً متعلق به مباحث دانشگاهی و مفاهیم مرتبط به سیپلاسپلاس سنتی است (مربوط به ۳۰ سال پیش)! یادگیری این مباحث هیچ مزیتی برای شما نخواهد داشت و به شدت پیشنهاد میشود جهت یادگیری این زبان حتماً به سراغ آموزشهای مدرن بروید. تنها بسترهای آموزشی مربوط به سیپلاسپلاس جدید در ایران (به زبان فارسی) مرجع آیاواستریم است.
-
3 امتیازبا سلام و درود، همهٔ ما میدانیم که امروزه کسبوکارهای اینترنتی و وابسته به فناوریهای مبتنی بر نرمافزار، یکی از حوزههایی به شمار میرود که در چهارچوب خود میتوانند پیشرفت بسیار چشمگیری داشته باشند. بنابراین، هر فردی که ایدهای در ذهن خود برای خلق یک کسبوکار دارد میتواند وارد این حوزهٔ «کسبوکارهای» اینترنتی شود. در این مقاله من به عناوین زیر اشاره خواهم کرد: گفتگوی صمیمانه و آزاد «مشاوره و ارزیابی مسائل» واقعیتهایی که مشتریان از آنها آگاه نیستند مشتری را برای مقایسه و دیدن نمونههای واقعی تشویق کنید معرفی و توصیف ابزارهایی که از آنها برای تولید و توسعه استفاده میکنید صداقت شما و تضمین وفاداری مشتری قرارداد، ارزیابی هزینهها و زمان توسعه مشاورهٔ رایگان یا پولی چگونه از دیگر برنامهنویسان و توسعهدهندگان متمایز و به یک برنامهنویس واقعی و حرفهای تبدیل شویم؟ بهروز باشید و از رفتارهای تعصبی بپرهیزید محصولات با کیفیت در سطح جهانی تولید کنید خدمات پشتیبانی، تضمین پاسخگو بودن طبیعی است که راهاندازی چنین مواردی نیاز به دانش و مهارتهای تخصصی در حوزهٔ مهندسی کامپیوتر، نرمافزار و شاخههای دیگر آن خواهد داشت. برای مثال: راهاندازی یک وبسایت برای معرفی کسبوکار مشتری نیازمند یک فرآیند ارزیابی، استعلام، ثبت، تخصیص فضای میزبانی، طراحی، برنامهنویسی، توسعه و پشتیبانی است. در این حالت مشتری میبایست با مراجعه به یکی از شرکتها و یا متخصصهای این حوزه خواستهٔ خود را به آن ارائه کند تا مطابق با آن کسبوکار ارزیابی و توسعه یابد. اگر شما به دنبال این هستید که سریعاً مشتری خود را قانع و پروژهای را برای انجام بپذیرید، شک نکنید که احتمال شکست و نارضایتی در هر دو طرف بسیار بالا خواهد بود. ممکن است شما رزومهٔ بسیار قوی با نمونهکارهای بسیار جذاب در اختیار داشته باشید که مشتری در لحظهٔ اول به تواناییهای شما مطمئن شود. اما این به تنهایی کافی نیست! گفتگوی صمیمانه و آزاد «مشاوره و ارزیابی مسائل» در این مقاله من به برخی از مشکلات مهمی که مشتریان در ابتدای کار با آن مواجه هستند میپردازم که عبارتند از: عدم شناخت کافی به ابزارها، روشها، الگوها و حتی افراد و شرکتهای انجام دهندهٔ این خدمات. جالب است بدانید که مشتری بر اساس دانستهها، شنیدهها و همچنین دیدههای خود از الگوهای نه چندان ارزیابی شده تصویری را از کسبوکار خود ترسیم میکند که کاملاً خام است که اگر توسط متخصصین مورد بررسی قرار نگیرد ممکن است به مسیر نادرست و نا آگاهانهای هدایت شوند که نتیجهٔ آن به جز ناامیدی و نا رضایت مشتری نخواهد بود. بنابراین اگرچه دنیای طراحی و توسعهٔ نرمافزار میتواند همهگیر باشد، اما واقعیت آن است که «باید کار را به کاردان سپرد» کاردانهایی که میتوانند با مورد ارزیابی قرار دادن ایدههای ذهنی مشتری آن را درک، هدایت و بهبود بخشد. من در بسیاری از جلسات کاری خودم برای شنیدن خواستههای مشتری نسبت به طرحی که در ذهن خود داشته این مشکلات را به خوبی دیده و درک میکنم. به عنوان مثال: مشتری در ابتدای کار مایل به بیان سریع تصویری از ایده یا راهکار خود برای توسعهٔ کسبوکاری است که شامل استراتژی کامل و نهایی شدهای نیست. البته من اطمینان میدهم این اشتباهات طبیعی بوده و یکی از وظایف برنامهنویسان حرفهای این است که با متکی بودن به علم روانشناسی و همدلی در شنیدن خواستههای مشتری سعی در تأیید همراه با اصلاح و هدایت آن به بهترین سمت ممکن باشد. در نظر داشته باشید که احتمال بسیار زیادی وجود دارد که ابتدای کار در همان دقایق اولیه جلسه مطالبی را از مشتری خود بشنوید که واقعاً در کسبوکار او نیاز نیست و یا حتی فراتر و متفاوتتر از آن چیزی است که در عمل باید به آن متکی بود. حتی در همان دقایق اول احتمال بسیار زیادی دارد که از مشتری چنین سوألاتی را بشنوید «شما بابت این کار چقدر هزینه میگیرید؟» البته این نوع سوألات حتی در پشت تلفن نیز پرسیده میشود، اما برای اینکه ارزش کار خودتان را حفظ کنید توصیه میشود هیچگاه بدون ارزیابی و اصول حرفهای در شنیدن خواستهٔ مشتری خود نه قیمت و نه زمانی برای انجام درخواست ارائه ندهید. این روشی ناشیانه است که معمولاً افراد غیر متخصص به کار میگیرند. بنابراین توصیه میشود صحبتها و ایدههای مشتری خود را با دقت گوش کنید. تأکید میکنم به هیچ عنوان ایدهٔ مشتری خود را سریعاً نکوبید و آن را رد نکنید «این امر موجب میشود مشتری نظرش در مورد شما تغییر کند» این روش در شأن متخصص حرفهای نیست. چرا که یکی از وظایف مهم شما ارائهٔ یک راهکار و مشاورهٔ مفید قبل از اخذ قرارداد و انجام آن است. سعی کنید سوألهایی را بپرسید که مشتری خود به آنها فکر نکرده است و با شنیدن آن حتماً نظرش جلب و از بُعد دیگری به کسبوکار خود و توسعهٔ آن نگاه خواهد کرد. شما به عنوان مشاور فنی باید بتوانید مشتری را قانع کنید که چه موردی ارزشمند و کدام بخش از خواستههای آن ارزش آنچنانی ندارد! چرا که مشتری نیاز دارد به مشکلات و ارزشهایی که در طرح ذهنی خود وجود دارد آگاه باشد تا به راحتی بتواند یک تصمیم صحیح بگیرد. واقعیتهایی که مشتریان از آنها آگاه نیستند قطعاً واقعیتهایی وجود دارد که مشتریان از آنها آگاه نیستند، چرا که آنها متخصص و افراد فنی نیستند. بنابراین احتمال بسیار زیاد دارد که مشتری ابتدا نمونهای از خواستههای خود را برای شما معرفی کند. به عنوان مثال: معرفی یک نمونه وبسایت یا نرمافزار (اپلیکیشن) که در نظر او بسیار جذاب و قابل قبول است. تمامی این مسائل وجود خواهد داشت، شما باید در نظر داشته باشید که تفاوت یک نمونه با خواستهٔ مشتری را شفاف سازی کنید. اگر قرار است بر اساس سلیقهٔ مشتری با او همکاری کنید بهتر است بدانید شما متخصص نیستید و نتیجهٔ پروژهای که بر روی آن کار خواهید کرد مطابق میل شما در بُعد تخصصی نخواهد بود. نمونه وبسایت مثال زده شده توسط مشتری را در مقابل خود مشتری ارزیابی کنید، اگر شما یک حرفهای باشید قطعاً میتوانید الگوهای پیاده سازی شده، روشهای برنامهنویسی، سیستم نرمافزاری، بسترها، تجربهکاربری و رابطکاربری آن را بررسی و نظر خود را برای مشتری ارائه دهید. در نظر داشته باشید زمانی که مشتری برای شما نمونه مثالی را ارائه میکند که شاید تا حدی با ایدهٔ ذهنی آن یکسان است، شما باید در نظر داشته باشید که اصول اساسی تولید محصولی که در نظر دارد را به او توضیح دهید. مشتری باید بداند که رفتار کاربرها، تجربهکاربری، برندینگ و اصول چیدهمان و همهٔ موارد دیگر در عین حال سادگی در کاربرد آن چقدر مهم است. تجربهکاربری هرچند برای خود یک تخصص کامل است، اما مشتری نیاز دارد تا شما در مورد این نکتهها به او یادآوری کنید. اگر شما فقط یک برنامهنویس هستید بهتر است مراجعی را برای مشتری و حتی خودتان در نظر بگیرید تا در بهتر شدن محصول مشارکت کند. مشتری را برای مقایسه و دیدن نمونههای واقعی تشویق کنید همهٔ مشتریان شما مانند هم رفتار نمیکنند، بعضی از آنها قبل از شما با افراد دیگری صحبت کردهاند و بعضی از آنها با شما به عنوان اولین نفر در رابطه با کسبوکارشان و خواستهٔ خود در ایجاد آن صحبت میکنند. بنابراین سعی کنید مشتری را به دیدن رقبا و نمونههایی که مشابه کسبوکار آن است تشویق کنید تا بتواند آنها را در واقعیت نیز ببیند. پیشنهاد میکنم دو نمونهٔ مشابه را در مقابل هم مقایسه کنید و برای مشتری توضیح دهید که چه تفاوتی بین ضعفها و قدرتها وجود دارد. معرفی و توصیف ابزارها و فناوریهایی که از آنها برای تولید و توسعه استفاده میکنید طبیعتاً همهٔ مشتریان شما با ابزارها، زبانهای برنامهنویسی و دیگر موارد آشنایی ندارند. اما برای جذب اعتماد و افزایش آگاهی مشتری لازم است به توصیف ابزارهایی که از آنها استفاده میکنید بپردازید. قرار نیست همهٔ موارد را به صورت فنی توضیح دهید، اما تا جایی که ممکن است به نکته مزیتها و مقایسهٔ تکنیکها و ابزارهایی که قرار است محصول مشتری را با آن توسعه دهید بپردازید تا اون نیز در جریان ذاتِ اصلی محصول خود قرار بگیرد. صداقت شما و تضمین وفاداری مشتری اگر به دنبال جذب مشتری با وفا و مشارکت طولانی مدت هستید، سعی کنید از همان دقایق ابتدائی نظرات خود را بیطرف و با صداقت کامل در قالب مشاورهی قانع کننده ارائه کنید. قرار نیست در همان جلسهٔ اول قرارداد اخذ کنید و یا هزینهای بابت کارتان دریافت کنید! اگر احساس میکنید مشتری شما به مهارتها و حضور شما ارزش قائل نشده است و به نظرات شما توجهی نمیکند خیلی محترمانه سعی کنید وارد این همکاری نشوید. چرا که حرف شنوی از یک متخصص یک ارزش اولیه برای ادامهٔ همکاری است. ناگفته نماند در مقابل ارزشهایی که مشتری به شما میدهد، مانند: شنیدن مشتاقانهٔ نظرات شما، به معنای آن است که این رابطهٔ کلامی در حل بسیاری از مسائل برای مشتری بسیار مهم بوده و شما از نتیجهٔ وقتی که بابتِ این مشاوره صرف میکنید مطمئن شوید. قرارداد، ارزیابی هزینهها و زمان توسعه قبل از اینکه مشتری به شما بگوید شرایط قرادادی چگونه است، شما نمونه قراردادی را با توجه به نتایج ارزیابی شده از نیاز مشتری آماده کنید. بندها و مادههای قرارداد را عادلانه مشخص کنید. تعهدات شما باید به گونهای باشد که مشتری شما از کار مطمئن شود. این قرارداد است که مشخص میکند شما چقدر به تواناییهای خودتان مطمئن هستید. متأسفانه بعضی از توسعهدهندگان به گونهای تعهدات را یکطرفه و به نفع خود تنظیم میکنند که گویی مشتری هیچ حقی در پروژه ندارد! حتی بندهایی دیده میشود که گاهاً توسعهدهنده اعلام کرده است منبعکد - سورسکد برنامه را با هزینهٔ بسیار زیاد و جدا از پروژه به مشتری تحویل خواهد داد! به نظر من این یک بی انصافی به تمام معناست! چرا که مشتری پول میدهد تا محصول خریداری کند! منطقیترین پیشنهاد از نظر من این است که بر اساس زمان و زحماتی که در ساخت و توسعهٔ پروژه صرف خواهد شد یک هزینه و زمانِ شفاف برای مشتری ارائه دهید. برای مثال: فازبندیهای ساخت پروژه در یک جدول استاندارد مانند WBS یا همان «ساختار شکست کار» استفاده کنید. مشاورهٔ رایگان یا پولی ممکن است با خود فکر کنید که من چرا باید دقیقهها و یا ساعتها وقت صرف مشاورهٔ کسانی صرف کنم که مشخص نیست مشتری من هستند یا خیر! برای تشخیص این موضوع که آیا مشاورههای شما در نهایت منجر به همکاری دو طرفه میشود یا خیر، کافی است به چند نکته توجه کنید. اول اینکه مشتری یا نمایندهای از مشتری به دفتر کسبوکار شما آمده است یا برعکس شما به دفتر کاری یا یک دیدار دوستانه رفتهاید! قطعاً زمانی که شما یک دفتر یا شرکت منظمی دارید طبیعی است که زمان خود را باید ارزشمند نگهدارید. بنابراین قبل از ورود به مشاورهٔ اصلی، اشکالی ندارد که بگویید برای ورود به آن هزینهای را دریافت خواهید کرد. به این نکته توجه داشته باشید که، پیشمشاوره با مشاورهٔ اصلی بسیار متفاوت است. در پیشمشاوره شما اولین دیدار را با مشتری خود خواهید داشت که در آن قرار است صحبتهای طرف مقابل را شنیده و از آن برای تجزیه تحلیل آن برای پاسخ در یک زمان مناسب نکتهبرداری کنید. در این نوع صحبت که معمولاً در دیدار اول و مقدماتی شکل میگیرد بهتر است هیچ صحبتی از هزینههایی که در ذهن دارید به مشتری انتقال ندهید چرا که در این مرحله «واقعاً نیاز نیست» و شما صرفاً باید یک شنوندهٔ خوب باشید. در نهایت بعد از شنیدن صحبتهای مشتری، لازم است از او بخواهید تا یک فرصت برای تجزیه تحلیل شنیدههای او بدهید. همانطور که در ابتدای مقاله توضیح دادم، احتمال اینکه مشتری در همان ابتدای صحبتهای خود درخواست میزانه هزینه و زمان برای انجام پروژه کند بسیار زیاد است. بنابراین اگر قبل از تجزیه تحلیل مسئله زمان و هزینهای برای آن مشخص کنید، دیگر نخواهید توانست در صحبتها و جلسات بعدی هزینهها و زمانبندی مشخصی که بعد از تجزیه تحلیل واقعیت به دست آوردهاید را به مشتری پیشنهاد و او را قانع کنید و هر چیزی که در سر داشتهاید را از دست خواهید داد. نکتهٔ کلیدی در این مرحله برای حرفهای برخورد کردن، این است که مشتری را متوجه این کنید که قرار است به او مشاوره و آموزشهای قبل از ورود به مرحلهٔ ساخت و توسعهٔ ایدهٔ ذهنی او را بدهید. در واقع قرار است یک ارزشآفرینی از این صحبتها برای مشتری ایجاد کنید تا به دانستههای خود اضافه کند «این کار برای مشتری شما ارزشمند و قابل قبول است» در این زمان است که شما میتوانید وارد مذاکرهٔ جدی و حرفهای شوید که شامل آموزشها و توضیحات کامل برای قانعسازی مشتری است که قطعاً دارای هزینه و ارزش به خصوصی خواهد بود. بنابراین یک جلسهٔ دیگر برای مشاورهٔ جدی با مشتری خود هماهنگ کنید تا نکات کلیدی و اساسی را برای هدایت هر چه بهتر او به مسیر درست و موفقیت را ترسیم کنید. چگونه از دیگر برنامهنویسان و توسعهدهندگان متمایز و به یک برنامهنویس واقعی و حرفهای تبدیل شویم؟ به احتمال بسیار زیاد هر یک از برنامهنویسان و طراحان در حوزهٔ کسبوکارهای اینترنتی که در زمینههای طراحی، توسعه و تولید محصولات نرمافزاری فعالیت میکنند، نظر بر این دارند که چون مهارت کار با زبانهای برنامهنویسی را در اختیار دارند و یا رزومه یا نمونهکارهای خوبی را دارند، پس بهترین هستند! متأسفانه من بارها شاهد غرور نابهجای بسیاری از برنامهنویسان بودهام که به شدت این رفتار را در شأن حرفهای ها نمیدانم. توصیه میکنم به دانستههای خود مغرور نباشید و از آنچه که در اختیار دارید به نحو عالی استفاده کنید تا از شما یک حرفهای واقعی بسازد. شرایطی که یک برنامهنویس حرفهای میتواند داشته باشد به صورت زیر است: تجربهٔ کافی و پُخته در زمینههای تخصصی تحصیلات مرتبط و مطالعات بسیار در حوزهٔ تخصصی و مرتبط با آن آشنا به اصول مشتری مداری برندینگ، معرفی فردی و تخصصی آشنا به اصول تجربهکاربری و سیستم روانشناسی مناسب با آن رزومهٔ خوب و واقعی نمونه کارهای واقعی و اصولی عدم وابستگی به ابزارهای محدود در توسعه مدارک و مجوزهای لازم در حوزهٔ فعالیتی چهارچوب مشخص و کاتالوگ معرفی خدمات و ارزشها توجه کنید که داشتن مجوز و گواهیهای فعالیتی در این حوزه بسیار مهم است. اگر شما به عنوان یک متخصص در این رشته فعالیت میکنید باید بدانید داشتن مدارک و گواهیهایی ملی و بینالمللی در این حوزه اعتبار خوبی در اختیار شما قرار میدهد که مشتری را بیشتر قانع خواهد کرد. پیشنهاد میکنم بهتر است خودتان را با یک رزومهٔ خوب و مجوزهای لازم از سمت «سازمان نظام صنفی رایانهای کشور» و «مرکز فناوری اطلاعات و رسانههای دیجیتال» معرفی کنید. اخذ این گواهیها در صورتی که شما واقعاً یک متخصص هستید در قالب شرکتی یا خصوصی، میتواند یک اعتبار لازم در قبال دانستههای شما و شرکت شما را در اختیار سازمانها و ارگانهای دولتی، خصوصی و نیمهخصوصی بدهد که اولویت انتخاب در زمان مزایدهها نیز با کسانی است که اعتبار لازم را دارند. واقعیت آن است، دریافت پروژههای بزرگ نه تنها نیاز به دانش و رزومهٔ بسیار خوب دارد، بلکه گواهیهایی که ثابت میکند شما یک متخصص هستید مهم است. این تنها گزینهای است که شما را با افرادی که غیر متخصص هستند متمایز میکند. بهروز باشید و از رفتارهای تعصبی پرهیز کنید همهٔ ما این واقعیت را میدانیم که در حوزهٔ صنعت علوم کامپیوتری، فناوری با سرعت بسیار چشمگیری در حال تغییر و تحولات بسیار زیادی است. این دلیل موجب میشود که در صورت عدم بهروزرسانی اطلاعات و دانش تکنیکی شرکت یا شخص برنامهنویس، از دیگر رقبا فاصله بگیرد. متأسفانه در کشور ما شرکتها و برنامهنویسان بسیاری هستند که به سبکها و اصولی که در نمونههای جهانی از آنها به خوبی یاد نمیشوند وابستگی نشان میدهند و بر بهترین بودن آن تأکید متعصبانهای دارند. شاید این تأکیدها در دید اولیه از جانب مشتری قابل درک باشد، اما واقعیت آن است که نباید خود را محدود به ابزارها و فناوریهایی کنید که از آیندهٔ آن بی خیر هستید! به عنوان مثال بررسی آیندهای از یک فناوری مانند IoT میتواند بسیاری از مسائل را برای شما یادآوری کند که چه ابزار و چهارچوبی میتواند برای پیشرفت روز افزون با حداقل محدودیتها مناسب است. در بسیاری از جوامع، وبسایتها، گروهها وکانالهای اینترنتی دیده میشود که افراد به ابزار و دانشی که فقط به آن محدود و مسلط هستند شدیداً تعصبی برخورد کرده و آن را بهترین انتخاب میدانند. لازم است یادآوری کنیم تعصب بر دانستهها تنها تأیید بر کم دانستن دارد و نه بیشتر! اگر منطقی باشیم یادگیری استانداردهای تضمین شده و پایدار، فناوریها، ابزارها و زبانهای برنامهنویسی قدرتمند و آیندهدار همیشه در پایداری و توسعهٔ سریع کسبوکارها موثر هستند. چرا که فناوری در زمان تغییر محیط را نیز تغییر میدهد. بنابراین توصیه من در این بخش آن است که در یادگیری ابزارها و زبانهای برنامهنویسی، تکنیکها و آشنایی با استانداردهای روز جهانی مصمم باشید و به هیچ عنوان به ابزارهای محدود به دانستههای خود تأکید شدید نکنید مگر با دلیل منطقی و علمی که تضمین کند انتخاب شما دقیقاً هم سو با پیشرفت است. محصولات با کیفیت در سطح جهانی تولید کنید با توجه به توضیحاتی که داده شد، شرکتها و توسعهدهندگانی که در حوزهٔ تولید نرمافزار فعالیت میکنند، معمولاً محصولاتی را توسعه میدهند که در مدیریت کسبوکارهای خود و دیگران موثر است. محصولات نرمافزاری هرچقدر هم قدرتمند باشند و هرچقدر شما کدهای منظم و قدرتمندی در تولید آنها نوشته باشید، کدهای شما از نظر مشتری یا کاربرانی که از آنها استفاده میکنند مخفی است. لازم به ذکر است که، یکی از رایجترین اشتباهاتی که نا خواسته در اکثر محصولات ایرانی دیده میشود عدم به کار گیری مباحث تجربهکاربری و رابطکاربری و استانداردهای توسعهٔ مناسب است. حقیقت این است که نمونه محصولات خارجیِ موفق فاقد این ایرادات هستند و در این صورت است که در نظر کاربر بسیار محبوب میشوند. هرچند بحث تجاری و تبلیغات رسانهای و جهانی در محبوبیت آنها بسیار مهم است، اما در نهایت این کاربر است که تصمیم میگیرد آن را بپذیرد یا خیر. منظور از کاربری صرفاً در زیبایی محیط نرمافزاری نیست، بلکه در دسترس بودن امکانات و ویژگیهایی که میتواند در برقراری ارتباط و وفاداری مشتری شما مفید باشد هم اشاره دارد. بنابراین، اگر شما دید کاربری نداشته باشید و صرفاً با توجه به سلیقههای خودتان محصولی را تولید کنید که فاقد اصول کاربری باشد در این صورت است که محصول شما تنها برای خودتان مهم و با ارزش خواهد بود. نکته: اصول استاندارد نسخهنگاری نرمافزار (محصول) را رعایت کنید و سعی کنید مشتری را در جریان تغییر تحولات و ویژگیهای اعمال شده در محصول قرار دهید. برای این کار میتوانید از استانداردهایی مانند نسخهنگاری معنایی استفاده کنید. خدمات پشتیبانی، تضمین پاسخگو بودن با توجه به نکاتی که اشاره شد، پشتیبانی و پاسخگو بودن در مراحل بعد از عقد قرارداد، طراحی و تولید محصول، یکی از مهمترین مواردی که در طولانی مدت وفاداری کاربران (مشتریان) شما را تضمین میکند، پاسخگو بودن و پشتیبانی است. حتی این موضوع میتواند به صورت یک قرارداد جداگانه با شرایط مخصوص خودش برای مشتری بیان شود تا در جریان شرایط و نحوهٔ پشتیبانی قرار بگیرد. علاوه بر قواعد و قوانین مشتری مداری و توسعهٔ کسبوکار، در چرخهٔ تولید نرمافزار نیز مهم است که بازخوردهای کاربری دریافت و مشکلات احتمالی محصول (نرمافزار) را بررسی و حل نمایید. این خود نوعی پشتیبانی و پاسخگویی و ارزش قائل شدن به مشتریان است که در عمل حتی به روشهای بسیار هوشمندانه میتوان آن را انجام داد. مشتریان شما در هر زمان که با مشکلی مواجه شوند حق دارند مشکلی که با آن مواجه شدهاند را به توسعهدهندهٔ محصول انتقال دهند. توسعهدهنده با بررسی بازخورد ارائه شده موظف است مشکل مربوطه را بررسی و آن را حل کند. این نکته در جملههای مشابه میتواند در بخشی از بندهای قراردادِ بین مشتری و توسعهدهنده یادآوری شود. شاید با خود فکر کنید که با چه روشهایی میتوان ارتباط بین مشتری و توسعهدهنده را برای حل مشکلی در محصول بررسی و مدیریت کرد، حتی بدون آنکه نیاز باشد به صورت حضوری وقت صرف آن کرد. در این باره پیشنهاد میکنم به توضیحات قبلی من در رابطه با ساختن محصول با کیفیت عمیقاً توجه کنید. منظور از توسعهٔ محصولات با کیفیت آن است که مشتری باید بتواند حتی در بازهٔ ۲۴ ساعته نظر خود را نسبت به مشکل، انتقاد یا پیشنهادی در رابطه با محصول ارائه کند تا در فرصت مناسب توسعهدهنده آن را بررسی کند. معمولاً این فرآیند به صورت سنتی با تلفن و مراجعهٔ حضوری صورت میگیرد، اما توصیهٔ من برای حفظ زمان و کارآیی بهتر این است که نرمافزار (محصول) خود را مجهز به خدمات پشتیبانی آنلاین در قالب سیستم هوشمند مجهز کنید. علاوه بر آن، استانداردهای سیاههٔ تغییرات (change log) و مشکلات گزارش شده را در محیط نرمافزار شفاف سازی کنید تا مشتری هم متوجه اعمال نظرات و انجام آن شود.
-
3 امتیازاگر شما توسعه دهندهٔ ++C هستید، توصیه میکنم این سری از مقالات را دنبال کنید زیرا در این تاپیک قصد دارم به چکیدهای از آخرین تغییرات مرتبط با سیپلاسپلاس پیشرفته اشاره کنم. بنابراین در بخش اول، مهمترین موارد منسوخ شده، اشکلات رفع شده و ویژگیهای جدید در استانداردهای اخیر را پوشش خواهیم داد که به صورت جزئی خواهد بود و سپس نسبت به هر کدام در مقالات جداگانه به کاربردهای پیشرفتهتر و جزئیات بیشتری اشاره خواهیم کرد. قبل از شروع، اگر میخواهید به لیستی از تغییرات و ویژگیهای کامل در استانداردها دسترسی داشته باشید به مقالهٔ زیر مراجعه کنید. در مقالهٔ فوق به لیست ویژگیهای جدید در استاندارد ۱۱، ۱۴، ۱۷ و ۲۰ اشاره شده است. در نظر داشته باشید که بزرگترین بهروز رسانی سی++ در ده سالِ اخیر مربوط به استاندارد ۲۰ است. این نسخه از زبان تقریباً 2.5 برابر بزرگتر از سی++ ۱۰ سال پیش است! این در حالی است که استاندارد ۱۷ تقریباً ۸۰٪ بزرگتر از استاندارد ۰۳ است. به عنوان مثال، طبق مستندات رسمی پیشنویسهها تغییرات استاندارد از ۸۷۹ صفحه به ۱۸۳۴ صفحه در این استاندارد رسیده است! چیزی حدود ۱۰۰۰ صفحه بیشتر از نسخههای قبلی ? تمامی این بهبودها خبر از بهتر شدن و در عین حال پیچیده شدن زبان اما همراه با سادهتر و سریعتر شدن آن میدهد. اما مشکلی که میتواند رخ دهد در این است که یادگیری آن و بهروزرسانی کدها نیز میتواند دردسر ساز باشد. بنابراین، برای پوشش دادن جزئیات و بهروزرسانیهای بیشتر در این مقاله سعی خواهم کرد که مهمترین موارد را معرفی کنم. جزئیات ++C نسخه ۱۷ (بهبودها و تغییرات) بیایید به آرامی شروع کنیم، امروز ما به عناصر حذف شده و یا به موارد بهبود یافتهٔ کتابخانه استاندارد بپردازیم. معرفی به صورت سلسله مراتبی عناصر حذف شده و توسعه یافته (در این بحث) شفاف سازی در زبان قالبها ویژگیها تغییرات اول کتابخانه تغییرات دوم کتابخانه مستندات و لینکها قبل از هر چیز، اگر شما خودتان میخواهید استاندارد جدید را کاوش کنید آخرین پیش نویسه را در این بخش مطالعه کنید. در صورتی که میخواهید بدانید کدام کامپایلر از ویژگیهای جدید پشتیبانی میکند، در این بخش آن را پیگیری کنید. علاوه بر این، لیستی از توصیفهای مختصر از تمامی ویژگیهای زبان سیپلاسپلاس ۱۷ تهیه شده است که در این بخش میتوانید آن را ببینید که در قالب PDF از طرف مرجع رسمی میباشد. مواردی که ترجیح داده شده است که حذف شوند حذف تریگراف تریگرافها کاراکترهای ویژه ترتیبی هستند که در موقع عدم پشتیبانی سیستم از نوع ۷ بیتی اَسکی (ASCII) همانند ایزو 646 استفاه شوند. برای مثال =?? کاراکتر ویژهای مانند # تولید شده را در قالب -?? تولید میکند. تمامی مجموعه کاراکترهای اصلی سیپلاسپلاس در قالب 7 بیتی اسکی قرار دارند. موضوع فوق به ندرت مورد استفاده قرار میگیرد، بنابراین حذف آن ممکن است به ترجمه ساده کد کمک کند. اگر شما میخواهید اطلاعات بیشتری در رابطه با کارآیی تیرگرافها در سی++ کسب کنید به این لینک مراجعه کنید. ---------------------------------------------------------------------------- | trigraph | replacement | trigraph | replacement | trigraph | replacement | ---------------------------------------------------------------------------- | ??= | # | ??( | [ | ??< | { | | ??/ | \ | ??) | ] | ??> | } | | ??’ | ˆ | ??! | | | ??- | ˜ | ---------------------------------------------------------------------------- شما جزئیات بیشتر را میتوانید در سند N4086 بیابید. اگر شما واقعاً به هر نحوی به گرافها در ویژوال استودیو نیاز دارید، نگاهی به مشخصه /Zc:trigraphs در بخش پیکربندی داشته باشید. همچنین، کامپایلرهای دیگر ممکن است مواردی را پشتیبانی نکنند. وضعیت انجام شده کنونی در کامپایلر های GCC:5.1 و Clang:3.5 میباشد. حذف کلمه کلیدی register کلمه کلیدی register در استاندارد 2011 سیپلاسپلاس منسوخ شده است و دیگر استفاده از آن معنایی ندارد. این کلمه کلیدی در حال حاضر حذف شده است. این کلمه کلیدی محفوظ است و ممکن است در نسخه های بعدی باز نویسی شود (مثلا autokeyword به عنوان یک چیز قدرتمند مجددا مورد استفاده قرار گرفته است). جزئیات بیشتر در رابطه با این مورد در P0001R1 قابل مشاهده است. البته فعلا در MSVC انجام نشده است اما در کامپایلرهای GCC 7.0 و Clang 3.8 انجام شده است. حذف Operator++ bool این اپراتور برای زمان بسیار زیادی است که منسوخ شده است! در سی پلاس پلاس ۹۸ تصمیم بر آن گرفته بودند که از آن استفاده کنند اما در نسخه ۱۷ سیپلاسپلاس کمیته موافقت خود را جهت حذف آن از زبان اعلام کرده است. جزئیات بیشتر در رابطه با این مورد در P0002R1 قابل مشاهده است. البته فعلا در MSVC انجام نشده است اما در کامپایلرهای GCC 7.0 و Clang 3.8 انجام شده است. حذف مشخصات استثنایی از استاندارد ۱۷ در سی پلاس پلاس ۱۷، مشخصات استثنایی بخشی از نوع سیستمی خواهند بود (به P0012R1 نگاه کنید). با این حال، استاندارد شامل مشخصات استثنایی قدیمی و منسوخ شده اند که به نظر غیرعلمی و غیرقابل استفاده است. void fooThrowsInt(int a) throw(int) { printf_s("can throw ints\n"); if (a == 0) throw 1; } کد بالا در سیپلاسپلاس ۱۱ رد (منسوخ شده است). تنها اعلامیه استثنایی علمی throw() است، به این معنی است که این کد چیزی را در قالب throw انجام نخواهد داد. اما از سیپلاسپلاس ۱۱ به اینور، برنامه نویسان توصیه کرده اند که کسی از آن استفاده نکند. برای مثال در کامپایلر Clang 4.0 شما باید خطای زیر را دریافت کنید: error: ISO C++1z does not allow dynamic exception specifications [-Wdynamic-exception-spec] note: use 'noexcept(false)' instead جزئیات بیشتر در رابطه با این مورد در P0003R5 قابل مشاهده است. البته فعلا در MSVC انجام نشده است اما در کامپایلرهای GCC 7.0 و Clang 3.8 انجام شده است. حذف auto_ptr این یکی از به روز رسانیهای خوبی است که در سیپلاسپلاس ۱۱، ما اشاره گرهای هوشمند را دریافت کردیم : unique_ptr,shared_ptr و weak_ptr. با تشکر از این حرکتی که کمیته انجام داده بود، معنای واقعی این به روز رسانی در این بود که زبان میتواند پشتیبانی مناسبی از انتقال منابع منحصربفرد را داشته باشد. در این میان auto_ptr یک چیز قدیمی و نادرست در زبان بود به نا به دلایلی auto_ptr در این جا منسوخ شده است و باید به صورت خودکار به unique_ptr تبدیل شود. توجه داشته باشیم که auto_ptr مدت کوتاهی است که از سیپلاسپلاس ۱۱ به اینور منسوخ شده است و بسیاری از کامپایلر ها منسوخ شدن آن را گزارش میدهند که به صورت زیر خواهد بود: warning: 'template<class> class std::auto_ptr' is deprecated در حال حاضر آن به وضعیت نامناسب تبدیل شده است، و اساساً کد شما کامپایل نخواهد شد. در اینجا خطا از طرف MSVC 2017 زمانی که از گزینه /std::c++latest استفاده کنید اعلام خواهد شد. error C2039: 'auto_ptr': is not a member of 'std' اگر شما نیاز به کمک از تبدیل از auto_ptr به unique_ptr دارید، میتوانید Clang Tidy را بررسی کنید، زیرا آن عمل تبدیل خودکار را انجام خواهد داد. اطلاعات بیشتر در سند N4190 موجود است. همچنین موارد مرتبط دیگری با سند N4190 وجود دارند که در کتابخانه خذف شده اند مانند: unary_function/binary_function ptr_fun() mem_fun()/mem_fun_ref() bind1st()/bind2nd() random_shuffle قوانین جدید خودکار برای Direct-List-Initialization از سی پلاس پلاس ۱۱ به اینور که ما یک مشکل بزرگی در این رابطه داشتیم: auto x { 1 }; از initializer_list اینطور نتیجهگیری شده است. با استاندارد جدید، ما میتوانیم این مشکل را حل کنیم. بنابراین آن میتواند به عنوان نوع int که اکثر مردم تصور میکنند شناسایی شود. برای اینکه این اتفاق بیافتد، ما نیاز داریم که دو روش تخصیص مقدار اولیه را درک کنیم: کپی و مستقیم. auto x = foo(); // copy-initialization auto x{foo}; // direct-initialization, initializes an // initializer_list (until C++17) int x = foo(); // copy-initialization int x{foo}; // direct-initialization برای مقدار دهی اولیه، سیپلاسپلاس ۱۷ قوانین جدیدی را معرفی میکند: For a braced-init-list with only a single element, auto deduction will deduce from that entry; For a braced-init-list with more than one element, auto deduction will be ill-formed. برای مثال: auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int> auto x2 = { 1, 2.0 }; // error: cannot deduce element type auto x3{ 1, 2 }; // error: not a single element auto x4 = { 3 }; // decltype(x4) is std::initializer_list<int> auto x5{ 3 }; // decltype(x5) is int جزئیات بیشتر را در سند N3922 میتوانید مشاهده کنید. همچنین جزئیات در رابطه با فهرست خودکار موجود هستند که توسط جناب آقای Ville Voutilainen اشاره شده است. این اضافات در سیپلاسپلاس از زمان MSVC 14.0، GCC 5.0 و Clang 3.8 کار میکنند. گزینه static_assert بدون هیچ نوع پیغامی این واضح است که، این به شما این امکان را می دهد که فقط بدون داشتن گذراندن پیام، نسخه دارای پیغام در دسترس خواهد بود. این سازگاری با سایر موارد مانند BOOST_STATIC_ASSERT وجود دارد. static_assert(std::is_arithmetic_v<T>, "T must be arithmetic"); static_assert(std::is_arithmetic_v<T>); // no message needed since C++17 جزئیات بیشتر در سند N3928 در دسترس است. پشتیبانی شده در MSVC 2017 ٬ GCC 6.0 و Clang 2.5. انواع مختلف شروع و پایان در محدوده حلقه از سیپلاسپلاس ۱۱ به بعد، محدوده مبتنی بر حلقه ها به صورت داخلی تعریف شده است: { auto && __range = for-range-initializer; for ( auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } } همانطور که میبینید، __begin و __end دارای نوع مشابه هستند. این ممکن است باعث مشکلاتی شود. برای مثال زمانی که شما چیزی شبیه یک نگهبان (محافظ) که از نوع داده دیگری است را داشته باشید مشکل ساز خواهد بود. در سیپلاسپلاس ۱۷ آن به صورت زیر تغییر کرده است: { auto && __range = for-range-initializer; auto __begin = begin-expr; auto __end = end-expr; for ( ; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } } انواع __begin و __end ممکن است متفاوت باشد چرا که فقط اپراتور مقایسه مورد نیاز است. این تغییر کلی باعث میشود که این ویژگی تجربه بیشتری را در این زمینه برای کاربران ارائه دهند. جزئیات بیشتر در P0184R0، پشتیبانی شده در MSVC 2017 ،GCC 6.0 و Clang 3.6.
-
3 امتیاز
نگارش 5.0
983 دریافت
هدف از این آموزشها آشنایی با امکاناتی که در Qt میتوان استفاده کرد میباشد، که شامل کدنویسی کمتر، خروجی و طرح های بیشتر و در نهایت استفاده در پلتفرمهای مورد مختلف است. لذا جهت بهرهمندی از این کتابخانه ما با در نظر گرفتن اینکه علاقهمندان با زبان ++C آشنایی لازم را دارند منتشر کردهایم. بنابراین در صورتی که علاقهمندان اطلاعات کافی در رابطه با خود زبان ندارند پیشنهاد میکنیم ابتدا اقدام به تهیه و مطالعه آموزشهای لازم در ++C نمایند که برخی از لینکهای رسمی و استاندارد آن را در زیر اعلام نمودهایم. نوع این کتاب الکترونیکی است، بعد از پرداخت میتوانید بر روی دکمهٔ دریافت فایل در همین صفحه کلیک کرده و آن را دریافت نمایید. در صورتی که درگاه پرداختی با مشکل مواجه شده باشد، میتوانید به شماره کارت ۶۱۰۴۳۳۷۸۸۴۵۳۳۳۴۸ (بانک ملت) واریز و آن را به آدرس kambiz.ceo@gmail.com و یا شناسهٔ تلگرامی @Kambiz_Asadzadeh اطلاع دهید تا تأیید شود. از تاریخ ۲۶ آذر ۱۴۰۲ دریافت این کتاب بدون پرداخت هزینه توسط نویسنده تأیید میشود، شما میتوانید بعد از مطالعه هزینهٔ آن را بپردازید. عنوان این آموزش "برنامه نویسی ++C همراه با کتابخانه های Qt 5.12.x (سطح مقدماتی ویرایش ۵) میباشد که به صورت زیر فهرست بندی شده است: فصل اول مقدمه کتابخانه Qt قابلیت ها در طراحی فناوری Qt Quick و QML نسخه های کیوت مجوز های موجود در این کتابخانه محیط های توسعه کیوت ویژگی های کیوت پشتیبانی از انواع سیستم عامل ها نصب و پیکربندی Qt فصل دوم انواه پروژه و ایجاد آن انواع پروژه ها ایجاد پروژه فصل سوم ساده ترین برنامه معرفی و کار با Signal و Slot ها و Event ها معرفی و کار با نمایش Windows معرفی و کار با لایه ها زبانه ها و بدنه های در طراحی معرفی و کار با قابلیت های HTML و CSS در طراحی فصل چهارم معرفی و کار با لایه های افقی و عمودی معرفی و کار با لایه های Grid در طراحی فرم معرفی و کار با جدا کننده ها Splitter فصل پنجم معرفی و کار با دایرکتوری ها معرفی و کار با فایل ها / خواندن و نوشتن در آن ها فصل ششم معرفی و کار با برچسب ها Label معرفی و کار با دکمه ها Button معرفی و کار با کنترل ورودی LineEdit معرفی و کار با چک باکس CheckBox معرفی و کار با RadioButton معرفی و کار با Combobox معرفی و کار با لیست ها / ListWidget معرفی و کار با لیست های درختی / TreeWidget معرفی و کار با Action ها معرفی و کار با Slider و Progress ها معرفی و کار با Statusbar در فرم فصل هفتم معرفی و کار با MessageBox معرفی و کار با Timer معرفی و کار با Thread ها فصل هشتم معرفی و کار با Map معرفی و کار با Hash معرفی و کار با QStringList لیست رشته ای فصل نهم معرفی و کار با الگوریتم های معرفی و کار شبکه / دانلود فایل بر اساس پروتکل های HTTP و FTP معرفی و کار با باینری و سریالیز کردن آبجکت ها معرفی و کار با TextStream ها فصل دهم مقایسه انواع حالت های کامپایل در Qt نحوه افزودن دیگر کتابخانه های C++ در محیط Qt Creator و استفاده همراه با کتابخانه Qt نحوه خروجی گرفتن / گسترش (Deployment) در Qt مقایسه و پیکربندی دو موتور قدرتمند OpenGL و ANGLE در پروژه درایور دیتابیس هایی که تحت این کتابخانه پشتیبانی میشوند ساخت راهانداز دیتابیس در پلتفرمهای Linux، macOS و Windows حق نشر کتاب و اهداف در نسخهٔ بعدی کتاب توجه : در داشتن هر گونه انتقاد و پیشنهاد در رابطه با این کتاب با آدرس شخصی نویسنده (kambiz.ceo@gmail.com) مکاتبه نمایید. نکته دوم : کسانی که این کتاب را یک بار خریداری میکنند نسخهٔ به روز رسانی شده آن را به صورت رایگان میتوانند دریافت کنند.رایگان
-
3 امتیازسلام. عدم دسترسی به یک سیستم مناسب و با خبر نبودن از حساب کاربری گیت هاب خود یکی از مشکلاتی بود که در این چند ساله برنامه نویسان با آن روبرو بودند. چک کردن حساب ایمیل در تلفن همراه می توانست تا حدودی به این موضوع کمک کند. اما یک اپلیکیشن اختصاصی برای این مورد می تواند این امر را به بهترین شکل پوشش دهد. بعد از کارهایی که برروی اپلیکیشن رسمی شرکت گیت هاب برای پلتفرم iOS انجام شد و خوشبختانه بدون هیچ مشکلی در بزرگ رویداد و کنفرانس شرکت و مایکروسافت - GitHub Universe 2019 در تاریخ November 13-14, 2019 رونمایی شد. به عنوان یکی از اعضای شرکت این نوید را می دهم که نوبت به آن رسید تا اپلیکیشن برای اندروید نیز پیاده شود. در حال حاضر این اپلیکیشن در حال توسعه است و هنوز رونمایی نشده است. برای این اپلیکیشن میزان پشتیبانی API 21+ Android device در نظر گرفته شده است و خواهد توانست از نسخه Android 5.0 به بالا را پشتیبانی کند. می توانید پیشنهادات و نظرات خود را نیز ایمیل کنید. Max [@] Asrez {.DOR.} com Hi, I'm Max Base. GitHub team did work on the official GitHub application for the iOS platform and fortunately unveiled at the big event and conference(GitHub Universe 2019 on November 13-14, 2019). As a member of the company, I have the promise that the app will launch for Android. This app is currently under development and has not been unveiled yet. This app is designed to support Android 21+ API and will support Android 5.0 or later. You can also email your suggestions and comments. Max [@] Asrez {.DOR.} com Best, Max Base با تشکر Max Base / مکس بیس
-
3 امتیازآیا این واقعاً امکانپذیر است؟ پاسخ : بله! من میدانم که ممکن است این مبحث تحت سی++ بسیار پیچیده و یک کار بیهودهای باشد! اما واقعیت این است که تکنیکهای پنهان بسیاری وجود دارد که ممکن است همه از آن باخبر نباشند! من قبلاً در مورد اینکه تحت ++C وبسایت میشه طراحی کرد یا خیر تحقیقاتی انجام داده بودم، از لحاظ امکان بودنش جواب مثبت بود اما اینکه به راحتی طراحی تحت Php یا دیگر زبانهای برنامهنویسی باشه خیر! خُب طبیعیه چون شما بسیار راحت یه اسکریپت رو مینویسی و روی سرور اجراش میکنی و سایت شما به خوبی و خوشی بالا میاد! ممکن است در همین قسمت از موضوع شما به این نتیجه رسیده باشید که خُب نیازی به ادامهٔ بحث نداریم! وقتی کار سختیه پس منطقی نیست و شما احتمالاً دیوانهای!!! ? واقعیت جریان این است بر خلاف آن چیزی که تصور کردهایم طراحی وبسایت با سیپلاسپلاس نه تنها بسیار راحت است بلکه بسیار هم جذاب خواهد بود! اما در نگاه اول ممکن است یک سری محدودیتهارا داشته باشد که همهٔ این موارد با کمی تأمل و بررسی قابل حل هستند به قدری که وقتی درگیر این جریان باشید شیفتهٔ آن خواهید شد. مزایای یک وبسایت تحت سیپلاسپلاس نسبت به دیگر زبانهای رایج سرعت خارقالعاده و غیر قابل مقایسه با زبانهای رایج امنیت بهتر کدهای شما مدیریت سادهتر و انعطافپذیری بالا مصرف بسیار بهینه و غیر قابل تصور از منابع سرور دسترسی نامحدود به کتابخانهها عدم محدودیت در دسترسی به برنامهنویسی سطح پایین عدم محدودیت در استفاده از توابع سیستمعامل عدم محدودیت در مدیریت سیستم و هر ویژگی دیگری که در زبانهای اسکریپتی اگر به آن نیاز داشته باشید مجبور هستید تا به صورت اکستنشن آن را تحت سیپلاسپلاس باز نویسی کنید. سیستم راهانداز وبسرور چگونه است؟ در هر سروری CGI به شما امکان این را میدهد که بتوانید تحت پروتکلهای استاندارد برنامههای تحت وب را اجرا کنید. شما میتوانید تحت آن و یا موارد دیگری مانند FastCGI و WSGI و دیگر موارد بهینه شدهٔ آن برنامهٔ تحت وب را بر روی سرور خود اجرا کنید. طراحی قالب هماهنگی با HTML, JavaScript, Css در سیپلاسپلاس چگونه خواهد بود؟ همهٔ گزینههای مربوط به وب را شما بدون هیچ محدودیتی در اختیار خواهید داشت. شما هیچ محدودیتی در استفاده از ویژگیهای HTML5 یا CSS3 و یا JavaScript و دیگر فریمورکها و کتابخانههای کارآمدی چون Angular.JS را نخواهید داشت. بنابراین از نظر طراحی رابط یک وبسایت همانند دیگر زبانهای رایج میتوانید روی آن حساب کنید. طراحی هسته و بکاِند وبسایت چگونه خواهد بود؟ همانند زبانها و فریمورکهای رایج تحت وب شما در سیپلاسپلاس میتوانید هستهٔ وبسایت یا سیستم وبسایت خود را تحت استاندارد سیپلاسپلاس و هر کتابخانهای که میپسندید و یا به آن تسلط دارید پیاده سازی کنید! به شرطی که قابلیتهای آن کتابخانه پاسخگوی نیازهای شما باشد. با این حساب شما میتوانید حتی سیستم مدیریت محتوای (CMS) خود را طراحی کنید! ? بله سیستم مدیریت محتوا تحت سیپلاسپلاس! کاملاً جدی هستیم ? قبل از هر چیز یک مزیت بسیار بزرگ در کنار مزیتهای دیگر این است که یک CMS تحت سیپلاسپلاس میتواند داشته باشد مصرف بهینه از منابع سرور خواهد بود. برای مثال در یک مقایسهٔ ساده و آزمایشی نتیجهٔ بسیار جالبی ارائه شده است. همانطور که میدانید Wordpress به عنوان یک سیستم مدیریت محتوای (بلاگ) شناخته شده و تحت Php توسعه یافته است. نسخهٔ سریعتر و بهینهتر آن با نام Ghost تحت Node.JS توسعه یافته است که ما نسخهٔ توسعه یافتهٔ آن را با یک عمل مشابه در C++1z مورد بررسی قرار داده ایم که نتایج آن بسیار جالب است! مصرف حافظه سیستم مدیریت محتوای Tegra ۳۵۰۰ درخواست در هر ثانیه 3.6 مگابایت سیستم مدیریت محتوای Ghost 100 درخواست در ثانیه 120 مگابایت پشتیبانی از پایگاههای داده به لطف کتابخانههای عظیم سیپلاسپلاس امکان مدیریت یک وبسایت تحت پایگاههای داده مختلفی ممکن است. برای مثال تحت Qt شما میتوانید به رایجترین درایورهای بانکاطلاعاتی دسترسی داشته و سیستم خود را به آنها مجهز کنید. نکته: احتمالاً در برنامهنویسی با نود جیاس و پیاچپی شناختی با کتابخانههای OpenSSL, Libcurl و موارد این چنینی داشته اید! کتابخانههای فوق عضو لیست کتابخانههای C و ++C هستند. بنابراین شما علاوه بر دسترسی مستقیم بر آنها به هزاران و شاید میلیونها کتابخانه در دنیا سیپلاسپلاس خواهید داشت. نمونهٔ اولیه اما شوقآور برای اثبات امکان طراحی وبسایت تحت سیپلاسپلاس چندی پیش من تصمیم گرفتم تا سیستم وبسایتی را تحت Php7 برای یکی از استارتآپها طراحی و پیاده سازی کنم که در این پست به آن اشاره شده است. از آنجایی که به لطف کتابخانهٔ Qt برنامههای سمت کاربر را توسط سیپلاسپلاس پیاده سازی کرده بودم به این فکر افتادم چرا سمت سرور و بخش وبسایت هم با آن هماهنگ نشود!؟ اینگونه هماهنگی بین برنامهها و پرفرمنس همهٔ آنها بسیار افزایش خواهد یافت در اولین نگاه این تفکر بسیار ناشیانه و بسیار ناممکن بود! تنها روشی که به کار گرفته بودم ارسال اطلاعات از طرف کاربر به سمت سرور و مدیریت آنها تحت معماری Restful Api بود که در قالب JSon آنها را تجزیه و مدیریت میکردم. با کمی تحقیق در مورد ویژگیهای سمت وب تحت Fast-CGI, uWSGI, DJango, ClearSilver و موارد مرتبط با آنها سعی کردم تا صفحهٔ بسیار سادهای از HTML را توسط سیپلاسپلاس هندل کنم. این کار نتایج بسیار موفقیت آمیزی را در بر داشت تا نتیجهٔ آن تبدیل به یک پروژهٔ سیستم مدیریت محتوا تحت ++C شد. من پروژهای با نام مفهومی Tegra که نام پروژهٔ قبلی تحت Php بود را در محیط Qt Creator با C++17 و کتابخانهٔ Qt باز سازی کرده و هستهٔ اولیهٔ آن را برای اجرای چند صفحه از یک وبسایت، احراز هویت، بازخوانی و نمایش لیستی از خبرها و مدیریت متا تگها و آدرس صفحات مربوط به هر صفحه را ایجاد کردم. سعی کرده ام در کمترین زمان ممکن برای آزمایش یک سری ویژگیهای اولیه از یک وبسایت آنها را مورد بررسی قرار بدم که عبارتند از هماهنگی با فریمورکهای طراحی مانند BootStrap و یا Angular.JS که خوشبختانه همهچیز بسیار خوب در کنار همدیگه کار میکنند. هستهٔ سیستم به صورت جدا و معماری طراحی آن بر پایهٔ MVC مورد آزمایش قرار گرفته است. در زیر تصاویری از صفحات تولید شده تحت سیستم مدیریت محتوای ساخته شده با سیپلاسپلاس را مشاهده میکنید. ? همه چیز در قدمهای اول قرار دارد و با توجه به سادگی تولید وب سایت بر خلاف تصوری که داشتیم بسیار توسعه و جای پیشرفت خواهد داشت. بخشی از نمونه کدهای این سیستم به صورت زیر آورده شده است تا ذهنیتی برای توسعهدهندگان ارائه شود: تکه کُد زیر عمل ارسال اطلاعات و تمامی لینکهای مربوط به بوت استرپ را برای سمت HTML ارائه میکند که در قالب استاندارد جدید C++17 آورده شده است: auto bootstrapCss = bootStrapLib.find("css"); if(bootstrapCss != bootStrapLib.end()) { c->setStash("BootstrapCss", bootstrapCss->second.c_str()); std::cout << "Found " << bootstrapCss->first << " " << bootstrapCss->second << '\n'; } کد مربوط به سمت قالب به صورت زیر خواهد بود: <!-- Bootstrap core css --> <link href="{{BootstrapCss}}" rel="stylesheet"> نتیجهٔ فوق در صورتی که CDN بر روی لوکال تنظیم شده باشد از روی کدهای کامپایل شده و یا استاتیک فراخوانی خواهد شد. در غیر اینصورت از روی یکی از سرورهای CDN فراخوانی میشوند. نحوهٔ ارسال متغیر از سمت سیپلاسپلاس به قالب بسیار ساده است! بسیار ساده از Php و یا Node.JS میباشد. با در نظر گرفتن ارسال اطلاعات از سمت سیپلاسپلاس به سمت رابط کاربری کافی است نام متغیرها را در قالب خود اعمال کنید. {% for post in news %} <div class="blog-post"> <h2 class="blog-post-title"><a href="news/{{post.uri}}">{{post.title}}</a></h2> <p class="blog-post-meta">{{post.date}} by <a href="#">{{post.author}}</a></p> <p>{{post.announcement|safe}}</p> </div><!-- /.blog-post --> {% endfor %}</div> این ساختار بر پایهٔ ساختار Angular.JS و DJango پیاده سازی شده است که به طور کامل پشتیبانی میشود. فعال سازی فناوری Angular.JS بر روی این سیستم جهت طراحی قالب تنها با دو دستور ساده اعمال میشود: <!-- Link to AngularJS --> <script src= "{{AngularJs}}"></script> <!-- Enable AngularJS Engine --> {{AngularJsSync|safe}} این دستورات در هستهٔ سیستم مدیریت محتوا در کلاسی با نام Template پردازش و در نهایت به سمت HTML هندل میشوند. بخشی از دستورات سمت هسته در سیپلاسپلاس ۱۷ برای مثال ارسال عنوان صفحه به صورت زیر است: std::optional<std::string> LoadListTemplate::getTitle() const { if (isset(title)) { return title; } else { return std::nullopt; } } سمت HTML کافی است دستور فوق را در نظر بگیریم: <title>{{title}}</title> اینها مثالهایی از مراحل توسعهٔ این سیستم است که میدانم آنچنان گسترده نیست، اما برای ثابت کردن طراحی و توسعهٔ وبسایت تحت سیپلاسپلاس مثالهای روشنی هستند. موفق و سربلند باشید! اطلاعیههای مربوط به این پروژه احتمالاً در کانالها و گروه تلگرامی و همین مرجع بازگو و در اختیار شما قرار گیرد.
-
3 امتیازدر این مقاله من قصد دارم به معرفی ده فریمورک برتر جهان در بازهٔ سالهای ۲۰۱۹ و ۲۰۲۰ اشاره کنم که در حوزهٔ صنعت وب کاربرد دارند. معمولاً در سایتها، وبلاگها و گروههای تلگرامی حرف از فریمورکهای شناخته شدهای مانند Asp.net core و یا Laravel به گوش میرسد. اما واقعیت این است که فریمورکهایی که در مورد آنها بحث میشود جایگاه خاصی در بین فریمورکهای قدرتمند و به عنوانی ناشناخته مانند Drogon، h2o، ulib و غیره ندارند! جالب است بدانید فریمورکهایی که در ادامه نامهایشان را میشنوید به قدری سریع و قدرتمند هستند که مو بر تنِ شما سیخ خواهد کرد! برای مثال در این مقایسه جایگاه فریمورکهای داتنت به بالاتر از ۵۰ و لاراول به بیشتر از ۲۰۰ رتبه میرسد! این در حالی است که بر خلاف انتظارِ عام، فریمورکهای تحت سی/سی++ و راست به عنوان سریعترین فریمورکها شناخته میشوند. در واقع مقایسه بر اساس نتایج گرفته شده از مرجع Techempower میباشد که هر ساله یک مقایسه در رابطه با کارآیی و کیفیت فریمورکهای وب میپردازد. سنجشِ فوق بر اساس وظایفی مانند سریالسازی جیسان، دسترسی به پایگاه داده و عملیات سمت سرور، پردازش و غیره میباشد. در این آزمایشها عملکرد فریمورک بر روی سیستمعامل، به صورت فولاِستک و میکرو اندازهگیری شده است که هر کدام را در رتبهٔ خاصی از وضعیت آن سوق میدهد. بهترین فریمورکها از نظر بنچمارک (کارآیی) در سال ۲۰۱۹ در دورِ ۱۸ بین ۲۲۰ فریمورک متعلق به h2o و ulib بوده است. کتابخانهٔ h2o یکی از قویترین مواردی است که میتوان به آن اشاره کرد. در سال ۲۰۲۰ این رتبهبندی به نفعِ فریمورک جدیدتری به نام دراگون (Drogon) و مجدداً ulib جمع بندی شده است که نشان میدهد فریمورک ulib به عنوان یکی از برترین فریمورکهای نوشته شده تحت سی و سی++ و همچنین دراگون تحت استانداردهای ۱۴ و ۱۷ زبان برنامهنویسی سیپلاسپلاس معرفی شده است. بنابرین بهتر است در مورد دراگون بیشتر بدانیم: این فریمورک تحت زبان برنامهنویسی ++C در استاندارد ۱۴ و ۱۷ توسعه یافته و بر روی سکوهای لینوکس، مک و ویندوز قابل اجراست. دراگون تحت ویژگی non-blocking I/O کار میکند و سرعت را همراه با دقت بسیار بالایی به خصوص بر روی پلتفرمهای FreeBSD تضمین میکند. لینک مخزن توسعه و کدهای دراگون. مثال از کد اولیه: #include <drogon/drogon.h> using namespace drogon; int main() { app().setLogPath("./") .setLogLevel(trantor::Logger::kWarn) .addListener("0.0.0.0", 80) .setThreadNum(16) .enableRunAsDaemon() .run(); } با توجه به مقایسههای صورت گرفته در آزمایشهای مختلف زیر رتبهبندی فریمورکها مشخص میشود. آزمایشهای فوق بر روی پردازندهٔ Dell R440 Xeon Gold صورت گرفته است که در این لینک آمده است. JSON serialization Single query Multiple queries Fortunes Data updates Plaintext آزمایشهای مربوطه تنها به ۱۰ مورد اول اشاره کرده است، بنابراین برای مشاهدهٔ لیست بیشتر و جزئیات آنها به مرجع آن مراجعه کنید.
-
3 امتیازبا توجه به محبوبیت صنعت وِب، سالهاست زبانهای برنامهنویسی در این زمینه پیشرفتها و کاربردهای چشمگیری را داشتهاند، از جمله جاوااسکریپت (JS) به عنوان یک زبان قابل اجرا در داخل مرورگر شناخته میشود. هرچند بسیار محبوب و کاربردی است، اما این زبان قطعاً مشکلات خودش را دارد که برخی از آنها عدم انعطافپذیر بودن، سرعت پایین اجرا و همچنین انواع غیر ایمن آن است که این باعث میشود برای محاسبات و کارهای پیچیده جوابگو نباشد. هرچند گزینههایی مانند CoffeeScript و TypeScript وجود دارند و نسبتاً ایرادات خام جاوااسکریپتی را پوشش میدهند، اما در نهایت کدهای نوشته شده به جاوااسکریپت تبدیل میشود. در این میان میتوان گفت وباسمبلی (WebAssembly) برای حل و مرتب سازی مشکلات جاوااسکریپت معرفی شده است و شدیداً در حال اثبات آن است که یک انقلاب در صنعت وِب را رقم میزند. با این تفاسیر، آیا وباسمبلی زبان برنامهنویسی است؟ این فناوری به خودی خود، یک زبان برنامهنویسی نیست، در واقع برنامهنویسان برنامههای خود را توسط زبانهای سطحبالا مانند C یا ++C و حتی Rust مینویسند و آن را کامپایل و در قالب باینری با پسوند فایل .wasm وارد میکنند. توجه داشته باشید که وباسمبلی جایگزینی برای جاوااسکریپت نیست، درواقع قرار است در کنار جاوااسکریپت اجرا شود. به عنوان مثال شما میتوانید فقط یک کد محاسباتی بالا را در WebAssembly بسازید و آن را در کنار سایر کدهای جاوااسکریپت با وزن سبکتر استفاده کنید. همچنین شما برای بارگذاری ماژول wasm در مرورگر به جاوااسکریپت نیاز دارید. فناوری وباسمبلی (WebAssembly) و یا WA چیست؟ وباسمبلی یا وَسم (Wasm، اغلب به طور مخفف) استانداردی باز است که یک قالب جدید دستورالعملهای باینری را معرفی میکند. این فناوری نوید این را میدهد که برنامهها با کارآیی (پرفرمنس) بومیِ خود در بستر وِب اجرا شوند. به عبارت سادهتر میتوان گفت، این فناوری امکان این را میدهد که کدهای نوشته شده با زبانهای سطح بالاتر مانند C و ++C یا Rust به ماژول Wasm کامپایل شوند که مستقیماً در مرورگرهای مدرن قابل اجرا هستند. معماری وباسمبلی وباسمبلی به گونهای طراحی شده است که بر روی دستگاههای مجازی مبتنی بر پشته (stack-based) اجرا شود. بر خلاف ماشینهای رجیستری که عملوندهای آنها بر روی پردازندهٔ مرکزی قرار دارند و محاسبات در آن بخش اتفاق میافتد، در یک ماشین مبتنی بر پشته، بیشتر دستورالعملها به جای اینکه بر روی رجیستر اعمال شوند، بر روی پشته مینشینند. برای افزودن دو عدد بر روی ماشین مبتنی بر پشته، شمارههای مربوطه را در پشته ارسال میکنید. سپس دستور ADD را فشار میدهید. سپس دو عملگر و دستورالعمل از بالای صفحه ظاهر میشود و نتیجهٔ اضافی در جای خود قرار میگیرد. برخی از این نوع ماشینها عبارتند از .Net، JVM Runtime و غیره. وباسمبلی به معنای سنتی، پشتهای ندارد. درواقع هیچ مفهومی از اپراتورهای جدید ندارد. حتی خبری از GC در آن وجود ندارد. در عوض وباسمبلی دارای یک حافظهٔ خطی است، یعنی حافظه به عنوان طیف پیوسته از بایتهای بدون نوع نمایش داده میشود. در صورت نیاز به فضای بیشتر، ماژول وباسمبلیِ شما میتواند بلوک حافظهٔ خطی را افزایش دهد. نکته: WebAssemble فقط چهار نوع داده دارد: i32، i64، f32، f64 برای اعداد صحیح 32 و 64 بیتی و انواع شمارههای شناور آیندهٔ توسعهٔ وب چگونه میشود؟ اگرچه ممکن است وباسمبلی، جاوا اسکریپت را از بین نبرد، اما قطعاً قصد این را دارد که چهرهٔ front-end توسعهٔ وب را تغییر دهد. البته راه بسیاری در پیش است تا همهٔ تغییرات را تجربه کنیم. اما به اندازهٔ کافی میتوان آیندهٔ وب را پیشبینی کنیم: تنوع از نظر زبانی خیلی سریع موازی تنوع زبانی این فناوری به طور چشمگیری تنوع در استفاده از زبانهای برنامهنویسی را برای ساخت برنامههای تحت وب افزایش میدهد. در حال حاضر لیست زیر زبانهایی است که وباسمبلی از آنها پشتیبانی میکند: C/C++ Rust C#/.Net Java Python Elixir Go سرعت و کارآیی بسیار بالا فناوری WASM باعث میشود عملکرد برنامهها شگفتانگیز شود. در این زمینه مستنداتی وجود دارد که فایرفاکس در یک سری از نمونههای اولیه آن را ثابت میکند. همچنین طبق تجزیه و تحلیل برنامههای کاربردی توسط فیگما منتشر شده است که نشان میدهد پیادهسازیهای صورت گرفت در قالب asm.js که خود از سرعت بسیاربالای به خاطر پشتیبانی از سی++ دارد، با این وجود با فعال بودن ماژول WebAssembly چیزی حدود ۳ برابر بهبود زمان اجرا گرفته است. در این موارد ثابت شده است که با استفاده از ++C و کامپایلر کلنگ (LLVM) سرعت اجرای برنامهها با فعال بودن وباسمبلی بسیار چشمگیر است. موازی سازی طبیعتاً این مورد بسیار قابل بررسی و توجه است، چرا که این مبحث به طور کامل در وِب پیادهسازی نشده است. از آنجایی که تغییر به سمت پردازندههای چند هستهای حدوداً از سال ۲۰۰۵ آغاز شد، این امر به طور فزایندهای اتفاق میافتد که برای دستیابی به عملکرد بیشتر، نرمافزارها به موازی سازی نیاز دارند. با توجه به اینکه جاوااسکریپت از سیستم موازی پشتیبانی نمیکند، تصور کنید که با فعالسازی WASM امکان استفاده از تمامی هستههای پردازنده فراهم شود. من به عنوان نویسندهٔ این مقاله، تصور شما را از این فناوری نمیدانم. اما قطعاً با این تفاسیر این فناوری به عنوان یک انقلاب بزرگ در حوزهٔ وِب محسوب میشود. با توجه به ساختار برنامههای نوشته شده توسط زبانهای قدرتمندی چون ++C میتوان تصور کرد که برنامههای بسیار بهینه و قدرتمندی را در حوزهٔ اجرایی مرورگرها پشتیبانی کند. در حال حاضر ممکن استد شما فکر کنید که چرا کسی باید زبان سادهای مثل جاوااسکریپت را خدشهدار کند و یا به سمت زبانهای پیچیدهای مانند Rust، C و ++C برود. اکنون وباسمبلی کاملاً جدید است و جامعهٔ کافی در اطراف خود ندارد. اما باید توجه داشت وقتی از طریق این فناوری میتوان به ویدئوها، تصاویر و کتابخانههای رمزنگاری، یا استفاده از موتورهای گرافیکی و فیزیکی که از OpenGL استفاده میکنند، و یا حتی کتابخانهها و فریمورکهای قدرتمندی مانند Qt و غیره را میتوان در حوزهٔ وب مورد استفاده قرار داد. بنابراین فناوری وباسمبلی میتواند مسیری را برای رشد صنایع مختلف به خصوص شرکتهای بازیسازی و غیره باز کند. افزایش کارآیی (پرفرمنس) بسیار شدید که توسط وباسمبلی فراهم میشود، همانند اجرای برنامههای دسکتاپی است که میتوان آن را بر روی وب نیز مشاهده کرد. با این روال ممکن است وباسمبلی در سالهای آینده، با نرمافزارهای رومیزیِ بومی برابری کند.
-
3 امتیازبه نام خدا با سلام خدمت دوستان گرامی. از آنجایی که کامپایل هر کتابخانه مرتبط با زبان C++ در ویندوز نکات و فوت و فن خاص خود را دارد لذا تصمیم بر آن شد تا در اینجا به نحوه کامپایل کتابخانه Curl در این سیستم عامل بپردازیم. مشخصات کلی کامپایلر و کتابخانه به شرح زیر میباشد: Curl: 7.68.0 Microsoft Build Tools: 15.9.18 Compiler and OS Architectures: x64 ابتدا به این سایت رفته و کد منبع Curl را دریافت نمایید، دقت کنید که باینری کتابخانه Curl برای ویندوز موجود است ولی با کامپایلر MinGW برای ویندوز کامپایل شده که مطلوب ما نمیباشد. به دلیل اعلام نویسندگان Curl در رابطه با نگهداری ضعیف در پشتیبانی از CMake لذا به شکل مستقیم از کنسول مایکروسافت و Makefile سازگار با آن یعنی Makefile.vc استفاده خواهد شد. پس از دریافت و استخراج محتویات، میبایست کنسولx64 Native Tools Command Prompt for VS 2017 را باز کرده و دستورات زیر را مطابق شکل در آن وارد میکنیم: F: cd F:\curl-7.68.0\winbuild که دستور اول برای تغییر درایور و دستور دوم نشانی محل استخراج کتابخانه Curl روی سیستم نگارنده مطلب میباشد. سپس دستور زیر را وارد میکنیم: nmake /f Makefile.vc mode=dll که در دستور بالا /f مشخص کننده نشانی makefileمورد نظر و modeمشخص کننده نحوه کامپایل کتابخانه به شکل ایستا یا پویا را شامل میشود که در اینجا کتابخانه به شکل پویا کامپایل میشود. چنانچه مایل باشیم کتابخانه به شکل ایستا کامپایل شود میبایست دستور زیر را وارد کنیم: nmake /f Makefile.vc mode=static پس از ورود دستور بالا کتابخانه در مسیر F:\curl-7.68.0\ پوشهای با نام buildsساخته و فایلهای حاصل از کامپایل را در آن ذخیره میکند که در تصویر زیر نتیجه نهایی کامپایل آورده شده است. حال یک پروژه ساده از نوع Plain C++ Application در Qt Creator به منظور آزمایش کامپایل صحیح کتابخانه Curl ایجاد میکنیم. قطعه کد زیر را در فایل main.cpp وارد میکنیم: #include <curl\curl.h> int main() { CURL *curl; curl = curl_easy_init(); curl_easy_cleanup(curl); return 0; } و درنهایت در فایل CMake پروژه دستورات زیر را وارد میکنیم: cmake_minimum_required(VERSION 3.5) project(Curl LANGUAGES CXX) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_executable(Curl main.cpp) target_include_directories(Curl PRIVATE "F:/curl-7.68.0/builds/libcurl-vc-x64-release-dll-ipv6-sspi-winssl/include") target_link_libraries(Curl PRIVATE "F:/curl-7.68.0/builds/libcurl-vc-x64-release-dll-ipv6-sspi-winssl/lib/libcurl.lib") در گام آخر نیاز است تا فایل dll حاصل از کامپایل کتابخانه را در کنار فایل اجرایی پروژه قرار داده تا برنامه بدون مشکل اجرا شود این فایل در شاخه bin واقع در پوشه builds محل کامپایل کتابخانه موجود میباشد. چنانچه کتابخانه را به شکل ایستا کامپایل کرده باشیم نیاز است تا ماکرو CURL_STATICLIB را قبل از ورود هرگونه فایل سرآیند کتابخانه Curl مطابق زیر تعریف کنیم: #define CURL_STATICLIB متن کامل کد با رعایت نکته گفته شده چنین میباشد: #define CURL_STATICLIB #include <curl\curl.h> int main() { CURL *curl; curl = curl_easy_init(); curl_easy_cleanup(curl); return 0; } چنانچه مشکل یا ایرادی در نوشته بالا ملاحظه نمودید، نگارنده مطلب را بی خبر نگذارید. سپاس فراوان.
-
3 امتیازWindows Access Control List (ACL) قسمت اول (مفاهیم) مباحث مورد بررسی در این مقاله: Access Control Access Control Model Access Control Components مقدمه: در این مقاله ما تلاش میکنیم که چگونگی اجرای امنیت در سیستم عامل های ویندوز را یادبگیریم. Access Control یکی از مهمترین و اساسی ترین مباحث در Windows SDK Platform از دسته امنیتی می باشد. ما با Access Control که در ویندوز استفاده میشود شروع می کنیم و سپس در هر بخش ، به جزئیات بیشتری می پردازیم. در این مسیر ما توابع موجود برای دستکاری و تعامل با شیئ های متنوع ویندوز در بحث امنیت را نیز بررسی می کنیم. برنامه کاربردی در بخش های بعدی ارائه خواهد شد. برنامه نمونه، برنامه سطح پایین به زبان C ، بدون هیچ رابط کاربری گرافیکی (GUI) برای یادگیری بهتر می باشد. Access Control: در سند های ماکروسافت (MSDN) ذکر شده است که در آغاز، سیستم عامل های ویندوز از استاندارد منسوخ کلاس C2 پیروی می کردند. Access Control به این موضوع اشاره میکند که چه کسی به چه منابعی از سیستم عامل میتواند دسترسی داشته باشد. برنامه ها توابع کنترل سطح دسترسی را فراخوانی می کنند تا تنظیم کنند که چه کسی میتواند به منابع خاصی دسترسی داشته باشد، یا اینکه دسترسی به منابع فراهم شده توسط برنامه ها را کنترل کند. Access Control Model: Access Control Model شما را قادر می سازد توانایی یک فرایند را برای دسترسی به securable object ها یا انجام کارهای مختلف مدیریت سیستم، کنترل کنید. یک فرایند، یک security context است که یک برنامه در آن اجرا می شود. معمولا security context با کاربر مرتبط است، بنابر این تمام برنامه ها تحت token فرایند، با permissions و privilegesصاحب کاربر اجرا می شوند. Access Control Components: دو مولفه اساسی در مدل کنترل دسترسی وجود دارد: Access tokens: که شامل اطلاعاتی در مورد کاربر داخل شده می باشد. Security descriptors: که حاوی اطلاعات امنیتی است که از یک securable object محافظت می کند. زمانی که یک کاربر وارد سیستم می شود، سیستم نام و رمز عبور کاربر را تایید می کند. اگر ورود به سیستم موفقیت آمیز بود، سیستم یک access token تولید می کند. هر فرایندی که به نمایندگی از این کاربر اجرا می شود یک نسخه از این access token را خواهد داشت. access token از شناسه های امنیتی (SID) تشکیل شده که حساب کاربری (user account) و هر حساب گروهی (group accounts) را که کاربر به آن تعلق دارد را شناسایی می کند. این شناسه حاوی لیستی از privileges است که توسط کاربر یا گروه کاربرها نگهداری می شوند. سیستم زمانی که یه فرایند سعی می کند تا به یک securable object دسترسی پیدا کند یا درخواست گرفتن امتیاز administration را می دهد، از این نشانه برای شناسایی کاربر استفاده میکند. وقتی یک securable object ایجاد می شود، سیستم به آن security descriptor اختصاصی می دهد که حاوی اطلاعات امنیتی است که توسط سازنده آن مشخص شده است، یا اگر توسط سازنده مشخص نشده باشد اطلاعات امنیتی پیش فرض را به آن اختصاص می دهد. برنامه ها می توانند از توابع برای بازیابی و تنظیم اطلاعات امنیتی برای یک شئ موجود استفاده کنند. security descriptor مالک شئ را مشخص می کند و میتواند شامل access control lists (ACLs) زیر باشد: Discretionary access control list (DACL): کاربرها و گروه هایی را که اجازه دسترسی به شئ را دارند یا ندارند مشخص می کنند. System access control list (SACL): که نحوه کنترل حسابرسی سیستم را برای دسترسی به شئ کنترل می کند. یک ACL از لیستی از access control entries (ACEs) تشکیل شده. هر ACE یک مجموعه حقوق دسترسی را مشخص می کند که شامل یک SID می شود که یک سرپرست برای کسی که حق اجازه دادن، رد کردن یا حسابرسی را می دهد، مشخص میکند. یک حساب کاربری (user account)، گروه کاربری (group account)، جلسه ورود (logon session) میتواند یک سرپرست باشد. یک جلسه ورود زمانی آغاز می شود که کاربر وارد کامپیتر شود. تمام فرایندها در یک logon session دارای primary access token شبیه به یکدیگر می باشند. access token شامل اطلاعات درباره security context جلسه ورود ، شامل SID کاربر، شناسه ورود به سیستم و logon SID می باشد. تصویر زیر نشان می دهد که وقتی یک کاربر وارد سیستم می شود چه اتفاقی می افتد. به خاطر داشته باشید که کاربر نکته مهمی نیست، بلکه نام کاربری و رمزعبور وی در سیستم ایجاد شده است. کاربر تنها به عنوان یک شئ در ویندوز اعتبار دارد. یک access token یک شئ است که security context یک فرایند یا ریسمان را توصیف می کند. اطلاعات داخل token شامل هویت و امتیازات یک حساب کاربر مرتبط با فرایند یا ریسمان می باشد. زمانی که یک کاربر وارد سیستم می شود، سیستم رمز ورود کاربر را با اطلاعات ذخیره شده در پایگاه داده امنیتی خود مقایسه کرده، و آن را تایید یا رد میکند. اگر رمز ورود تایید گردد، سیستم یکaccess token تولید میکند. هر فرایندی از طرف این کاربر اجرا گردد یک کپی از این access token را دارد. سیستم از این access token برای شناسایی کاربر، زمانی که یک ریسمان با یک شئ قابل اطمینان در تعامل است یا تلاش می کند که یک کار سیستمی را انجام دهد که به امتیاز (خاصی) نیاز دارد استفاده میکند. access token ها از اطلاعات زیر تشکیل شدند: SID صاحب حساب. SID های گروه هایی که کاربر عضو آن هستند. SID ورود به سیستم نشان دهنده logon session اخیر می باشد. لیستی از privilege هایی که توسط کاربر یا گروه های کاربر در اختیار دارد. صاحب SID. SID برای primary group. DACL پیشفرض، که سیستم از آن استفاده می کند، زمانی استفاده می شود که کاربر یک securable object، بدون مشخص کردن یک security descriptor می سازد. منبع access token. اینکه آیا token یک token اصلی است یا جعل هویت است (primary or impersonation). لیست اختیاری محدود کننده SID ها(optional list of restricting SIDs). سطح جعل هویت جاری. سایر آمار. هر primary token یک access token است که معمولا فقط به وسیله هسته ویندوز ساخته می شود. ممکن است آن به یک فرآیند اختصاص داده شود تا اطلاعات امنیتی پیش فرض برای آن فرآیند را نشان دهد. impersonation token یک access token است که برای گرفتن اطلاعات امنیتی یک فرآیند کلاینت ایجاد شده است و به سرور اجازه می دهد تا فرایند کلاینت را در عملیات امنیتی جعل هویت کند. هر فرایند یک primary token دارد که security context حساب کاربر که با فرایند مرتبط است را توصیف میکند. به صورت پیشفرض، سیستم از primary token زمانی استفاده می کند که یک ریسمان یک فرایند با یک securable object در تعامل باشد. علاوه بر این، یک ریسمان می تواند یک حساب کاربر را جعل هویت کند. جعل هویت به ریسمان اجازه می دهد با استفاده از security context با securable object ها در تعامل باشد. ریسمانی که کلاینت را جعل هویت می کند هر دو خاصیت primary token و impersonation token را دارد. شما می توانید با فراخوانی تابع OpenProcessToken() هندل primary token فرایند را بازیابی کنید. AdjustTokenGroups(): اطلاعات گروه را در access token تغییر می دهد. AdjustTokenPrivileges(): یک (یا چند) privilege را در access token فعال یا غیر فعال می کند. CheckTokenMembership(): مشخص میکند که یک SID مشخص شده در یک access token فعال است یا خیر. CreateRestrictedToken(): یک access token جدید می سازد که یک نسخه محدود شده از access token موجود می باشد. restricted token های شده می توانند SID های غیر فعال، privilege های پاک شده، و یک لیست از SID های محدود شده داشته باشند. DuplicateToken(): یک access token جدید از روی access token موجود می سازد. DuplicateTokenEx(): یک primary token یا impersonation token می سازد که یک نسخه از یک access token موجود را کپی می کند. GetTokenInformation(): اطلاعات یک access token را بازیابی می کند. IsTokenRestricted(): مشخص میکند که آیا یک token یک لیست از SID های محدود کننده دارد یا نه. OpenProcessToken(): هندل یک primary access token که مربوط به به یک فرایند است را بازیابی می کند. OpenThreadToken(): هندل یک impersonation access token که مربوط به به یک نخ است را بازیابی می کند. SetThreadToken():به یک نخ یک impersonation token را حذف یا اختصاص می دهد . SetTokenInformation(): صاحب token، primary group یا DACL پیشفرض را تغییر می دهد. تابع های access token از ساختار های زیر برای توصیف کامپوننت های access token استفاده می کنند. TOKEN_CONTROL: اطلاعاتی که یک access token را مشخص می کند. TOKEN_DEFAULT_DACL: عضو DACL پیش فرض سیستم که از آن در security descriptors اشیائ جدیدی که توسط نخ ها ساخته می شود استفاده می کند. TOKEN_GROUPS: یک (یا چند) SID و ویژگی های group SID ها در access token را مشخص می کند. TOKEN_OWNER: مالک پیش فرض SID برای توصیف کننده اشیائ جدید. TOKEN_PRIMARY_GROUP: یک primary group SID پیش فرض برای توصیف کننده امنیت شئ جدید. TOKEN_PRIVILEGES: یک privilege مرتبط با یک access token. همچنین مشخص می کند که آیا privilege ها فعال شده اند یا خیر. TOKEN_SOURCE: منبع access token. TOKEN_STATISTICS: آمار مرتبط با یک access token. TOKEN_USER: SID کاربر مرتبط با access token. تابع های access token از enumeration type های زیر استفاده می کنند. TOKEN_INFORMATION_CLASS: نوع اطلاعاتی که قرار است ازaccess token گرفته شود یا تنظیم شود را مشخص می کند. TOKEN_TYPE: نوع access tokenرا مشخص میکند که قرار است از نوع primary یا impersonation باشد. تصاویر دیگر از ساختار token: مثال: Privilege: حق سیستم برای انجام کارهای مختلف مربوط به سیستم مانند خاموش کردن سیستم، بارگیری دیوایس درایور یا تغییر زمان سیستم. access token کاربر، شامل یک لیست از privilege ها که به وسیله کاربر یا گروه کاربر ها نگه داری می شود. securable object: یک شئ است که می تواند یک security descriptor داشته باشد. هر چیزی در ویندوز که Windows objects نام گرفته باشد securable است. برخی اشیاء بی نام، مانند اشیاء process و thread، هم نیز می توانند security descriptors داشته باشند. برای اکثر securable object میتوانید یک security descriptor در هنگام فراخوانی تابع سازنده شئ مشخص کنید. برای مثال می توانید security descriptor را در توابع CreatFile و CreatProcess مشخص کنید. به علاوه، تابع های امنیتی ویندوز شما را قادر می سازند تا اطلاعات امنیتی securable objects سیستم عامل های دیگر را گرفته یا تنظیم کنید. security context: ویژگی های امنیتی یا قانون هایی که در حال حاضر قابل اجرا هستند. برای مثال، کاربر فعلی که وارد سیستم شده است یا شماره شناسایی شخصی که با یک کارت هوشمند وارد شده. security descriptor: ساختار و داده های همراه که شامل اطلاعات امنیتی برای یکsecurable object است. security descriptor صاحب شئ و primary group را مشخص می کند. همچنین میتواند حاوی یک DACL (که دسترسی به یک شئ را کنترل می کند)، و یک SACL (برای کنترل دستیابی به شئ) است. پایان قسمت اول
-
3 امتیازپاسخ به این سوأل صرفاً از نظر نوع زبان کافی نیست و شاید منطقی نباشد. و چون ساختار و قوانین تحت چهارچوب مشخصی برای این موضوع نداریم، از نظر من دلایل بسیاری وجود دارد که بر روی قیمتگذاری میتواند تأثیرگذار باشد که به آنها اشاره میکنم: تجربه و کیفیت خدماتِ قابل ارائهی فرد یا شرکت توسعهدهنده جهت انجام آن اینکه شخص یا شرکت مربوطه بتواند تضمین کند یا آسودگی خاطر را به مشتری بدهد که پروژهی آن در زمان مشخص با نتیجهی قابل قبول ارائه خواهد شد بسیار مهم است، قطعاً اطمینان خاطر و جلوگیری از احتمالات دوبارهکاری و نا رضایتی خودش ارزشمند خواهد بود که ممکن است در هزینهی نهایی پروژه موثر باشد. تضامین و خدمات پس از فروش «پشتیبانی، بهروزرسانی و غیره» هرچند پشتیبانی و بهروزرسانی محصولات نرمافزاری یکی از مراحل توسعه و چرخهی نرمافزار است، اما در دسترس بودن و تضمین پشتیبانی از سمت توسعهدهنده قطعاً در هزینههای آن نسبت به دیگر موارد متفاوت خواهد بود. نوع قرارداد و مذاکراتی که ممکن است طرفین در قبال تعهد به آنها هزینههایی را اضافه کند معمولاً در قراردادهای طرفین به نکاتی اشاره میشود، مانند: در دسترس بودن منبعکد «سورسکد» و یا مستند سازی غیر معمول و اختصاصی که حتماً در قیمت نهایی یک محصول و پروژه موثر خواهد بود. محدودیتها و دلایل قانع کننده برای انتخاب یک ابزار و نیاز به دانش و مهارتهای تخصصی ممکن است پروژهای که به شما پیشنهاد میشود، با یک سری محدودیتهای فنی بر اساس نوع زبان، مهارت و بسترهای پیادهسازی مواجه باشد که با توجه به ارائهی راهکارهای مناسب توسط متخصص «توسعهدهنده» که واقعاً نیاز به تجربه و دانش در حل آن است وابسته خواهد بود. در چنین حالتهای ارزش حل مسائل میتواند در خود پروژه تأثیر بگذارد. در نهایت بعد از بررسی موارد این چنینی که من تنها به برخی از آنها اشاره کردم، میتوانید به خروجیها و نتایج حاصل از خود ابزار که در اینجا «++C» است اشاره کرده و مشتری را نسبت به آن قانع کنید. برای مثال، ویژگیِ چند-سکویی خود به تنهایی یک مزیت بسیار بزرگ است که میتواند در حذف هزینههای احتمالی مانند بازنویسی در زمان توسعه و بهروز رسانی در قالب سکوهای مختلف موثر باشد. نوع مذاکره در ساخت و توسعه در قالب زمان مشخص برای سادهسازی مسئله و حل بایدها و نبایدها نیز مشخص سازی یک نرخ یا رنج قیمت برای کار بر روی پروژه میتواند موثر باشد. برای مثال، بر اساس تعداد ساعت و زمان مشخص در روز میتوانید یک محاسبهی مشخصی برای مشتری خود انتقال دهید تا هم زمان تحویل و هم مدت زمات مورد نیاز برای توسعه را بداند. دربارهی همین موضوع چند-سکویی که تنها یک ویژگی از مزایای سیپلاسپلاس است مثالی بزنم: فرض کنید قرار است مشتری یک نرمافزار تحت موبایل از شما درخواست کند، در این صورت اگر قرار باشد منطقی مذاکره کنید، بهتر است مشتری را متوجه این سازید که برای ساخت یک اپلیکیشن در سکوهای مختلف مانند iOS، Android و غیره نیاز به تخصص، زمان و هزینههای جدا از هم است. اما اگر شما به عنوانی توسعهدهندهی تمام عیار فولاِستک هستید، میتوانید مشتری را قانع کنید که صرفاً با یکپارچهسازی کدهای توسعه و ساختار بهینهی برنامههای نوشته شدهی تحت سی++ از صرف هزینههای احتمالی جهت توسعه جلوگیری میکنید و حتی در آینده نیازی نیست هزینههای اضافه بر مشتری تحمیل کنید. در این رابطه باید به یک هزینهی قابل قبول همراه با حفظ ارزشهای وارده را مطرح کنید. برای مثال، اگر قرار است یک اپلیکیشن برای دو پلتفرم مختلف توسعه یابد، اگر قیمتی بابت یک نرمافزار در دو سکوی مختلف استعلام و یا تخمین زده شده باشد، بهتر است شما با در نظر گرفتن نصف و یا حداکثر دو سوم آن همان کارها را با حفظ ارزشهای فنی و کاربری مشتری انجام دهید. بر اساس چنین مواردی نیازی به افزایش یا کاهش هزینهها در یک پلتفرم وجود ندارد چرا که تنها کاری که انجام خواهید داد همگردانی «کامپایل» کدها بر روی پلتفرم دیگر خواهد بود.
-
3 امتیازخب ! Build System چیست ؟ تمام برنامههایی که مینویسیم، معمولاً یک main.c دارند که نقطهٔشروع (start point) برنامهٔما هست. آیا همیشه همین یک فایله ؟ آیا همیشه نیازه که به یکصورت برنامه را کامپایل کنیم ؟ خب مسلماً جواب "نه" هست. چرا که ممکنه برنامهٔ شما دارای دهها فایل داشتهباشه، و نیاز داشتهباشید که هر فایل رو به صورتخاصی با فلگهای خاصی کامپایلکنید. اینجاس که "بیلد سیستم"ها وارد کار میشوند. به احتمال زیاد نمونههای زیادی مشاهده کردید که وقتی یک سورسیرا (source) از مخازن آنلاین گیت، مثل گیتهاب یا گیتلب دریافت میکنید در فایل راهنما (README.md) در بخش Build نوشته که وارد دایرکتوری بشید و دستور make و بعد make install را وارد کنید، دقیقاً کاری که میکنید اینکه برنامهٔ GNU Make را صدا میزنید که فایل تنظیمات رو از دایرکتوری جاری بخواند و دستورات تعیین شده رو انجام بده، این دستورات در فایلی به نام Makefile نوشته میشود. نصب کردن GNU Make این برنامه معمولاً روی تمام سیستمعاملهای معقول مثل GNU/Linux یا اقوام BSD نصب هست، درصورتیکه نبود میتوانید با استفاده از مدیربستهٔ سیستمعاملتون اقدام به نصب کنید، مثلاً برای نصب روی سیستمعامل Debian - Ubuntu - Ubuntu Mint میتوانید به اینصورت عمل کنید : $> apt install make چه کنیم با GNU Make ؟ اوّل از همه باید یک برنامهای داشتهباشیم که بخوایم براش Build System تعیین کنیم و دستورات Makefileش رو بنویسیم. یک نمونهٔ ساده کد چند تکهای را میتوانید از اینقسمت دریافت کنید. ما سه فایل arg.c/arg.h و main.c را به اینصورت داریم (یک ساختار معقول) : . ├── build ├── obj └── src ├── arg.c ├── arg.h └── main.c خب حالا ما باید Makefile خودمان را داخل دایرکتوری ریشه درست کنیم، قبلاً هم گفتم : "برنامهٔ GNU Make به دنبال فایلی به اسم Makefile یا GNUmakefile یا makefile میگرده". در Makefile میتوانیمما قوانین (rule) برای ساخته شدن چیزی و متغیرهایی تعریف کنیم. اینجا من توضیحات خلاصهای را میگویم، باقیماندهٔ مطالب را باید از مستنداترسمی GNU Make یا راهنمای سریع دنبال کنید. هر قوانینای که تعریف میکنیم دارای این ساختار هست : نیازها : هدفها دستورات مثلاً ما میخواهیم که برنامهٔکامپایل شدهٔمان، با اسم args در دایرکتوری build/ قرار بگیره. اینجا "هدف"ما میشه build/args و نیازما هم فایلهای کامپایل شدهٔ arg.c و main.c هست. اوه ! یک هدف دیگههم پیدا شد؛ الآن هدف دوّمما فایلهای کامپایل شدهٔ obj/arg.o و obj/main.o هست و نیازمان هم سورسهای این فایلها یعنی src/arg.h و src/arg.c و src/main.c. خب خیلی زیاد شدن، بهتره که از آخر شروع کنیم و نیازهایمان را برطرف کنیم، اوّلین نیاز فایلهای کامپایلشده هستن : obj/main.o obj/arg.o : src/main.c src/arg.c src/arg.h gcc -c -o obj/main.o src/main.c gcc -c -o obj/arg.o src/arg.o * نکته : سعی نکنید دستورات Makefile را از منطقهٔ کد کپی نکنید، کمی تلاش کنید و بنویسید. خب قبول دارم خیلی زیاد و زشت شد، بیاید این قانون (rule) را به دو تیکه قسمت کنیم : obj/arg.o : src/arg.c src/arg.h gcc -c -o obj/arg.o src/arg.c obj/main.o : src/main.c gcc -c -o obj/main.o src/main.c اگر تا انتها متن ادامه بدید حتماً کوتاهترم خواهد شد :). خب؛ object fileها یا همان فایلهای کامپایل شدهیمان را به دستآوردیم. حالا باید قانون (rule) نیاز اوّلمان را بنویسیم، چه چیزی نیاز داشتیم ؟ فایل کامپایل شدهٔ build/args که نیاز به object fileها داشت، حالا object fileها را داریم و باید نیاز هدفمان را برطرف کنیم : build/args : obj/main.o obj/arg.o gcc -o build/args obj/main.o obj/arg.o obj/arg.o : src/arg.c src/arg.h gcc -c -o obj/arg.o src/arg.c obj/main.o : src/main.c gcc -c -o obj/main.o src/main.c تمام شد. ما دستورات Build System خودمان را به زبان برنامهٔ GNU Make نوشتیم؛ حالا کافیه که فقط وارد دایرکتوریای که فایل Makefile هست بشیم و از ترمینال برنامهٔ make را فراخوانی کنیم : $> make gcc -c -o obj/main.o src/main.c gcc -c -o obj/arg.o src/arg.c gcc -o build/args obj/main.o obj/arg.o حالا میتوانیم برنامهٔ خودمان را اجرا کنیم : $> build/args -name Ghasem -family Ramezani Input Name is [Ghasem] Input Family is [Ramezani] دقّت کرده باشید ما توی نوشتن Makefileمان نیازمندیهارو یکی بالاتر از دیگری نوشتیم. چرا ؟ به خاطر اینکه GNU Make میاد از اوّل فایل شروع میکنه و قوانین (rules)ها را اجرا میکنه. بزارید با یک مثال نشان بدم. Makefile زیر را مدنظرتون داشتهباشید : obj/arg.o : src/arg.c src/arg.h gcc -c -o obj/arg.o src/arg.c obj/main.o : src/main.c gcc -c -o obj/main.o src/main.c build/args : obj/main.o obj/arg.o gcc -o build/args obj/main.o obj/arg.o ما نیاز اصلی خودمان را آخرین قانون (rule) نوشتیم. حالا برنامهٔ make را اجرا میکنیم تا رفتارَش را بهتر متوجه بشیم : $> make gcc -c -o obj/arg.o src/arg.c دیدید ؟ خیلی ساده برخورد کرد، اوّلین قانون (rule) را نگاه کرد تنها نیازمندیش فایلهای src/arg.c و src/arg.v بودن که وابسته به چیزی نبودند و هدفشان را تأمین کردند. اگر بخواهیم باقی قوانین (rules) را فراخوانی کنیم، باید صراحتاً مشخص کنیم : $> make obj/main.o gcc -c -o obj/main.o src/main.c $> make build/args gcc -o build/args obj/main.o obj/arg.o خب دیگه امیدوارم دلیل اینکهما نیازمندی اصلیه خودمان را اوّلین قانون (rule) قرار دادیم را متوجه شده باشید. وقتی make به نیازمندیه obj/arg.o و obj/main.o برای تأمین build/args برمیخوره ادامهٔ قوانین را پیمایش میکنه تا نیازمندیها را برطرف کنه. (اگر گیج شدید احتمالاً، پیشنهاد میکنم همین موارد را روی کاغذ کشیده و قسمت : نیازمندیها و هدفها و دستورات هر قانون را مشخص کنید.) میتوانیم قوانینی (rules) تعریف کنیم برای کارهای خاصی، مثلاً همان make install، یعنی قانون install را فراخوانی کن؛ حالا ما قانون clean را برای حذف کردن فایلهای کامپایلشده مینویسیم : clean : yes | rm -vf build/* obj/* البته باید در اینجا نکتهای را هم حواسمان باشد، باید به GNU Make بگوییم که قانون clean ، یک قانون الکیهست، و با یک "هدف" اشتباه نشود. به اینصورت قانون را ویرایش میکنیم : .PHONY : clean clean : yes | rm -vf build/* obj/* نگرانیای هم دربارهٔ Wildcard ها نداشتهباشید، GNU Make دستتون را باز گذاشته :). متغیرها در GNU Make مسلماً هرجا سخنی از متغیراست، سر و کلهٔ راحتیکار (و تا حدودی پیچیدگی) پیدا میشود. ما میتوانیم متغیرهم داخل Makefile خودمان داشتهباشیم. مثلاً فرض کنید که نیاز دارید تمام سورسکدها با کامپایل clang و سطحبهینهسازیه 3 کامپایل بشند. نیازی نیستکه هربار اینارو تایپ کنیم. کافیه براشون متغیرتعریف کنیم : CC = clang OP = -O3 OBJECT = obj/main.o obj/arg.o ARGS = src/arg.c src/arg.h build/args : $(OBJECT) $(CC) $(OP) -o build/args $(OBJECT) obj/arg.o : $(ARGS) $(CC) $(OP) -c -o obj/arg.o src/arg.c obj/main.o : src/main.c $(CC) $(OP) -c -o obj/main.o src/main.c clean : yes | rm -vf build/* obj/* متغیرهای به خصوصی نیز در GNU Make تعریف شدهاند که میتوانند کار مارا بسیار راحتتر کنند، برای مثال میتوانیم قانون object fileها را به اینصورت بازنویسی کنیم : obj/%.o : src/%.c $(CC) $(OP) -c -o $@ $? برای اطلاعات بیشتر به راهنمایسریع GNU Make مراجعه کنید. یادداشتها یا Code Comments برای استفاده از قابلیت Comment گذاری در کد، کافیه که اوّل خط خودتون از کاراکتر # استفاده کنید. خب دوستان، سعی کردم کلیّات مبحث را بگم؛ ابزار Make قابلیتهای بسیار زیادی داره که حتماً باید خودتون مطالعه کنید. مثلاً خواستید Makefile شما یک Makefile دیگه را صدا بزنه، یا حتیٰ دستورات شرطی اجرا بکند و یا از همه مهمتر بر اساس معماری پلتفرم شما عملیات کامپایل را انجام بده و ... . - موفقوپیروز باشید. ?
-
3 امتیازبا سلام، طبق بررسیهای لازم تغییراتی در گروههای کاربری اعمال شده است که از این پس کاربرانی که به عنوان کاربران فعال در حوزهٔ یادگیری و مشارکت در بحثها فعال میکنند از گروه پیشفرض کاربران عادی به کاربران رسمی تغییر دسترسی خواهند داشت. طبق آخرین اصلاحیه در سند( شرایط کسب مجوز فعالیتی و ارتقا حسابکاربری) ، کاربران عضو در این گروه دسترسی لازم برای ارسال تصویر، افزودن امضاء و همچنین عدم نیاز به تایید مطالب توسط مدیریت را خواهند داشت.
-
3 امتیازآموزش زبان برنامهنویسی سوئیفت - جلسه چهارم مواردی که در این جلسه یاد خواهید گرفت: کامنتها، دو ویژگی نوعهای داده Int، آپِریِترها ( Operators )، کلمات کلیدی break,continue,fallthrough کامنتها در زبان برنامهنویسی سوئیفت مثل اکثر زبانهای برنامهنویسی دیگر، از کامنتها استفادهای زیادی میشود و معمولا برای اهدافی کامنتها استفاده میشوند و میتوانند شامل موارد زیر باشند: برای غیرفعال کردن موقتی یک قسمت یا بخشی از کُد برای توضیح دادن کدها برای دیگر برنامهنویسان یا توسعهدهندگان یا توضیح کد برای اینکه در مراجعات بعدی به پروژه کارکرد همان قسمتی که کامنت کردید را متوجه شوید انواع کامنتها در زبان برنامهنویسی سوئیفت؛ تَک خطی ( single-line ) چند خطی ( multi-line ) در کامنت تک خطی، با گذاشتن دو علامت // میتوانید توضیحات خود را فقط در همان خط درمورد کُد مورد نظر بنویسید و بعد از آن کامنت شما در واقع در حال تعریف دستور جدید هستید! این کامنت، به این صورت استفاده میشود؛ let _web_site_name : String = "www.iostream.ir" print(_web_site_name) // Ouput the string of www.iostream.ir در مثال بالا همانطور که مشاهده میکنید از کامنت تک خطی استفاده کردیم، و بعد از این کامنت شما نمیتوانید انتظار داشته باشید که در خط جدید دوباره حالت کامنتگذاری برای شما همچنان فعال باشد! چرا که در خط بعدی دستوری جدید داریم نه کامنتی ادامهی کامنت قبل!. و اما کامنت چند خطی که میتوانید در تعداد خطهای بیشتر، توضیحات خود را بنویسید؛ let _web_site_name : String = "www.iostream.ir" /* We can also use from of print("String.. and \(_web_site_name)") */ print(_web_site_name) در مثال بالا که مشاهده میکنید، شما هیچ محدودیتی برای اضافه کردن توضیحات بیشتر برای خود کدهای خود ندارید و تا هر چند خط توضیحات که مدنظرتان بود، میتوانید استفاده کنید. دو ویژگی نوع دادهی Int اگر بخواهیم کوچکترین و بزرگترین عدد موجود از نوع دادهی Int را بدست آوریم، از دو ویژگی max,min استفاده میکنیم. هر دو ویژگی به همراه مثال در زیر آورده شدهاند؛ print("Max => \(Int.max)") print("Min => \(Int.min)") با اجرای کدهای بالا، بزرگترین مقدار موجود نوع دادهی Int و همچنین کوچکترین آن به شما نمایش داده خواهد شد. آپِریِترها ( Operators ) آپریترها در هر زبان برنامهنویسی به عنوان پایه و اساس محاسبات و در بعضی موارد برای کارهای دیگر استفاده میشوند. محاسباتی مانند، جمع، تفریق،تقسیم،ضرب و باقی مانده و ... در سوئیفت این 8 دسته آپریتر وجود دارد: اِنتسابی ( Assigment Operator ) محاسباتی ( Arithmetic Oprerator ) باقیمانده ( Remainder Operator ) مُرکب ( Compound Assigment Operator ) مقایسهای ( Comparison Operators ) ترِنِری ( Ternary Conditonal Operators ) دامِنه ( Range Operator ) منطقی ( Logical Operators ) اینها، کل آپریترها در سوئیفت هستند که هر کدام عمل مخصوص به خود را انجام میدهند. در مثالهای زیر هر کدام از اینها را به همراه مثال برای شما آوردهایم. آپریتر اِنتسابی ( Assigment Operator ) اگر ما یک مقداری را به متغییری انتساب میدهیم، عملا داریم از آپِریِتر انتساب ( = ) استفاده میکنیم. چرا که کدنویسی از سمت چپ شروع میشود و این هم کاملا منطقی هم است که مقدار دهی به یک متغییر از سمت چپ صورت میگیرد و مقدار سمت راست را درون خود ذخیره میکند. به این مثال دقت کنید؛ let _web_site_name : String = "www.iostream.ir" // Assigment Operator ( = ) print("Type of \(type(of : _web_site_name ) and the website of name \(_web_site_name)") در مثال بالا مشاهده میکنید که مقدار www.iostream.ir که یک مقدار رشتهای/متنی است را در متغیر web_site_name ذخیره میکنیم. این کار با استفاده از این علامت ( = ) انجام شده است. در خط بعد هم نوع متغییر و مقدار موجود در متغییر web_site_name که ذخیره شده است را نمایش میدهیم. آپریترهای محاسباتی ( Arithmetic Oprerator ) در قسمتهایی از پروژه پیش آمده که ما باید محاسباتی را انجام بدهیم. این کار با استفاده از این آپریترها انجام میشود. که شامل: +،-،/،* و ٪ هستند. برای هر کدام از اینها، مثالهایی در زیر آورده شده است؛ جمع ( + ) var number_one, number_two : Int8 number_one = 50 number_two = 50 print("Result = > ", number_one + number_two) // Output the number 100 در مثال بالا همان طور که مشاهده میکنید، ابتدا دوم متغییر با نوع Int8 تعریف کردهایم و سپس در خطوط بعد به آنها مقادیر ۵۰ را دادهایم. در نهایت عمل جمع ( + ) را روی آنها به صورت مستقیم انجام داده و نمایش میدهیم. یا اگر سادهتر بخواهیم تعریف کنیم، آپریتر ( + ) عمل جمع کردن اعداد و یا متصل کردن دو رشته را بر عهده دارند؛ var web_site_name, platform_name : String web_site_name = " www.iostream.ir :)" platform_name = " www.fanoox.com ;)" print("Binding two string => ", web_site_name + platform_name) // Ouput the website name and platform name => www.iostream.ir :) www.fanoox.com ;) و به همین راحتی میتوانید تا بینهایت عمل جمع و متصل کردن رشتهها را انجام دهید. تنها نکتهای که باید توجه داشته باشید این است که سوئیفت در برخورد با اعداد و این آپریتر، آن عبارت را محاسباتی در نظر میگیرد و در برخورد دو یا چند رشته، آن عبارت را عمل متصل کردن و الحالق ( Concatentation ) در نظر میگیرد. تفریق ( - ) برای کم کردن دو مقدار عددی از هم استفاده میشود؛ var number_one, number_two : Int8 number_one = 80 number_two = 30 print("Result => ", number_one - number_two) // Output the number 50 مثال بالا به خوبی نشان میدهد که دو مقدار ۸۰ و ۳۰ از هم کم شده و در نتیجه، خروجی برابر ۵۰ خواهد بود. ضرب ( * ) عمل ضرب کردن دو عدد را انجام میدهد؛ var number_one, number_two : Int8 number_one = 50 number_two = 20 print("Result => ", number_one * number_two) // Output the number 1000 دقت کنید که نباید به حرف ( x ) که شبیه به ضرب در ریاضیات است اشتباه گرفته شود. تقسیم ( / ) عمل تقسیم کردن دو عدد را انجام میدهد؛ var number_one, number_two : Double number_one = 50.0 number_two = 20.0 print("Result => ", number_one / number_two) // Output the number 2.5 در محاسباتی که عمل تقسیم را انجام میدهیم باید به این نکته دقت کنیم که اگر پروژهی ما عملا برای محاسبات کار خاصی است باید از نوع دادهی Double یا Float استفاده کنیم که البته در محاسبات معمولی، نوع دادهی Float جوابگوی نیاز ما هم هست، اما در محاسباتی که نیاز به دقت بالایی دارند باید از نوع دادهی Double استفاده کنیم. باقیمانده ( ٪ ) توجه داشته باشید که این علامت را با درصد که شبیه همین است اشتباه نگیرید! چرا که در دنیای واقعی ما، علامت درصد برای نشان دادن مقداری از چیزی در یک محصول یا خدمات است ولی در دنیای کامپیوتر و برنامهنویسی این علامت، به معنای باقی ماندهی بین دو عدد است که بعد از تقسیمهای پیدرپی که صورت میگیرد، بدست میآید. این باقی مانده یا ۰ است یا ۱ ( حتما شما هم عاشق صفر و یکی هستید که اساس کار کامپیوتر و سیستم شما را تشکیل میدهد! ). این مثال را ببینید تا بهتر متوجه این موضوع شوید؛ var number_one, number_two : Int8 number_one = 10 number_two = 2 print("Result => ", number_one % number_two) // Output the number 0 اگر جزئیتر بخواهیم وارد شویم به این صورت است که ابتدا عدد ۱۰ بر ۲ تقسیم ( / ) شده و سپس حاصلی که بدست میآید ۵ است و سپس دوباره ۵ تقسیم بر ۲ شده و ۲ بدست میآید و در اینجا باقیمانده ۲ ٪ ۲ میشود ۰. آپِریِترهای مُرکب ( Compound Assigment Operator ) که شامل عبارتهای کوتاهشده یا به اصطلاح میانبری برای عمل انتساب و محاسبه را فراهم میکند که شامل: =+،=-،=*،=/،=٪ است. در زیر توضیح مختصر به همراه یک مثال آورده شده است. انتساب و جمع ( =+ ) در این حالت ما هم عمل انتساب را داریم و هم عمل جمع، با یک تیر دو نشان بزنید! به مثال زیر دقت کنید. var number_one : Int8 = 50 number_one += 50 print("Result =>", number_one) // Output the number 100 در خط دوم که ما با آن کار داریم، متغییر number_one مقدار ۵۰ را هم به آن اضافه به خودش اضافه کرده و در نهایت در خود متغییر number_one ذخیره و نتیجه ۱۰۰ نمایش داده میشود. که بدون استفاده از میانبر، به این شکل بود؛ var number_one : Int8 = 50 number_one = number_one + 50 print("Result =>", number_one) // Output the number 100 حتی میتوانیم برای اتصال یک رشته به رشتهی دیگر استفاده کنیم؛ var web_site_name : String = "www.iostream.ir :) " web_site_name += " www.fanoox.com ;) " print("Result =>" web_site_name) // Ouput the web site of name => www.iostream.ir :) www.fanoox.com ;) که در شکل ساده به این شکل نوشته میشد؛ var _web_site_name_and_platform_name : String = "www.iostream.ir :) " + " www.fanoox.com ;) " print("Result => ", _web_site_name_and_platform_name) // Ouput the web site of name and platform name => www.iostream.ir :) www.fanoox.com ;) انتساب و تفریق ( - ) مقدار سمت راست را از مقدار سمت چپ کم میکند و نتیجه در همان متغییر ذخیره خواهد شد؛ var number : Int8 = 80 number -= 30 print("Result =>", number) // Ouput the number 50 مقدار ۸۰ که مقدار فعلی متغییر number است، از مقدار ۳۰ که در سمت راست متغییر قرار دارد، کم میشود و در نهایت مقدار ۵۰ در همان متغییر یعنی number ذخیره خواهد شد. انتساب و ضرب ( =* ) ضرب مقدار سمت راست در مقدار فعلی متغییر سمت چپ را انجام میدهد؛ var number : Int8 = 80 number *= 30 print("Result =>", number) // Ouput the number 2400 انتساب و تقسیم ( / ) مشابه آپِریِتر تقسیم ( / )، تقسیم مقدار سمت راست را به متغییر سمت چپ انجام میدهد؛ var number : Int8 = 10 number /= 2 print("Result =>", number) // Ouput the number 5 انتساب و باقیمانده ( ٪ ) عمل باقیماندهی دو عدد که شامل مقدار فعلی متغییر سمت چپ و مقدار سمت را است را محاسبه کرده و در متغییر سمت چپ ذخیره میکند؛ var number : Int8 = 10 number ٪= 5 print("Result =>", number) // Ouput the number 0 آپِریِترهای مقایسهای ( Comparison Operators ) برای مقایسهی بین دو مقدار و در نتیجه به دست آوردن مقدار True یا False مورد استفاده قرار میگیرند. بیشترین استفادهی آنها در شرطها است، اما میتوان به صورت مستقیم هم از آنها هم استفاده کرد. این آپِریِترها شامل ==،=!،>،<،=<،=>،==!،=== هستند. برای هر کدام مثالی در زیر آورده شده است. مساوی ( == ) برای مقایسه دو مقدار استفاده میکنیم که در صورتی که مقادیر دو طرف مساوی باشند، مقدار True و در غیر اینصورت مقدار False برگشت داده خواهد شد؛ print("True and False => ", 2 == 2) // Output the true print("True and False => ", 2 == 3) // Output the false در مثال بالا به دلیل اینکه ۲ با ۲ برابر است، مقدار نمایش داده شده، true است. و در خط بعدی به این دلیل که مقدار ۲ برابر با ۳ نیست، مقدار false نمایش داده میشود.همچنین میتوانید در شرطها و حلقهها هم استفاده کنید: if 2 == 2 { print("Ok!") }else { print("NO!") } // Ouput the string Ok! نامساوی ( =! ) اگر مقدار برابر با مقدار مقابل خودش نباشد، نتیجه true و در غیر اینصورت نتیجه false خواهد بود. علامت ! ( نَقیض ) دقیقا معنا و مفهوم ( == ) را عوض میکند ( یعنی اگر مقداری true باشد، برعکس شده ( false ) و اگر false باشد ( true ) میشود. print("True and False => ", 2 != 3) // Output the true print("True and False => ", 2 != 2) // Output the false در مثال بالا، ۲ مساوی ۳ نیست و این درست است!. در خط بعدی ۲ برابر با ۲ است و این درست است! که در نتیجه، برعکس آن یعنی false نمایش داده میشود. کوچکتر ( > ) اگر مقدار سمت چپ کوچکتر از مقدار سمت راست بود، نتیجه true و در غیر اینصورت نتیجه false است؛ print("The operator ( < ) => ", 1 < 2) // Output the boolean true print("The operator ( < ) => ", 2 < 1) // Output the boolean false بزرگتر ( < ) اگر مقدار سمت چپ بزرگتر از مقدار سمت راست بود، نتیجه true و در غیر اینصورت نتیجه false خواهد بود؛ print("The operator ( > ) => ", 1 > 2) // Output the boolean false print("The operator ( > ) => ", 2 > 1) // Output the boolean true بزرگتر یا مساوی ( =< ) اگر مقدار سمت چپ، بزرگتر یا مساوی مقدار سمت راست بود، نتیجه true است، در غیر اینصورت، نتیجه false خواهد بود؛ print("The operator ( >= ) => ", 1 >= 1) // Output the boolean true print("The operator ( >= ) => ", 1 >= 2) // Output the boolean false کوچکتر یا مساوی ( => ) اگر مقدار سمت چپ، کوچکتر یا مساوی مقدار سمت راست بود، نتیجه true است، در غیر اینصورت، نتیجه false است؛ print("The operator ( <= ) => ", 1 <= 2) // Output the boolean false print("The operator ( <= ) => ", 1 <= 1) // Output the boolean true نکته: اولویت مساوی ( = ) در این مورد بالاتر از بزرگتر < یا کوچکتر > است و بنابراین در حلقهها اگر این آپِریِتر باشد، اولویت با آن است. مقایسهی دو شئ ( === ) برای مقایسهی دو شئ ( object ) استفاده میشود. اگر هر دو شئ از یک مرجع ( refrence ) باشند یا به عبارت دیگر شئهای ساخته شده در حافظهی به نام Heap با تمام ویژگیها و متغییرها نگهداری شوند و اگر شئ دیگر از همان حافظهای که یک شئ دیگر استفاده میکند وجود داشته باشد، این آپِریِتر درمورد آن دو شئ نتیجهی true و در غیر اینصورت نتیجهی false را نمایش میدهد. در مبحث شئگرایی بیشتر در این مورد صحبت خواهیم کرد، در حال حاضر فقط همین را که بدانید، کافیست. به مثال زیر دقت کنید: class WebsitePlatform { var website_name, platform_name : String init(web_name : String, platform : String) { self.website_name = web_name self.platform_name = platform } } let _web_site_and_platform_one = WebSitePlatform(web_name : "www.iostream.ir", platform : "www.fanoox.com") let _web_site_and_platform_two = WebSitePlatform(web_name : "www.iostream.ir", platform : "www.fanoox.com") if _website_and_platform_one === _website_and_platform_two { print("This is refrence!") }else { print("No,this is not refrence!") } اگر این قطعه کد را اجرا کنید، به شما پیغام NO, this is not refrence را میدهد! چرا که هر دو شئ به صورت جداگانه در حافظهی Heap ذخیره شدهاند و هیچکدام به دیگر ارجاعی ندارد و به اصطلاح با هم ارتباطی ندارند و اگر ما بیایم به این شکل عمل کنیم، آنوقت دیگر یک ارجاع داریم به یک شئ مشخص؛ class WebsiteAndPlatform { var website_name, platform_name : String init(web_name : String, platform : String) { self.website_name = web_name self.platform_name = platform } } let _website_and_platform_one = WebSiteAndPlatform(web_name : "www.iostream.ir", platform : "www.fanoox.com") let _website_and_platform_two = _website_and_platform_one if _website_and_platform_one === _website_and_platform_two { print("This is refrence!") }else { print("No,this is not refrence!") } به جای ایجاد شئ جدید، همان شئ اول را به متغییر دوم انتساب میدهیم که در واقع الان دو شئ داریم که شئ دومی به شئ اولی اشاره میکند. یعنی اینکه الان با هم در ارتباط هستند و شئ دومی ارجاعیست به شئ اول؛ نتیجه خروجی هم This is refrence است. نامساوی بودن دو شئ ( ==! ) اگر دو شئ از یک مرجع نبودند، و هر کدام در حافظهای جداگانه نگهداری میشوند، نتیجه به صورت true و اگر دو شئ از یک مرجع بودند، نتیجه false خواهد بود. کاملا برعکس علامت ( === ). به مثال زیر دقت کنید: class WebsiteAndPlatform { var website_name, platform_name : String init(web_name : String, platform : String) { self.website_name = web_name self.platform_name = platform } } let _website_and_platform_one = WebSiteAndPlatform(web_name : "www.iostream.ir", platform : "www.fanoox.com") let _website_and_platform_two = WebSiteAndPlatform(web_name : "www.iostream.ir", platform : "www.fanoox.com") if _website_and_platform_one !== _website_and_platform_two { print("This is refrence!") }else { print("No,this is not refrence!") } مثال بالا هم که کاملا واضح است! اینکه اگر دو شئ با هم ارجاعی نداشتند، پس نتیجه true است و در غیر اینصورت اگر ارجاع داشتند، نتیجه false و شرط آخر اجرا خواهد شد که No, this is not refrence است. آپریتر ترِنِری ( Ternary Conditonal Operators ) سه قسمت دارد؛ مسئله/شرط مقدار اول مقدار دوم ابتدا شرط قرار خواهد گرفت و سپس به دنبال آن آپِریِتر ? و بعد از آن جواب اول که در صورت درست بودن شرط، برگشت داده میشود و علامت کالُن ( : ) بعد از جواب اول قرار میگیرد که در صورتی که نتیجه نادرست یا false باشد، مقدار بعد ( : ) برگشت داده میشود. به مثال زیر توجه کنید؛ let _website_name_and_platform_name : String = 2 > 1? "www.iostream.ir" : "www.fanoox.com" print("Result =>", _website_name_and_platform_name) // Output the www.iostream.ir در مثال بالا همانطور که مشاهده میکنید، ابتدا شرط یا مسئله قرار میگیرد و سپس مقدار بعد آپِریِتر ? و مقدار اول و دوم که با ( : ) از هم جدا میشوند. در این مثال نتیجه، www.iostream.ir است، چرا که ۲ بزرگتر از ۱ است و این کاملا منطقی است که نتیجهی true دارد. آپریتر دامِنه ( Range Operator ) بیشتر در حلقهها استفاده میشود و نحوهی کار آن را در جلسهی قبل توضیح داده شده است؛ for index_number_one in 0...20 { print(index_number_one, separator : " ",terminator : "") // Output the number 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 } for index_number_two in 0..<20 { print(index_number_two, separator : " ",terminator : "") // Output the number 0 1 2 3 4 5 6 7 8 9 10 11 12 13 15 16 17 18 19 } آپریترهای منطقی ( Logical Operators ) شامل !،&&،|| هستند که بیشتر استفادهی آنها در حلقههاست، اما شما میتوانید در هر جایی از پروژهی خودتان که نیاز به آنها داشتید، استفاده کنید. نَقیض ( ! ) کار آن، برعکس کردن یا نقض کردن یک مقدار است که امکان دارد true یا false باشد. به عنوان مثال اگه مقدار متغییری true است و این آپِریِتر را در ابتدای آن مقدار قرار بدهید، خروجی برابر است با false. و همین مورد هم برعکس صدق میکند، یعنی اگر شما مقدار متغییری false داشتید، با گذاشتن این عبارت در ابتدای متغییر، نتیجه true خواهد شد؛ var isname_website_iostream : Bool = false print(!is_name_website_iostream) // Output the bool true isname_website_iostream = true print(!isname_website_iostream) // Output the bool false درست بودن دو یا چند شرط ( && ) اگر در شرط یا عبارتی بخواهیم دو شرط را بررسی کنیم که هر دو هم حتما باید درست ( true ) باشند از این آپِریِتر استفاده خواهیم کرد؛ let web_sitename, platform_name : String web_sitename = "www.iostream.ir" platform_name = "www.fanoox.com" if web_sitename == "www.iostream.ir" && platform_name == "www.fanoox.com" { print(web_sitename, platform_name) } else { print("None") } در قطعه کد بالا، هر دو شرط مبنی بر اینکه دو مقدار متغییر تعریف شده باید برابر با مقدار تعیین شده در شرط باشند تا مقادیر چاپ شوند. در غیر اینصورت با خروجی None روبرور خواهیم شد. درست بودن حداقل یک شرط ( || ) اگر یکی از شرطها در بین چندین شرط که برقرار است و به عبارتی نتیجه درست ( true ) داشته باشد، وارد بدنهی شرطه خواهد شد و دستورات را اجرا میکند. اگه تمامی شرطها نادرست ( false ) باشند، دستورات داخل بدنه اجرا نخواهند شد؛ var web_sitename, platform_name : String web_sitename = "www.iostream.ir" platform_name = "www.fanoox.com" if web_sitename == "www.iostream.ir" || platform_name == "www.fanoox.ir" { print(web_sitename, platform_name) } else { print("None") } در مثال بالا شرط دوم برقرار نیست! چرا که متغییر platform_name با مقدار سمت راست آن برابر نیست. اما از آنجایی که از ( || ) استفاده کردهایم، پس شرط اول درست بوده و دستورات داخل بدنهی شرط if اجرا خواهند شد. کلمات کلیدی continue,break,fallthrough کلمهی کلید continue اگر بخواهیم در یک حلقه در یک جایی به بعد دستورات اجرا نشوند و حلقه مقدار فعلی را نادیده بگیرد، از این کلمهی کلید کمک خواهیم گرفت؛ for index in 0...20 { if index == 5 { continue } print(index) } /* Output the number 0 1 2 3 4 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 */ همانطور که در مثال بالا مشاهده میکنید، در حلقهی for شرط داخل حلقه بر این مبنا است که هر زمانی که متغییر index مساوی مقدار ۵ شد، به ادامهی دستورات پایان بده ( continue ) و مجدد حلقه را از سر بگیر. به همین خاطر است که عدد ۵ نمایش داده نشده است. کلمهی کلید break با این کلمهی کلید به راحتی میتوانید هر جایی از حلقه که دیگر نیازی نداشتید ادامه پیدا کنید، حلقه را متوقف یا به اصطلاح بشکنید!. با این کار دیگر حلقه تکرار نشده و دستورات بعد از حلقه اجرا خواهند شد؛ for index in 0...5 { if index == 2 { break } print(index) } /* Output the number 0 1 */ کلمهی کلید fallthrough شاید در جایی از دستور شرطی switch لازم داشتید که caseهای بعدی هم اجرا شوند. با این کلمهی کلیدی میتوانید این کار را انجام دهید؛ let _number : Int8 = 1 switch _number { case 2: print(2) case 1: print(1) fallthrough case 3: print(3) fallthrough default: print("None") } بعد از هر caseی که میخواهید اجرا شود باید این کلمهی کلیدی را قرار دهید. امیدوایم این جلسه هم مورد رضایت شما عزیزان قرار گرفته باشد.
-
3 امتیاززبانی را انتخاب کنید که پاسخگوی برنامهٔ تحت بلاکچین شما باشد! فناوری بلاکچین به سرعت در حال تبدیل شدن به یکی از مهمترین پیشرفتهای فناوری در چند دههٔ گذشته است. این سیستم، معاملات ناشناس و همتا را بین کاربران امکانپذیر میکند که اساساً بر پایهٔ انقلاب رمزنگاری است. بازار جهانی بلاکچین در حال حاضر حدود ۱.۲ میلیارد دلار تخمین زده میشود و کارشناسان پیشبینی میکنند که تا سال ۲۰۲۵ به ارزش ۵۷ میلیارد دلار برسد که در سال بیش از ۶۹ درصد رشد خواهد داشت. عمدهٔ شرکتها و سرمایهدارانِ سرمایهگذار در توسعهٔ فناوری جدید رمزنگاری، قراردادهای هوشمند دفترچههای توزیعشده برای بانکهای سنتی، توکنهای بازی و سیستمهای مدیریت زنجیره تأمین با شرکتهای مشاوره بلاکچین همکاری میکنند. توسعهدهندگان در حال حاضر از زبانهای برنامهنویسی محبوبی مانند C++ و JavaScript برای ساختن برنامههای سفارشی بلاکچین استفاده میکنند. علاوه بر این، مهندسان رمزنگاری زبانهایی مانند Simplicty و Solidity را برای این کار طراحی کردهاند. اما، آنها آیا اینها بهترین زبانهای برنامهنویسی برای فناوری بلاکچین هستند؟ بلاکچین چیست؟ بانکداری سنتی از یک بانک به عنوان رهبر و واسط استفاده میکند. جهت انتقال پول به یک دوست، یک شخص ابتدا حسابی داشته باشد و بخواهد که پول را به یک شماره حساب خاص که برای اوست انتقال دهد. بانک، حساب ارسال کننده را برای وجه بررسی میکند و آن وجه را به مقصد منتقل میکند و معامله در حساب فرستنده ثبت میشد. همچنین بانک دریافت کننده نیز همین کار را باید انجام دهد. با این حال، مشکل سیستم بانکی سنتی این است که سوابق در داخل ذخیره میشوند و در برابر هک و دستکاریهای آسیبپذیر هستند. بلاکچین با ذخیره کردن تمامی سوابق به صورت آنلاین در یک دفترچهٔ مستعار (بینام) ذخیره میکند که توسط هر کسی قابل دسترس است. بلاکچین از بلاکها استفاده میکند، یا مجموعهای از دادهها، مشابه سطرها و ستونهای صفحههای گسترده جهت ذخیره دادهها استفاده میکند. بلاکها به ترتیب متوالی به «زنجیر» اضافه میشوند. برخلاف دفترچههای سنتی، که در داخل ذخیره میشوند، هر کاربرِ بلاکچین دارای سوابق کاملی از کل بلاکچین در رایانهٔ خود است. این بدان معنی است که در صورت داشتن کد هش (رمزشدهٔ) مربوطه میتوانند به سرعت هر معاملهای را که اتفاق افتاده است را پیدا کنند. از آنجایی که این دادهها به صورت عمومی ذخیره میشوند، هرگز قابل تغییر یا حذف نیستند! در نتیجه آرامش خاطر را به کاربران فراهم میکند. زبان برنامهنویسی JavaScript (جاوااسکریپت) از آنجایی که گیتهاب به تازگی این زبان را به عنوان محبوبترین زبان برای توسعهدهندگان اعلام کرده است، به طور باورنکردنی بیش از ۹۵٪ وبسایتها به طریقی از آن استفاده میکنند. با این حال، جاوااسکریپت تنها پادشاه وب نیست؛ چرا که به عنوان یک زبان انعطافپذیر در بلاکچین استفاده میشود. یکی از دلایلی که جاوااسکریپت را برای توسعهدهندگان میبخشد نحوهٔ دستیابی به مدیریت کدها به صورت ناهمزمان (ناهمگام) است. این امر در بلاکچین بسیار مهم است، زیرا ممکن است هزاران یا حتی میلیونها معاملات در همان زمان آغاز شود! برنامهنویسی موازی یک برنامه را قادر میسازد تا چندین عمل را به صورت همزمان انجام دهد در حالی که برنامهنویسی استاندارد و همزمان نمیتوانند آن حجم را تحمل و کنترل کنند. با اجرای چندین کار به صورت همزمان، کد ناهمزمان میتواند باعث افزایش پاسخگویی و عملکرد برنامه شود. این امر باعث میشود برنامههای بلاکچین بتوانند حجم بسیار زیادی از اقدامات را بدون عملکرد کُند و نا امید سازی کاربر، آن را انجام دهند. زبان برنامهنویسی C++ (سیپلاسپلاس) سیپلاسپلاس همچنین به عنوان یکی از قدرتمندترین و محبوبترین زبانهای برنامهنویسی در دنیای فناوری شناخته میشود و در صنعت بلاکچین نیز یک قدرت غالب است. زبان شیءگرایی برای توسعه بلاکچین مناسب است، زیرا از همان اصول کپسولهسازی، انتزاع، چندریختی و مخفی کردن دادهها استفاده میکند. به عنوان مثال بلاکچین از ویرایشهای ناخواسته از دادهها جولوگیری میکند. توسعهدهندگان همچنین به دلیل قابلیت کنترل حافظه، از C++استفاده میکنند. این زبان به شما اجازه میدهد تا بلوکهای ایمن را نگه داشته و تعداد زیادی از درخواست منابع را مدیریت کنید. با اجازه دادن به هر نود (گره) شبکه میتوانید بلوکهای فردی را پذیرفته یا رد کنید. همچنین C++ به دلیل پشتیبانی و مدیریت وظایف موازی و نخی به طور گسترده در بلاکچین مورد استفاده قرار میگیرد. این زبان قادر به مدیریت هردو ویژگی موازی و غیرموازی در وظایف است، در واقع میتواند به خوبی انجام وظایف تک-نخی/تک رشتهای (single-thread) را بهبود دهد. نمونهٔ فوقالعادهای از برنامههای اساسی از بلاکچین که با C++ نوشته شده است EOS نام دارد. این نرمافزار به صورت منبعباز در سال ۲۰۱۸ توسط بلاک منتشر شد و به گونهای طراحی شده است که معاملات را سریعتر از گزینههای دیگر پردازش میکند. این نرمافزار اجازه میدهد تا در کمتر از یک ثانیه معامل را تأیید کرده و فقط در دو دقیقه آن را نهایی کنید. زبان برنامهنویسی Solidity این زبان یک نمونهٔ هوشمند است که با همکاری توسعهدهندگان Ethereum و بلاکچین توسعه یافته است. این زبان به صورت اختصاصی دامنههای بسیاری از اصول و اصطلاحات مشابه به جاوااسکریپت را برای ایجاد برنامههای با کیفیت بالا و غیر متمرکز فراهم میکند. توسعهدهندگان، این زبان را برای این ترجیح میدهد که به شما این امکان را فراهم میکند تا یک کد سطح بالا را برای شبکهٔ بلاکچینی Ethereum، دومین بلاکچین رمزنگاری محبوب، که میتواند به زبان سطح پایین و کد ماشین کامپایل شود. در حال حاضر Solidity در طیف گستردهای از سکوها (پلتفرمهای) بلاکچینی از جمله، Ethereum، Tendermint، Ethereum Classic و Counterparty موجود است. زبان برنامهنویسی Simplicity این یک زبان کاملاً جدید است که در تاریخ نوامبر ۲۰۱۷ برای قراردادهای خاص و هوشمندِ بلاکچین طراحی و منتشر شده است. این زبان برای افزایش بهرهوری و پنهانسازی اجزای منطقی سطح پایین از مهندسان است که یکی از دلایلی است که به سرعت در جامعه محبوب میشود. مانند C++، این یک زبان شیءگرایی است که برای جولوگیری از خطاها و تغییر دادهها در بلاکچین استفاده میکند. خلاصه بلاکچین اینجاست تا بماند! فناوری محبوب (Record-Keeping) چیزی است که تبادلات رمزنگاری را ممکن میسازد و بطور گسترده توسط شرکتها، افراد و خدمات مشاورهای بلاکچین، برای توسعهٔ نرمافزار مورد استفاده قرار میگیرد. توسعه دهندگان میتوانند به راحتی از زبانهای محبوب مانند C++ و JavaScript برای توسعهٔ بلاکچین استفاده کنند. از طرفی این انجمن اخیراً زبانهایی به عنوان Solidity و Simplicity را ایجاد کرده است که باعث میشود تا فرآیند توسعهٔ رمزنگاری روانتر شود.
-
3 امتیازجزئیات در ++C ویرایش ۱۷: کد نویسی ساده با توجه به مشخصاتی که در استاندارد ISO/IEC 14882:2017 که ارائه شده است، ویژگیهای جدید برای این معرفی میشوند تا کد شما تمیز تر و بهتر و در کل رَساتر اعمال شوند. این مقاله را برای مطلع شدن از جزئیات بیشتر بخوانید. سیپلاسپلاس ۱۷ چندین ویژگی بزرگ زبان را ارائه میدهد که باعث میشود کد ما زیباتر و بهتر شود. بنابراین بیایید باهم یک نگاهی به این ویژگیها داشته باشیم. ممکن است شما بگویید که بیشترین ویژگیهای جدید زبان (به جز پیشرفت های کتابخانه استاندارد - STL) برای نوشتن کد ساده تر و پاکتر میباشند. با توجه به مجموعه جزئیات سیپلاسپلاس ۱۷ که بسیاری از چیزهای بزرگ را مورد بررسی قرار داده است، ما امروز تنها برای بعضی از ویژگی ها که از داخل این مجموعه عظیم بیرون کشیدهایم اشاره خواهیم داشت که باعث میشود کد شما فشردهتر و بهینه تر شود. پیوندهای ساخت یافته / اعلانهای تجزیه عبارت Init-statement برای if/switch متغیرهای درون خطی (inline) شرط constexpr if و چند موارد دیگر پیوندهای ساخت یافته، آیا اغلب با tuple ها کار کردهاید؟ اگر نه، پس احتمالاً باید به آن نگاهی کنید. tuple ها تنها برای بازگشت مقادیر چند گانه از یک تابع پیشنهاد نمیشوند، آنها پشتیبانی ویژگیای از زبان را داشتند. به طوری که باعث میشود کد ساده تر و پاکتر شود. برای مثال (std::tie که از مرجع اصلی سیپلاسپلاس به دست آمده است) به صورت زیر است: std::set<S> mySet; S value{42, "Test", 3.14}; std::set<S>::iterator iter; bool inserted; // unpacks the return val of insert into iter and inserted std::tie(iter, inserted) = mySet.insert(value); if (inserted) std::cout << "Value was inserted\n"; توجه داشته باشید که باید iter و inserted را ابتدا وارد کرده باشید. سپس شما میتوانید از std::tie استفاده کنید. با این حال این بخش کوچکی از کد نمونه است: std::set<S> mySet; S value{42, "Test", 3.14}; auto [iter, inserted] = mySet.insert(value); اینجا توجه داشته باشید که یک خط به جای سه خط جایگزین شده است! این کد سادهتر و خواناتر و درعین حال ایمن تر است، اینطور نیست؟ همچنین، شما هم اکنون میتوانید از const استفاده کنید و آن را به صورت const auto [iter inserted] بنویسید که صحیح است. پیوند ساختاری تنها به tuple ها ختم نمیشود، چرا که ما سه مورد دیگر را داریم: اگر مقدار دهی اولیه یک آرایه باشد: // works with arrays: double myArray[3] = { 1.0, 2.0, 3.0 }; auto [a, b, c] = myArray; اگر مقدار دهی اولیه std::tuple_size<> را پشتیبانی کند و تابع get را فراهم کند که شایع ترین مورد است. auto [a, b] = myPair; // binds myPair.first/second به عبارت دیگر، شما میتوانید کلاسهای خود را پشتیبانی کنید، با فرض این که شما تابع get را در پیاده سازی رابط کلاس خود اضافه کرده باشید. اگر مقدار دهی اولیه فقط شامل اعضای عمومی شود در این صورت: struct S { int x1 : 2; volatile double y1; }; S f(); const auto [ x, y ] = f(); در حال حاضر این روش برای دریافت یک مرجع از یک عضو tuple آسان است. auto& [ refA, refB, refC, refD ] = myTuple; و یکی از جالبترین استفادهها (پشتیبانی از حلقهها است): std::map myMap; for (const auto & [k,v] : myMap) { // k - key // v - value } پیوند ساختاری یا تقسیم بندی اعلانها برای این ویژگی، ممکن است شما نام های دیگری را دیده باشید، "اعلان تجزیه". همانطور که میبینیم، این دو نام در نظر گرفته شده است، اما فعلاً استاندارد سازی در حالت پیشنویسه است و با نام "پیوندهای ساختاری" میباشند. جزئیات بیشتر در رابطه با این مورد در اسناد P0217R3، P0144R0 و P0615R0 موجود هستند. همچنین این مورد با کامپایلرهای GCC 7.0،MSVC2017 و Clang 4.0 سازگار است. عبارت Init-statement برای if/switch نسخه جدید عبارت شرطی if و switch در سیپلاسپلاس جدید به صورت زیر است: if (init; condition) , switch (init; condition) قبلاً باید به صورت زیر مینوشتیم: { auto val = GetValue(); if (condition(val)) // on success else // on false... } در اینجا val یک دامنه جدا کننده بدون دارد که باعث "نشت - فقدان" در خاتمه دهنده دامنه خواهد شد. در حالی که شما در نسخه جدید میتوانید به صورت زیر بنویسید: if (auto val = GetValue(); condition(val)) // on success else // on false... متغیر val تنها در داخل عبارات if و else قابل رویت است، بنابراین آن یک "نَشت" نخواهد داشت. condition ممکن است چندین عبارت باشد نه تنها if بنابراین متغیر val یکی از دو مقدار true/false را خواهد داشت. چرا این ویژگی کاربرد دارد؟ اجازه دهید تا به شما بگوییم زمانی که میخواهید چندین چیز را در یک رشته را جستجو کنید به صورت زیر خواهید داشت: const std::string myString = "My Hello World Wow"; const auto it = myString.find("Hello"); if (it != std::string::npos) std::cout << it << " Hello\n" const auto it2 = myString.find("World"); if (it2 != std::string::npos) std::cout << it2 << " World\n" ما باید از نامهای مختلفی برای it استفاده کنیم و یا اینکه آن را با دامنه خاتمه دهنده جدا سازیم. { const auto it = myString.find("Hello"); if (it != std::string::npos) std::cout << it << " Hello\n" } { const auto it = myString.find("World"); if (it != std::string::npos) std::cout << it << " World\n" } عبارت جدید شرطی if در نسخه جدید یک دامنه اضافه را در یک خط ایجاد میکند. if (const auto it = myString.find("Hello"); it != std::string::npos) std::cout << it << " Hello\n"; if (const auto it = myString.find("World"); it != std::string::npos) std::cout << it << " World\n"; همانطور که قبلاً اشاره شده است، متغیر تعریف شده در عبارت شرطی if در بلوک دیگری قابل مشاهده است. بنابراین شما میتواین به صورت زیر بنویسید: if (const auto it = myString.find("World"); it != std::string::npos) std::cout << it << " World\n"; else std::cout << it << " not found!!\n"; به علاوه، شما میتوانید آن را با پیوند ساختاری بر اساس کد نمونه از جانب (Herb Sutter) استفاده کنید: // better together: structured bindings + if initializer if (auto [iter, succeeded] = mymap.insert(value); succeeded) { use(iter); // ok // ... } // iter and succeeded are destroyed here جزئیات بیشتر در اسناد زیر آمده است: سند P0305R1 ویدیو موجود در یوتیوب با عنوان (C++ Weekly - Ep 21 C++17’s if and switch Init Statements) این مورد با کامپایلرهای GCC 7.0،MSVC-2017.3 و Clang 3.9 سازگار است. متغیرهای درون خطی (inline) با شروع مقدار دهی دادههای غیر استاتیک، اکنون میتوانیم یک متغیر عضو را دی یک مکان اعلام کنیم. با این حال، با متغیرهای استاتیک یا const static، معمولاً باید آن را در برخی از فایلهای cpp تعریف کنید. در سیپلاسپلاس ۱۱ و کلید واژه constexpr که مارا قادر میسازد تا در یک مکان اعلان و تعریف متغیرهای استاتیک را انجام دهیم، اما این امکان تنها به constexpr محدود میشود. قبلاً فقط روشها/توابع میتوانستند به عنوان inline تعریف شوند، حالا شما میتوانید این کار را با متغیر ها در داخل فایل هدر انجام دهید. یک متغیر اعلام شده درون خطی معنای مشاهبی دارد بنابراین همانند یک تابع inline تعریف میشود. آن را میتوان به واحدهای ترجمه چند گانه نیز تعریف کرد. مثالهای زیر را ببینید: struct MyClass { static const int sValue; }; inline int const MyClass::sValue = 777; و حتی struct MyClass { inline static const int sValue = 777; }; همچنین توجه داشته باشید که متغیرهای constexpr به طور ضمنی inline هستند، بنابراین نیازی به استفاده به صورت constepr inline myVar = 10; نمیباشد. این ویژگی چرا کد را ساده تر میکند؟ برای مثال، تعداد زیادی از هدرها در کتابخانه تنها تعدادی از روش های (هک) را محدود میکنند (مانند استفاده توابع درون خطیinline و یا قالب ها) و در نهایت مزیت constexpr این است که مقدار دهی اولیه شما نباید constexpr باشد. جزئیات بیشتر در رابطه با این ویژگی در سند زیر موجود است: سند P0386R2 این مورد با کامپایلرهای GCC 7.0 و Clang 3.9 سازگار است اما فعلاً با MSVC سازگاری ندارد. ویژگی مربوط به constexpr if ممکن است در بعضی جاها به قابلیت std::enable_if در سیپلاسپلاس ۱۴ نگاه کنید که آن به راحتی با constexpr if جایگزین میشود. بنابراین، در اکثر موارد، ما اکنون میتوانیم تنها با نوشتن عبارت یک constexpr if این کار را بهتر و تمیز تر انجام دهیم. این ویژگی برای برنامه نویسی metaprogramming/template بسیار مهم است که احتمالاً طبیعت آن بسیار پیچیده خواهد بود. یک مثال ساده با تابع Fibonacci: template<int N> constexpr int fibonacci() { return fibonacci<N-1>() + fibonacci<N-2>(); } template<> constexpr int fibonacci<1>() { return 1; } template<> constexpr int fibonacci<0>() { return 0; } حال میتوان آن را تقریباً در یک حالت نرمال (نسخه بدون کامپایل) نوشت: template<int N> constexpr int fibonacci() { if constexpr (N>=2) return fibonacci<N-1>() + fibonacci<N-2>(); else return N; } در رویداد ۱۸ هم جلسات هفتگی سیپلاسپلاس در جیسون ترنر نمونهای را میتوان یافت که در آن عبارت constexpr if هیچ منطق اتصال کوتاهی را در زمان کامپایل انجام نمیدهد، بنابراین این کد باید کامپایل شود: if constexpr (std::is_integral<T>::value && std::numeric_limits<T>::min() < 10) { } در کد فوق برای T شما در std::string خطایی کامپایل را دریافت خواهید کرد زیرا numeric_limits برای رشته ها تعریف نشده اند. در جلسات C++NOW 2017 آقای Bryce Leblbach با عنوان جلسه خود C++17 Features در ۱۶ دقیقه مثال بسیار زیبایی را در رابطه باconstexpr if زد که میتواند برای تابع get استفاده شود که آن برای پیوند ساختاری مورد استفاده قرار میگیرد. struct S { int n; std::string s; float d; }; template <std::size_t I> auto& get(S& s) { if constexpr (I == 0) return s.n; else if constexpr (I == 1) return s.s; else if constexpr (I == 2) return s.d; } قبلاً ما باید به صورت زیر مینوشتیم: template <> auto& get<0>(S &s) { return s.n; } template <> auto& get<1>(S &s) { return s.s; } template <> auto& get<2>(S &s) { return s.d; } همانطور که میبینید، مشکل سوال برانگیز اینجاست که کد در این جا ساده تر است. اگر چه در این مورد فقط از یک ساختار ساده استفاده شده است، با برخی از نمونه های واقعی دنیا، کد نهایی باید بسیار پیچیده تر از این باشد بنابراین باید constexpr if کد تمیز تری نسبت به این مورد باشد. این مورد با کامپایلرهای GCC 7.0،MSVC-2017.3 و Clang 3.9 سازگار است. ویژگیهای دیگر ما میتوانیم در رابطه با بسیاری از ویژگی های جدید سیپلاسپلاس صحبت کنیم اما در این پست ما بیشتر در رابطه با قطعات بزرگتر تمرکز کردهایم. با این حال، فقط برای یادآوری، ممکن است بخواهید ویژگیهای زیر را در نظر بگیرید که آنها نیز کد ها را ساده تر میکنند: الگو یا قالبها (templates) عبارت Fold الگو برای کلاس ها بنابراین برای ذکر ویژگیهای بیشتر در رابطه با نسخه جدید در پستهای آن ها را پوشش خواهیم داد. شک نکنید که، سیپلاسپلاس ۱۷ پیشرفت واقعی را در برابر کد های جمع و جور و آسان فراهم گرده است. یکی از بهترین چیزها constexpr است که آن به ما اجازه میدهد کد template/metaprogramming را به روش کد استاندارد شده بنویسیم. این یک مزیت بسیار بزرگی است. ویژگی دوم: پیوند ساخت یافته (که حتی برای حلقه ها کار میکند) مانند حسی را القا میکند که در زبانهای پویایی مثل Python وجود دارد. همانطور که میبینید، تمام ویژگیهای ذکر شده در حال حاضر در Clang، MSVC و GCC قابل اجرا هستند. اگر شما با نسخههای اخیر این کامپایلر ها کار میکنید میتواین بلافاصله با سی++ ۱۷ کار کرده و آن را تجربه کنید.
-
2 امتیازدر سالی که گذشت (۲۰۲۲)، سیپلاسپلاس محبوبترین زبان برنامهنویسی با رشد شاخص محبوبیت ۴.۶۲٪ انتخاب شد! جایزه زبان برنامهنویسی سال TIOBE به ++C تعلق گرفت! این جایزه به زبان برنامهنویسی تعلق میگیرد که بیشترین افزایش محبوبیت را در یک سال تجربه کرده است. شاخص TIOBE میزان محبوبیت زبانهای برنامهنویسی را اندازهگیری میکند. با این حال، قبل از نتیجهگیری، توجه به این نکته مهم است که Index (شاخص) نه چیزی در مورد کیفیت یک زبان برنامهنویسی میگوید و نه ادعا میکند. این رتبهبندی با تجزیه و تحلیل تعداد مهندسان ماهر در یک زبان خاص، تعداد دورههای آموزشی در آن زبان و تعداد فروشندگان شخص ثالثی که محصولات یا خدمات مرتبط با آن زبان را ارائه میدهند، محاسبه میشود. این فهرست ماهانه بهروز میشود و بر اساس دادههای موتورهای جستجوی محبوب مانند گوگل، بینگ و یاهو است. جایزهٔ زبان برنامهنویسی سال TIOBE در ژانویه هر سال بر اساس رتبهبندی سال قبل اعلام میشود. سیپلاسپلاس یک زبان برنامهنویسی در سال ۲۰۲۲ انتخاب شد که با محبوبیت رشد ۴.۶۲ درصد و بیشترین رشد انتخاب شده است. این زبان برنامهنویسی سطح بالا با کارایی بالا و چندمنظوره برای توسعهٔ نرمافزارهای سیستمی، برنامههای کاربردی و بازیهای ویدیویی با انعطافپذیری و قابلیت کنترل سطوح پایین است. این زبان در نوامبر ۲۰۲۲ جاوا را پشتسر گذاشت و به رتبهٔ سوم شاخص رسید و محبوبیت آن به طور پیوسته در حال افزایش است. نایب قهرمان در سال ۲۰۲۲ به ترتیب C با رشد ۳.۸۲ و پایتون با ۲.۷۸ درصد رشد بودهاند.
-
2 امتیازیک سوأل بسیار مهم و پر مخاطب در بارهٔ زبانبرنامهنویسی سیپلاسپلاس در سالهای اخیر این است که «آیا جایگزینی برای این زبان وجود دارد و یا قابل جایگزین است»؟ در بسیاری از پاسخها نشان از گزینههایی مانند Go، Rust و D دیده میشود که بهتر است نسبت به نظرات متخصصهای برنامهنویسی به این موضوع پرداخته شود، ابتدا باید در نظر گرفت که هر ابزاری میتواند جایگزینی داشته باشد اما شرایط و نحوهٔ استفادهٔ آن در رابطه با نیاز متفاوت است. اخیراً سوألات زیادی در این موضوع دیده شده است که میگویند، Rust یک زبان برنامهنویسی ایمن، سریع و سیستمیِ جایگزین برای سیپلاسپلاس است! اما آیا واقعاً اینگونه است یا صرفاً ما بر اساس احساسات و اشتیاق به بهروز شدن به این موضوع میپردازیم؟ پاسخ برای این سوأل به صورت زیر در مدلهای مختلف میتواند مطرح شود که نتیجهگیری و تصمیم از خلاصهٔ آن به عهدهٔ خودِ شماست. من بر این باورم که زبانهای برنامهنویسی همه و همه در حال بهروز رسانی و بهتر شدن نسبت به نسخهها، استانداردها، و نسلهای گذشتهٔ خودشان هستند و به هیچ عنوان هیچ زبانی تا به امروز به طور جدی منسوخ شده اعلام نشده است. برای درک این مطلب بهتر است ابتدا به واژهٔ «منسوخ شده» یا «Deprecated» بپردازیم، این واژه زمانی مورد استفاده قرار میگیرد که شرایط زیر بر آن حاکم باشد: گزینهٔ مورد نظر به طور رسمی از طرف سازنده، پشتیبان یا صاحب آن بد دانسته شده و رسماً کنار گذاشته شود. گزینهٔ مورد نظر بهروز رسانی نشود و آخرین بهروز رسانی آن نیز شامل مشکلاتی باشد که بعد از مدتها نیز حل نشده باشد. گزینهٔ مورد نظر دیگر مورد استفاده قرار نگیرد و کاربردی هم در بین رقبای خود نداشته باشد. گزینهٔ مورد نظر دیگر پشتیبانی نشود و به قولی مُرده باشد. گزینهٔ مورد نظر به علاوهٔ این که شامل این موارد میشود، باید دارای یک جایگزین مناسب و عالی باشد. با توجه به این معیارها و با در نظر گرفتن رسالت هر یک ابزارها باید به آن توجه کرد که هر زبان یا ابزار برنامهنویسی خارج از این، در مرحلهٔ پیشرفت قرار گرفته است که آن نشان دهندهٔ زنده بودن و کاربردی بودن آن است. از طرفی، زبانی مثل سیپلاسپلاس جایگزین نمیشود چرا که هیچ یک از دلایل و معیارهای بالا شامل حال آن نمیشود، اتفاقاً برعکس این زبان دارای ویژگیهای معیاری زیر است: این زبان به طور رسمی توسط کمیتهٔ استانداردسازی که متعلق به هیچ یک از شرکتهای غول صنعتی و یا خصوصی نمیباشد پشتیبانی میشود. این زبان به طور مداوم در حال بهروز رسانی است و کاربردهای چند-منظوره و همه جانبهٔ خود را داراست. این زبان از ویژگیهای از ویژگیهای بسیار خوب به همراه سریعترین بازدهیها را داراست. این زبان رقیبهای بسیاری دارد، اما هیچ کدام از آنها هنوز در عمل و دامنهٔ وسیعی موفق به نمایش عملکرد بهتری نبودهاند. این زبان همانند دیگر ابزارها دارای مشکلاتی است، اما با توجه به پوشش و پشتیبانی از ویژگی BC در روند استانداردسازی و بهروز رسانی به خوبی از پس آنها بر آمده است. برای مثال، زبان جاوا یکی از بهترین زبانهای برنامهنویسی است و خیلی از شرکتها مانند گوگل در سیستمهای توزیع شده از آن استفاده میکنند. اما به معنای این نیست که به سرعت سی++ میرسد و در حد مقایسه با آن است. این زبان میتواند دهها و صدها برابر کندتر از سی++ باشد و این مربوط به طراحی، ساختار و مسائل مربوط به زبان است. از طرفی سیپلاسپلاس محبوب است زیرا که ویژگیهای زیر را دارد و طی سالهای بسیاری آن را ثابت کرده است: کارآیی (پرفرمنس) و سرعت فوقالعادهٔ این زبان، البته خیلی از زبانها ادعا میکنند که همچین ویژگیای را دارند که در عمل نتیجهٔ جالبی مشاهده نمیشود. ذاتِ چند-سکویی و چند-منظوره بودن آن، حداقل همهٔ سیستمها میتوانند کدهای سی++ را کامپایل و اجرا کنند. این زبان به راحتی میتواند با زبانها و فناوریهای دیگری ارتباط برقرار کرده و با آنها تعامل داشته باشد. این زبان به عنوان یکی از کممصرفترین زبانهای برنامهنویسی از نظر مصرف انرژی محسوب میشود. بسیاری از مهندسین این زبانها را به صورت مقطعی و بارها دیده و با آن آشنا هستند. کتابخانههای پیشفرض استاندارد STL و دیگر کتابخانههای سی++ بسیار قدرتمند و گسترده هستند. کتابخانههای نوع سوم (Third-Party) بسیار قدرتمند و بهروز هستند. اولویتهای سیستمهای یونیکس و حتی ویندوز اکثراً بر روی C و ++C است و بازنویسی آنها با زبانهای دیگر هزینهٔ بسیاری را به ارمغان میآورد. بسیاری از وابستگیهای ایجاد شده در سالهای بسیار طولانی بر اساس سی و سی++ بوده و بازنگری و بازنویسی آنها مشروط بر این که رابطها باید بازنویسی شود بسیار سخت و کاری مشابه اختراع دوبارهٔ چرخ است. عملکرد تا حدی قابل پیشبینی است و میتواند آن را درک کرد، چیزی که در زبانهایی مانند جاوا، سیشارپ و گو نمیتواند پیشبینی کرد چرا که پیشبینی چرخهٔ GC دشوار است، هیچ رقیب جدیای در این باره در سطح سی++ وجود ندارد که مدیریت حافظه را برای شما در قالب یک RAII ارائه کند، هرچند در مورد Objective-C و Rust میتوان آنها را به صورت جداگانه مورد بررسی قرار داد و نه عین آن. پشتیبانی از پارادایم (سبک)های طراحی را سی++ به خوبی پشتیبانی میکند، برای مثال برنامهنویسی عمومی در زمان کامپایل را به خوبی ارائه میکند. پشتیبانی از برنامهنویسی سیستمی و سطح پایین در این زبان یک مزیتی دیگری است که در کنار تمامی ویژگیهای سطح بالای خود ارائه میکند. اما در این میان زبانهایی مثل Rust، Go، Swift و غیره ادعای جایگزینی را دارند اما ادعاهای فنی به تنهایی کافی نیستند، در دسترس بودن گسترده از جامعه به اندازهٔ کافی به همراه جامعهٔ معتمد به آن مهم است. علاوه بر ویژگیهای فنی زبان سی++، یک نقطه قوت بسیار مهم این زبان در بحث غیر فنی آن است، در واقع در پشت این زبان نه یک پیادهسازی محدودی وجود دارد و نه یک سازمان که در آینده در مورد آن تصمیم بگیرد و آن را کنترل کند. در حالی که تمامی زبانهای مطرح و ادعا کننده داخل یک چهارچوبی کنترل میشوند که به شدت آیندهٔ آنها را تیره و تار میکند. به طور کلی آزاد بودن یک ابزار و قدرت یک جامعه فارغ از جغرافیا، سازمان، نژاد و زبان یک قدرت بسیار خارقالعادهای را برای یک ابزار به ارمغان میآورد که به تنهایی بسیار اهمیت دارد. در این اواخر بسیاری از مهندسین به فکر بازنویسی بسیاری از موارد شدن و تحقیقات نشان میدهد ابزارهایی گرافیکی بسیار قدرتمند و سریع که اخیراً طراحی شدهاند، مانند وُلکان که با سی++ نوشته شده است زمانی میتوانند با راست و زبانهای دیگر امروزی بازنویسی شوند که یک سیستمعامل جدید با زبانهای جدید ساخته شود! بنابراین صرفاً میتوان یک نسخهٔ Wrapper یا همان (پوشنده) چرا که تقریباً همهٔ سیستمعاملهای مدرن امروزی با زبانهای سی و سی++ نوشته شدهاند. از طرفی تولید یک سیستمعامل بسیار پر خطر است و سرمایهگذاری کلان، زمان و هزینههای بسیاری را میطلبد و تا زمانی که چنین نرمافزارهایی تحت سلطهٔ زبانهایی مانند سی++ قرار گرفته باشند پادشاهی سیپلاسپلاس ادامه خواهد داشت. نکتهٔ پایانی من معتقدم هر ابزار و زبانهای برنامهنویسی جایگاه و شرایط استفادهٔ خودشان را شامل میشوند، دقیقاً مانند ابزارهای موجود در یک جعبهابزار بهتر است ابزارهای خود را طوری بچینید که در جای لازم از مناسبترین آنها استفاده کنید. با این حال زبانها و ابزارهای مانند سی یا سی++ طی سالها ثابت کردهاند که معمولاً در همهٔ حوزهها غالب هستند و میتواند هر کاری را که بخواهید با آنها انجام دهید و یا با یک جایگرین مناسب آن را مدیریت کنید و این بستگی به مهارت و انتخاب شخصی شما دارد. همچنین صحبتهای اخیر کمیتهٔ استانداردسازی در رابطه با نحو ۲ از سیپلاسپلاس میتواند مفهوم خوبی در آیندهٔ این زبان باشد. مقالات مرتبط با این موضوع که میتواند به عنوان مکملی از پیش تعریف شده برای شما مفید باشد:
-
2 امتیازقسمت اول: Block Environment Block (PEB) از زمان معرفی Win2k (ویندوز 2000) در ویندوز وجود داشته است و از آن زمان به بعد نسخه های جدیدتر ویندوز بهبود یافته است. در نسخه های قبلی ویندوز ، انجام برخی کارهای ناخوشایند مانند پنهان کردن ماژول های بارگذاری شده موجود در یک فرآیند (برای جلوگیری از پیدا شدن آنها - بدیهی است که این چیز زیبایی نیست) سوءاستفاده می شود. چرا این موضوع مهم را “Process Environment (PEB)” مینامیم؟ PEB ساختاری است که اطلاعات مربوط به روند فعلی را تحت مقادیر خود نگهداری می کند - برخی از زمینه ها (فیلد ها یا داده ها) خود ساختارهایی هستند که حتی داده های بیشتری را در خود جای می دهند. هر فرآیندی PEB خاص خود را دارد و هسته Windows نیز به PEB هر فرآیند حالت کاربر دسترسی دارد تا بتواند داده های ذخیره شده در آن را پیگیری کند. این ساختار از کجا می آید؟ ساختار PEB از هسته ویندوز ناشی می شود (اگرچه در حالت کاربر نیز قابل دسترسی است). PEB از Block Environment Thread (TEB) ناشی می شود که معمولاً به آن Thread Information Block (TIB) نیز گفته می شود. TEB مسئول نگهداری اطلاعات مربوط به thread فعلی است - هر thread ساختار TEB خاص خود را دارد. آیا می توان از Block Environment Block یا Block Environment Block برای اهداف مخرب سوء استفاده کرد؟ البته آنها می توانند! در واقع ، آنها در گذشته برای اهداف مخرب مورد سوء استفاده قرار گرفته اند ، اما مایکروسافت طی سالهای اخیر تغییرات زیادی را برای جلوگیری از این امر انجام داده است. مثالی در گذشته بود که روت کیت ها یک DLL را به یک فرایند در حال اجرا تزریق می کردند و سپس به ساختار PEB فرآیند فعلی که به آن تزریق کرده بودند دسترسی پیدا می کردند (ساختار PPEB اشاره گر به ساختار PEB است) تا بتوانند لیست را پیدا کنند. از ماژول های بارگذاری شده و ماژول خود را از لیست حذف کنید ... بنابراین هنگامی که کسی ماژول های بارگذاری شده فرآیند آسیب دیده را برشمارد ، ماژول تزریق شده را از نظر پنهان می کند. این به عنوان وصله حافظه شناخته می شود زیرا شما می توانید با وصله PEB حافظه را تغییر دهید. تلاش مایکروسافت برای این کاهش رفتار این بود که از تغییر دستی لیست که نشان دهنده ماژول های بارگذاری شده در حالت کاربر است جلوگیری کند-شما همچنان می توانید برای خواندن داده ها در حالت کاربر به آن دسترسی داشته باشید و همچنان می توانید حافظه را از حالت کرنل وصله کنید. پایان قسمت اول ?
-
2 امتیازپادکستِ مربوط به شفافسازی تقریبی از مسیرِ توسعهدهندگی تحت سی++ و ساخت محصولِ هدفمند زمان مورد نیاز : ۲۰ دقیقه و ۱۱ ثانیه Podcast-03.mp3
-
2 امتیازفایل صوتیِ مربوط به نحوهٔ آموزش صحیح و روش یادگیری اصولی. زمان اختصاص یافته شده : ۲۶ دقیقه. Teaching-Learning.mp3
-
2 امتیازمدتی است در مورد مسدود شدن اپلیکیشنهای ایرانی برای iOS از طرف شرکت اپل خبرهایی به گوش میرسد که در سایتها و پایگاههای خبری از سمت نویسندگان و افراد غیرفنی تجزیه تحلیل و روشهای دور زدن آنها ارائه میشود. واقعیت بر دلیل نوشتن این مقاله این است که این فرصت و مشکلات کنونی آبی گلآلود برای سودجویانی شده است که کاربران از آن بیخبرند! هر روز یک توسعهدهنده یک سایت جدید راهاندازی میکند و با ادعای ارائه بستری نامحدود اقدام به تبلیغات میکند. بنده نیز به عنوان توسعهدهنده وظیفهٔ خودم میدانم که یک بار برای همیشه توضیحات شفاف و روشنی را در اختیار کاربران iOS قرار دهم تا متوجه اصلِ موضوع باشند (بعد از آن تصمیم با خود شما)! اول از خودمان شروع کنیم، آیا واقعاً حرکتهایی که ما داشتهایم درست بوده است؟ به گونهای که انگار اقدامات ما ایرانیها بدون عیب و ایراد بوده و اپل بدون دلایل منطقی اقدام به تحریم ما کرده است! (هدف از این مقاله به هیچ عنوان طرفداری از اقدامات شرکت اپل نیست، چرا که این شرکت به عنوان فروشندهٔ محصولات خود وظیفه دارد به پشتیبانی و ارائهٔ خدمات به کاربرانش باشد نه اینکه هم سود کند و هم به خاطر مسائل سیاسی برخی از مشتریان خود را محدود کند. بنابراین ما اپل را هم محکوم به آن میکنیم که هیچ ارزشی به کاربران و توسعهدهندگان ایرانی به خاطر مسائل سیاسی قائل نیست)، و در مقابل مشترکین و حتی شرکتها و فروشگاههای اپلیکیشن موظف هستند به جای توجیح کارهای غیر قانونی و ناعادلانهٔ خود (و استفاده از چنین فرصتها)، اقدامات به شفاف سازی روشهای انتشار و توسعه کنند که مسلماً کاربران عادی و غیر حرفهای از این امر بی خبرند! به گونهای که انگار ما عادت کردهایم هر زمان که مشکلی گریبان گیر ملت ما میشود به جای حل آن از روش صحیح و قانونی، اقدام به فشار بیشتر و سوء استفاده از آن فرصت کنیم که اصلاً روش انسان دوستانهای نیست (حداقل از فرهنگ اصیل ایرانی چنین انتظاراتی نداریم). اما واقعیت امر در چیست و دلایل مسدود سازی نرمافزارها بر روی iOS در چیست؟ اینطور که به گوش میرسد و به گفتهٔ پایگاههای خبری و سایتهای فناوری خبرها اینگونه است که، اپل تا کنون چندین بار برخی اپلیکیشنهای ایرانی را مسدود یا رَد اعتبار کرده است ولی این بار، اپلیکیشنهای پرداخت الکترونیکی و موبایلی مانند آسان پرداخت و نرمافزار بانکهای معروف ایرانی تحریم شدند. افزون بر این، اپهای محبوب و پر کاربردی مانند اسنپ، تپسی، فونپی، دیجیکالا، فیدیبو، سیباپ نیز جزو تحریم شدهها هستند. در قدم اول ممکن است دلایل این کار را به خاطر مسائل سیاسی بدانیم، این مسئله تا حدی ممکن است درست باشد، اما با بازنگری و یادآوری حریم خصوصی و حقوق مشتری در جامعهٔ بشری از سمت اپل نیز حکم میکند که جوابگوی خدمات پس از فروش خودش باشد. بنابراین بهانه تراشی بخشی از اقدامات میتواند باشد اما مسئلهٔ اصلی این نیست! اجازه دهید جایگاه خودمان را برعکس در نظر بگیریم، با این حساب که ما به عنوان خدمات دهندههای ایرانی بستری را فراهم کرده باشیم که به جامعهٔ بزرگی از دنیا خدمات ارائه میدهیم. بنابراین قوانین و چهارچوبهای شفاف و مشخصی را عنوان خواهیم کرد که خارج از آن باید اقدام به یادآوری و گوشزد، تذکر و در نهایت برخورد قانونی و تحریم را در برنامه داشته باشیم که یک روند قانونی و طبیعی است. این قوانین در صورتی اجرا میشوند که حقوق توسعه، تولید، نشر و پشتیبانی رسمی محصولات نادیده گرفته شود. بنابراین فرض کنید شما صاحب فروشگاهی هستید که نویسندگان (توسعهدهندگان) و ارائهدهندگان خدمات آن همگی ساعتها، ماهها و سالها زمان بر توسعه و تولید محصولات خود گذاشتهاند. حال ممکن است آن را رایگان و یا حتی با دیدگاه تجاری در اختیار کاربران قرار دهند. بنابراین عقل و منطق اجازه میدهد که شما نرمافزار رایگان را به صورت رایگان و نرمافزارهای تجاری را در قبال پرداخت هزینهٔ آن مورد استفاده قرار دهید. در غیر این صورت اگر محصولی که شما ارائه دادهاید با نقض این موارد مواجه شود (بدون شک اولین تصمیمی که خواهید گرفت حذف خدمات پس از فروش، پشتیبانی و ... خواهد بود). اما واقعیت این مسئله چیست؟ آیا اپل اقدام به تحریم بی دلیل بر روی اپلیکیشنهای ایرانی داشته است؟ اگر منطقی به قضیه فکر کنیم، به راحتی میتوان این مسائل را بررسی و دلایل تحریم را درک کرد؛ من در این مقاله ابتدا به دلایل تحریم اپل میپردازم که پاسخ روشن و صریح این اقدامات اخیر را در این باره به شما خواهد داد. هرچند من به عنوان یک برنامهنویس باید به دنبال توسعه و تولید محصولات و حتی دور زدن تحریمهای ناشیانه در این حوزه باید باشم، اما اینکه هم نوعان و همکاران خودم هم در این باره خبرها و اطلاعات دروغ را به مشتریان این حوزه میدهند قابل تحمل نیست! چرا که اول باید از خودمان شروع کنیم! بهتر است در نظر داشته باشیم قوانینی که در اپل نیز ذکر شدهاند به این اشاره دارد که در صورت خروج از این چهارچوب که ممکن است امنیت و حقوق مادی و معنوی توسعهدهنده و ناشر را پایمال کند، هیچ گونه تعهدی در رابطه با ادامهٔ همکاری و یا پشتیبانی از آن خدمات را نخواهند داشت. بنابراین شخصاً ندیدم حتی در یکی از فروشگاههای ایرانی اشارهای به این حقوق شده باشه (حتی برعکس و شدیداً بر خلاف مواردی هستند که ذکر شدهاند که با دلیل و اسناد معتبر خود مرجع اپل آنها را شفاف سازی خواهم کرد). به عنوان مثال، اگر شما یک کاربر عادی یا حتی تازه کار باشید، یا اگر شما یک توسعهدهندهٔ تازهکار و حتی حرفهای باشید بهتر است به این بخش از قوانین اپل (App Store Review Guidelines) توجه جدی کنید! این بخشی از قوانین صریح و شفاف اپل در حوزهٔ اپلیکیشنهای iOS و فروشگاه خودش است که در زیر آمده است: App Store Review Guidelines Introduction Apps are changing the world, enriching people’s lives, and enabling developers like you to innovate like never before. As a result, the App Store has grown into an exciting and vibrant ecosystem for millions of developers and more than a billion users. Whether you are a first time developer or a large team of experienced programmers, we are excited that you are creating apps for the App Store and want to help you understand our guidelines so you can be confident your app will get through the review process quickly. The guiding principle of the App Store is simple - we want to provide a safe experience for users to get apps and a great opportunity for all developers to be successful. We do this by offering a highly curated App Store where every app is reviewed by experts and an editorial team helps users discover new apps every day. For everything else there is always the open Internet. If the App Store model and guidelines are not best for your app or business idea that’s okay, we provide Safari for a great web experience too. On the following pages you will find our latest guidelines arranged into five clear sections: Safety, Performance, Business, Design, and Legal. The App Store is always changing and improving to keep up with the needs of our customers and our products. Your apps should change and improve as well in order to stay on the App Store. A few other points to keep in mind: We have lots of kids downloading lots of apps. Parental controls work great to protect kids, but you have to do your part too. So know that we’re keeping an eye out for the kids. The App Store is a great way to reach hundreds of millions of people around the world. If you build an app that you just want to show to family and friends, the App Store isn’t the best way to do that. Consider using Xcode to install your app on a device for free or use Ad Hoc distribution available to Apple Developer Program members. If you’re just getting started, learn more about the Apple Developer Program. We strongly support all points of view being represented on the App Store, as long as the apps are respectful to users with differing opinions and the quality of the app experience is great. We will reject apps for any content or behavior that we believe is over the line. What line, you ask? Well, as a Supreme Court Justice once said, “I’ll know it when I see it”. And we think that you will also know it when you cross it. If you attempt to cheat the system (for example, by trying to trick the review process, steal user data, copy another developer’s work, manipulate ratings or App Store discovery) your apps will be removed from the store and you will be expelled from the Developer Program. You are responsible for making sure everything in your app complies with these guidelines, including ad networks, analytics services, and third-party SDKs, so review and choose them carefully. Some features and technologies that are not generally available to developers may be offered as an entitlement for limited use cases. For example, we offer entitlements for CarPlay Audio, HyperVisor, and Privileged File Operations. Review our documentation on developer.apple.com to learn more about entitlements. We hope these guidelines help you sail through the App Review process, and that approvals and rejections remain consistent across the board. This is a living document; new apps presenting new questions may result in new rules at any time. Perhaps your app will trigger this. We love this stuff too, and honor what you do. We’re really trying our best to create the best platform in the world for you to express your talents and make a living, too. در قوانین ذکر شده به صراحت عنوان شده است که اگر به فکر برنامههای آزمایشی هستید بهتر است از محیط Xcode با همان حساب توسعهدهندگی استفاده کنید که تنها بر روی دستگاه خودتان میتواند اجرا شود. در صورتی که به فکر بحث تجاری آن هستید باید تمامی حقوق مربوطه را رعایت کنید و حتی نباید به فکر کپی کردن، درز اطلاعات، به خطر اندازی حریم خصوصی و دیگر مسائل بپردازید که در این صورت اپل محصول شما را رَد خواهد کرد. فشار دو طرفه، بهانه تشدید بهانه... بهانه و باز هم بهانه!!! مسلماً برای همه روشن است که سیاستهای آمریکایی و شرکتهای آن منتظر بهانههایی هستند که سریعاً فشارها را به سمت ملت ایران وارد کنند، بنابراین مانند اقدامات اخیر Github که متأسفانه مجبور هستند بر اساس سیاستهای دولتی خود اقدام به محدود سازی خدمات خود به ایرانیها باشند (اپل بسیار مشتاقانهتر به دنبال بهانه و ایجاد فشار به ملت ما میشتابد). بنابراین باز هم یادآوری کنیم محصولی که بابت آن پول پرداخت میشود اعمال محدودیت و فشار بر آن دیگر جایز و انساندوستانه نیست! جالبتر از این موارد یادآوری این موضوع است که دوستان داخلی به جای حل مشکلات با فرصت طلبیها و سوء استفادهها و بیانصافیها هم فشار وارده را بر کاربران iOS بیشتر کردهاند و هم وضعیت و بهانههای بیشتری به دست شرکت اپل میدهند! این واقعیتی است که باید پذیرفت (به گونهای که در شرایط اقتصادی کنونی هم فشار از خارج هم داخل بر ملت ما وارد است). کاش منصفانه به فکر راه حلهای مشکلات کنونی باشیم... ملت ما در چنین شرایطی هر جا که به کمک هم شتاب کردهاند موفقتر بودهاند و خواهند بود (اما به روش درست نه غلط!!!). حال با در نظر گرفتن نقض قوانین صریح از سمت فروشگاههای ایرانی که به آن هم افتخار میکنند، آیا نباید انتظار داشت تا روزی اپل یا هر شرکت دیگری صبرش به پایان برسد و خیس و خُشک را باهم بسوزاند؟! بخشی از ادعاهایی که بزرگترین مرجع ایرانی (سیباپ) اپلیکیشنهای iOS ارائه شده است به صورت زیر میباشد: زمانی که دسترسی به هزاران اپلیکیشن خارجی با ارزش ۵۰،۰۰۰ دلار در کشور ما با افتخار حقوق توسعهدهنده و ناشر را زیر سوأل میبرد نباید انتظار داشت چنین تحریمهایی حق ماست؟ حال آنکه چنین فروشگاههایی جدیداً از محدودیتهای اخیر سوء استفاده کرده و حتی با وعدههای دروغین اقدام به فروش اشتراک ویژه میکنند که در ازای آن هیچ تضمینی از امنیت، حقوق مادی و معنوی و حتی اجرا شدن نرمافزارهای موجود در آن فروشگاه وجود ندارد! متأسفانه دروغها و فرصت طلبیها از چنین فرصتها به جای حل مسائل و اختلافهای سیاسی و تجاری چیزی به جز بدتر کردن وضعیت کنونی نخواهد داشت. حتی هیچ شانسی برای بهتر شدن وضعیت کنونی باقی نخواهد ماند. نقل قول زیر از طرف سیباپ است که ادعا کرده است با پرداخت اشتراک شما قادر به دانلود بدون مشکل اپلیکیشنها خواهید بود. راه حلهای ناشیانه و واقعا مسخره که از طرف فروشگاهها و نویسندگان خبری اخیر به دستمان رسیده است به صورت زیر هستند: استفاده از نسخه وب اپلیکیشن حقیقت نفهته در پشت این راه حلها به این صورت است که یک فناوری به عنوان PWA یا همان (Progressive web applications) وجود دارد که همان نسخهٔ وب به شمار میآید! در واقع اپلیکیشنهای نوشته شده به این روش بسیار بدتر از حتی یک وبسایت کامل هستند و تنها به روشهای غیر بومی و خارج از محیط Xcode تحت فناوریهای وب مانند HTML, CSS و JavaScript توسعه داده میشوند. در نهایت هیچ ربطی به نسخهٔ اصلی و نوشته شده به روش طبیعی نرمافزارهای iOS ندارد و تنها نسخهٔ محدود شدهای از وبسایت خدماتی است که با حقههای فریبنده و کاملاً ناشیانه اقدام به ساخت میانبر و ایجاد آیکون بر روی صفحه گوشی شما میکنند که اینطور برداشت کنید نسخهٔ واقعی اپلیکیشن را نصب کرده اید!!! در حالی که بهتر است به جای آن از همان وبسایت استفاده کنید. مسخره است نه؟! دسترسی به برنامههایی که پیشتر از اپ استور دانلود کردهاید دسترسی به برنامههایی که پیشتر از اپاستور دانلود شده است روشی کاملاً مسخرهتر است که به شما پیشنهاد میدهد تا نسخههای قدیمی اپلیکیشنهایی که اپل آنها را نگهداشته است اما توسعهدهندهگان آنها هم نمیتوانند آن را بهروز رسانی کنند استفاده کنید! این کار چه فایدهای دارد دقیقاً؟ تعداد اپلیکیشنهایی این چنینی بسیار محدود هستند مانند دیوار ... که آخرین بهروز رسانی آن به ۲ سال پیش مربوط است!!! جیلبریک کردن این روش ممکن است کارایی داشته باشد، اما تمامی مسائل امنیتی و خدماتی که اپل آنها را ارائه میکند را از بین برده و در واقع در این روش هیچ تضمینی برای حفظ اطلاعات و صحت عملکرد دستگاه شما وجود ندارد (در واقع شما از روش بسیار خطرناک از بین هزاران حفرههای شکافته شدهٔ امنیتی عبور کرده و از برنامهٔ مورد نظرتان که شاید آن یک اپلیکیشن بانکی و ... باشد استفاده میکنید). راه حل سیب اپ (بزرگترین فروشگاه ایرانی برای برنامه های iOS) این پیشنهاد زمانی معتبر است که فروشگاه و یا فروشگاههای مربوطه با شفافیت کامل بیان کنند که راهحلهای فعلی هیچکدام نهایی نیست و اصلاً مخصوص کاربر نیست!!! چرا که مشتری نه توسعهدهنده است و و نه شرکت! بنابراین زمانی که با حرکتهای ظاهراً حرفهای اما در حقیقاً کاملاً غیر حرفهای از هر کاربر یک توسعهدهنده یا شرکت و یا سازمان میسازند طبیعی است که باید هزینههایی مانند ۹۹ تا ۲۹۹ دلار در سال را بپردازند که مسلماً منجر به پولی شدن حق نصب اپلیکیشن خواهد بود که از بیخ غلط است! بنابراین انتظار میرود تحت هیچ شرایطی مردم را نَفَهم فرض نکنیم! مطمئنان هر عقل سلیمی میتواند تشخیص دهد که این روش دقیقاً همان مثال معروف (ماهی گرفتن از آب گلآلود است) در واقع شما باید پول به چیزی بپردازید که خودش روش غیرقانونی و نامناسب است!!! برخی از توسعهدهندگان و سایتهای خبری و حتی استورها چنین ادعا میکنند که هیچ محدودیتی در توسعه و انتشار برنامههای iOS وجود ندارد، آیا این حقیقت است؟ طبق توضیحاتی که در بالا اشاره کردم، هیچ روش منطقی در داخل کشور وجود ندارد که قانونی باشد، اگر کسی مدعی به انتشار است مطمئنان از همین روشهایی که اشاره شد استفاده میکند که خارج از این نیست. فروشگاههای جدید و مدعی بدون محدودیت چگونه کار میکنند؟ متأسفانه با وجود شرایط کنونی و محدودیتهای اپل افراد و فروشگاههای زیادی در چندین ماه اخیر ایجاد شدهاند که از این فرصت برای ارائه خدمات به شیوهٔ PWA و دو روش دیگر که ذکر شد استفاده میکنند که هیچ یک از آنها ارائه دهندهٔ خدمات واقعی نیستند. (اگر شما فروشگاهی را میشناسید که از روشهای قانونی برای نشر برنامهها استفاده میکند که نیاز نباشد هر چند وقت یک بار برنامه را حذف و دوباره نصب کنند و یا در بهترین حالت شما را به عنوان توسعهدهندهٔ اپل معرفی نکنند به ما معرفی کنید تا به گوش همگان برسانیم!). روشهای پیشنهادی و رسمی اپل چیست؟ طبق اسناد رسمی، اپل میگوید اگر شما برنامهٔ خودتان را به صورت استاندارد توسعه دادهاید میتوانید به دو روش آن را منتشر کنید؛ روش اول این است که آن را در فروشگاه اپل منتشر کنید (که در این روش بنابر اساس سیاستهایی که دارند مسلماً تحریم ما خواهد بود که شاهدش بودیم - حذف اپلیکیشنهای ایرانی از فروشگاه اپل). روش دوم آن است که شما اپلیکیشن خود را در قالب روشهای Ad-Hoc ایجاد کنید که محدود بر ۱۰۰ دستگاه (کاربر) خواهد بود. این روش نیز به گونهای قابل استفاده است اما محدود بر تعداد کاربران خواهد بود و برای اهداف داخلی و سازمانی خودمان طراحی شده است و بدون شک امضاء و مدیریت آن همراه با تولید آمار بسیار زیادی از تأییدیهها سرسام آور خواهد بود. درواقع اپل میگوید اگر میخواهید در دامنهٔ بزرگتر یعنی جهان، استفاده کنندهٔ اپلیکیشن شما باشد باید در فروشگاه من آن را منتشر کنید تا هم امنیت و هم پشتیبانی آن را تضمین کنم. روشهای دیگر نیز با عنوان (Enterprise Program) مطرح هستند که مخصوص تیمهای توسعهای که در برنامه Enterprise یا همان تجاری ثبت نام کردهاند نیز میتوانند از توزیع داخلی استفاده کنند. این روش همان روشی است که اپل برای عموم اکثراً محدود کرده است و مختص تحریمهای ایران نیست. درواقع همان روشی که بعضی از شرکتهای ایرانی هر روز میگویند اپلیکیشن را از لینک جدید دریافت کنید!!! که البته همراه با هزینهٔ سالانه ۲۹۹ دلار است! روشهای محدودتر دیگری وجود دارد که کاربران با محدودیت بیشتری با آن میتوانند برنامهها را صرفاً برای مصارف ازمایشی و خودمانی استفاده کنند که این دسته با عنوان University Program شناخته شده اند و توانایی نشر برنامه به جامعهٔ هدف بزرگتری را نخواهند داشت. با توجه به این تعاریف مشخص است که دو روش پیشفرض استاندارد و Ad-Hoc باقی مانده است. تکلیف روش اول مشخص است که تا زمانی که تحریمها وجود دارد نباید انتظار داشت که در اپاستور بتوان اپلیکیشنهای ایرانی را بارگذاری کرد. اما روش ادهاک همان روشی است که اجازه میدهد با خرید و ثبت دستگاه در بانک گواهیهای معتبر اپل اپلیکیشنهای خود را به مدت ۱ سال یا بیشتر امضا کنید (این روش برای توسعهدهندگان) پیشنهاد شده است که احتمالاً روشهای فعلی استورها این باشد! مسلماً این روش هزینهٔ شارژ و امضای توسعهدهنده را خواهد داشت. البته لازم به ذکر است این روش قطعی نیست و اگر اپل بداند که به زودی هم خواهد دانست میلیونها کاربر توسعهدهنده پیدا کرده است! مسلماً طی اقداماتی روشهایی برای حل آن ارائه خواهد داد. خب راه حل منطقی چیست؟ با توجه به مستندات و منابع رسمی که اعلام کردهاند، از اولین ساعتهای مسدود شدن نرمافزارهای بانکی و پرداختی، شرکتهایی که در این مجموعه اپ یا اپهایی داشتند؛ راهحل موقت خود را ارایه کردند، عمدهترین راهحل استفاده از اپهای مسدود شده روی گوشیهای آیفون، مراجعه به نسخه وب اپلیکیشن یا استفاده از پلتفرمهای دیگری مانند اندروید است. مدیران اسنپ و دیجیکالا از کاربرانشان درخواست کردند به طور موقت نسخه وب آنها را استفاده کنند تا مشکل حل شود. برخی شرکتها مانند سیباپ و تپسی، نسخه جدید و مجزایی از اپاستور ارایه داده و از کاربرانشان درخواست کردند این اپلیکیشن را از روی سایت آنها دریافت و نصب کنند. سیباپ در پیامهای ویدیویی و اطلاعیه رسمی، به کاربران خود وعده داده است بهزودی نسخه جدیدی از اپلیکیشن سیباپ ارایه خواهد شد که دیگر مشکل مسدود بودن یا عدم اعتبارسنجی توسط اپل را ندارد (که این روش زمانی قابل تأیید خواهد بود که به روشهایی غلطی که در بالا اشاره شد عمل نشود و رسالت و شعارهای فریبانهٔ خود را تغییر دهند) که مسلماً باید اول حقوق مادی و معنوی و حریم خصوصی مصرف کننده را تضمین کنند و در نهایت به روشهای قانونی مجوزهای لازم را از اپل دریافت کنند که با توجه به شرایط حاکم کمی غیر ممکن و دور از انتظار است!!! روشهای بهتری جهت نصب و راهاندازی اپلیکیشنهای ایرانی وجود دارد که با نامهای Add-Hoc نیز معروف هستند که محدود به نوع توسعهدهنده و تجاری معرفی میشوند. البته روشهای تجاری همان روشهایی است که سیباپ و دیگر شرکتها مورد استفاده قرار دادهاند. اما روش روش نوع توسعهدهنده میتواند با در نظر گرفتن ثبت دستگاه شما در پروفایل این مشکل را تا حدی برطرف کند که فروشگاههایی مانند اناردونی با در نظر گرفتن هزینهٔ ثبت دستگاه آن را تا به مدت ۱ سال تضمین میکنند. روش درست و صحیحتر آن است که دقیقاً طبق قوانین اپل عمل شود، در واقع تمامی مادهها و تبصرههای عنوان شده توسط شرکت اپل در اپاستور را باید پذیرفت. اما مشکل اصلی و اساس این مشکلات این است که اپل قبلاً هم گفته است حاضر به ارائهٔ خدمات به ایران نیست. (یاد شعار استیو جابز مرحوم افتادم که ما خواهیم گفت کاربر از چه چیزی باید استفاده کنند نه آنها) در واقع اپل با این اقدامات و فشارهای خود رسماً میگوید شما بهتر است از محصولات دیگر استفاده کنید که عمل زشت و بسیار نژادپرستانه است. آیا فروشگاههای داخلی به داد مردم میرسند یا از آب گلآلود ماهی میگیرند؟ قضیه این است!!! خوشبختانه در حالت عادی خدمات فروشگاههای داخلی خوب به نظر میرسد، اما وقتی به واقعیتهای آنها میپردازیم میبینیم که فرصتهای خوبی برای پول به جیب زدنهای خیلی خوشگل فراهم شده است که هرچند برای فراهم سازی بستر آن باید زحمت کشید و پول خرج کرد... اما در ازای چه خدماتی چه چیزی به دست میآورند؟ وقتی به خدماتی قرار است پولی پرداخت شود، آن سرویس باید بدون هیچ دغدغه و مشکلات مادی و معنوی قابل استفاده باشد. با توجه به عدم شفاف سازی کاربران که دلیل آن را نداشتن دانش فنی میدانند. از جانب بعضی از توسعهدهندگان و فروشگاههای ایرانی ترجیح دادهشده است که، خدمات ارائه شود اما با دریافت هزینه! کافی است یک حساب کتاب ساده انجام دهید، وقتی شما قرار است توسعهدهندهٔ اپل باشید باید هزینهٔ سالیانه آن را پرداخت کنید که چیزی حدود ۹۰ تا ۱۲۰ دلار بسته به مالیات متغیر است. و اگر قرار است امضاء از نوع سازمانی داشته باشید باید هزینهای معادل ۲۹۹ دلار برای آن بپردازید که در نهایت هر ۱۰ الی ۲۰ روز یک بار هزینه نزدیک به ۳ میلیون تومان برای خرید اکانت تجاری باید تقدیم کنید! در قبال آن به دست آوردن برخی از فروشگاهها مانند سیباپ هزینهی حداقل ۳۰،۰۰۰ تومان را بابت آن دریافت میکنند. به گفتهٔ خودشان تعداد کاربران میلیونی... با پرداخت چنین هزینههایی معادل صدها شاید هم هزاران و میلیونها برابر آن را به دست خواهند آورد!!! فرصت خوبی برای راهاندازی کسبوکار و به قول قدیمیها (ماهی گرفتن از آب گلآلود) است نه! البته فروشگاههایی هم وجود دارند که با روشهای PWA ادعای به اشتراک گذاری اپلیکیشنها را دارند که از اشاره به نسخه وب بودن و محدودیتهای آن دریغ میکنند. اخیراً هم که با حقهبازیهای هرچه تمام هزینههای چند برابری با وعدههای دروغین به مردم خدمات میدهند که شخصاً با خرید حساب ۱ ساله بعد از ۳ ماه دوباره از ما پول خواستن! حالا که در جریان واقعیت قرار گرفتهاید، بهتر است خودتان قضاوت کنید (چرا که به عنوان یک برنامهنویس این ننگ است که بدانیم اما به زبان نیاوریم که چه چیزی به خُرد ملت میدهیم). آیندهٔ نرمافزارهای iOS ایرانی چطور خواهد شد؟ شما کاربران عزیز باید در نظر داشته باشید که هیچ روش رسمی و قانونی به جز مواردی که اشاره شده است وجود ندارد، مشخص نیست با این وضعیت چه بلایی به بازار اپلیکیشنهای ایرانی در پلتفرم iOS خواهد آمد، اما با توجه به مسائل سیاسی که دولت ایالات متحدهٔ آمریکا اعمال کرده است و تمامی تحریمهای بانکی و ... از قبل گریبان گیر ما شده است کمی بعید است بدون حل مسائل سیاسی این دو کشور به این راحتی ها بتوان راه حلهای دائمی و مطمئن معرفی کرد. بنابراین، باید منتظر ماند تا دید آیا نظر اپل در این بهانه تراشیها تغییر خواهد کرد یا خیر! البته بر اساس نظرات کارشناسی برخی از حقوقدانها و سیاستمداران اینطور عنوان میشود که شرکتها بعضاً مجبور هستند بر خلاف میل خود طبق دستورات دولت خودشان اقدام کنند. در نهایت، باید منتظر ماند و دید که آیا حتی با پذیرفتن هزینههای بسیار بالا و رعایت قوانین کامل اپل باز هم اقدام به مسدود کردن برنامههای ایرانی خواهد کرد یا خیر. هدف از این مقاله این است که با چشمان باز حقیقت پنهاد در پشت این مسائل را بدانید.
-
2 امتیازمدتی قبل بود که من در رابطه با شاخصهای در حال رشد زبانهای برنامهنویسی در کانالهای شخصی نظری داده بودم که با توجه به وضعیت شاخص، زبان برنامهنویسی ++C سریعترین رشد را بعد از مدتها به خود اختصاص داده است. این تغییرات و بیداری زبان طبق انتظاری که داشتم بعد از ظاهر شدن زبان برنامهنویسی Rust در بین ۲۰ زبان برنامهنویسی برتر و همچنین نهایی شدن استانداردهای 2a و پیشرفتهای اخیر به خصوص رضایتبخشی کاربران از استاندارد 17 زبان ++C رخ داده است که دور از انتظار هم نبود. طبق شاخص محبوبیت طی چند سال گذشته، ++C با توجه به شاخص TIOBE در سپتامبر، سریعترین زبان در حال رشد در بسته برنامهنویسی است. این زبان در سالهای گذشته، محبوبیت سهم خود را در فراز و نشیبها داشته است. اما با مقیاسه با سالهای گذشته در حال حاضر رسماً سریعترین رشد را در بین تمامی زبانهای تحت پوشش اتوماسیون QA در شرکت Tobie را دارد. با این حال مدیرعامل Tobie جناب Paul Jansen گفته است، من فکر میکنم که استاندارد جدید سی++ یکی از دلایل این رشد اصلی باشد. به خصوص ویژگیهای جدید module که قرار است جایگزین مکانیزم وحشتاک قبلی شود. با این روند سی++ بیشترین رشدها که متعلق به #C با ۱.۱۸+ و R با ۱.۳۳+ را شکست میدهد.
-
2 امتیازاین تاپیک جهت معرفی و اطلاع رسانی در رابطه با اهداف نسخههای جدید، بهروزرسانیها، تاریخ انتشار و موارد مرتبط با آن ایجاد شده است. در این تاپیک به موضوعات مرتبط خواهیم پرداخت. جهت شروع نسخهٔ ۵.۱۲.۰ کیوت با پشتیبانی LTS را معرفی میکنیم. همانطور که میدانید کمپانی و تیم توسعهدهنده با فعالیتهای بسیار زیاد خود مُدام در حال بهروز رسانی و حل مشکلات بازخورد شده از سمت کاربران برای این کتابخانه هستند. بر خلاف نسخههای پیشین نسخههای سری ۵ با بهروزرسانیهای پیدرپر مواجه شده است که شاید این بزرگترین تمایز تیم توسعه دهنده در نسخههای قبلی است. کتابخانهٔ کیوت معمولاً در نسخههای اصلی از ویژگیها و تغییرات چشمگیری مواجه میشود که میتوان آنها را در تغییرات یا افزوده شدن به ماژولهای هسته، فرعی و افزونههای آن اشاره کرد. البته به این مورد نیز باید اشاره کنیم که این بهروزرسانیها تنها برای خود کتابخانه نبوده و معمولاً محیط توسعهٔ آن نیز همراه خود بهروزرسانی و حتی به صورت جداگانه منتشر میشود که در اینجا تاپیک مخصوص آن آورده شده است. از آنجایی که انتظار میرود کیوت در نسخهٔ ۵.۱۲.۰ با بهروزرسانیهای اساسی آمده است. یکی از مهمترین آنها تغییر بر روی کامپایلرها و پشتیبانی کامل از استانداردهای جدید C++ است. در این نسخه کامپایلرهای GCC به نسخهٔ ۸ و کامپایلرهای Clang به نسخهٔ ۷ و مهمتر از همه در محیط ویندوز بهروز رسانی MinGW به نسخهٔ ۷ بوده است. البته ناگفته نماند با توجه به تغییرات اخیر گوگل در NDK که اعلام کرده است کامپایلر پیشفرض GCC به Clang تغییر کرده است این تغییر نیز در کیوت اعمال و با هماهنگی ۱۰۰٪ از ویژگیهای جدید توسعه اندروید هماهنگ شده است. بنابراین شما در بخش کیتها شاهد وجود کامپایلرهای متعددی خواهید بود که بهروز رسانی شده اند. نکتهٔ مهم برای توسعه دهندگان ویندوز : اگر به خاطر داشته باشید در نسخههای ۵.۱۰.۰ به بعد کامپایلر ۳۲ بیتی MSVC به طور غیر منتظرهای حذف شده بود که با بازخورد کاربران روبرو و در نهایت در این نسخه نسخهٔ ۳۲ بیتی کامپایلر MSVC افزوده شده است. مهمترین بهروزرسانیهای کیوت ۵.۱۲.۰ ویژگیهای اضافه شده به هسته: افزوده شدن ویژگی جدید CBOR به عنوان فرمت جدید همانند JSon برای سریالیز دادهها. افزوده شدن متد hashLength برای QCryptographicHash که طول خروجی هَش شده را بر میگرداند. افزوده شدن متد wildcardToRegularExpression به QRegularExpression جهت معرفی راحتتر کد کاربر. افزوده شدن متد anchoredPattern به QRegularExpression جهت پیاده سازی تطبیق کد کاربر. افزوده شدن QRegularExpression برای کلاس QSortFilterProxyModel ویژگیها و تغییرات در QtGui افزوده شدن پشتیبانی از ویژگی Windows UI Automation در WinRT QPA برای برنامههای مبتنی بر UWP که آن را قادر میسازد تا با ابزارهای قابل دسترس در سمت UI دسترسی داشته باشند. جایگزین شدن ویژگیهای مرتبط با دستگاههای ورودی mouse، touchpad، touchscreen و tablet با ویژگیهای متحد بر پایهٔ ویندوز ۸ و جدیدتر. افزوده شدن QGradient جدید بر پایه https://webgradients.com افزوده شدن فرمتهای 4xU16 ،RGBA64 به QImage جهت خواندن فرمتهای PNG و TIFF و همچنین امکان آپلود و گرفتن آنها از OpenGL. ویژگیها و تغییرات در QtNetwork افزوده شدن DTLS برای پشتیبانی از UDP افزوده شدن یک بازنگری مجدد برای ترنسفر ایمن در بکاِند. افزوده شدن پشتیبانی از ALPN در پروتکل HTTP/2 جهت امنیت ترنسفر اطلاعات. افزوده شدن پشتیبانی از ویژگی PKCS#8 در بکاِند عمومی (WinRT و ترنسفر اطلاعات) افزوده شدن QPasswordDigestor به عنوان یک فضای نام که شامل توابعی برای استخراج کلید بر پایه رمزعبور میباشد (در حال حاضر PBKDF1 و PBKDF2) در دسترس هستند. ویژگیها و تغییرات در QtQml پشتیبانی از موتور نسخهٔ ۸ جاوا اسکریپت فراهم شده است (ECMAScript 7) ماژول ECMAScript میتواند به طور مستقیم توسط QJSEngine::importModule() بارگذاری شود و میتواند فایلهای .qml را در زمان استفاده از فایلهای .mjs را فراهم سازد. ویژگیها و تغییرات در QtQuick نوعهای Pointer Handlers به Input Handlers تغییر نام پیدا کردهاند (البته ویژگیهای مربوط به این دسته در این شاخه وجود دارند) و اکنون به طور کامل به عنوان یک ویژگی پشتیبانی شده در یک کلاس QML تحت Qt Quick پشتیبانی میشود. (رابطهای برنامهنویسی سمت سیپلاسپلاس برای آنها هنوز عمومی نشده است). نوع HoverHandler نوع جدیدی برای شناسایی ویژگی Mouse hover می باشد. این ویژگی میتواند شناور ماوس را در موارد عمیقی شناسایی کند. بر خلاف MouseArea، شما میتوانید چندین آیتم با HoverHandler به صورت همزمان قرار دهید (برای مثال نوار کناری (SideBar) و یک دکمه بر روی آن. نوع DragHandler به عنوان یک نوع چند-نقطهای بشمار میرود. اگر شما مقدار minimumPointCount را به ۲ تغییر دهید، به کشیده شدن تنها با دو انگشت واکنش نشان خواهد داد. این ویژگی میتواند به مراتب آزادیهای بیشتری را در توسعه به شما ارائه دهد. کشیده شدن توسط یک انگشت میتواند یک حرکت خاص را انجام دهد و کشیده شدن توسط دو انگشت میتواند کارهای دیگری را انجام دهد (به عنوان مثال زاویهٔ شیب را تغییر دهد). افزوده شدن پشتیبانی از مخازن از پیش تولید شدن جهت سرعت بخشید به اجرا در زمان استارتآپ. افزوده شدم آیتم TableView به عنوان یک نوع دیگری از نوع Item View همانند ListView که بر خلاف آن ویژگی چند ستونه شدن را دارا میباشد. بر خلاف Qt Quick 1.x ویژگی ظاهری برای آن طراحی نشده است. اما جای آن فراهم شده است تا توسط delegates ها بتوانید بر اساس تقاضا آنها را فراهم کنید. ویژگی DelegateChooser به عنوان پیش نمایشی از تکنولوژی ارائه شده است که به عنوان delegate های Item Views ها مانند TableView بسته به مقادیر آنها کاربرد دارد. ویژگیها و تغییرات در QtQuick Controls 2.x کنترل Dial ویژگی inputMode را اضافه کرده است. که دو روش جدید جهت تعامل به صورت عمودی و افقی را فراهم میکند. این ویژگیهای ورودی از یک سیستم ورودی نسبی استفاده میکنند. به این معنی است که بر خلاف سیستم ورودی مطلق قبلی، اغییرات در موقیع شماره گیری به آن اعمال میشود. این ویژگی در نتیجهٔ آن تاثیر میگدارد و باعث میشود شماره گیر پرش کمتری داشته و آن را از عملیاتی که ممکن است مضر باشد تضمین کند. کنترل Popup ویژگیهای leftInset، bottomInset، topInset و rightInset را به بخش پس زمینه مشابه کنترلهای paddings در contentItem اضافه کرده است. اضافه شدن خاصیتهای implicitWidth و impliciyHeight ویژگیهای implicitHeaderWidth و implicitContentWidth و غیره برای ساده سازی پیوندهای اندازهٔ ضمنی و پیچیده ارائه شده است. در کنترلهای SwipeView و DialogButtonBox خاصیتهای contentWidth و contentHeight افزوده شده است. در کنترل RageSlider خاصیت valueAt() به عنوان تابع اضافه شده است، که اجازه میدهد تا مقادیر در هر زمان از تغییر برای tooltip بهروز و تنظیم شوند. در کنترل RangeSlider خاصیتهای first.mode() و second.mode() به عنوان سیگنالهایی مشابه سیگنال moved() اضافه شدهاند. در آیتم پایه Control، در صورتی که به صراحت مشخص شده باشد، baselineOffset به صورت خودکار فاصلهٔ بالای کنترل و baselineOffset از contentItem را کنترل میکند. مشخص سازی استایل برای این کنترل نیاز نیست. در کنترل Popup، خاصیتهای anchors.centetIn به عنوان یک راه حل مناسب اجازه تنظیم مرکز یک popup را میدهد. آیتم QQuickStyle، افزوده شدن ویژگیهای stylePathList() و addStylePath() به عنوان مدیریت فهرستی از سبکهای موجود در کیوت کوئیک کنترل ۲ را فراهم میکند. کنترل Slider، RangeSlider ویژگی touchDragThreshold را برای پیکربندی آستانهٔ شروع کشیدن (لمس) لغزنده فراهم میکند. کشیدن ماوس در این ویژگی تاثیری ندارد. در کنترلهای TextArea و TextField خاصیت placeHolderTextColor برای راحتی کار برای افزودن رنگ در متن پیشفرض و نمایشی در پس زمینهٔ کنترل اضافه شده است. در ویژگی Material، یک سری موارد مورد استفادهٔ انبوه برای استفاده از این سبک در پلتفرمهای دسکتاپ افزوده شده است.برخی از کنترلها از ارتفاع و اندازهٔ قلم کوچکتری استفاده میکنند. جهت پیکربندی آن نیز میتوان از متغیر QT_QUICK_CONTROLS_MATERIAL_VARIANT جهت مشخص سازی تراکم و یا با تنظیم Variant=Dense در فایل پیکربندی qtquickcontrols2.conf استفاده کرد. کنترل DialogBoxButton خاصیت buttonLayout به آن اضافه شده است که میتواند برای ترتیب و مرتب ساختن دکمهها از آن استفاده شود. کنترل Tumbler، تابع positionViewAtIndex() را اضافه کرده است که میتواند عملکرد توابع مربوط به PathView و ListView را بسته به مقدار آنها بسته بندی کند. این امکان اجازه میدهد تا مقدار currentIndex بدون انیمیشن تغییر یابد. در Control و Popup، خاصیتهای horizontalPadding و verticalPadding به عنوان روش مناسب جهت تنظیم جپ و راست و یا بالا و پایین فاصلهها در یک حرکت در نظر گرفته شده است. کنترل Tooltip، روشهای show() و hide() را برای نمایش پارامترهای خاص اضافه کرده است. ویژگیها و تغییرات در QtSerialBus افزوده شدن یک افزونهٔ مجازی CAN برای شبیه سازی CAN بدون سختافزار. افزوده شدن گزینههای پیکربندی برای canbusutil برای عنوان برای تنظیم میزان بیتریت. افزوده شدن CAN FD به پلاگین PeakCAN. افزوده شدن توابع readAllFrames() و clear() به QCanBusDevice. ویژگیها و تغییرات در QtWebEngine بهروز رسانی شده به Chromium 69 رابط QWebEngineUrlScheme برای تنظیم و پیکربندی نوع و امنیت در طرحهای سفارشی URL. ویژگیهای WebActions در معرض QML قرار گرفتهاند. اکنون میتوان صفحههاتی که آنها را خوانده وی ا از آنها دانلودی صورت گرفته است را خواند. گواهینامههای SSL از این پس پشتیبانی میشوند. خواندن آنها از تنظیمات macOS و Windows و بانک اطلاعاتی NSS در Linux امکانپذیر است. ویژگیها و تغییرات در Qt Labs Platform در آیتمهای Menu، MenuItem و SystemtryIcon خاصیت iconName و iconSource منسوخ شده است. در آیتمهای Menu، MenuItem و SystemtryIcon خاصیت icon.mask افزوده شده است. ویژگیها و تغییرات در Qt Virtual Keyboard یک رابط واسط برای کلید مجازی تعریف شده است. تمامی روشهای ورودی فعلی و برخی از ویژگیهای ویژهٔ لایههای آن مانند Hunspell، OpebWnn و غیره به ویژگیهای اضافی منتقل شدهاند. این ویژگی اجازه میدهد تا ساخت و سازهای نوع سوم بدون دستکاری ورودیهای پیشفرض این ماژول صورت بگیرد. با معرفی این ماژول افزونههای اضافی میتوانند با آن لینک شوند. این ماژول رابطهای برنامهنویسی لازم ++C را برای ایجاد یک روش ورودی جدید فراهم میکند. افزوده شدن گزینهٔ build time به امکان محدود سازی تمامی سبکها در پلاگین را فراهم میکند. پشتیبانی از MyScript برای تشخیص دست نویس اضافه شده است. ویژگی تشخیص Vietnamese در دست خط اضافه شده است. افزوده شدن لایههای جدید، آلبانی، آمریکایی، انگلیسی، فرانسوی، کانادایی، اندونزیایی، مالایی، پرتغال برزیبی، اسلواکی، اسلوونیایی، اسپانیایی مکزیکی، تایلندی، ترکی، ویتنامی و اکراینی. لایههای بیشتر در بارهٔ زبان روسی نیز اضافه شده است. برخی از لغت نامهها به صورت پیش فرض تحت یک افزونه اضافه شدهاند. فرهنک لغت کاربری Hunspell افزوده شده است. ویژگیها و تغییرات در Qt Bluetooth افزوده شدن توانایی جهت کشف دادهها از طریف QBluetoothDeviceDiscovery ویژگیها و تغییرات در Qt 3D افزوده شدن ویژگی جهت بارگیری درون یک فایل که شامل نام و شناسهٔ مشخصی است در بخش نمایه به عنوان انیمیشن فراهم شده است. فعال شدن منحنیهای ثابت در انیمیشن. رفع مشکلات مربتط با QNodes ها در برخی شرایط. رفع و بهبود در نمایش بافتها در اشیاء نوع TextureImage دیگر به عنوان فرزند بافت در نظر گرفته نمیشود. زمانی که در یک حلقهٔ شبیه سازی شده قرار گرفته نشود، استفاده از پردازنده کاهش پیدا خواهد کرد. نوع EntityLoader از این پس قادر به بارگیری از یک Component به خوبی یک فایل است. پشتیبانی از سیستم رندرینگ OpenGL ES 3.1 فراهم شده است. عملکردها و یک سری باگها در بخش بک اند رفع و کارآیی آن بهبود داده شده است. ویژگیها و تغییرات در Qt Wayland Compositor افزوده شدن پشتیبانی از نسخهٔ پایدار xdg-shell (همچنین نسخهٔ ناپایدر ۵ آن منسوخ شده است). پشتیبانی از xdg-decoration-unstable-v1 برای سمت سرور جهت اعمال دکوراسیون پنجرهها اعمال شده است. ویژگیها و تغییرات در Qt WebSocket تابع "bytesToWrite" به این ماژول افزوده شده است. ویژگیها و تغییرات در Qt Location پلاگین MapboxGL بهروزرسانی شده و پشتیبانی از QNX7 فراهم شده است. حذف خاصیتهای add و remove و افزوده شدن آن به MapItemView آیتم MapItemView هماکنون کلاس MapItemGroup را طبقه بندی میکند و به خودی خوب غیر قابل تغییر میباشد. در حال حاضر PlaceSearchModel اجازه میدهد تا مدل به صورت پراکنده پُر شود. ویژگی Map.visibleArea جهت محدود کردن مناطق قابل مشاهده بر روی نقشه اضافه شده است. ویژگی geoShape در آیتمهای مربوط به MapItem به صورت R/W تنظیم شده است و یک تنظیم کننده مجازی در کلاس پایه دارد. پشتیبانی از نگهدارندهٔ حفرهها در QGeoPolygon فراهم شده است. افزوده شدن پشتیبانی از Route Legs به پلاگین. ویژگیها و تغییرات در Qt Test خطاهای مربوط به std::tuple در زمان استفاده از QCOMPARE تشخیص داده میشوند. ماژولهای جدید افزوده شدن ماژول Qt Remote Objects با پشتیبانی کامل. افزوده شدن پلاگین Qt WebGL Streaming با پشتیبانی از استریم در مرورگر و اپلیکیشنهای تحت وب. تغییرات مرتبط با پلتفرمها در QTimeZone از ICU در صورتی که در دسترس باشد استفاده میکند (اولویت استفاده با Api مایکروسافت میباشد). در سیستمعامل macOS پشتیبانی از QSurfaceType::MetalSurface فراهم شده است. در macOS پشتیبانی از QSurfaceType::VulkanSurface و QVulkanWindow از طریق MoltenVK فراهم شده است. در Wayland نسخهٔ پایدار xdg-shell افزوده و نسخهٔ ناپایدار ۵ آن منسوخ شده است. با استفاده از پنجرههای پیشفرض نمایش آنها زیباتر و بهتر شده است. پشتیبانی از ویژگیهای اضافی xdg-decoration-unstable-v1 و xdg-output-unstable-v1 فراهم شده است. فناوریهای جدید به عنوان پیشنمایش ویژگی Qt for WebAssembly امکان این را فراهم میسازد تا برنامههای تحت کیوت در بستر مرورگر با استفاده از WebAssembly اجرا شوند. تغییرات مرتبط با Qt for Automation ویژگی Qt MQTT پشتیبانی کامل از پروتکل MQTT سطح ۵ ویژگی Qt KNX پشتیبانی از KNXnet/IP Core نسخهٔ ۲ پشتیبانی از KNXnet/IP Routing نسخهٔ ۱ پشتیبانی از KNXnet/IP Tunneling نسخهٔ ۲ پشتیبانی از KNXnet/IP و برقراری ارتباط از طریق TCP پشتیبانی از KNXnet/IP Secure به صورت پیش نمایش از فناوری ویژگی Qt OPC UA پشتیبانی از Eventsها افزوده شدن رابطهای برنامهنویسی جهت خواندن به صورت دستهای افزوده شدن رابطهای برنامهنویسی جهت نوشتن به صورت دستهای افزوده شدن یک TranslateBrowsePathsToNodeIds به رابطهای برنامهنویسی رابطهای مرورگری بهبود یافته شده پشتیبانی از انواع Argument و ExpandedNodeId نودها میتوانند از این پس از به وسیلهٔ ExpandedNodeId استفاده شوند. پشتیبانی از آرایه های چند بعدی بهبود یافته است. پشتیبانی از خواندن و نوشتن اشیاء اضافی فراهم شده است. ماژولهای منسوخ (حذف در نسخههای بعدی) ماژول Qt Script ماژول Qt Quick Controls 1 ماژول Qt Canvas 3D
-
2 امتیازمن یک زمانی خدای روی زمینم ++C بود حدودا یک سال و نیم فقط ++C کار بودم تمام تلاشم این بود که همه چیز رو با سیپلاسپلاس بنویسم اما بعد فهمیدم ابزار امده تا کار رو برای مکانیک آسان تر کنه ن این که کار رو سخت کنه مثل این میمونه که شما از آچار فرانسه برای باز کردن پیچ استفاده کنی، زبان هم دقیقا همین طوره. ممنون خیلی مفید بود.
-
2 امتیازدر این مقاله من قصد دارم در رابطه با تفاوتهای اختصاص دادن حافظه در اِستَک و هیپ توضیحاتی دهم که بسیاری از علاقهمندان راجع به آنها سوال کردهاند. با توجه به اینکه، از اوایل سیستمهای کامپیوتری این تمایز در این وجود داشته است که برنامه های اصلی در حافظه فقط خواندنی مانند ROM ، PROM و یا EEPROM نگه داری میشوند. به عنوان دیگر از زمانی که سیستم ها پیچیدهتر شدند برنامهها از حافظههای دیگری مانند RAM به جای اجرا در حافظه ROM استفاده کردند. این ایده به خاطر این بود که تعدادی از قسمت های حافظه مربوط به برنامه نباید تغییر یابند و در این حالت باید حفظ شوند. در این میان دو بخش .text و .rodata بخشیهایی از برنامه هستند که میتواند به بخش های دیگر برای وظایف خاص تقسیم شوند که در ادامه به آنها اشاره شده است. بخش کد، به عنوان یک بخش متنی (.text) و یا به طور ساده به عنوان متن شناخته میشود. جایی است که بخشی از یک فایل شیء یا بخش مربوطه از فضای آدرس مجازی برنامه که حاوی دستورالعمل های اجرایی است و به طور کلی فقط خواندنی بوده و اندازه ثابتی دارد میباشد. بخش .bss که به عنوانی بخشی ویژه (محل نگه داری اطلاعات تخصیص داده نشده (مقدار دهی نشده)) محلی که متغیرهای سراسری و ثابت با مقدار صفر شروع میشوند. بخش داده (.data) حاوی هر گونه متغیر سراسری و یا استاتیک که دارای یک مقدار از پیش تعریف شده هستند و میتوانند اصلاح شوند. تصویر زیر طرح معمولی از یک حافظه برنامه ساده کامپیوتری را با متن، داده های مختلف، و بخشهای استک و هیپ و bss را نشان میدهد. .section.data < initialized data here> .section .bss < uninitialized data here> .section .text .globl _start _start: <instruction code goes here> برای مثال در کد C به صورت زیر خواهد بود: int val = 3; char string[] = "Hello World"; مقادیر برای این نوع متغیرها در ابتدا در حافظه فقط خواندنی ذخیره میشوند. (معمولا در داخل .text) و در زمان اجرای برنامه که به صورت روتین خواهد بود در بخش .data کپی میشوند. بخش BSS یا همان .BSS در برنامهنویسی کامپیوتر، نام .bss یا bss توسط بسیاری از کامپایلرها و لینکرها برای بخشی از دیتا سِگمنت (Data Segment) استفاده میشود که حاوی متغیر های استاتیک اختصاصی که تنها از بیت هایی با ارزش صفر شروع شده است میباشد. این بخش به عنوان BSS Section و یا BSS Segment شناخته میشود. به طور معمول فقط طول بخش bss نه data در فایل آبجکت ذخیره میشود. برای نمونه، یک متغیر به عنوان استاتیک تعریف شده است static int i; این در بخش BSS خواهد بود. حافظه هیپ (Heap) ناحیهٔ هیپ (Heap) به طور رایج در ابتدای بخشهای .bss و .data قرار گرفته است و به اندازههای آدرس بزرگتر قابل رشد است. ناحیهٔ هیپ توسط توابع malloc, calloc, realloc و free مدیریت میشود که ممکن است توسط سیستمهای brk و sbrk جهت تنظیم اندازه مورد استفاده قرار گیرد. ناحیه هیپ توسط تمامی نخها، کتابخانههای مشترک و ماژولهای بارگذاری شده در یک فرآیند به اشتراک گذاشته میشود. به طور کلی حافطه Heap بخشی از حافظه کامپیوتر شما است که به صورت خودکار برای شما مدیریت نمیشود، و به صورت محکم و مطمئن توسط پردازنده مرکزی مدیریت نمیشود. آن بیشتر به عنوان یک ناحیه شناور بسیار بزرگی از حافظه است. برای اختصاص دادن حافظه در ناحیه هیپ شما باید از توابع malloc(), calloc() که توابعی از C هستند استفاده کنید. یکبار که شما حافظه ای را در ناحیه هیپ اختصاص دهید، جهت آزاد سازی آن باید خود مسئول باشید و با استفاده از تابع free() این کار را به صورت دستی جهت آزاد سازی حافظه اختصاص یافته شده انجام دهید. اگر شما در این کار موفق نباشید، برنامه شما در وضعیت نَشت حافظه (Memory Leak) قرار خواهد گرفت. این بدین معنی است که حافظه اختصاص یافته شده در هیپ هنوز خارح از دسترس قرار گرفته و مورد استفاده قرار نخواهد گرفت. این وضعیت همانند گرفتگی رَگ در بدن انسان است و حافظه نشت شده جهت عملیات در دسترس نخواهد بود. خوشبختانه ابزارهایی برای کمک کردن به شما در این زمینه موجود هستند که یکی از آنها Valgrind نام دارد و شما میتوانید در زمان اشکال زدائی از آن جهت تشخیص نواحی نشت دهنده حافظه استفاده کنید. بر خلاف حافظه اِستک (Stack) حافظه هیپ محدودیتی در اندازه متغیرها ندارد (جدا از محدودیت آشکار فیزیکی در کامپیوتر شما). حافظه هیپ در خواندن کمی کُند تر از نوشتن نسبت به حافظه اِستک است، زیرا جهت دسترسی به آنها در حافظه هیپ باید از اشاره گر استفاده شود. بر خلاف حافظه اِستک، متغیرهایی که در حافظه هیپ ساخته میشوند توسط هر تابعی در هر بخشی از برنامه شما در دسترس بوده و اساسا متغیرهای تعریف شده در هیپ در دامنه سراسری قرار دارند. حافظه اِستک (Stack) ناحیهٔ اِستک (Stack) شامل برنامه اِستک، با ساختار LIFO کوتاه شده عبارت Last In First Out (آخرین ورودی از همه زودتر خارج میشود) به طور رایج در بالاترین بخش از حافظه قرار میگیرد. یک (اشاره گر پشته) در بالاترین قسمت اِستک قرار میگیرد. زمانی که تابعی فراخوانی میشود این تابع به همراه تمامی متغیرهای محلی خودش در داخل حافظه اِستک قرار میگیرد و با فراخوانی یک تابع جدید تابع جاری بر روی تابع قبلی قرار میگیرد و کار به همین صورت درباره دیگر توابع ادامه پیدا میکند. مزیت استفاده از حافظه اِستک در ذخیره متغیرها است، چرا که حافظه به صورت خودکار برای شما مدیریت میشود. شما نیازی برای اختصاص دادن حافظه به صورت دستی ندارید، یا نیازی به آزاد سازی حافظه ندارید. به طور کلی دلیل آن نیز این است که حافظه اِستک به اندازه کافی توسط پردازنده مرکزی بهینه و سازماندهی میشود. بنابراین خواندن و نوشتن در حافظه اِستک بسیار سریع است. کلید درک حافظه اِستک در این است که زمانی که تابع خارج میشود، تمامی متغیرهای موجود در آن همراه با آن خارج و به پایان زندگی خود میرسند. بنابراین متغیرهای موجود در حافظه اِستک به طور طبیعی به صورت محلی هستند. این مرتبط با مفهوم دامنه متغیرها است که قبلا از آن یاد شده است، یا همان متغیرهای محلی در مقابل متغیرهای سراسری. یک اشکال رایج در برنامه نویسی C تلاش برای دسترسی به یک متغیر که در حافظه اِستک برای یک تابع درونی ساخته شده است میباشد. یعنی از یک مکان در برنامه شما به خارج از تابع (یعنی زمانی که آن تابع خارج شده باشد) رجوع میکند. یکی دیگر از ویژگیهای حافظه اِستک که بهتر است به یاد داشته باشید این است که، محدودیت اندازه (نسبت به نوع سیستم عامل متفاوت) است. این مورد در حافظه هیپ صدق نمیکند. خلاصه ای از حافظه اِستک (Stack) حافظه اِستک متناسب با ورود و خروج توابع و متغیرهای درونی آنها افزایش و کاهش مییابد نیازی برای مدیریت دستی حافظه برای شما وجود ندارد، حافظه به طور خودکار برای متغیرها اختصاص و در زمان نیاز به صورت خودکر آزاد میشود در اِستک اندازه محدود است متغیرهای اِستک تنها در زمان اجرای تابع ساخته میشوند مزایا و معایب حافظه اِستک و هیپ حافظه اِستک (Stack) دسترسی بسیار سریع به متغیرها نیازی برای باز پس گیری حافظه اختصاص یافته شده ندارید فضا در زمان مورد نیاز به اندازه کافی توسط پردازنده مرکزی مدیریت میشود، حافظه ای نشت نخواهد کرد متغیرها فقط محلی هستند محدودیت در حافظه اِستک بسته به نوع سیستم عامل متفاوت است متغیرها نمیتوانند تغییر اندازه دهند حافظه هیپ (Heap) متغیرها به صورت سراسری قابل دسترس هستند محدودیتی در اندازه حافظه وجود ندارد تضمینی برای حافظه مصرفی وجود ندارد، ممکن است حافظه در زمانهای خاص از برنامه نشت کرده و حافظه اختصاص یافته شده برای استفاده در عملیات دیگر آزاد نخواهد شد شما باید حافظه را مدیریت کنید، شما باید مسئولیت آزاد سازی حافظه های اختصاص یافته شده به متغیرها را بر عهده بگیرید اندازه متغیرها میتواند توسط تابع realloc() تغییر یابد در اینجا یک برنامه کوتاه وجود دارد که در آن متغیرها در یک حافظه اِستک ایجاد شده اند. #include <stdio.h> double multiplyByTwo (double input) { double twice = input * 2.0; return twice; } int main (int argc, char *argv[]) { int age = 30; double salary = 12345.67; double myList[3] = {1.2, 2.3, 3.4}; printf("double your salary is %.3f\n", multiplyByTwo(salary)); return 0; } ما متغیرهایی را اعلان کردهایم که یک int، یک double و یک آرایه که سه نوع double دارد هستند. این متغیرها داخل اِستک وارد و به زودی توسط تابع main در زمان اجرا حافظه مورد نیاز خود را دریافت خواهند کرد. زمانی که تابع main خارج میشود (برنامه متوقف میشود) این متغیرها همگی از داخل حافظه اِستک خارج خواهند شد. به طور مشابه، در تابع multiplByTwo() متغیر twice که از نوع double است، داخل اِستک وارد شده و در زمان اجرای تابع multiplyByTwo() حافظه به آن اختصاص مییابد. زمانی که تابع فوق خارج شود یعنی به نقطه پایان اجرایی خود برسد، حافظه اختصاص یافته شده به متغیرهای داخلی آن نیز آزاد خواهند شد. به طور خلاصه توجه داشته باشید که تمامی متغیرهای محلی در این نوع تعریف تنها در طول زمان اجرایی زمانی تابع زنده هستند. به عنوان یک یادداشت جانبی، روشی برای نگه داری متغیرها در حافظه اِستک وجود دارد، حتی در زمانی که تابع خارج میشود. آن روش توسط کلمه کلیدی static ممکن خواهد شد که در زمان اعلان متغیر استفاده میشود. متغیری که توسط کلمه کلیدی static تعریف میشود، بنابراین چیزی مانند متغیر از نوع سراسری خواهد بود، اما تنها در داخل تابعی که داخل آن ایجاد شده است قابل مشاهده خواهد بود. این یک ساختار عجیب و غریب است، که احتمالا به جز شرایط بسیار خاص نیازی به آن نباشد. نسخهٔ دیگری از برنامه فوق در قالب حافظه هیپ به صورت زیر است: #include <stdio.h> #include <stdlib.h> double *multiplyByTwo (double *input) { double *twice = malloc(sizeof(double)); *twice = *input * 2.0; return twice; } int main (int argc, char *argv[]) { int *age = malloc(sizeof(int)); *age = 30; double *salary = malloc(sizeof(double)); *salary = 12345.67; double *myList = malloc(3 * sizeof(double)); myList[0] = 1.2; myList[1] = 2.3; myList[2] = 3.4; double *twiceSalary = multiplyByTwo(salary); printf("double your salary is %.3f\n", *twiceSalary); free(age); free(salary); free(myList); free(twiceSalary); return 0; } همانطور که میبینید، استفاده از malloc() برای تخصیص حافظه در حافظه Heap و استفاده از free() جهت آزاد سازی حافظه تخصیص یافته میباشد. این مواجه شدن چیز بسیار بزرگی محسوب نمیشود اما کمی مبهم است. چیز دیگری که باید به آن توجه داشته باشید علامت ستاره (*) است که در همه جای کدها دیده میشود. اینها چه چیزهایی هستند؟ پاسخ این سوال این است : اینها اشاره گر هستند! توابع malloc() و calloc() و free() با اشارهگرهایی مواجه میشوند که مقادیرشان واقعی نیست. اشاره گرها نوع داده ای خاصی در C هستند که آدرس حافظه مربوطه را بر میگردانند. در خط ۵ متغیر twice یک متغیر از نوع double نیست، اما اشاره به یک double دارد. آن آدرس حافظه ای است که نوع double در آن بلوک از حافظه ذخیره شده است. در ++C توسط کلمه کلیدی new که خود آن نیز یک اپراتور محسوب میشود میتوان حافظه ای را در Heap اختصاص داد. به عنوان مثال: int* myInt = new int(256); آدرسهای موجود در حافظه توسط اپراتور new به اشارهگر مربوطه پاس داده میشود. به مثال زیر توجه کنید، متغیر تعریف شده در حافظه اِستک قرار گرفته است: int variable = 256; سوالی که ممکن است افراد کنجکاو از خود بپرسند این است که چه زمانی از Stack و چه زمانی از Heap باید استفاده کنیم؟! خب پاسخ این سوال اینگونه خواهد بود، زمانی که شما نیاز به یک بلوک بسیار بزرگی از حافظه دارید، که در آن یک ساختار بزرگ یا یک ارایه بزرگی را ذخیره کنید و نیاز داشته باشید که متغیرهای شما به مدت طولانی در سرتاسر برنامه شما در دسترس باشند در این صورت از حافظه Heap استفاده کنید. در صورتی که شما نیاز به متغیرهای کوچکی دارید که تنها نیاز است در زمان اجرای تابع در دسترس باشند و قابلیت خواندن و نوشتن سریعتری داشته باشند از نوع حافظه Stack استفاده کنید. فقط فراموش نکنید که حافظه Heap تحت توابع molloc(), realloc(), calloc() و free() مدیریت میشوند. هرچند اشارهگر های هوشمند نیز در ++C وجود دارند اما در بسیاری از مواقع که نیاز است بسیار جزئی و حساس بر روی کدهای خود کار کنید از مدیریت حافظه به صورت دستی استفاده کنید.
-
2 امتیازآموزش زبان برنامهنویسی سوئیفت - جلسه اول مواردی که در این جلسه یاد خواهید گرفت: مقدمه زبان برنامهنویسی سوئیفت ، نوشتن اولین دستور و معرفی متغییرها با سلام و عرض ادب خدمت شما دوستان عزیز و همراهان خوب همیشگی وبسایت آیوٌ اِسترِیم. در خدمت شما هستیم با یک دورهٔ جذاب برنامهنویسی به زبان سوئیفت! علاقهمندان زیادی به توسعهٔ محصولات و نرمافزارهای شرکت اَپل وجود دارن و از این رو با مسائلی دست به گریبان هستند که یکی از آنها؛ نبود آموزش کامل و به بیانی ساده است! مورد دوم هم که خیلی واضح هست،تَحریمه! که به جز اینکه قِشر کمدرآمد جامعه از پس خرید آنها بر نمیآیند، شامل تحریمهای دیگر هم میشود. و خیلیها بخاطر علاقه به یادگیری نمیتوانند شروع کنند به توسعهٔ محصولات نرمافزاری شگفتاَنگیز! از این رو تنها یک راه وجود داره و آن هم استفاده از نسخهٔ هَکشدهٔ سیستم عامل مَک هستش که به شما امکان استفاده از امکانات یک سیستمعامل مَک واقعی را میدهد! البته هدف این نیست که بگوییم استفاده از این روش خوب هست! بلکه برای آن دسته از عزیزانی که توانایی خریدن محصولات اَپل رو ندارند گفتیم که در غیر اینصورت اگه توانایی خرید دارید که بهترین راهش همین است که بخرید و لذت یک سیستمعامل متفاوت و جدید را داشته باشید :). خُب، اصل مطلب! اینکه در این دورهٔ آموزشی چه چیزهایی را یاد خواهید گرفت، فقط و فقط سه چیز است؛ مقدمات یادگیری Syntax ( سِینتَکس) زبان و کدنویسی مقدماتی یادگیری رابطکاربری ( User Interface ) ایجاد یک پروژهٔ ساده ماشینحساب و بعد از این مباحث هم کُلیت کار دستتان میآید و به راحتی میتوانید از منابعی مُعتبر، دانش و مهارت خودتان را بالا ببرید. زبان برنامهنویسی سوئیفت ( Swift ) چیست ؟ سوئیفت یک زبان برنامهنویسی از نوع کامپایلری برای توسعه محصولات نرمافزاری macOS , iOS , watchOS و tvOS است که توسط شرکت اَپل ساخته شده. قبل از این از زبان برنامهنویسی Objective-C برای توسعه محصولات برای موارد ذِکر شده استفاده میشد که بعد از آن این زبان جایش را به سوئیفت داد اما همچنان از Objective-C هم استفاده میشود. هدف در اینجا آموزش زبان است و شما میتوانید برای توضیحات بیشتر به مرجع این زبان، اینجا مراجعه کنید. شروع کدنویسی برای شروع کدنویسی به زبانبرنامهنویسی سوئیفت میتونید از یک برنامه موبایل هم حتی استفاده کنید! البته تنها در بخش مقدماتی. نام این نرمافزار موبایلی Sedona Swift Compiler است که میتوانید از فروشگاه Play دانلود و نصب کنید. یا از نرمافزاری ساده بر روی ویندوز خود کُدنویسی را شروع کنید که این کار برای سیستمعام لینوکس هم صِدق میکند که با نصب یک بسته میتوانید در لینوکس هم کُدنویسی با این زبان شیرین و ساده را شروع کنید. یا در نهایت اگر سیستمعامل مک دارید که چه بهتر و اگر ندارید از نسخهٔ هکشدهٔ آن استفاده کنید که عرض کردیم در مواقعی که واقعا چارهای ندارید!( الخصوص برای بخش رابط کاربری ( User Interface ) ). اولین چیز در هر زبان برنامهنویسی که آموزش داده میشود؛ سلام جهان! ( !Hello World ) همیشگی است?!. پس این کُد ساده را ببینید که این پیغام را به راحتی در کنسول چاپ میکند: print("Hello World!") به همین سادگی که مشاهده کردید، با استفاده از متد print پیغام Hello World را چاپ کردیم. اگر این دستور رو اجرا کنید، با همین پیغام در کنسول ویرایشگر خود مواجه میشوید. پس در نتیجه، این تابع برای چاپ مقادیر در سوئیفت هست. شاید دقت کرده باشید که سِمیکالُن نذاشتیم! سوئیفت این اجازه رو میدهد که بدون گذاشتن سِمیکالُن برنامهی خودتان را اجرا کنید که البته بگذارید هم مسئلهای پیش نمیآید، مگر در موقعی که چندین دستور در یک خط داشته باشید که آن موقع واجب میشود و باید حتما بگذارید، وگرنه کامپایلر اخطار خواهد داد! تابع print یک تابع سراسری در سوئیفت است که چندین آرگومانت دریافت میکند و اساس کار آن، چاپ اطلاعاتی است که به آن میدهیم. و چندین آرگومانتهای پیشفرض هم دریافت میکند که میتوانیم بسته به نیاز از آنها استفاده کنیم. در اولین آرگومانت، ما میتوانیم تا هر چند مقدار یا همان آیتمها، به آن بدهیم و در خروجی نمایش دهیم. به این شکل که میبینید: print("www.iostream.ir", "www.fanoox.com", item3, item4, ...) در آرگومانت دوم، که separator است، میتوانیم مشخص کنیم که اگر اطلاعات زیادی میخواهیم به خروجی ارسال و یا همان نمایش دهیم، در بین هر کدام از این اطلاعات، چه نمادی/علامتی قرار گیرد؟. که ما میتونیم اون نماد/علامت رو در بین دو "" ( دابل کوتیشن ) مشخص کنیم. به عنوان مثال: print("www.iostream.ir", "www.fanoox.com", separator : " :)) ") // Output the ==> www.iostream.ir :)) www.fanoox.com همانطور که مشاهده کردید، میتوانیم از هر نماد/علامتی که نیاز داشتیم در بین انبوهی از دادهها استفاده کنیم. در آرگومانت سوم، میتوانیم مشخص کنیم که اطلاعات در خط بعدی ( New line ) چاپ شوند یا در همان خط فعلی نمایش داده شوند! که به صورت زیر است: print("www.iostream.ir", terminator : "") print("www.fanoox.com") /*Output the => www.iostream.ir www.fanoox.com that not of include is new line */ در حالت پیشفرض تابع به صورت "terminator : "\n است که به معنی " در در پایان چاپ اطلاعات، اطلاعات دیگر را که بعد از این مقادیر چاپشده میآیند را چاپ کن ". برای تعریف متغییر در سوئیفت به دو صورت میتوانید عمل کنید: تعریف بدون تعیین نوع تعریف با تعیین نوع همچنین ما دو نوع متغییر داریم: متغییری که مقدارش میتواند در ادامهٔ برنامه تغییر کند متغییری که مقدارش فقط در هنگام تعریف مشخص و قابل تغییر در سراسر برنامه نیست ( ثابتها ) برای تعریف متغییر بدون نوع به این صورت عمل میکنیم: var website_name = "www.iostream.ir" print(website_name) // or print("The website name is \(website_name)") همانطور که مشاهده میکنید تعریف یک متغییر که همواره مقدارش تغییر کنید با کلمهٔ کلید var تعریف میشود و بعد از آن نام و مقدار آن میآید. در این حالت کامپایلر به صورت ضمنی خودش از روی مقدار، نوع متغییر را متوجه میشود و اگر شما این دستور را بنویسید: var website_name = "www.iostream.ir" print(type(of : website_name )) // or print("Type is => \(type(of : website_name )") // Result => String به شما مقدار String یا همان رشتهای را نمایش میدهد. اما در حالت تعیین نوع برای متغییر به این صورت است: var website_name : String = "www.iostream.ir" print(webiste_name) // or print("The website_name is \(website_name)") که شما صراحتا ( دستی ) نوع را مشخص کردید و کامپایلر در اینجا و در ادامهٔ برنامهٔ مقدار غیری از String ( رشته ) را قبول نمیکند. همانطور که مشاهده میکنید، برای تعریف نوع برای متغییر باید از دو کالُن ( : ) استفاده کنید و سپس حرف اول نوع متغییر را بزرگ بنویسم ( البته در این زبان ) مانند؛ Int و سپس با گذاشتن علامت انتساب ( = ) مقدار مورد نظر خود را به آن اختصاص دهیم. نکتهای دیگری که وجود دارد در چاپ کردن مقادیر است که شما میتوانید با دو روش فوق که ذکر شده است، مقادیر را چاپ کنید که یکی بصورت آیتم به آیتم یعنی print( item1, item2, item3 , ...) و تا هر چند آیتم را که حاوی مقادیر هستند به خروجی بفرستید و نمایش دهید و اما در حالت دوم باید Syntax متفاوتی استفاده کنید و آن هم ادغام رشته با مقادیر متغییرهاست! که مثالش را بالا برای شما عزیزان زدهام و مقادیر متغییرها باید بین دو پرانتز و قبل پرانتز از یک بکاسلش رو به عقب استفاده کنید!. و اما برویم به سراغ ثابتها! از اسم این متغییرها واضح است که یک بار تعریف میشوند و مقدار ثابتی دریافت میکنند و در ادامهٔ برنامه و یا رَوند پروژه هیج تغییری نمیکنند و در طول برنامه یا پروژه مقادیرشان ثابت است! بیاید با یک مثال شروع کنیم؛ ثابتها در سوئیفت با کلمهٔ کلید let تعریف میشوند و همانند متغییرها شامل نام و نوع هم هستند: let _website_name = "www.iostream.ir" _webiste_name = "iostream.ir" // Error , beacuse it's a constant print(_website_name) // or print("The website name => \(_website_name)") همانطور که میبینید، تغییر دادن مقادیر ثابتها باعث بروز خطا میشود و اجازهٔ چنین کاری به شما داده نخواهد شد. برای تعریف با تعیین نوع هم به این شکل میتوایند عمل میکنید: let _number : Int = 20 _number = 40 // Error , beacuse it's a constant print(_number) // or print("The number => \(_number)") امیدواریم این جلسه مورد رضایت شما عزیزان قرار گرفته باشد.
-
2 امتیازدر این قسمت میخوایم تلاش کنیم کودا (cuda) رو بر روی اوبونتو (Ubuntu) نصب کنیم نسخه کودا که نصب کردم ۱۰.۰ هست و همچنین اوبونتو ۱۸.۰۴ ولی بعید میدونم فرق خاصی داشته باشه نصب بقیه ورژن های چه کودا چه اوبونتو. اول از همه به قسمت Software & Updates برید و پنجره Additional Drivers رو انتخاب کنید و کارت گرافیک خودتون رو نصب کنید بعد از اینکه نصب شد سیستم رو ریبوت کنید یا در ترمینال خط زیر و بزنید: sudo reboot در مرحله بعد باید ملزومات کودا رو نصب کنید و از اونجایی که وقتی فایل deb رو نصب کنید این وابستگی ها خودشون نصب میشن ماهم دستی خودمون نصب میکنیم چون از deb استفاده نمیکنیم! پس: sudo apt-get install freeglut3 freeglut3-dev libxi-dev libxmu-dev این خط پکیج های لازم رو برای کتابخانه های GL - GLU - Xi - Xmu و چندین تای دیگه رو میگیره که بعدا به عنوان وابستگی نصب میشن. حالا به سایت Cuda Zone و دانلود رو بزنید بعدش تو صفحه باز شده Architecture و Distribution و Version روخودتون بر اساس لینوکسی که دارید پیش ببرید و برای دریافت اطلاعات در اوبونتو میتونید از lsb_release -a استفاده کنید. در قسمت نوع نصاب (installer type) گزینه runfile (local) رو انتخاب کنید و دوتا فایل رو که یکی در حد چندین مگابایت و دیگری چیزی در حدود ۲ گیگابایت هست رو دانلود کنید. حالا نوبت نصب cuda-toolkit و نمونه ها (samples): sudo sh cuda_10.0.130_410.48_linux.run اینو که زدید بعدش سوالاتی مثل سوالات زیر پرسیده میشه ازتون و دقت کنید مثل نه دقیقا برای همین سوالات و بخونید و ببینید کدوم پرسیده میشه و کدوم پرسیده نمیشه البته اگر کودا ۱۰ نصب میکنید دقیقا همین سوالا پرسیده میشه یا اینکه خود شرکت عوض کرده خلاصه دقت کنید تا در زندگی پیشرفت کنید!! Install NVIDIA Accelerated Graphics Driver for Linux-x86_64 396.26? (y)es/(n)o/(q)uit: n Install the CUDA 10.0 Toolkit? (y)es/(n)o/(q)uit: y Enter Toolkit Location [ default is /usr/local/cuda-10.0 ]: Do you want to install a symbolic link at /usr/local/cuda? (y)es/(n)o/(q)uit: y Install the CUDA 10.0 Samples? (y)es/(n)o/(q)uit: y Enter CUDA Samples Location [ default is /home/kinghorn ]: /usr/local/cuda-10.0 برای بعضی ها شاید سوال: You are attempting to install on an unsupported configuration. Do you wish to continue? (y)es/(n)o [ default is no ]: y هم پرسیده بشه که جوابش و y بدید که بگذرید. سوال اول داره اجازه میگیره که درایور کارت گرافیک رو نصب کنه: از اونجایی که بالا ما نصبش کردیم حتما حتما حتما بزنید n و تقریبا مهمترین قسمت این نصب هم همینه که اینو بزنید n. سوال دوم داره اجازه نسخه کودا تولکیت (cuda toolkit) رو ازتون میگیره که این برمیگرده به نسخه ای که دانلود کردید و برای مثلا من نسخه ۱۰.۰ بود. سوال سوم مکان رو ازتون میخواد که شما همون پیش فرض رو بذارید یعنی دکمه Enter رو بزنید تا برسید به سوال چهارم. سوال چهارم هم اجازه برای نصب symbolic در مکانی که در سوال بالا بهش دادید و سوال پنجم هم نصب نمونه هاست و مکانش رو در سوال ششم بصورتی که نوشتم با این تفاوت که بجای فایل کودا فایل کودا نسخه خودتون و قرار بدید. Enter CUDA Samples Location [ default is /home/kinghorn ]: /usr/local/cuda-x.x بحای x.x نسخه خودتون رو بنویسید. بعضی اوقات خطاهایی بدلیل کارت گرافیک و اینا میاد که خودش چند خط بعد نوشته جلو کلمه try چه چیزی بزنید و اگر اون ارور هارو دریافت کردید اون خط رو بزنید و ان شالله نصب میشه بعد از این کارا اون فایل چند مگابایتی رو حالا اجرا کنید sudo sh cuda_10.0.130.1_linux.run اسمش هم دیگه به چیزی که دارید نصب میکنید بستگی داره و خلاصش اینه که فایلی که اسم کوتاه داره همون چند مگابایتیه هست و اون فایل که اسم بلندی داره ۲ گیگابایتیه هستش. حالا نوبت مقدار دهی Environment Variables: در اینجا مقدار Environment هارو با این فرض مقدار دهی میکنیم که چندین کاربر (user) داریم. البته سیستم خود من تک کاربره هست ولی همچنان با این متد رفتم شما هم میتونید برید و مشکلی نداره sudo nano /etc/profile.d/cuda.sh با این خط به فایل در مسیر داده شده به اسم cuda.sh میسازیم و بعد از اون با دستور nano باز میکنیم و متن رو داخلش قرار میدیم: export PATH=$PATH:/usr/local/cuda/bin export CUDADIR=/usr/local/cuda بعد از اون فایل رو ذخیره میکنیم یعنی کلید ها Ctrl + x سپس y و بعد از اون Enter رو میزنیم و ذخیره میشه فایل بعد از این خط زیر و اجرا میکنیم تا فایل مورد نظر باز بشه sudo nano /etc/ld.so.conf.d/cuda.conf حالا خط زیر و انتقال میدیم داخلش و بعد همون دکمه های قبلی رو میزنیم تا فایل ذخیره بشه /usr/local/cuda/lib64 بعد از این کار دستور زیر و اجرا میکنیم و بعد از دستور زیر یه بار log out میکنیم تا محتویات اجرا شن و بعدش دیگه دسترسی دارید از شل (shell) برای استفاده از دستور ها رو دارید sudo ldconfig حالا اگر این و انجام دادید که خوشا به سعادتتون و خسته نباشید اگرم منتظرید که تک کاربرشو بگم بفرما: یه فایل بنام cudax.x-env میسازید که اون x.x ورژن کودا شماست مثلا sudo nano cuda10.0-env بعدشم سه خط و زیر و بهش اضافه میکنیم و با همون دکمه های قبلی ذخیرش میکنیم export PATH=$PATH:/usr/local/cuda-10.0/bin export CUDADIR=/usr/local/cuda-10.0 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda-10.0/lib64 تو این سه خط میبینید نسخه کودا هم اضاف کردم در صورتی که میتونستم فقط کودا رو بنویسیم ولی اینطوری شما میتونید چندین ورژن کودا نصب کنید و هرکدوم Environment Variables خودشو داشته باشه و حالا هر وقت خواستید به سادگی با دستور source cuda-10.0-env حالا با دستور مقدار Environmentها رو قرار میدیم یا به قول معروف set میکنیم. البته همچنین فایل رو میتونید هرجایی که خواستید بذارید ولی یادتون باشه که مسیرش رو اگر تغییر دادید موقع زدن خط بالا ادرس رو به source بدید. تموم! به همین راحتی کودا رو نصب کردید ( البته امیدوارم! ) با دستور nvcc --version ورژن کودا نصب شده بهتون نمایش داده میشه و با دستور nvidia-smi هم اطلاعات کارت گرافیتون. حالا میخوام یه نمونه کد تست کنیم که جمع دو ماتریس هست: اول با ترمینال و بعدش با vscode انجام میدیم, در ترمینال یه فایل میسازیم با پسوند .cu یعنیsudo nano firstcuda.cu و بعدش وقتی باز شد خطوط پایین رو داخلش قرار میدیم #include "cuda_runtime.h" #include "device_launch_parameters.h" #include <stdio.h> __global__ void addKernel(int *c, const int *a, const int *b){ int i = threadIdx.x; c[i] = a[i] + b[i]; } int main(){ const int arraySize = 5; const int a[arraySize] = { 1, 2, 3, 4, 5 }; const int b[arraySize] = { 10, 20, 30, 40, 50 }; int c[arraySize] = { 0 }; cudaError_t cudaStatus; int *dev_a = 0, *dev_b = 0, *dev_c = 0; cudaMalloc((void**)&dev_c, arraySize * sizeof(int)); cudaMalloc((void**)&dev_a, arraySize * sizeof(int)); cudaMalloc((void**)&dev_b, arraySize * sizeof(int)); cudaMemcpy(dev_a, a, arraySize * sizeof(int), cudaMemcpyHostToDevice); cudaMemcpy(dev_b, b, arraySize * sizeof(int), cudaMemcpyHostToDevice); addKernel << <1, arraySize >> >(dev_c, dev_a, dev_b); cudaDeviceSynchronize(); cudaMemcpy(c, dev_c, arraySize * sizeof(int), cudaMemcpyDeviceToHost); printf("{1,2,3,4,5} + {10,20,30,40,50} = {%d,%d,%d,%d,%d}\n", c[0], c[1], c[2], c[3], c[4]); cudaStatus = cudaGetLastError();if (cudaStatus != cudaSuccess)printf("cudaDeviceReset failed!"); return 0; } بعد ذخیره کنید و دستور nvcc firstcuda.cu -o firstcuda رو بزنید. این دستور یعنی با کامپیالر nvcc برنامه firstcuda.cu رو کامپایل کن و خروجی -o بنام firstcuda بده. که خروجی در همون پوشه هست که هموطوری که میدونید بطور پیش فرض همه این ها در قسمت home هستند. حالا خروجی رو اجرا کنید یعنی ./firstcuda و این دستور خروجی رو اجرا میکنه و به شما نمایش میده. خروجی که باید نمایش داده بشه {1,2,3,4,5} + {10,20,30,40,50} = {11,22,33,44,55} حالا بریم سراغ vscode که یکم بیشتر ولی رنگی تره, بقول معروف هرچی رنگین تر باشی سخت تر بدست میای! از قسمت ترمینال (Terminal) گزینه New Terminal رو انتخاب کنید و بعد بنویسید touch test.cu که با این دستور شما فایل test.cu رو میسازید.حالا کد هارو داخلش قرار بدید بعدش میتونید از داخل ترمینال داخل vscode بقیه مراحل و مثل قبل برید و کامپیال کنید و بعدشم اجرا کنید فایل خروجی رو ولی راه قشنگ تر اینه که از قسمت ترمینال گزینه Configure Default Build Task رو انتخاب کنید بعد از اون یه پنجرکی (پنجره کوچک!) باز میشه که روی Create tasks.json file from template کلیک کنید و بعدشم گزینه Others. حالا در فایل جدیدی که ساخته شده با پسوند .json باید خط های زیر رو قرار بدید { "version": "2.0.0", "tasks": [ { "label": "build", "type": "shell", "command": "nvcc", "args": [ "test.cu", "-o", "${workspaceFolderBasename}" ] } ] } خب حالا باید درستش کنیم: اولین چیز لیبل (label) هست که نشون دهنده اسم task میشه و بعد از اون نوع که باید شل (shell) باشه و مهم تر از همه command که نشون دهنده کامپیالرمون هست باید nvcc باشه تا سیستم به طور خودکار کتابخانه هایی که استفاده شده در کد رو تشخیص بده. ارگومان ها اول اسم برنامه هست و بعدی به معنای خروجی هست و سومی نام فایل خروجی که اونی که نوشته شده یعنی هم اسم فایلی که داخلشیم. بعد از سیو کردن (Ctrl + s) وقتی از قسمت ترمینال گزینه Run Task رو میزنیم build نمایش داده میشه و وقتی میزنیمش این کد کامپیایل میشه و در همون فولدر خروجی رو بهمون میده و اگرم دقت کنید یک فایل a.out هم براتون نمایش داده میشه در vscode. حالا کاری میکنیم که وقتی ساخته شد اجرا هم بشه و در ترمینال vscode نمایش داده بشه. اگر دقت کرده باشید خطی جدید به صورت "problemMatcher": [] اضافه شده برای همین در پایین که کل کد هست این خط هارو وارد نکنید: { "version": "2.0.0", "tasks": [ { "label": "build", "type": "shell", "command": "nvcc", "args": [ "test.cu", "-o", "${workspaceFolderBasename}" ], "problemMatcher": [] }, { "label": "run", "type": "shell", "command": "./${workspaceFolderBasename}", "dependsOn": [ "build" ] } ] } این قسمت جدیدی که اضافه شده داره میگه task با نام run اجرا کنه فایل رو (که در قسمت command برابر قرار داده شده این عمل) و باید حتما build اجرا شده باشه و به نوعی مثل همون شرط کار میکنه. اگر بخوایم اسمی خاص و همچنین در فولدر بندی خاصی این عملیات انجام بشه باید آدرس هارو بهشون بدیم: یعنی اول باید به مقدار آرگومان ورودی سوم قسمت build باید آدرس رو کامل وارد کنیم و همچنین در قسمت command بخش run هم همچین کاری کنیم به زبان ساده بخوام بگم میشه: ما یه فولدر بنام Practice داریم که تو اون فولدر فایل های مختلفی داریم که یه فولدر ساختیم بنام Cuda برای پروژه های کودا و همچنین یه فولدر در Cuda ساختیم به نام اسم پروژه ( فرض کنیم test.cu) پس آدرس فایل test.cu میشه Practice/Cuda/Test/test.cu حالا اگر بخوایم اینو اجرا کنیم و خروجی رو ببینیم باید فایل .json رو اینطوری بنویسیم (دقت کنید به بزرگ و کوچیک بودن کلمات!): { "version": "2.0.0", "tasks": [ { "label": "build", "type": "shell", "command": "nvcc", "args": [ "Practice/Cuda/Test/test.cu", "-o", "Practice/Cuda/Test/test" ], "problemMatcher": [] }, { "label": "run", "type": "shell", "command": "./Practice/Cuda/Test/test", "dependsOn": [ "build" ], "problemMatcher": [] } ] } الان یه فایل ورودی با اون آدرس و با پسوند .cu به کامپایلر داده میشه و بعدش فایلی با نام test که نامی دلخواه هست و هرچی خواستید میتونید بذارید ساخته میشه به عنوان خروجی و در قسمت run میاد فایل رو با آدرس دقیقا در قسمت command میگیره و اجراش میکنه (دقیقا همون کاری که در ترمینال اوبونتو میکنید اینجا اومدید دکمه ایش کردید). حالا از قسمت Run Task روی run کلیک میکنیم تا کامپیال و هم چنین اجرا بشه. فایل نهایی شما (بعد از اجرا کردن) باید تقریبا به شکل زیر باشه (تقریبا برای این میگم شاید فردی بخواد وابستگی هارو بیشتر کنه و یا اسم برنامه چیز دیگه ای باشه و ...) { "version": "2.0.0", "tasks": [ { "label": "build", "type": "shell", "command": "nvcc", "args": [ "test.cu", "-o", "${workspaceFolderBasename}" ], "problemMatcher": [] }, { "label": "run", "type": "shell", "command": "./${workspaceFolderBasename}", "dependsOn": [ "build" ], "problemMatcher": [] } ] } خروجی زیبا رو در ترمینال میتونید تماشا کنید و لذت ببرید?خسته نباشید ان شالله همیشه پیروز و موفق باشید :] منبع اصلی هم مقاله Dr Donald Kinghorn و همچنین چندین (خیلی زیاد) ویدیو و مقاله و پاسخ جواب های دیگه تا تونستم بالاخره نصب کنم و بدون مشکل استفاده کنم.
-
2 امتیازآموزش زبان برنامهنویسی سوئیفت - جلسه هفتم مواردی که در این جلسه یاد خواهید گرفت: مجموعهها ( Collections ) مجموعهها در سوئیفت در واقع متغییرهایی هستند که بیشاز یک مقدار را نگهداری میکنند و هر کدام، هم طبق عملکردی که دارد، دادهها را ذخیره و در اختیار برنامهنویس میگذارد. منظور از هر کدام، ۴ نوع مجموعه است که در اینجا مشاهده خواهید کرد؛ آرایه ( Array ) سِت ( Set ) دیکشنری ( Dictionary ) تاپِل ( Tuple ) در جلسهی قبل، با اولین مجموعه؛ یعنی آرایهها به طور کامل آشنا شدید و در این جلسه با سِتها ( Sets ) کامل آشنا خواهید شد. به خاطر داشته باشید که هر کدام از این مجموعهها منحصر به فرد عمل کرده و هیچکدام شبیه هم نخواهند بود. سِتها ( Sets ) چیستند؟ سِتها کار شما را برای ذخیره کردن دادههای غیرتکراری راحت میکنند! یعنی اینکه شما به راحتی و بدون اینکه نگران باشید چه تعداد مقادیر تکراری دارید، میتوانید به روند توسعه پروژهی خودتان ادامه دهید و مابقی کار را به این یکی نوع از مجموعهها بسپارید. این در صورتی است که شما نمیخواهید دائما بررسی کنید که آیا دادههای تکراری دارید یا نه و با تعریف این نوع، خیالتان آسوده خواهد شد. همچنین دادههایی که در این نوع به نمایش درخواهند آمد، به صورت نامنظم هستند! یعنی اینکه اگر شما مقادیر خودتان را به صورت منظم اضافه کرده باشید، خروجی آن چیزی نیست که به صورت منظم خواسته باشید. در واقع میتوان گفت، Setها؛ دادههای غیرتکراری و نامنظم را در خود نگهداری میکنند. برای تعریف یک Set به این صورت عمل خواهیم کرد، میتوانیم به دو صورت عمل کنیم؛ استفاده از کلاس و تعیین نوع داده استفاده از کلاس بدون تعیین نوع داده به اولین مورد، یعنی استفاده از کلاس و تعیین نوع داده میپردازیم؛ پس به این صورت عمل خواهیم کرد؛ var setـvar = Set<String>() // Or any data type همانطور که مشاهده میکنید، ابتدا یک متغییر تعریف خواهید کرد و سپس نام کلاس Set را میآورید و در نهایت در بین <> نوع دادهی خود را مشخص میکنید و سپس پرانتز () را قرار میدهید. در حال حاضر، شما یک Set خالی خواهید داشت! چرا که هیچ دادهای برای آن در نظر نگرفتهاید. برای اینکار به شکل زیر عمل خواهیم کرد؛ var set_var = Set<String>() // Or any data type set_var.insert("www.iostream.ir") set_var.insert("www.fanoox.com") set_var.insert("Tegra CMS") set_var.insert("www.ModernCpp.ir") set_var.insert("Apple") set_var.insert("Google") set_var.insert("Apple") set_var.insert("Google") set_var.insert("Microsoft") // Iterator in the set_var for items in set_var { print("Items in the set_var collection : ", items) /* Items in the set_var collection : www.iostream.ir Items in the set_var collection : www.fanoox.com Items in the set_var collection : Tegra CMS Items in the set_var collection : www.ModernCpp.ir Items in the set_var collection : Apple Items in the set_var collection : Google Items in the set_var collection : Microsoft */ } برای اینکه بتوانیم دادهای یا مقداری را ذخیره کنیم، از متد insert استفاده میکنیم که در بالا هم مشاهده میکنید. اما نکتهای که به احتمال زیاد شما هم متوجه آن شدهاید، این است که ما دو بار مقدار Google و Apple را ذخیره کردهایم! اما همانطور که در تعریف Set گفتیم، در خروجی فقط یکبار این مقادیر نمایش داده میشوند، حتی اگر به تعداد زیاد بخواهید دادهی تکراری وارد کنید! چرا که این نوع ( Set ) فقط مقادیر غیرتکراری را ذخیره خواهد کرد. تعریف دیگر آن به این صورت است؛ var setـvar : Set = [1,2,3,4,5,6,7,8,9,10] print(set_var) // Output is [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] در این مورد، شما مانند تعیین نوع برای متغییر، نام کلاس Set را بعد از دو نقطه ( که به آن هم کالُن ( : ) گفته میشود ) آورده و سپس مانند یک آرایه، مقادیر و دادههای خودتان را در بین دو قُلاب [] مینویسید. برای نمایش دادن آن هم کافیست که نام آن را بیاورید، همانند تعریف بالا. این نکته را به یاد داشته باشید که کامپایلر، به صورت ضمنی ( Implicit ) نوع داده را تشخیص داده و نیازی به ذکر نوع داده نخواهید داشت. ویژگیها ( Properties ) و متدها به دست آوردن تعداد اعضا با استفاده از ویژگی count میتوانید به تعدا اعضای یک Set دسترسی داشته باشید؛ var set_var : Set = [1,2,3,4] print(set_var.count) // Output is 4 بررسی خالی بودن یا نبودن Set و همچنین اگر میخواهید خالی بودن یا نبودن را بررسی کنید، isEmpty این امکان را در اختیار شما قرار داده است؛ var set_var : Set = [1,2,3,4,5,6,7,8,9,10] if set_var.isEmpty { print("set_var is empty!") } else { print("set_var not empty") // This will run code } اضافه کردن عضو جدید در حالت عادی نمیتوانیم به Setهای خودمان عضوی یا دادهای اضافه کنیم! در تعریف دوم شما دیدید که ما به صورت مستقیم این کار را انجام دادیم، اما در ادامهی برنامه شاید نظرمان عضو شود و بخواهیم عضو را حذف و عضو دیگری را اضافه کنیم؛ برای این منظور از متد insert استفاده خواهیم کرد؛ var celebrities : Set = ["Steven Paul jobs", "William Henry Bill Gates lll", "Elon Reeve Musk"] celebrities.insert("Jeffrey Preston Bezos") celebrities.insert("Sergey Brin") celebrities.insert("Lawrence Lary Page") همانطور که مشاهده کردید، ما با استفاده از متد insert میتوانیم عضوهای جدیدی را اضافه کنیم. حذف یک عضو برای این کار ما از متد remove استفاده میکنیم؛ var celebrities : Set = ["Steven Paul jobs", "William Henry Bill Gates lll", "Elon Reeve Musk"] celebrities.remove("Steven Paul jobs") print(celebrities) // Output is ["William Henry Bill Gates lll", "Elon Reeve Musk"] این متد یک آرگومان دریافت خواهد کرد و همان عضوی است که میخواهید حذف شود. بررسی وجود داشتن یا نداشتن یک مقدار خاص از متد contains برای این منظور استفاده میکنیم؛ var celebrities : Set = ["Steven Paul jobs", "William Henry Bill Gates lll", "Elon Reeve Musk"] if celebrities.contains("Elon Reeve Musk") { print("Elon Reeve Musk is available in the celebrities") // This will run code } else { print("Elon Reeve Musk is'n available in the celebrities") } نکته متدهای کار با Set، با خود Set اصلی کاری نداشته و بسته به متد، یک Set جدید برگردانده میشود. گَردش در Set برای اینکه بتوانیم به تکتک اعضای یک Set دسترسی داشته باشیم، از حلقهی for استفاده میکنیم، به این کار گردش میگویند. در جلسهی قبل، توضیحی مختصر در این باره دادهایم که میتوانید مطالعه کنید. پس به گردش در Set به این صورت است؛ var celebrities : Set = ["Steven Paul jobs", "William Henry Bill Gates lll", "Elon Reeve Musk"] for items in celebrities { print("Celebrities : ", items) /* Celebrities : Steven Paul jobs Celebrities : William Henry Bill Gates lll Celebrities : Elon Reeve Musk */ } به همین سادگی، میتوانید بین عضوهای مختلف گردش کرده و پردازشهای لازم را بنابر نیاز انجام دهید. مرتبسازی در حالت پیشفرض، نوع Set هیچ مبنایی برای مرتبسازی ندارد و دادهها را به صورت تصادفی نمایش خواهد داد؛ در صورتی که بخواهید بر اساس ترتیب دادهها را نمایش دهید، میتوانید از متد sorted استفاده کنید؛ var celebrities : Set = ["Steven Paul jobs", "William Henry Bill Gates lll", "Elon Reeve Musk"] for items in celebrities.sorted { print("Sorted celebrities : ", items) /* Sorted celebrities : Elon Reeve Musk Sorted celebrities : Steven Paul jobs Sorted celebrities : William Henry Bill Gates lll */ } فقط توجه داشته باشید که این متد باید در حلقه مورد استفاده قرار گیرد. ایجاد یک Set جدید با ترکیب دو Set یا ( Union ) با استفده از متد union شما میتوانید یک Set کاملا جدید، ایجاد کنید؛ var celebrities_some_one : Set = ["Steven Paul jobs", "William Henry Bill Gates lll", "Elon Reeve Musk"] var celebrities_two_some : Set = ["Jeffrey Preston Bezos","Sergey Brin","Lawrence Lary Page"] var celebrities_final : Set = celebrities_some_one.union(celebrities_two_some) print(celebrities_final) ذخیره یک مقدار مشترک ( Intersection ) اگر دو Set داشته باشیم و یک مقدار در هر دو یکسان باشد، متد intersection میتواند همهی مقادیر دیگر را پاک کرده و فقط همان مقدار را در قالب یک Set جدیدی برگرداند؛ var numbers_one : Set = [1,6,3] var number_two : Set = [5,6,3] var number_final : Set = number_one.intersection(number_two) print(number_final) // Output is [6, 3] همانطور که مشاهده کردید، در خروجی مقدار 3 , 6 را خواهیم داشت، چرا که باقی مقدار تکراری نبوده و در نتیجه حذف خواهند شد. حذف مقادیر یک Set و مقادیر مشابه ( Subtracting ) اگر بخواهیم مقادیر یک Set را به طور کامل حذف کنیم و همچنین اگر مقداری تکراری وجود داشت، آن را هم حذف کرده و فقط Set اول را داشته باشیم، از متد subtracting استفاده خواهیم کرد؛ var numbers_one : Set = [1,6,3] var number_two : Set = [5,6,3] var number_final : Set = number_one.subtracting(number_two) print(number_final) // Output is [1] مشاهده میکنید که خروجی برابر ۱ است! چرا که Set اول فقط مقدار ۱ را دارد و مابقی مقادیر در Set اول و دوم تکرار هستن و در نهایت حذف خواهند شد. ایجاد یک Set جدید با مقادیر غیر تکراری ( SymmetricDiffernce ) در متد union شما مقادیر غیرتکراری را نخواهید داشت و در Set جدیدی که ساخته خواهد شد و یا به طور مستقیم در خروجی نمایش داده میشود، فقط یکبار مقادیر نمایش داده میشوند؛ اما با متد symmetricDifference شما مقادیر دو طرف Set را حذف خواهید کرد و فقط مقادیری که دیگر تکراری نیستند، نمایش داده میشود. اجازه بدهید با ذکر یک مثال، این موضوع را شفافتر کنیم؛ var numbers_one : Set = [1,6,3] var number_two : Set = [5,6,3] var number_final : Set = number_one.symmetricDiffernce(number_two) print(number_final) // Output is [1,5] همانطور که مشاهده میکنید، ما مقادیر ۳ و ۶ را نخواهیم داشت! چرا که در این متد، مقادیر تکراری هر دو Set حذف خواهند شد و دادههایی که تکراری نیستند، در یک Set جدید ایجاد میشوند. امیدواریم که این جلسه مورد رضایت شما عزیزان قرار گرفته باشد.
-
2 امتیازآموزش زبان برنامهنویسی سوئیفت - جلسه ششم مواردی که در این جلسه یاد خواهید گرفت: آرایهها ( Arrays ) آرایهها چیستند؟ اگر شما یک بسته کِبریت را تصور کنید، حداقل تا 50 تا دانه کبریت داخل آن است! همهی آنها هم همه کبریت هستند نه چیز دیگر. البته میشود چیز دیگری هم گذاشت داخل آن اما در برنامهنویسی نمیتوانید همچین کَلکی را سوار کنید! ( در بعضی از زبانهای برنامهنویسی ). آرایهها در سوئیفت مجموعهای از مقادیر را داخل خودشان نگهداری میکنند و مانند یک متغییر میمانند با این تفاوت که یک متغییر معمولی یک مقدار رو میتواند ذخیره کند ولی متغییر آرایهای اینگونه نیست. به این دنبالهی عددی دقت کنید؛ 1,2,3,4,5,6,7,8,9,10 بهنظر شما میشود اینها را در یک متغییر معمولی ذخیره کرد؟ به طوری که هر کدام از عددها را که بخواهیم سریع به ما بدهد؟ مسلما خیر. تازه اگر شما بخواهید برای هر کدوم از این اعداد، یه متغییر جداگانه تعریف کنید؛استاندارد پروژهتان به شدن پایین میآید و زبانی هم که با آن برنامهنویسی میکنید به همان مقدار به شما واکنش نشان خواهد داد ( هر کُنشی واکنشی دارد...!? ) کاهش سرعت اجرا، زیادنویسی، اگه برای سایر توسعهدهندههای دیگر باشد، به احتمال زیاد طرف پروژهی شما نمیآیند! به عنوان مثال، تعریف متغییر بدون آرایه؛ let number_one : Int8 = 1 let number_two : Int8 = 2 let number_three : Int8 = 3 let number_four : Int8 = 4 let number_five : Int8 = 5 let number_six : Int8 = 6 let number_seven : Int8 = 7 let number_eight : Int8 = 8 let number_nine : Int8 = 9 let number_ten : Int8 = 10 خودتان باشید، حاضرید به این شکل پروژهای را به این شکل پیش ببرید؟! حالا فکر کنید ۱۰۰۰ دادهی مختلف بخواهید تعریف کنید! تعجب میکنید، اینطور نیست؟! اما خوشبختانه همیشه راه نجات هست... آن هم استفاده از آرایهها است! آرایهها به شما کمک میکنند تا دادههای زیادی که مورد نیاز پروژهی شما باشد، تعریف و استفاده کنید. نحوهی تعریف به سه روش میتوانید آرایههای خودتان را تعریف کنید؛ استفاده از نوع و سازنده ( Construct ) استفاده از کلاس Array، نوع متغییر و سازنده تعریف آرایه بدون هیچ واسطهای! نکته آرایههای سوئیفت از موقعیت ( Index ) صفر ( ۰ ) شروع خواهند شد. در ادامه متوجه این موضوع خواهید شد، اما همیشه این را به خاطر داشته باشید که اولین عضو در یک آرایه در موقعیت صفرم آن آرایه قرار میگیرد و به همین ترتیب، موقعیت اول، حاکی از مقدار دوم، موقعیت دوم، مقدار سوم و الی آخر... پس این مورد را در پروژههایتان حواستان باشد! چرا که با یک اشتباه، ساعتها زمان و انرژی خود را تَلف میکنید تا یک اشتباه کوچک را پیدا و رفع کنید. اولین مورد که در لیست بالا گفته شده، به این صورت است که شما یک متغییر تعریف میکنید ( از کلمات کلیدی var و یا let میتوانید استفاده کنید) و بعد یک نام شفاف و دلخواه خواهید نوشت و در نهایت از نوع و سازنده به این شکل استفاده میکنید؛ var first_array = [Int]() print(first_array) // Output is empty or [] در روش دوم میتوانید از کلاس Array استفاده کنید! به این شکل که مشاهده میکنید؛ var first_array = Array<Int>() print(first_array) // Output is empty or [] و در نهایت میتوانیم بدون هیچ واسطهای ( بدون استفاده روش اول و دوم )، آرایهمان را تعریف کنیم؛ var first_array = [1,2,3,4,5,6,7,8,9,10] print(first_array) // Output is [1,2,3,4,5,6,7,8,9,10] به نظر میآید که این برای شما راحتتر و قابلدرکتر باشد تا موارد قبل، اینطور نیست؟ اما خُب، آنها را هم برای دوستانی که عاشق پیچدگی هستن نوشتیم! شما میتوانید از هر روشی که مدنظرتان بود استفاده کنید. نوع دادهای هم که مشخص میکنید، بستگی به پروژهی شما دارد؛ var first_array = ["www.iostream.ir","www.fanoox.ir","www.ModernCpp.ir"] print(first_array) // Output is empty or ["www.iostream.ir", "www.fanoox.ir", "www.ModernCpp.ir"] همینطور شما میتوانید از مقادیری پیشفرض برای آرایههایتان ستفاده کنید! به عنوان مثال شما در همان موقعی که تعریف آرایهی خودتان را انجام میدهید، میخواهید تا ۱۰ خانه از آرایهتان دادههای تکراری داشته باشد. اینکار را میتوانید با استفاده از سازنده ( Construct ) انجام بدهید؛ var first_array = [Int](repeating: 20, count: 10) print(first_array) // Output is [20,20,20,20,20,20,20,20,20,20] در کد بالا گفته شدهکه عدد ۲۰ را ( repeating: 20 ) به تعداد ۱۰ بار ( count: 10 ) در آرایهی first_array قرار گیرد. خروجی را همانطور که مشاهده میکنید، مقدار ۲۰ به تعداد ۱۰ بار در first_array تکرار شده. ترکیب دو آرایه با هم برای اینکار فقط کافی است با استفاده از آپِریتر +، یک آرایهی جدید بدست بیاوریم؛ var first_array = [1,2,3,4,5] var two_array = [6,7,8,9,10] var result_array = first_array + two_array print(first_array) // Output is [1,2,3,4,5,6,7,8,9,10] دسترسی به کُل یا یک از دادههای آرایه برای اینکه بتوانید به کل آرایه دسترسی داشته باشید و آن رو نمایش بدهید، میتوانید به این صورت عمل کنید؛ var first_array = [1,2,3,4,5] print(first_array) // Ouput is [1,2,3,4,5] البته میتوانید در مواقعی که نیاز به آرایه کامل دارید استفاده کنید! به عنوان مثال پارامتر توابع و ... برای اینکه بتوانید به یک دادهی خاص که موردنظر شما است، دسترسی داشته باشید؛ باید از موقعیت ( Index ) آرایه استفاده کنید؛ var website_name = ["www.iostream.ir","www.fanoox.com","www.ModernCpp"] var langauge_name = ["C++","C","Swift"] print(website_name[0]) // Output is www.iostream.ir print(langauge_name[2]) // Ouput is Swift در قطعه کد بالا، ابتدا باید نام آرایه بیاورید و بعد از آن با استفاده از دو براکت ( [] ) و قرار دادن شماره موقعیت، به مقدار آن دسترسی داشته باشید. همانطور هم که مشاهده میکنید، گفتیم که آرایهها از موقعیت صفرم شروع میشوند که در بالا با آوردن website_name و سپس شماره موقعیت ( Index Number ) به اولین عضو آن یعنی www.iostream.ir دسترسی پیدا کرده و آن را نمایش میدهیم. اگر از ۲ برای آرایه استفاده کنید، به شما خروجی Swift را خواهد داد! چرا که عضو دوم آرایهی langauge_name مقدار Swift است. اضافه کردن داده به آرایه اگه بخواهیم یک عضو ( مقدار جدید ) به آرایه اضافه کنیم، از متُد append که مربوط به کلاس آرایهها است، استفاده میکنیم. در جلسههای بعد با کلاسها، و متدها آشنا خواهید شد. به این مثال توجه کنید؛ var first_array = [1,2,3,4,5] // Before print("Before \(first_array)") // Ouput is [1,2,3,4,5] first_array.append(6) // After print("After \(first_array)") // Output is [1,2,3,4,5,6] با استفاده از موقعیت ( Index ) میتوانیم یک مقدار را به یک موقعیت یا همان خانهای از آرایه که مشخص کردیم، اضافه کنیم؛ var first_array = [1,2,3,4,5] first_array[0] = [10] print(first_array) // Output is [10,2,3,4,5] یا میتوانیم از آپِریتر ترکیبی =+ استفاده کنیم برای اضافه کردن گروهی از دادهها؛ var first_array = [1,2,3,4,5] // Before print(first_array) // Ouput is [1,2,3,4,5] first_array += [6,7,8,9,10] // After print(first_array) // Output is [1,2,3,4,5,6,7,8,9,10] با استفاده از متد insert میتوانید یک عضو جدید را به موقعیتی ( Index ) که مدنظرتان است، اضافه کنید! به عنوان مثال در آرایهی زیر، میخواهید که عدد ۳، در خانه یا موقعیت آخر قرار بگیرد؛ var first_array = [1,2,3,4,5] // Before print("Before \(first_array)") // Ouput is [1,2,3,4,5] first_array.insert(6, at: 4) // After print("After \(first_array)") // Output is [1,2,3,4,5,6] این متد دو پارامتر دریافت میکند؛ یکی برای عضو جدید و یکی دیگر برای موقعیتی که میخواهید عضو جدید قرار بگیرد که همانطور که مشاهده میکنید، مقدار ۶ در موقعیت آخر قرار گرفته است که مقدار ۵ را دارد. حذف یک عضو برای حذف یک مقدار از آرایه، از متدهای remove و removeLast استفاده میکنیم. اولین متد؛ یک موقعیت مشخص برای حذف عضو میخواهد، در حالی که متد دوم؛ آخرین عضو را حذف میکند؛ var first_array = [1,2,3,4,5] // Before remove print("Before \(first_array)") // Ouput is [1,2,3,4,5] first_array.remove(at: 0) // After remove print("After \(first_array)") // Output is [2,3,4,5] // Using removeLast first_array.removeLast() print(first_array) // Output is [2,3,4] با استفاده از at: 0 در متد remove مشخص کردیم که میخواهیم عضو اول را حذف کنیم که در خروجی هم میتوانید ببینید و در متد removeLast آخرین عضو آرایه ( در این مثال 5 ) رو حذف کردیم. و در نهایت شما میتوانید در یک رِنج ( بازه ) مشخص؛ که تعیین میکنید، عضو اضافه کنید! چیزی شبیه به حلقهی for! این مثال را ببینید؛ var first_array = [1,2,3,4,5] first_array[0...4] = [6,7,8,9,10] print("Before \(first_array)") // Ouput is [6,7,8,9,10] گردش در آرایه گردش یعنی اینکه بتوانیم بین اعضای یک آرایه که یکی یکی آنها را انتخاب میکنیم، کارهایی را که مدنظرمان است را انجام دهیم! که با استفاده از یک حلقهی for میتوانیم در عضوهای آن این کار را انجام دهیم. به این مثال توجه کنید؛ var first_array = [1,2,3,4,5] for item in first_array { print("Item : \(item)") } /* Item : 1 Item : 2 Item : 3 Item : 4 Item : 5 */ اگه بخواهیم که هم موقعیت ( Index ) و هم مقدار آرایه رو داشته باشیم؛ از متد enumerated استفاده میکنیم که به ما یک تاپِل ( Tuple ) خواهد داد ( در جلسات بعد بعدا مفصلا دربارهی تاپل صحبت خواهیم کرد) و در حلقه استفاده میکنیم؛ var first_array = [1,2,3,4,5] for (index,item) in first_array.enumerated() { print("Index of : \(index) and Item : \(item)") } /* Index of : 0 and Item : 1 Index of : 1 and Item : 2 Index of : 2 and Item : 3 Index of : 3 and Item : 4 Index of : 4 and Item : 5 */ Count و isEmpty ( دو ویژگی از کلاس آرایه ) شاید بخواهید بدانید تعداد عضوهای یک آرایه به چه تعدا هستند؟ این مورد به خصوص در حلقهها و یا موقعیتهای دیگر بسیار موثر خواهد بود! برای اینکار از ویژگی ( Property ) به نام count استفاده میکنیم که فقط خواندنی ( read-only ) است و هیچ مقداری رو نمیتوانید به آن ضافه کنید! ( درمورد ویژگیها مفصلا در جلسات بعد توضیح خواهیم داد ) و فقط میتوانید از مقدار آن که تعداد اعضای آرایه است، استفاده کنید؛ var first_array = [1,2,3,4,5] print(first_array.count) // Output is 5 اگه هم میخواهید خالی بودن یا نبودن یک آرایه را بررسی کنید؛ متد isEmpty این امکان را در اختیار شما قرار داده است؛ var first_array = [1,2,3,4,5] if first_array.isEmpty { print("Empty") } else { print("Not Empty") } // Not Empty امیدواریم که این جلسه مورد رضایت شما عزیزان باشد.
-
2 امتیازWindows Access Control List (ACL) قسمت دوم (مفاهیم) مباحث مورد بررسی در این مقاله: Access Rights for Access-Token Objects Security Descriptors Securable Objects Access Rights for Access-Token Objects: برنامه نمی تواند لیست کنترل دسترسی یک شئ را تغییر دهد مگر اینکه برنامه حق انجام آن کار را داشته باشد. این حقوق توسط یک security descriptor در access token شئ کنترل می شود. برای گرفتن یا تنظیم کردن security descriptor برای یک access token، می توانید تابع GetKernelObjectSecurity() و تابع SetKernelObjectSecurity() را فراخوانی کنید. زمانی که تابع OpenProcessToken() یا OpenThreadToken() را برای گرفتن یک هندل access token فراخوانی می کنید، سیستم دسترسی درخواستی را در برابر DACL در security descriptor توکن بررسی می کند. موارد زیر حقوق دسترسی معتبر برای اشیاء دارای access token می باشند: DELETE، RED_CONTROL، WRITE_DAC و WRITE_OWNER دسترسی استاندارد می باشند. Access token از SYNCHRONIZE به عنوان دسترسی استاندارد پشتیبانی نمی کنند. ACCESS_SYSTEM_SECURITY برای دریافت یا تنظیم SACL در security descriptor شئ. در قسمت زیر دسترسی خاص برای access token ها ذکر شده اند: TOKEN_ADJUST_DEFAULT: مورد نیاز برای تغییر owner، primary group یا DACL یک access token. TOKEN_ADJUST_GROUPS: مورد نیاز برای تنظیم ویژگی های (attributes) یک گروه در یک access token. TOKEN_ADJUST_PRIVILEGES: مورد نیاز برای فعال یا غیر فعال کردن یک privileges در یک access token. TOKEN_ADJUST_SESSIONID: مورد نیاز برای تنظیم session ID یک access token. امتیاز(privilege) SE_TCB_NAME مورد نیاز می باشد. TOKEN_ASSIGN_PRIMARY: مورد نیاز برای متصل شدن به یک primary token یک فرایند. برای انجام این کار امتیاز SE_ASSIGNPRIMARYTOKEN_NAME مورد نیاز است. TOKEN_DUPLICATE: مورد نیاز برای کپی کردن یک access token. TOKEN_EXECUTE: STANDARD_RIGHTS_EXECUTE و TOKEN_IMPERSONATE را ترکیب می کند. TOKEN_IMPERSONATE: مورد نیاز برای متصل شدن به یک impersonation access token یک فرایند. TOKEN_QUERY: مورد نیاز برای پرس و جو درباره یک access token. TOKEN_QUERY_SOURCE: مورد نیاز برای پرسو جو در باره منبع (source) یک access token. TOKEN_READ: ترکیبی از STANDARD_RIGHTS_READ و TOKEN_QUERY می باشد. TOKEN_WRITE: ترکیبی از STANDARD_RIGHTS_WRITE، TOKEN_ADJUST_PRIVILEGES، TOKEN_ADJUST_GROUPS و TOKEN_ADJUST_DEFAULT می باشد. TOKEN_ALL_ACCESS: ترکیبی از تمام دسترسی های ممکن مرتبط با token. Security Descriptors: یک security descriptor از اطلاعات امنیتی تشکیل شده است که با یک securable object مرتبط است. یک security descriptor از یک ساختار SECURITY_DESCRIPTOR که با security information مرتبط است تشکیل شده. یک security descriptor می تواند شامل security information زیر باشد: SID های owner و primary group یک شئ. یک DACL که حقوق دسترسی، که تعیین کننده مجاز بودن یا رد شدن دسترسی یک کاربر یا گروه خاصی را مشخص می کند. یک SACL که انواع تلاش های دسترسی که سوابق حسابرسی را برای شئ ایجاد شده مشخص می کند. مجموعه ای از بیت های کنترلی که به معنای یک security descriptor یا اعضای جداگانه آن است. ویندوز تابع هایی (API) را برای تنظیم یا بازیابی کردن security information موجود در security descriptor اشیاء ارائه کرده است. بعلاوه، تابع هایی نیز برای ساخت و مقدار دهی (اولیه) کردن یک security descriptor برای یک شئ وجود دارد. برنامه هایی که با security descriptor ها در اشیاء Active Directory کار می کنند می توانند از توابع امنیتی ویندوز یا رابط های امنیتی ارائه شده توسط Active Directory Service Interfaces (ADSI) استفاده کنند. Securable Objects: یک Securable Objects یک شئ است که می تواند یک security descriptor داشته باشد. هر نوع از Securable Object مجموعه ای از دسترسی های خاص و دسترسی های عمومی را تعریف می کند. در قسمت پایین می توانید تابع هایی را مشاهده کنید که برای دستکاری اطلاعات امنیتی برخی از Securable Objects مشترک نشان می دهد. Files or directories on an NTFS file system: GetNamedSecurityInfo()، SetNamedSecurityInfo()، GetSecurityInfo()، SetSecurityInfo() Named pipes, Anonymous pipes: GetSecurityInfo()، SetSecurityInfo() Processes, Threads: GetSecurityInfo()، SetSecurityInfo() File-mapping objects: GetNamedSecurityInfo()، SetNamedSecurityInfo()، GetSecurityInfo()، SetSecurityInfo() Access tokens: SetKernelObjectSecurity()، GetKernelObjectSecurity() Window-management objects (window stations and desktops): GetSecurityInfo()، SetSecurityInfo() Registry keys: GetNamedSecurityInfo()، SetNamedSecurityInfo()، GetSecurityInfo()، SetSecurityInfo() Windows services: GetNamedSecurityInfo()، SetNamedSecurityInfo()، GetSecurityInfo()، SetSecurityInfo() Local or remote printers: GetNamedSecurityInfo()، SetNamedSecurityInfo()، GetSecurityInfo()، SetSecurityInfo() Network shares: GetNamedSecurityInfo()، SetNamedSecurityInfo()، GetSecurityInfo()، SetSecurityInfo() Interprocess synchronization objects (events, mutexes, semaphores, and waitable timers): GetNamedSecurityInfo()، SetNamedSecurityInfo()، GetSecurityInfo()، SetSecurityInfo() Job objects: GetNamedSecurityInfo()، SetNamedSecurityInfo()، GetSecurityInfo()، SetSecurityInfo() Directory service objects: این اشیاء توسط Active Directory Objects اداره شده. تصویر زیر یک مثال از رابطه بین securable object (a folder) و security descriptor را نمایش می دهد. پایان قسمت دوم
-
2 امتیازبا سلام وقت بخیر, در این مطلب میخواهیم در مورد روش کارکرد پیام رسان ها بیشتر بدانیم و با یکدیگر کد یک پیام رسان ساده را پیاده و بررسی کنیم. طرز کار کرد پیام رسان در نظر داشته باشید که هر پیام رسانی که بر ساختار ها پیاده شده باشد از دو قسمت تشکیل شده است. نرم افزار اصلی برای مدیریت درخواست ها (سرور) نرم افزار برای کاربران (کاربر) به نرم افزار اولی سمت SERVER خواهیم گفت و به بعدی سمت CLIENT خواهیم گفت. روم یا تالار گفتگو ما تنها یک اتاق برای گفتگو در نظر میگیریم و هر کاربری که به سرور متصل شود را در همان تالار اضافه خواهیم کرد. تالار های گفتگو صرفا برای تقکیک سازی ارسال و دریافت ها و محدود کردن بازه ی کاربران مورد نظر... (ممکن است یک کاربر در چند اتاق بطور همزمان باشد.) سیستم های پیام رسان پیشرفته تر مانند تلگرام و ... تالار های زیادی را شامل می شوند. (هر کاربر خودش در کانال و گروه های مختلفی عضو است که هر کدام از آنها یک کانال متفاوت محسوب می شوند.) * دقت شود که منظور از کانال صرفا یک اتاق یا تالار گفتگو است و منظور کانال ارتباطی و پروتکل نیست. نرم افزار اصلی نرم افزار اصلی وظیفه دارد تا تمام کاربرانی که وارد تالار شده اند را به یاد داشته باشد و هر لحظه اماده دریافت درخواست هایی از طرف کاربرانش باشد. و پیام هایی را که از کاربران دریافت می کند برای تمامی کاربران دیگر هم ارسال کند که بسته به خلاقیت و نیاز می تواند هر یک از این بخش ها متفاوت طراحی شود. نرم افزار اصلی باید از قبل اجرا شده باشد. تا کاربران دیگر با استفاده از نرم افزار مخصوص به خودشان بتوانند به سرور متصل شوند و ارسال و دریافت داشته باشند. در نظر داشته باشید که اگر در نرم افزار اصلی اختلالی پیش بیایید و متوقف بشوند. قطا برای تمام کاربران مشکل پیش می آید. مگر اینکه از پایگاه های داده ی داخلی استفاده کرده باشند. (با خلاقیت می توان به گونه های متفاوتی چنین ساختاری را پیاده کرد) نرم افزار کاربران این نرم افزار جذاب ترین بخش است چرا تمام قابلیت هایی را که در اختیار کاربر قرار می دهیم را مستقیما طراحی می کنیم. در نظر داشته باشید که هر چیزی که در این نرم افزار طراحی می شود باید در نرم افزار اصلی پشتیبانی شوند... بنابراین اگر این دو بخش توسط دو فرد یا دو گروه مجزا طراحی می شوند آنها باید توسط داکیومنت ها و جلساتی به نظرات مشابه ای رسیده باشند. (اگرچه اینها تخصص و وظیفه ی تحلیلگر سیستم است! نه بطور همزمان وظیفه توسعه دهنده و برنامه نویس نرم افزار) پیاده سازی یک نمونه اکنون در نظر داریم تا با استفاده از ساختار کتابخانه BoostAsio پروژه ای را با نام BoostAsioChat ایجاد کنیم که در آن می خواهیم یک پیام رسان با حداقل ترین امکانات پایه طراحی کنیم که بیشتر جنبه شخصی و تفریحی دارد. زیرا از ساختار های استاندارد و ایمن و کاربری کاملا بدور است! (می توانید خودتان توسعه دهید و آنرا جالب تر بسازید) ساختار نرم افزار اصلی و سرور را به این صورت تعریف می کنیم : typedef deque<message> messageQueue; class participant { public: virtual ~participant() {} virtual void deliver(const message& messageItem) = 0; }; typedef shared_ptr<participant> participantPointer; class room { public: void join(participantPointer participant); void deliver(const message& messageItem); void leave(participantPointer participant); private: messageQueue messageRecents; enum { max = 200 }; set<participantPointer> participants; }; class session : public participant, public enable_shared_from_this<session> { public: session(tcp::socket socket, room& room) : socket(move(socket)), room_(room); void start(); void deliver(const message& messageItem); private: void readHeader(); void readBody(); void write(); tcp::socket socket; room& room_; message messageItem; messageQueue Messages; }; class server { public: server(boost::asio::io_context& io_context, const tcp::endpoint& endpoint) : acceptor(io_context, endpoint); private: void do_accept(); tcp::acceptor acceptor; room room_; }; int main(int argc, char* argv[]); ساختار نرم افزار کاربر را هم به این صورت تعریف می کنیم : typedef deque<message> messageQueue; class client { public: client(boost::asio::io_context& context, const tcp::resolver::results_type& endpoints) : context(context), socket(context); void write(const message& messageItem); void close(); private: void connect(const tcp::resolver::results_type& endpoints); void readHeader(); void readBody(); void write(); boost::asio::io_context& context; tcp::socket socket; message readMessage; messageQueue writeMessage; }; int main(int argc, char* argv[]); در نظر داریم تا در این پروژه از thread ها نیز استفاده کنیم... در مورد این مفهوم ها می توانید بصورت مجزا تحقیق کنید. بنابراین روش کامپایل این پروژه به این صورت خواهد بود : $ g++ client.cpp -lpthread -o client $ g++ Server.cpp -lpthread -o server آزمایش همانطور که گفته شد در ابتدا نرم افزار اصلی و سرور باید اجرا شود. در اینجا ما تمام ارتباطات شبکه را بر روی یک سیستم در شبکه داخلی برقرار خواهیم کرد... پس نگرانی در مورد ساختار های درونی شبکه و آی پی / دی ان اس / دامین نخواهیم داشت. بنابراین ای پی را می توانید ای پی داخلی یا localhost در نظر بگیرید. برای آزمایش پورت فرضی 4000 را در نظر میگیریم و نرم افزار اصلی را روی این پورت اجرا میکنیم : $ ./server 4000 در این مرحله متوجه می شوید که نرم افزار اصلی با موفقیت اجرا شده است و همچنان اجرا مانده است. بله درست است... نرم افزار اصلی هر لحظه باید منتظر دستور کاربران باشد. اگر لحظه ای برای نرم افزار اصلی اختلالی پیش آید نخواهد توانست دستورات کاربران را انجام یا پاسخ دهد. بنابراین این پردازش را قطع نکنید و اجازه دهید تا نرم افزار اصلی اجرا بماند. در محیط دیگری نرم افزار سمت کاربر را نیز اجرا کنید. این نرم افزار را می توانید به تعداد دلخواه وارد کنید. (همانطور که ممکن است 6 نفر همزمان به سرور متصل باشند / یا ممکن است هیچ فردی به سرور متصل نشوند) ابتدا یک کاربری را به سرور با پورت 4000 و شبکه داخلی وصل می کنیم : $ ./client localhost 4000 first user: you can type message here... حال در محیط دیگری با کاربر جدیدی نیز وارد می شویم : $ ./client localhost 4000 second user: you can type message here... در این پروژه نمونه از کاربران نام کاربری یا نام نمی پرسیم.. و صرفا وقتی وارد محیط گفتگو می شوند... یا زمانی که به سرور متصل می شوند منتظر هستیم تا انها پیامی را بنویسند... هر پیامی را که بنویسند به سرور ارسال می شود و سرور وظیفه دارد تا آنرا برای تمام کاربران بفرستد. و این روند درون یک حلقه بی نهایت تکرار می شوند. پس این ارتباط دو طرفه خواهد بود و هم کاربران برای سرور اطلاعات ارسال می کنند و هم سرور برای کاربران اطلاعات ارسال خواهد کرد. در نظر داشته باشید که کاربر اول می تواند پیامی را بنویسد و به کاربران دیگر ارسال شود. ممکن است کاربر سومی اصلا تصمیمی به نوشتن پیام نداشته باشد و صرفا تمایل به خواندن پیام دیگران داشته باشند. و این کاملا اختیاری است. و ما کاربران را اجباری نمیکنیم. اگرچه شما می توانید با خلاقیت خودتان اینها را با متغییر های کمکی و دستورات شرطی پیاده کنید. کد ها برای پیام ها یک ساختار در نظر میگیریم و بصورت مشترک در هر دو نرم افزار استفاده خواهیم کرد... بنابراین اینرا در هدر پیاده خواهیم کرد. هدر پیام : (message.hpp) #ifndef message_HPP #define message_HPP #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; class message { public: enum { headerLength = 4 }; enum { maxBodyLength = 512 }; message() : bodyLength_(0) { } const char* data() const { return data_; } char* data() { return data_; } size_t length() const { return headerLength + bodyLength_; } const char* body() const { return data_ + headerLength; } char* body() { return data_ + headerLength; } size_t bodyLength() const { return bodyLength_; } void bodyLength(size_t new_length) { bodyLength_ = new_length; if(bodyLength_ > maxBodyLength) bodyLength_ = maxBodyLength; } bool decodeHeader() { char header[headerLength + 1] = ""; strncat(header, data_, headerLength); bodyLength_ = atoi(header); if(bodyLength_ > maxBodyLength) { bodyLength_ = 0; return false; } return true; } void encodeHeader() { char header[headerLength + 1] = ""; sprintf(header, "%4d", static_cast<int>(bodyLength_)); memcpy(data_, header, headerLength); } private: char data_[headerLength + maxBodyLength]; size_t bodyLength_; }; #endif نرم افزار اصلی و سرور : (server.cpp) #include <iostream> #include <cstdlib> #include <deque> #include <memory> #include <list> #include <set> #include <utility> #include <boost/asio.hpp> #include "message.hpp" using boost::asio::ip::tcp; using namespace std; typedef deque<message> messageQueue; class participant { public: virtual ~participant() {} virtual void deliver(const message& messageItem) = 0; }; typedef shared_ptr<participant> participantPointer; class room { public: void join(participantPointer participant) { participants.insert(participant); for(auto messageItem: messageRecents) participant->deliver(messageItem); } void deliver(const message& messageItem) { messageRecents.push_back(messageItem); while(messageRecents.size() > max) messageRecents.pop_front(); for(auto participant: participants) participant->deliver(messageItem); } void leave(participantPointer participant) { participants.erase(participant); } private: messageQueue messageRecents; enum { max = 200 }; set<participantPointer> participants; }; class session : public participant, public enable_shared_from_this<session> { public: session(tcp::socket socket, room& room) : socket(move(socket)), room_(room) { } void start() { room_.join(shared_from_this()); readHeader(); } void deliver(const message& messageItem) { bool write_in_progress = !Messages.empty(); Messages.push_back(messageItem); if(!write_in_progress) { write(); } } private: void readHeader() { auto self(shared_from_this()); boost::asio::async_read(socket, boost::asio::buffer(messageItem.data(), message::headerLength), [this, self](boost::system::error_code ec, size_t) { if(!ec && messageItem.decodeHeader()) { readBody(); } else { room_.leave(shared_from_this()); } }); } void readBody() { auto self(shared_from_this()); boost::asio::async_read(socket, boost::asio::buffer(messageItem.body(), messageItem.bodyLength()), [this, self](boost::system::error_code ec, size_t) { if(!ec) { room_.deliver(messageItem); readHeader(); } else { room_.leave(shared_from_this()); } }); } void write() { auto self(shared_from_this()); boost::asio::async_write(socket, boost::asio::buffer(Messages.front().data(), Messages.front().length()), [this, self](boost::system::error_code ec, size_t) { if(!ec) { Messages.pop_front(); if(!Messages.empty()) { write(); } } else { room_.leave(shared_from_this()); } }); } tcp::socket socket; room& room_; message messageItem; messageQueue Messages; }; class server { public: server(boost::asio::io_context& io_context, const tcp::endpoint& endpoint) : acceptor(io_context, endpoint) { do_accept(); } private: void do_accept() { acceptor.async_accept([this](boost::system::error_code ec, tcp::socket socket) { if(!ec) { make_shared<session>(move(socket), room_)->start(); } do_accept(); }); } tcp::acceptor acceptor; room room_; }; int main(int argc, char* argv[]) { try { if(argc < 2) { cerr << "Usage: server <port> [<port> ...]\n"; return 1; } boost::asio::io_context io_context; list<server> servers; for(int i = 1; i < argc; ++i) { tcp::endpoint endpoint(tcp::v4(), atoi(argv[i])); servers.emplace_back(io_context, endpoint); } io_context.run(); } catch (exception& e) { cerr << "Exception: " << e.what() << "\n"; } return 0; } نرم افزار دوم و سمت کاربر : (client.cpp) #include <iostream> #include <thread> #include <cstdlib> #include <deque> #include <boost/asio.hpp> #include "message.hpp" using boost::asio::ip::tcp; using namespace std; typedef deque<message> messageQueue; class client { public: client(boost::asio::io_context& context, const tcp::resolver::results_type& endpoints) : context(context), socket(context) { connect(endpoints); } void write(const message& messageItem) { boost::asio::post(context, [this, messageItem]() { bool write_in_progress = !writeMessage.empty(); writeMessage.push_back(messageItem); if(!write_in_progress) { write(); } }); } void close() { boost::asio::post(context, [this]() { socket.close(); }); } private: void connect(const tcp::resolver::results_type& endpoints) { boost::asio::async_connect(socket, endpoints, [this](boost::system::error_code ec, tcp::endpoint) { if(!ec) { readHeader(); } }); } void readHeader() { boost::asio::async_read(socket, boost::asio::buffer(readMessage.data(), message::headerLength), [this](boost::system::error_code ec, size_t) { if(!ec && readMessage.decodeHeader()) { readBody(); } else { socket.close(); } }); } void readBody() { boost::asio::async_read(socket, boost::asio::buffer(readMessage.body(), readMessage.bodyLength()), [this](boost::system::error_code ec, size_t) { if(!ec) { cout.write(readMessage.body(), readMessage.bodyLength()); cout << "\n"; readHeader(); } else { socket.close(); } }); } void write() { boost::asio::async_write(socket, boost::asio::buffer(writeMessage.front().data(), writeMessage.front().length()), [this](boost::system::error_code ec, size_t) { if(!ec) { writeMessage.pop_front(); if(!writeMessage.empty()) { write(); } } else { socket.close(); } }); } boost::asio::io_context& context; tcp::socket socket; message readMessage; messageQueue writeMessage; }; int main(int argc, char* argv[]) { try { if(argc != 3) { cerr << "Usage: client <host> <port>\n"; return 1; } boost::asio::io_context context; tcp::resolver resolver(context); auto endpoints = resolver.resolve(argv[1], argv[2]); client c(context, endpoints); thread t([&context](){ context.run(); }); char line[message::maxBodyLength + 1]; while(cin.getline(line, message::maxBodyLength + 1)) { message messageItem; messageItem.bodyLength(strlen(line)); memcpy(messageItem.body(), line, messageItem.bodyLength()); messageItem.encodeHeader(); c.write(messageItem); } c.close(); t.join(); } catch (exception& e) { cerr << "Exception: " << e.what() << "\n"; } return 0; } این پروژه آزمایشی بصورت رایگان و اوپن سورس در اینترنت بخصوص اینجا وجود دارد و می توانید آنرا مستقیما بصورت کامل دانلود کنید. با تشکر, Max Base / مکس بیس
-
2 امتیازآموزش زبان برنامهنویسی سوئیفت - جلسه پنجم مواردی که در این جلسه یاد خواهید گرفت: متغییر آپشِنال (Optionals Variable ) ، رشتهها و کارکترها (String & Character ) متغییرهای آپشِنال ( Optionals Variable ) چیستند؟ این نوع متغییرها، برای مدیریت دادهی شما استفاده میشوند! همانطور که از نام آنها هم مشخص است، به معنی اختیاری! یعنی یا یک مقدار وجود دارد یا ندارد! در سوئیفت، شما باید بعد از تعریف یک متغییر مقدار آن را هم تعیین کنید و نمیتوانید آن را بدون مقدار به حال خود رها کنید! به عنوان مثال کُد زیر را ببینید: var website_name print(website_name) // Error compiler در صورتی که این کد را اجرا کنید، با خطای کامپایلر مواجه میشوید. دلیلش هم آن است که در این زبان، باید مقدار هر متغییر را باید بلافاصله بعد از تعریف آن بدهید و حالت پیشفرض نخواهیم داشت ( در برخی از زبانها حالت پیشفرضی برای متغییرها در نظر گرفته میشود مانند ++C ) این موضوع با نوع هم بخواهید تعریف کنید باز هم به خطای کامپایلر خواهید خورد: var website_name : String print(website_name) // Error compiler اما اگر به آن مقدار خالی ( "" => دابل کوتیشن ) بدهید، خروجی را برای شما نمایش خواهد داد، اما فقط خالی!: var website_name : String = "" print(website_name) // Print empty این برای همهی نوعهای دادهی دیگر هم صدق میکند. اما هر دفعه در کدهای خودتان برای بررسی کردن آنها باید شرط بگذارید ( if,else,ifelse و .. ) که ببینید کداممتغییر مقدار دارد یا ندارد. از این گذشته، با اینکار کدهای تمیزی هم نخواهید داشت. پس اینجا باید از آپشنالها استفاده کنیم. به این قطعه کد دقت کنید: var website_name : String? // website_name is automatically set to nil if name == nil{ print("website_name has nil value") } در مثال بالا، شما تعریف متغییر آپشنال ( Optional ) را میبینید که با علامت سوال ( ? ) همراه است. ابتدا شما باید، کلمهی کلیدی var را همراه با یک اسم، بیاورید و بعد با استفاده از دو نقطه ( : ) که کالُن در برنامهنویسی خوانده میشود استفاده کنید. و درنهایت به همراه نوع داده و علامت سوال را در جهت انگلیسی ( ? ) قرار میدهید. متغییر شما در حال حاضر مقدار nil را دارد که به صورت اُتوماتیک، به متغییر شما داده شده است که خود شما هم میتوانید این مقدار را برای تمای متغییرهای آپشنال خودتان قرار دهید. nil به معنای هیچ یا هیچچیز است. یعنی الان هیچ دادهای ندارید. حالا شما میتوانید هر زمانی که خواستید، به متغییر خود مقدار بدهید. نکته متغییر آپشنال شما به اصطلاح ( Wrapper ) به معنی بستهبندی، روپوش شده است! یعنی اینکه دادههای متغییر شما بستهبندی شده و در هنگامی که نیاز به اطلاعات آن داشتید باید با استفاده از علامت تعجب ( ! ) آن را ( Unwrapper ) کنید و یا از حالت بستهبندی شده خارج و اطلاعات خودتان را دریافت کنید! به عبارتی دیگر، اطلاعاتی که شما در متغییر خودتان ذخیره کردید در حالت آپشنال، بین دو پرانتز قرار گرفتند و به همین خاطر به آن میگویند Wrapper یا محافظت شده است!. به این مثال دقت کنید: var website_name : String? = "www.iostream.ir" if name == nil{ print("website_name has nil value") } else{ print(website_name!) // Print www.iostream.ir } همانطور که در مثال بالا مشاهده میکنید، اگه متغییر ما مقداری نداشت ( nil )، شرط اول اجرا خواهد شد و در غیر اینصورت، مقدار www.iostream.ir نمایش داده میشود. شما میتوانید در هر زمانی که نیاز داشتید، متغییر خودتان را برابر با nil کنید: var website_name : String? = "www.iostream.ir" website_name = nil if name == nil{ print("website_name has nil value") } else{ print(website_name!) // Print www.iostream.ir } خروجی برابر است با؛ website_name has nil value. به خاطر داشته باشید که به هیج وجه نمیتوانید به متغییرهای عادی کلمهی کلیدی nil رو بدهید! این فقط برای متغییرهای آپشنال است. رِشتهها و کارِکترِها (String & Character ) رشتهها مجموعهای از کارکترها هستند که یک حرف یا یک متن کامل را درون خودشان ذخیره میکنند ( همان متن یا نوشته ). مانند "www.iostream.ir" و یا "Apple". و کارکترهایی که در نهایت میتوانند تا دو حرف را در خودشان ذخیره کنند، مثل؛ "AP" و یا "IO". بگذارید چند نمونه بیاوریم تا بهتر و شفافتر متوجه بشوید: let website_name : String = "www.iostream.ir" print(website_name) و یا اینکه یک کارکتر داشته باشیم؛ let company_name : Character = "A" print(company_name) دقت داشته باشید که در حال حاضر که این زبان در این نسخهی یعنی ( 5.1 ) به سر میبرد، تنها از یک کارکتر پشتیبانی میکند اما در مورد کارکترهای یونیکُد ( Unicode ) اینگونه رفتار نمیکند و هیچ اخطاری از سمت کامپایلر، داده نمیشود. به این مثال دقت کنید؛ let unicode_character : Character = "\u{1F1EE}\u{1F1F7}" print(unicode_character) // Ouput iran flag در خروجی میتوانید مشاهده کنید که پرچم کشورمان نمایش داده میشود و آن هم به دلیل استفاده از کارکترهای یونیکد است. بنابراین، در این مورد بدون اینکه نوع دادهی کارکتر ( Character ) به کارکترهای یونیکد، ایرادی بگیرد، معادل آن را که حاوی یک کارکتر است ( در این مثال پرچم ایران که خود یک کارکتر است ) ذخیره میکند. اما درمواردی دیگر به علت اینکه که کارکتر یونیکدی نخواهیم داشت، بیشتر از یک کارکتر بخواهیم ذخیره کنیم باید از نوع دادهی رشته ( String ) استفاده کنیم نه Character. تعریف رشته شما با تعریف یک متغییر یا ثابت، نام آن و در نهایت نوع و مقدار آن، میتوانید یک رشته یا همان دنبالهای از کارکترها داشته باشید. و یا از سازنده (در محبث کلاسها کامل دربارهی آن توضیح خواهیم داد) خود نوع String استفاده کنید؛ let website_name : String = String("www.iostream.ir") print(website_name) یا اینکه به صورت کوتاه شده، بدون تعریف صَریح نوع، آن را به این شکل بنویسید: let website_name = "www.iostream.ir" let platform_name = String("www.fanoox.com") print("Website name : \(website_name) and Platfrom name : \(platform_name)") خالی قرار دادن رشته ما میتوانیم به دو صورت به متغییرها رشتهای خود مقدار خالی بدهیم! یا با استفاده از دو دابِل کُوتِیشِن ( "" ) یا با استفاده از یک نمونه از نوع رشته ( ()String ). به مثالهای زیر دقت کنید: let website_name = "" let platform_name = String() print(website_name,platform_name) // Empty بررسی خالی بودن یا نبون رشته شما میتوانید با استفاده از ویژگی isEmpty از کلاس String، بررسی کنید که آیا متغییر شما خالی است یا نه؟ به مثال زیر دقت کنید: let website_name = "" if website_name.isEmpty { // True print("website_name is empty!") } متصل کردن دو رشته با استفاده از آپِریِتر + شما میتوانید دو یا چند رشته را به هم متصل کنید؛ let website_name : String = "www.iostream.ir" let platform_name : String = "www.fanoox.com" let addition : String = website_name + " and " + platform_name print(addition) // www.iostream.ir and www.fanoox.com یا اینکه از حالت کوتاه شدهی آن استفاده کنید؛ let website_name : String = "www.iostream.ir" let platform_name : String = "www.fanoox.com" website_name += " and " + platform_name print(addition) // www.iostream.ir and www.fanoox.com ترکیب اطلاعات با یک رشته همچنین شما میتوانید یک رشتهی حاوی اطلاعات داشته باشید و در عین حال آنها در خروجی برای ذخیره در متغییرهای دیگر استفاده کنید! چگونه؟ به این صورت؛ let website_name : String = "www.iostream.ir" let platform_name : String = "www.fanoox.com" let addition = "Website name : \(website_name) and Platfrom name \(platform_name)" print(addition) // Website name www.iostream.ir and Platform name www.fanoox.com با استفاده از این الگو ()\ شما میتوانید تا بینهایت اطلاعات در داخل یک رشته قرار بدهید! فقط کافی است متغییرها، ویژگیهای یک کلاس، توابعی که مقدار برگشتی دارند ( درمورد توابع در جلسات بعد کاملا صحبت خواهیم کرد ) و هر چیزی که حاوی داده یا همان اطلاعات باشد قرار بدهید. اول یک اِسلش رو به عقب ( Backward Slash ) و بعد از آن هر اطلاعاتی که میخواهید داخل رشته باشند را داخل دو پرانتز () قرار میدهید. بدست آوردن طول یک رشته برای به دست آوردن طول یک رشته از ویژگی count از کلاس String استفاده میکنیم؛ let website_name : Stirng = "www.iostream.ir" print(website_naem.count) // website_name length is 15 اگر تکتک کارکترهای www.iostream.ir را بشمارید، میبینید که مقدار 15 به دست میآید. پس در خروجی هم عدد 15 را خواهیم داشت. مقایسه دو رشته اگه بخواهید یک رشته را با یک رشتهی دیگه مقایسه کنید، میتوانیم بطور مستقیم یا با استفاده از شرطها این کار را انجام دهیم؛ let website_name : String = "www.iostream.ir" let platform_name : String = "www.fanoox.com" print(website_name == platform_name) // False if website_name == platfrom_name { // False print("Equal") } else { print("Not Equal") // Not Equal } با آپِریِتر == در شرط if بررسی میکنیم که آیا website_name و platform_name با هم مساوی هستند یا نه، که Not Equal یعنی برابر نیستند را در خروجی خواهیم داشت. بررسی شروع یا پایان یک رشته با دو متد ( در جلسات آینده با متدها کاملا آشنا خواهید شد ) hasPrefix و hasSuffix میتوانیم بررسی کنیم که آیا رشتهی ما با ورودی که میدهیم، مطابقت دارد یا نه. به عنوان مثال رشتهی www.iostrea.ir رو میخواهیم بررسی کنیم که با www شروع میشود یا نه. برای این کار از متد hasSuffix استفاده میکنیم: let website_name : String = "www.iostream.ir" print(website_name.hasSuffix("wwww")) // False // Or if website_name.hasSuffix("www") { // True print(website_name) // www.iostream.ir } خروجی اول False است! چرا که ورودی ما ( wwww ) است و با اول رشتهی www.iostream.ir مطابقت ندارد ولی در دستور شرطی ( if ) که گذاشتیم، مقدار True است. چرا که ورودی ما ( www ) با اول www.iostream.ir مطابقت دارد. حالا اَگه بخواهیم که آخر رشتهی خود را بررسی کنیم که آیا آن چیزی که میخواهیم، با آخر رشته تمام میشود یا نه، از متد hasPrefix استفاده میکنیم: let website_name : String = "www.iostream.ir" print(website_name.hasPrefix(".com")) // False // Or if website_name.hasPrefix(".ir") { // True print(website_name) // www.iostream.ir } خروجی False و www.iostream.ir است. آخر دامنه وبسایت www.iostream.ir با ( ir. ) تمام میشود اما ما دامنهی com. را قرار دادیم که در نتیجه False خواهد شد. ولی در دستور شرطی یعنی if این موضوع درست است! چرا که دامنهی وبسایت با ir. تمام خواهد شد و این متد هم همین را میخواهد! پس در نتیجه True و مقدار متغییر website_name نمایش داده میشود. امیدواریم که این جلسه مورد رضایت شما عزیزان قرار گرفته باشد.
-
2 امتیازآموزش زبان برنامهنویسی سوئیفت - جلسه سوم مواردی که در این جلسه یاد خواهید گرفت: انواع داده و حلقهها در زبان برنامهنویسی سوئیفت ما با انواعی از دادهها روبرو هستیم! طبق دیگر زبانهای برنامهنویسی نوع دادههای پرکاربرد را معرفی خواهیم کرد و همچنین دیگر نوعهای داده را در ادامه بازگو میکنیم که شما با دقت بتوانید در پروژههای خودتان نوعهای دادهی مناسب پروژهی خودتان را انتخاب کنید. همچنین باید در نظر داشته باشید که در هر پروژهی نرمافزاری به کار بردن نوعهای دادهای که اصلا شاید مناسب قسمتی از پروژه یا نیازی به آن نباشد و با نوع دادهای دیگر مسئله بهتر و بهینهتر حل شود و استفاده کنید، استاندارد پروژهی شما کاهش پیدا خواهد کرد و مطمعن هستم که شما دوست ندارید نرمافزاری غیراستاندارد و بهینه داشته باشید! بنابراین در انتخاب نوعهای داده در پروژههای خودتان نهایت دقت را به خرج دهید! چه کسی دوست ندارد که پروژهای کارآمد و بهینه داشته باشد که هر توسعه دهندهای با دیدن نظم و بهینه بودن پروژهاش، آن را تحَسین کند؟!. درمورد حلقهها هم یک توضیح مختصر خواهیم داد و بعد به سراغ کُدنویسی خواهیم رفت که مطمئنن قسمت هیجانی برای هر برنامهنویسی است?. همهی ما در برنامهنویسی نیاز داریم که چندین خط کد رو بنویسم تا در نهایت برنامهی ما به خوبی اجرا شود، البته اگه بقیهی قسمتهای کدهایتان به درستی کار کند! اما همین چند خط کد رو مثلا چاپ اعداد ۰ تا ۱۰ در نظر بگیرید؛ print(0) print(1) print(2) print(3) print(4) print(5) print(6) print(7) print(8) print(9) print(10) احتمالا با خودتان میگوید چه برنامهنویسی داریم که چنینکاری میکند؟! این همه کد! حالا فکر کنید از ۰ تا ۱۰۰۰ باید به همین شکل بنویسید! کاری با خطوط کدها و حتی منطقی بودن آن هم نداریم! اما واقعا حوصله، زمان و انرژی باارزشتان چه میشود؟ پس راهحل چیست؟ درست حدس زدید! حلقهها! این مسئله را به سادگی و زیبایی هر چه تمامترحل کردند. پس مثال بالا را با یک حلقه مینویسیم؛ for index in 0...5 { print(index) // Output => 0,1,2,3,4,5 } فقط با چندین خط کد این مسئله برطرف شد! حال شما میتوانید به جای عدد ۵، عدد ۱۰۰۰ یا بیشتر را قرار بدهید. پس متوجه شدید که کاربرد حلقهها در برنامهنویسی چقدر مهم و حیاتی هستند! که برای تکرار دستوراتی هستند که دادههای زیادی به صورت مستقیم یا غیر مستقیم در برنامه مورد استفاده قرار میگیرد و عملا بدون حلقهها باید کدهای زیادی بنویسید تا این دادهها نمایش داده شوند!. انواع داده در سوئیفت، ما با انواعی از داده سر و کار داریم که عبارتاند از: انواع دادهی صحیح و اعشاری Int۸؛ نوع دادهی عددی ۸بیت است، به این صورت که فقط توانایی ذخیره ۱بایت را دارد. و مقادیر ۱۲۷ تا ۱۲۷- را پوشش میدهد. UInt8؛ این نوع داده عددی فقط و فقط یک مقدار از ۰ تا ۲۵۵ را پوشش خواهد داد و ۱بایت است. که در واقع کوتاه شدهی نام Unsigned Integer، است که به معنای نوع بدون علامت ( - ) است. Int۳۲؛ این نوع داده ۴بایتی ( ۴ * ۸ ) است، و مقداری از ۲۱۴۷۴۸۳۶۴۷ تا ۲۱۴۷۴۸۳۶۴۷- را پوشش میدهد. UInt32؛ مانند UInt8، است، با این تفاوت که فقط مقادیر صحیح بدون علامت ( - ) را قبول میکند و ۴بایت است. از مقدار ۰ تا ۴۲۹۴۹۶۷۲۹۵ را پوشش میدهد. Int۶۴؛ مقداری بیشتری در خود ذخیره میکند و در نتیجه تعداد بایتهای بیشتری را هم از حافظه اشغال میکند! که ۸بایت است. یعنی اینکه مقدار عددی تا ۲۰ رقم عدد صحیح با علامت ( + ) و بدون علامت ( - ) را ذخیره میکند. از مقدار ۹۲۲۳۳۷۲۰۳۳۶۸۵۴۷۷۵۸۰۸ تا ۹۲۲۳۳۷۲۰۳۳۶۸۵۴۷۷۵۸۰۸- را پوشش میدهد. UInt۶۴؛ مانند Int64 است که مقدار بیشتری ذخیره میکند که فقط شامل اعداد صحیح بدون علامت ( - ) است و ۸بایتی. از مقدار ۰ تا ۱۸۴۴۶۷۴۴۰۷۳۷۰۹۵۵۱۶۱۵ را پوشش میدهد ( دو برابر Int64 ). Float: این نوع دادهی اعشاری است و ۴بایتی. مقادیر اعشاری از ۱.۲E-38 تا ۳.۴E-38 را پوشش میدهد ( تا ۶ رقم اعشار ). البته این اعدا و این نوع نوشتاری، نمادهای علمی هستند!. Double: در این نوع اعشاری یک تفاوت وجود دارد و آن اینکه فضای بیشتری را در اختیارمان میگذارد و همینطور دقت بالایی را هم در محاسبات به همراه دارد. ۸بایتی است و از مقدار ۲.۳E-308 تا ۱.۷E+308 را پوشش میدهد ( تا ۱۵ رقم اعشار ). برای هر کدام یک مثال خواهیم زد؛ var int_8_byte : Int8 = -50 print(int_8_byte) var uint_8_byte : UInt8 = 50 print(uint_8_byte) var int_32_byte : Int32 = -560 print(int_32_byte) var uint_32_byte : UInt32 = 560 print(uint_32_byte) var int_64_byte : Int64 = -1567 print(int_64_byte) var uint_64_byte : UInt64 = 1567 var float : Float = 18.5 print(float) var double : Double = 19.75 print(double) این قطعه کدها را در اِدیتور ( Editor ) یا IDE خودتان وارد و اجرا کنید تا نتیجه را بصورت زنده مشاهد کنید ( لطفا کُپی و پیست نکنید! ) خودتان بنویسید تا هم لذت کدنویسی را بچشید و هم اینکه بهتر یاد بگیرید. در این میان، دقت کنید که نوع دادهی خودتان را به درستی در پروژههای نرمافزاری استفاده کنید و طبق نیاز نرمافزار خود از دادهی مورد نیاز استفاده کنید. به عنوان مثال، یک بخشی از برنامهی شما نیاز به دادهای به اندازهی ۸بایت دارد، ولی شما میآید و یک دادهی ۶۴بایتی تعریف میکنید برای آن! با اینکار حافظهی سیستم شما و آن کسی که نرمافزار شما را اجرا خواهد کرد، احتمالا صدای فَن آن در خواهد آمد! پس دقت کنید. نوع دادهی بُولیَن ( Boolean ) دو مقدار True یا False دریافت میکند. از این نوع داده بیشتر در دستورات شرطی استفاده میشود و بخشهایی از برنامه که نیاز به بررسی و درستی یا نادرستی یک عبارت دارد. نحوهی تعریف و استفاده از آن هم به این شکل است؛ let _boolean : Bool = true // Or false print(_boolean) در این تعریف شما میتوانید با تعریف نوع دادهی Bool و سپس مقدار به آن، از آن در قسمتهای مختلف برنامه استفاده کنید. نوع دادههای رشتهای و کارکتری String؛ یک دنبالهای از رشته ( همان متن ) را در خود ذخیره میکند؛ let _web_site_iostream : String = "www.iostream.ir" print(_web_site_iostream) Character؛ فقط و فقط یک کارکتر را قبول میکند( به جز کارکترهای کنترلی )؛ let _character : Character = "i" let _character_control : Character = "\n" print(_character) // Output => i print(_character_control) // Output => new line همانطور که مشاهده کردید، چندین نوع داده در زبان برنامهنویسی سوئیفت وجود دارد که شما باید با توجه به پروژهی خودتان از آنها در جای مناسب استفاده کنید. حلقهها و انواع آن حلقهها در سوئیفت به طور متفاوتی تعریف میشوند، اما همهی آنها کار یکسانی انجام میدهند! یعنی تکرار دستورات! حلقهی اول که قصد معرفی آن را داریم، for است؛ for index in 0...5 { print(index) } در این تعریف همانطور که مشاهده میکنید، با تعریف کلمهی کلید for و بعد از آن یک نام دلخواه و معنیدار، برای اینکه مقادیر هر بار در آن ذخیره شوند ( در واقع نقش یک متغییر را بازی میکند ) و بعد کلمهی کلید in قرار میگیرد و در نهایت باید یک رِنج ( بازه ) مشخص از یک عدد تا یک عدد دیگر انتخاب کنیم که بین اینها با سه نقط ( ... ) از هم جدا میشوند! این به این معنی است که در این تعریف عدد اولی که تعیین میشود، تا عدد دوم به صورت کامل در index ذخیره خواهند شد و هیچ گونه کم و زیادی صورت نمیگیرد!. اما اگر بخواهیم یک عدد کمتر و یا در واقع یک تکرار کمتر داشته باشیم از این تعریف استفاده میکنیم؛ for index in 0..<5 { print(index) } در این صورت با آپریتر > ( کوچکتر ) میتوانیم یک عدد و در واقع یک تکرار کمتر داشته باشیم. اگر بخواهیم درمورد آرایه که در جلسات بعد دربارهی آنها صحبت خواهیم کرد، یک مثال بزنیم، به این صورت است؛ let _array_number = [10,20,30,40] for index in _array_number { print(index) } همانطور که میبینید، تعریف و استفاده از حلقهی for ساده و آسان است. حلقهی while، حلقهی دومی است که به معرفی آن خواهیم پراخت. این حلقه به این صورت تعریف خواهد شد؛ var number : Int8 = 0 while (number < 10) { print(number) number += 1 } در حلقه و در قسمت شرط آن شما میتوانید هر شرطی را که باعث ورود به بدنهی حلقه ( {} ) شود، تعریف کنید. کلمهی کلید while در ابتدا تعریف میشود و سپس شرطی را که مدنظرتان است، تعریف میکنید ( در بین دو پرانتز ) و سپس در بدنه شرط، دستورات خود را مینویسید. در نهایت، حلقهی آخر، حلقهی repeat استکه کارکردآن دقیقا همانند حلقهی do, while در سایر زبانهای برنامهنویسی است! نحوهی تعریف و استفاده از آن هم به این شکل است؛ var repeat : Int8 = 0 repeat { print(repeat) repeat += 1 } while repeat < 1 در این حلقه، بدنهی حلقه که شامل دستورات هستند ابتدا اجرا میشود و سپس شرط بررسی میشود! درست همانند do, while. این حلقه با کلمهی کلید repeat تعریف شده و سپس در بین آکولادها ( {} ) دستورات نوشته خواهند شد و بعد از آخرین آکولاد ( { ) جلوی آن و یا بعد آن کلمهی کلید while و سپس شرط را مینویسم. فقط توجه داشته باشید که while در اینجا نیازی به پرانتز ندارد!. البته این دستور فقط یک بار اجرا خواهد شد! چرا که متغییر repeat کوچکتر از ۱ نیست، بزرگتر از آن هم نیست و در واقع مساوی است ( مقدار repeat در همان ابتدا اول یک بار افزایش ( repeat =+ 1 ) داده میشود و مقدار ۱ را درون خود ذخیره میکند ). پس شرط نادرست ااست و حلقه دیگر اجرا نخواهد شد. نکته؛ دقت کنید که در تمامی حلقهها نیاز به آکولاد باز و بسته برای تعریف دستورات است و شما نمیتوانید بدون تعریف این آکولادها کدهای خودتان را بنویسید! پس این مورد را دقت کنید. به جزء حلقهی while دیگر حلقهها نیازی به پرانتز () برای تعریف شروط ندارند. امیدواریم که این جلسه هم مورد رضایت شما عزیزان قرار گرفته باشد.
-
2 امتیازمعرفی نسخهبندی معنایی ویرایش ۲.۰ در دنیای مدیریت نرمافزار مکان مخوفی به نام «جهنم وابستگی» (dependency hell) وجود دارد. هر چه سیستم شما بزرگتر باشد و بستههای (package) بیشتری با نرمافزار شما یکپارچه شده باشند، احتمال بیشتری وجود دارد که روزی خود را دراین گودال ناامیدی بیابید. در سیستمهایی با وابستگیهای زیاد، انتشار بستهی جدید به زودی میتواند تبدیل به یک کابوس شود. اگر ویژگیهای وابستگیها بسیار جزئینگرانه باشد، در خطر قفل نسخه (version lock) خواهید بود (ناتوانی برای بروزرسانی یک بسته، بدون اجبار جهت انتشار نسخههای جدید همهی بستههای وابسته). اگر وابستگیها بسیار ضعیف مشخص شده باشند، به ناچار زخم بیقاعدگی نسخه را خواهید خورد (به فرض سازگاری بیش از حد معقول با نسخههای آتیتر). جهنم وابستگی آنجایی است که قفل نسخه و یا بیقاعدگی نسخه از پیشرفت رو به جلوی آسان و امن پروژهی شما جلوگیری میکند. برای پاسخگویی به این مشکل، من یکسری قوانین و پیشنیازهای ساده را پیشنهاد میدهم که نحوهٔ تخصیص و افزایش شمارههای نسخه را دیکته میکند. این قوانین برپایهی شیوههای موجود رایج و گستردهی در حال استفاده، هم در نرمافزارهای متنباز و غیر متنباز است، اگرچه لزوماً محدود به آن نیست. برای آنکه این سیستم کار کند نخست لازم است یک API عمومی (public) تعریف کنید. این امر ممکن است شامل مستندسازی، یا بوسیلهی خود کد مقید شده باشد. صرف نظر از این موضوع، مهم است که این API دقیق و واضح باشد. زمانیکه API عمومی خود را مشخص کردید، تغییرات آن را با افزایش معین شمارهی نسخهی خود مرتبط میسازید. قالب نسخهای به صورت X.Y.Z را در نظر بگیرید. خطاهایی که تاثیری بر API ندارند، نسخهی وصله (Patch) را افزایش میدهند، افزایش یا تغییر API که با نسخههای قبلی سازگار است، نسخهی جزئی (Minor) را افزایش میدهند، و تغییرات API که با نسخههای قبل ناسازگار هستند، نسخهی اصلی (Major) را افزایش میدهند. این سیستم را «نسخهبندی معنایی» مینامیم. بر اساس این طرح، شمارههای نسخه و روشی که تغییر میکنند، معنی و مفهومی را دربارهی کد تحت آن نسخه، و آنچه که از یک نسخه تا نسخهای دیگر ویرایش شده است، انتقال میدهد. به فرض اینکه نسخهی MAJOR.MINOR.PATCH یا اصلی.جزیی.وصله داده شده است: شمارهی نسخهی اصلی (MAJOR) را زمانی افزایش دهید که تغییرات API ناسازگار اعمال کردهاید، شمارهی نسخهی جزئی (MINOR) را زمانی افزایش دهید که قابلیتهایی اضافه کردهاید که با نسخههای قبل سازگار هستند، شمارهی نسخهی وصله (PATCH) را زمانی افزایش دهید که تصحیح خطاهایی (bug) اعمال کردهاید که با نسخههای قبل سازگار هستند. برچسبهای اضافی برای پیشنشر و ساختن فراداده به صورت پسوندهایی برای قالب MAJOR.MINOR.PATCH فراهم است. ویژگیهای نسخهبندی معنایی (SemVer) کلمات کلیدی «باید»، «نباید»، «نیاز است»، «میبایست»، «نمیبایست»، «توصیه شده است»، «ممکن است» و «اختیاری» در این مستند میبایست بر مبنای آنچه در RFC 2119 تعریف شده است، معنا شوند. نرمافزارهایی که از نسخهبندی معنایی استفاده میکنند باید یک API عمومی اعلام کنند. این API میتواند در خود کد اعلام شود، یا به طور واضح در مستندسازی وجود داشته باشد. هر طور که انجام شود، میبایست دقیق و جامع باشد. یک شمارهی نسخهی عادی باید قالب X.Y.Z را داشته باشه طوری که در آن X ،Y و Z اعداد صحیح غیرمنفی هستند و نباید صفر اضافه (leading zero) داشته باشند. X نسخهی اصلی، Y نسخه جزیی، و Z نسخهٔ وصله است. هر عنصر باید به صورت شمارشی افزایش یابد. به عنوان مثال 1.9.0 -> 1.10.0 -> 1.11.0. زمانیکه یک بستهی نسخهبندی شده منتشر شد، محتوای آن نسخه نباید دستکاری شود. هرگونه تغییری باید به عنوان نسخهی جدید منتشر شود. نسخهی اصلی شمارهٔ صفر (0.y.z) برای توسعههای ابتدایی است. هرچیزی در هر زمانی ممکن است تغییر کند. API عمومی نمیبایست ماندگار در نظر گرفته شود. نسخهٔ 1.0.0 API عمومی را تعریف میکند. روشی که شمارهٔ نسخهی بعد از این انتشار افزوده میشود، به این API عمومی و نحوهٔ تغییر آن وابسته است. نسخهی وصله Z (x.y.Z | x > 0) باید در صورتی افزوده شود که تصحیحهای خطای سازگار با نسخهٔ قبلی معرفی شده باشند. یک تصحیح خطا به عنوان یک تغییر داخلی تعریف میشود که رفتارهای نادرست را اصلاح میکند. نسخهٔ جزیی Y (x.Y.z | x > 0) باید در صورتی افزوده شود که عملکرد سازگار با نسخههای قبل جدیدی به API عمومی معرفی شده باشد. همچنین اگر هرگونه عملکرد API عمومی به عنوان منسوخشده برچسب خورده باشد، این شماره باید افزوده شود. اگر عملکرد جدید یا بهبود قابل توجهی در کدهای داخلی معرفی شده باشد، ممکن است نسخهٔ جزیی افزوده شود. ممکن است که شامل تغییرات سطح وصله هم باشد. زمانیکه نسخه جزیی افزوده شود، نسخهٔ وصله باید به 0 بازنشانده شود. نسخهی اصلی X (X.y.z | X > 0) باید در صورتی افزوده شود که هرگونه تغییرات ناسازگار با نسخههای قبل به API عمومی معرفی شده باشد. ممکن است این تغییرات شامل سطوح جزیی و وصله نیز باشد. نسخهی جزئی و وصله زمانیکه نسخهی اصلی افزوده میشود باید به 0 بازنشانی شوند. یک نسخهی پیشانتشار ممکن است با اضافه کردن یک خط تیره و یک سری شناسههایی که به وسیلهی نقطه از هم جدا شدهاند و بلافاصله به دنبال نسخهی وصله میآیند، نشانهگذاری شود. شناسهها باید تنها شامل اعداد و حروف الفبای اَسکی (ASCII) و خط تیره [A-Za-z0-9] باشند. شناسهها نباید تهی باشند. شناسههای عددی نباید با صفر اضافه آغاز شوند. نسخهی پیشانتشار از اولویت پایینتری نسبت به نسخهی عادی مرتبط برخوردار است. یک نسخهی پیشانتشار حاکی از آن است که نسخهی ناپایدار است و ممکن است نیازمندیهای سازگاری مورد نظر را آنگونه که در نسخهی عادی مرتبط نشان داده شده است، برآورده نکند. مثال: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92. متادیتای ساخت (build metadata) ممکن است با افزودن یک علامت جمع (+) و یک سری شناسههایی که به وسیلهٔ نقطه ازهم جدا شدهاند، و بلافاصله به دنبال نسخهی وصله یا پیشانتشار میآیند، نشانهگذاری شود. شناسهها باید تنها شامل اعداد و حروف الفبای اَسکی (ASCII) و خط تیره [A-Za-z0-9] باشند. شناسهها نباید تهی باشند. متادیتای ساخت میبایست در زمان تعیین اولویت نسخه درنظر گرفته نشود. بنابراین دو نسخه که تنها در متادیتای ساخت با یکدیگر متفاوت هستند، اولویت یکسان دارند. مثال: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f8 اولویت اشاره دارد به اینکه چگونه نسخهها زمانیکه مرتب شدهاند با یکدیگر مقایسه میشوند. اولویت باید به وسیلهی جداسازی نسخه به اصلی، جزیی، وصله و شناسههای پیشانتشار به همین ترتیب، محاسبه شود (متادیتای ساخت در اولویت نمایان نمیشود). اولویت، به وسیلهٔ اولین تفاوت تعیین میشود هنگامی که این مشخصهها از چپ به راست مقایسه شوند، بدین صورت: نسخههای اصلی، جزیی و وصله همیشه به صورت عددی مقایسه میشوند. مثال: 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1. زمانی که اصلی و جزیی و وصله برابر هستند، یک نسخهٔ پیشانتشار از اولویت کمتری نسبت به نسخهٔ عادی برخوردار است. مثال: 1.0.0- alpha < 1.0.0 اولویت برای دو نسخهی پیشانتشار با نسخهی اصلی، جزیی و وصلهی مشابه باید به وسیلهی مقایسهی هر مشخصهای که با نقطه جدا شده، از چپ به راست مشخص شود تا زمانی که یک تفاوت به شرح زیر یافت شود: شناسههایی که تنها شامل اعداد صحیح هستند به صورت عددی و شناسههایی که با حروف یا خطهای تیره به صورت الفبایی به ترتیب ASCII مقایسه می شوند. مشخصههای عددی همیشه از اولویت کمتری نسبت به مشخصههای غیرعددی برخوردار هستند. مجموعههای بزرگتری از بخشهای پیشانتشار اولویت بیشتری نسبت به مجموعههای کوچکتر دارند، اگر همه مشخصههای اولویت برابر باشند. مثال: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0. چرا از نسخهبندی معنایی استفاده شود؟ این ایدهای جدید یا انقلابی نیست. در واقع، احتمالاً شما چیزی مشابه به این را پیش از این انجام دادهاید. مشکل اینجاست که «مشابه» به اندازهی کافی خوب نیست. بدون انطباق با نوعی تعریف رسمی، شمارههای نسخه ضرورتاً برای مدیریت وابستگی (dependency) بلااستفاده هستند. بوسیلهی اختصاص اعداد و تعاریف واضح به ایدههای بالا، برقراری ارتباط میان کاربران نرمافزار شما و اهدافتان آسانتر میشود. بهمجرد اینکه این اهداف واضح شود، مشخصات وابستگی انعطافپذیر (نه آنچنان انعطافپذیر) میتواند نهایتاً ایجاد شود. یک مثال ساده میتواند نشان دهد که چگونه نسخهبندی معنایی میتواند جهنم وابستگی را به خاطرهای از گذشته تبدیل کند. کتابخانهای به نام «Firetruck» را در نظر بگیرید. این کتابخانه به یک بسته به نام «Ladder» که به صورت معنایی نسخهبندی شده، احتیاج دارد. در زمانی که firetruck ساخته شده، Ladder در نسخهی 3.1.0 است، شما میتوانید وابستگی Ladder را با آسودگی به عنوان بزرگتر یا برابر با 3.1.0 و نه کمتر از 4.0.0 تعیین کنید. شما میتوانید آنها را در سیستم مدیریت بستهٔ خود منتشر کنید و بدانید که آنها با نرمافزار وابسته موجود سازگار هستند. بدون شک به عنوان یک توسعهدهندهی مسئولیتپذیر شما خواهید خواست که هر بسته همانطورکه اعلان شده ارتقاء یابد. دنیای واقعی مکان به هم ریخته ایست، ما جز اینکه هشیار باشیم نمیتوانیم کاری دربارهی آن انجام دهیم. آنچه شما میتوانید انجام دهید این است که بگذارید نسخهبندی معنایی به شما یک راه عاقلانه ارائه دهد، تا بستهها را منتشر کرده و ارتقاء دهد بدون آنکه نسخههای جدیدی از بستههای مستقل را راه اندازی کند و شما را عذاب نداده، در وقت شما صرفهجویی کند.. اگر همهی اینها مطلوب به نظر میرسد، همهی آنچه شما برای شروع استفاده از نسخهبندی معنایی احتیاج دارید این است که اعلام کنید که در حال انجام این کار هستید و از قوانین پیروی کنید. به این وبسایت از طریق صفحه README خود لینک بزنید، در نتیجه دیگران دربارهٔ قوانین خواهند دانست و از آن نفع خواهند برد. سوالات متداول چگونه باید با نسخهها در فاز توسعهی ابتدایی 0.y.z کنار بیایم؟ سادهترین کار برای انجام دادن این است که توسعهٔ ابتدایی خود را از انتشار 0.1.0 آغاز کنید و سپس نسخهٔ جزیی را برای هر انتشار آتی افزایش دهید. چگونه بدانم چه زمانی باید 1.0.0 را منتشر کنم؟ اگر نرمافزار شما در طول تولید مورد استفاده قرار گرفته است، احتمالاً میبایست هماکنون 1.0.0 باشد. اگر یک API ماندگار دارید که کاربران روی آن حساب میکنند، شما باید 1.0.0 باشید. اگر در مورد سازگاری با نسخههای قبل خیلی نگران هستید، احتمالاً میبایست هماکنون 1.0.0 باشید. آیا این روش، توسعه و تکرار سریع را کند نمی کند؟ نسخهی اصلی صفر تماماً در مورد توسعهٔ سریع است. اگر شما API را هر روز تغییر میدهید، یا باید هنوز در نسخهی 0.y.z باشید یا در یک شاخهی توسعهی جداگانه که بر نسخهی اصلی بعدی کار میکند هستید. اگر حتی کوچکترین تغییرات ناسازگار با نسخههای قبل در API عمومی نیازمند یک نسخهٔ اصلی باشد، آیا من خیلی سریع به نسخه 42.0.0 نخواهم رسید؟ این سوال یک توسعهدهندهی مسئولیتپذیر و آیندهنگر است. تغییرات ناسازگار نمیبایست به راحتی در نرمافزاری که کدهای وابستهی زیادی دارد معرفی شود. هزینهای که برای ارتقاء باید متحمل شد میتواند قابل توجه باشد. اجبار برای ایجاد نسخههای اصلی برای انتشار تغییرات ناسازگار، یعنی شما به تأثیر تغییراتتان فکر خواهید کرد و نرخ هزینه/سود مورد نظر را خواهید سنجید. مستندسازی تمامی API عمومی کار بسیار زیاد میبرد! این مسئولیت شما به عنوان یک توسعهدهندهی حرفهای است تا به طور مناسب نرمافزار که میبایست توسط دیگران مورد استفاده قرار گیرد را مستندسازی کنید. مدیریت پیچیدگی نرمافزار یک بخش فوقالعاده مهم ازکارآمد نگهداشتن پروژه است، و انجام آن سخت است اگر کسی نداند که چگونه نرمافزار شما را استفاده کند یا چه متدهایی برای صدا زدن امن است. در دراز مدت، نسخهبندی معنایی و پافشاری بر یک API عمومی خوشتعریف میتواند همه چیز و همه کس را در اجرا کردن راحت در موقعیت مناسبی نگه دارد. چه کار میتوانم بکنم اگر تصادفاً یک تغییر ناسازگار با نسخههای قبل را به عنوان نسخهی جزئی منتشر کردم؟ به مجرد اینکه متوجه این مورد بشوید، تنظیمات نسخهبندی معنایی را به هم زدهاید، مشکل را حل کنید و یک نسخهی جزیی جدید که مشکل را تصحیح کند و سازگاری با نسخههای قبل را بازگرداند، منتشر سازید. حتی تحت این شرایط، این پذیرفته شده نیست که انتشارهای نسخهبندی شده را دستکاری کنید. اگر مناسب است نسخهی متخلف را مستندسازی کنید و کاربران خود را از مشکل مطلع سازید تا آن ها نیز از نسخهی متخلف آگاه باشند. چه کار باید بکنم اگر وابستگیهای خودم را بدون تغییر دادن API عمومی بهروزرسانی کردم؟ این مورد تا زمانی که API عمومی را متأثر نسازد سازگار تلقی خواهد شد. نرمافزاری که صریحاً به همان وابستگیهایی که بستهی شما وابسته است، وابسته باشد، باید مشخصات وابستگی خود را داشته باشد و نویسنده باید هرگونه مغایرت را ذکر کند. تشخیص اینکه آیا تغییر ازنوع دستکاری در سطح جزیی است یا سطح وصله، به این بستگی دارد که آیا شما وابستگیهای خود را جهت تصحیح یک خطا یا برای یک کاربرد جدید بهروزرسانی کردهاید. من معمولاً کد اضافی برای موارد آتی در نظر میگیرم، که بدون شک این موارد افزایش سطح جزیی میباشد. چه می شود اگر من بدون اعلام قبلی API عمومی را به صورتی تغییر دهم که با تغییر عدد نسخه سازگار نباشد؟ (یعنی کد به نادرست تغییر اصلیای را در انتشار وصله معرفی میکند) از بهترین قضاوت خود استفاده کنید. اگر شما مخاطبان زیادی دارید که به شدت به وسیلهی تغییر رفتار به آنچه قبلاً برای API عمومی در نظر گرفته شده، متأثر خواهند شد، پس بهترین کار انجام یک انتشار نسخهی اصلی است، حتی اگر اصلاح اعمال شده مؤکداً یک انتشار وصله محسوب شود. به یاد داشته باشید، نسخهبندی معنایی تماماً دربارهی انتقال معنا بوسیله چگونگی تغییر عدد نسخه میباشد. اگر این تغییرات برای کاربران شما مهم است، از عدد نسخه برای آگاهسازی آنها استفاده کنید. چگونه باید با منسوخ کردن عملکرد (deprecating functionality) کنار بیایم؟ منسوخ کردن عملکرد موجود بخشی عادی از توسعهی نرمافزار است و معمولاً برای اینکه پیشرفت رو به جلو حاصل شود مورد نیاز است. زمانیکه بخشی از API عمومی خود را منسوخ میکنید، باید دو کار انجام دهید: ۱) مستندسازی خود را بهروزرسانی کنید تا به کاربر اجازه دهید از تغییرات باخبر شود. ۲) یک انتشار جزیی که در آن قسمت منسوخ شده در جایگاه خود باشد منتشر کنید. قبل از آنکه عملکرد را به طورکامل در یک انتشار اصلی حذف کنید حتماً باید حداقل یک انتشار جزیی که شامل قسمت منسوخ شده است وجود داشته باشد تا کاربران به راحتی بتوانند به API جدید منتقل شوند. آیا SemVer محدودیت اندازه بر روی رشتهی نسخه دارد؟ خیر، اما از قضاوت مناسبی استفاده کنید. به عنوان مثال یک نسخهی ۲۵۵ نویسهای احتمالاً مفید نخواهد بود! همچنین، سیستمهای خاص ممکن است محدودیتهای خود برای اندازهی رشته اعمال کنند. - منبع
-
2 امتیازهمانطور که میدانید اخیرأ فناوری وباسمبلی (Qt for WebAssembly) معرفی شده است، توسعهدهندگان کیوت یک نمایشگر برای اجرای خروجیهای QML در مرورگر طراحی کردهاند که به شما این امکان را میدهد تا کدهای نوشته شدهی خود را در محیط مرورگر اجرا کنید. در این بخش میتوانید آخرین نسخهی مرتبط با Qt Design Viewer را برای آزمایش پیدا کنید، نمایشگر Qt Design Viewer با چند طرح آماده برای آزمایش همراه است. برای اجرای یک برنامهی سفارشی تحت QML، باید یک پروندهی qmlproject. که پروندهی اصلی QML است را تعریف کنید. این همان قالب اساسی پروژه است که توسط Qt Design Studio و Qt Creator برای پروژههای QML استفاده میشود. پوشهی پروژه باید به صورت یک فایل Zip فشرده شود و سپس در Qt Design Viewer بارگذاری گردد. همچنین میتوانید از نسخهی Qt Design Studio 1.3 یک فایل منبع را از پروژه ایجاد کرده و بستهای را که به صورت خودکار ایجاد شده است را بارگذاری کنید. آزمایشهای مربوطه بر روی مرورگرهای Safari، Chrome، FireFox و Edge انجام شده است و عملکرد اجرای QML در تمامی آنها بسیار خوب است. البته زمان تدوین و پیکربندی به مرورگر شما بستگی دارد، اما عملکرد واقعی برنامه پس از اجرا همانند نسخهی دسکتاپ است. سیستم Qt Design Viewer همراه با اکثر ماژولهای QML به عنوان بخشی از کیوت است که در نسخهی ۵.۱۴ ساخته شده است. همچنین، این محیط بر روی سیستمعاملهای iOS و Android اجرا میشود که یک روش ساده را برای اجرای طرحهای آزمایشی ارائه میکند. این فناوری جدید است، بنابراین در صورت مشاهدهی مشکلات آن را به تیم توسعهدهندهی آن گزارش دهید.
-
2 امتیازبا سلام، یا توجه به مقالهٔ ذکر شده زیر در ارتباط با انتخاب زبان برنامهنویسی و تفاوت عمدهٔ زبانهای کامپایلری و مفسری لازم است تعاریفی در رابطه با جزئیات زبانهای کامپایلری که خود تفاوتهایی را شامل میشوند بپردازیم. در صورتی که مقالهٔ زیر را مطالعه نکردهاید پیشنهاد میکنیم قبل از خواندن این مقاله آن را مرور کنید. در این مقاله شما تفاوت عمدهٔ آنها را خواهید آموخت که شامل توضیحات کامپایلر و روشهای کامپایل میباشد. کامپایلر چیست؟ کامپایلر به ابزار (برنامه یا مجموعهای از برنامهها) گفته میشود، که متنِ نوشته شدهٔ برنامهنویسان (در قالب کُد) را که از سطح بالاتر (زبان مبدأ) برخوردار است و درک آن برای انسان مُیسر میباشد، دریافت کرده و آن را به زبان سطح پایینتر (زبان مقصد) مانند اسمبلی یا کُد ماشین ترجمه میکند. زبانهای کامپایلری در دو دستهی بومی (Native) و مجازی (Virtual) کامپایل از نوع بومی روشی است که کدهای نوشته شده را به صورت مستقیم به کُد ماشین ترجمه میکند. کامپایل از نوع مجازی روشی است که کدهای نوشته شده را ابتدا به کُدمیانی (کدمشترک یا همان بایت کُد - Byte Code) در جاوا و زبان میانی (CIL) در Net. تبدیل میکند که خودِ آن شبیه به کُد ماشین است. در این فرایند کد مربوطه توسط کامپایلر مخصوص یعنی JIT (کامپایلری از نوع Just-In-Time) در زمان اجرا توسط سیستمعامل، به دستورالعملهای قابل فهم برای پردازنده تفسیر و اجرا میشود (که این فرایند شبیه به فرایند عملکرد اجرایی مفسرها است). زبانهای بومی (زبانهایی که کد آنها به کد ماشین به صورت مستقیم توسط کامپایلر قبل از اجرای آنها توسط سیستمعامل، ترجمه میشوند که به اصطلاح ahead-of-time (جلوتر از زمان) یا همان AOT نام دارد) مانند: C, C++, Rust, Haskell, Clean, Swift, Go, Fortran, D زبانهای مجازی (زبانهایی که کد آنها توسط یک رابط میانی به زبان مشترک ترجمه میشود) : Java و خانوادهٔ داتنت مانند C#, Visual Basic.Net و C++/CLR نکته قابل توجه در مورد C++/CLR آن است که این نوع استاندارد در مورد سیپلاسپلاس بر پایهٔ چهارچوب داتنت است. در این نسخه از زبان شما با محدودیتهای بسیاری مواجه بوده و به ویژگیها و کیفیت نهایی برنامههای تولید شدهٔ واقعی در قالب Native محروم خواهید بود. روش کامپایل و و انواع آنها کامپایلرها به صورت بومی (Native) و کراس (Cross) تقسیم بندی میشوند. به طور کلی آن دسته از کامپایلرها که کدهای باینری را تولید میکنند از نوع محلی یا همان Native نام دارند؛ در واقع به هر کامپایلی که بر روی سیستمهای معماری x86 نوع x86، بر روی سیستمهای x86-64 نوع x86-64 و بر روی سیستمهای PowerPC نوع powerpc و بر روی arm نوع arm را تولید کند کامپایل بومی میگویند. چرا که تنها برای یک پلتفرمِ هدف کدهای ماشین رو تولید خواهد کرد (در صورت نیاز برای اجرا بر روی پلتفرمهای دیگر باید آن را بر روی پلتفرم متناسب با آن پیکربندی کنید) در واقع یک وابستگی به سختافزار وجود خواهد داشت که کدهای شما بر اساس آن تولید میشود. اما در رابطه با کامپایلرها از نوع Cross یا به اصطلاح عبوری وابستگی خاصی به سختافزار ندارند، در این روش کافی است سختافزار، پلتفرم (معماری و سیستمعامل) مورد نظر را یک بار برای آن معرفی کرده و اقدام به کامپایل کنید. کامپایل به صورت کراس کدها را به برنامهٔ قابل اجرا برای بیشتر از یک پلتفرم فراهم میکند. برای مثال در صورتی که بر روی پلتفرم ویندوز هستید میتوانید برنامهٔ نوشته شدهٔ خود را برای پلتفرم اندروید یا آیاواس که برای arm هستند ارائه دهید. اولین کامپایلری که این ویژگی را پشتیبانی میکند GCC است. این امکان وجود دارد که شما کدهای نوشته شدهٔ خود را بر روی پلتفرم میزبان برای پلتفرمهای هدف (مقصد) کامپایل کنید. البته جدیداً کامپالر کلَنگ (Clang) به عنوان یکی از بهترین انتخاب بین برنامهنویسان ++C جهت کراسکامپایل مطرح میشود. کامپایلرهای پیشنهادی: GCC Clang MSVC مزایا و معایب زبانهای کامپایلری از نوع کلاس بومی (Native) از سرعت بسیار بالایی برخوردار هستند (دلیل آن ترجمهٔ مستقیم کدها به کد ماشین است) در مقابل بزرگترین مزیتی که زبانهای نوع کلاس مجازی (Byte Code) دارند به خاطر وجود یک برنامهٔ واسط جهت شبیهسازی کدهای ترجمه شده به کد قابل فهم برای پردازنده، اجرا شدن آنها در هر پلتفرم بدون کامپایل مجدد امکان پذیر است که البته این ویژگی خود نیازمند نصب بودن JVM بر روی پلتفرم مربوطه میباشد. در نوع بومی برای اجرا در هر پلتفرم لازم است سورس کدها را برای پلتفرم مقصد کامپایل کنید که نیازی به وجود ماشین مجازی مانند JVM یا برنامهٔ خاصی ندارد. کدهای میانی تحت کامپایلِ درجا JIT : Just In Time همانطور اشاره شد زبانهای برنامهنویسی Java و خانوادهٔ Net. به ترتیب توسط Java Byte Code بر روی ماشین مجازی جاوا JVM و CIL : Common Intermediate Language بر روی زیر ساخت CLI : Common Language Infrastructure از هم جدا میشوند. در نظر داشته باشید CIL نام تغییر یافتهٔ MSIL میباشد. معنای ماشین مجازی CLR و JVM جیویام یا همان JVM : Java virtual machine نوعی ماشین مجازی (واسطی) است که وظیفه اجرای کد جاوا را برعهده دارد. زمانی که در مورد برنامههای نوشته شده توسط جاوا صحبت میکنیم، حتما باید JVM بر روی سیستم شما نصب باشد تا قابلیت اجرا شدن برنامههای تحت جاوا را داشته باشد. سیاِلآر یا همان CLR : Common Language Runtime نوعی ماشین مجازی (واسطی) است که کدهای مربوط به CIL را برای سیستم تفسیر و اجرا میکند. البته تفاوتهایی در خروجی این کد با کدهای جاوا وجود دارد که در آن زبان IL به عنوان یک زبان شبیه به زبان ماشین مانند اسمبلی (assembly) میباشد. در CLR کدهای تولید شدهٔ بایتکد، کمتر از دستورالعملها و ابردادههای JVM است. تفاوت اصلی CLR و JVM تفاوت اصلی JVM و CLR در این است که JVM جهت اجرای کدهای جاوا استفاده میشود و CLR مدیریت برنامههای اجرایی داتنت را مدیریت میکند. به طور کلی، JVM امکان اجرای کدهای کامپایل شدهی جاوا را فراهم میکند که در بسیاری از سیستمعاملها و سختافزارها موجود است. از سوی دیگر، CLR یک بستر (محیطی) را برای اجرای برنامههای نوشته شده در چهارچوب داتنت همراه با امکان مدیریت حافظه، مدیریت خطاها، امنیت و غیره را فراهم میکند. نسل جدید JIT برای داتنت (نام کد RyuJIT) به لُطف Net. و نسخهٔ Net Core. نام RyuJIT کُد شناسه از کامپایلر Net. است که وظیفهٔ آن ترجمهٔ کدهای #C به بایتکُد IL است که RyuJIT کدهای بایتکُد از نوع IL را به کُد ماشین ترجمه میکند. همانطور که مشخص است، جهان به سمت محاسبات ۶۴ بیتی حرکت میکند، اما باید در نظر داشته باشید سرعت برنامههای ۶۴ بیتی همیشه بیشتر از ۳۲ بیتیها نمیباشد! برای مثال نمونهای از آن را میتوان به کامپایلر JIT برای داتنت مثال زد؛ تغییرات و بهبودهایی که در نسل بعدی کامپایلر JIT بر روی Net Core. صورت گرفته است نسخهٔ ۶۴ بیتی آن است که اجازه میدهد برنامهها دو برابر سریعتر از نسخهٔ قبلی خود در داتنِت اجرا شود. این امر باعث میشود که نظرات شما را در مورد این نسخه از کامپایلر داتنت تغییر دهد. همانطور که به نظر میرسد، معماری ۳۲ بیتی x86 کامپیوترها که از زمانهای ایجاد تا به کنون در نوع خود بسیار عالی بودهاند، اما مشکل بزرگی که دارند متاسفانه پشتیبانی تا حداکثر ۴ گیگابایت حافظهٔ اصلی (Ram) است. با توجه به رُشد روز افزون معماری ۶۴ بیتی x64 نیاز به حافظههای بیش از ۴ گیگابایت جدی شد و امروزه ما میبینیم که اکثر سختافزارها و حتی دستگاههای موبایل نیز مجهز به حافظههای بیش از ۴ گیگابایت هستند. برای بهرهمندی از قابلیتهای معماری جدید Net Core. کامپایلر خود را با بهینهسازیهای چشمگیری ارائه داده است که میتواند تا دو برابر سریعتر از نسل قبلی خود عمل کند. در نظر داشته باشید که، معماری RyuJIT تقریبا نه سال پیش طراحی شده است و کارهای اجرایی از هفت سال پیش آغاز شده است. RyuJIT به عنوان یک کامپایلر تکامل یافته از JIT32 موجود (که از x86 و ARM32 پشتیبانی میکند) اجرا شد و به تدریج جایگزین بسیاری از بخشهای "بَکاِند" آن کامپایلر با یک تخصیص دهندهٔ رجیستر جدید و تولید کنندهٔ کد همراه با برخی از ویژگیهای جدید و بهبود یافته در "فرانتاِند" برای بهینه سازی در اجرا معرفی شده است. در طول این انتقال به کدهای نسل جدید معماری، سعی بر این بوده است که کدهای نسل قبل را در کنار نسل جدید نگه داشته شود. انجام این کارها مزایایی داشته است مانند حفظ هزینهها و باز نویسیهای بسیار! اما مسلماً هزینههایی هم دربر داشته است که کمترین آنها سردرگم بودن توسعهدهندگان در بارهٔ آیندهٔ Jit بوده است. در حال حاضر عملکرد RyuJIT برای کدهای قدیمی بسیار خوب بوده است و سرانجام وقت آن رسیده است که کدهای نسل قبل در JIT در آیندهای نزدیک تمرکز شود. نسل جدید از JIT با تمرکز بر پشتیبانی از معماری ۶۴ بیتی با نام RyuJIT سریعتر از JIT64 است. زبانهایی که از JIT/CLR پشتیبانی میکنند زبانهای اصلی این کامپایلر C#, VB.Net و C++ Managed یا همان C++/CLR میباشند. نکته: سی++ در این نسخه تغییراتی از جانب مایکروسافت داشته است و از نسخهٔ استاندارد آن کمی متفاوت است. برای مثال مدیریت حافظه به صورت خودکار و همچنین تغییرات جزئی از قبیل سینتکس را دارا میباشد. ساختار برنامههای زبان کامپایلری از نوع بومی (Native) در زبانهای مادر C و ++C در صورتی که تمایل دارید در رابطه با جزئیات ساختار برنامههای سریعترین زبانهای برنامهنویسی یعنی C و ++C مطلع شوید توصیه میشود مقالهٔ مرتبط با آن را که در زیر آمده است مطلعه کنید.
-
2 امتیازبا سلام، در این پست ما قصد داریم در رابطه با نحوهٔ آغاز یادگیری کیوت توضیح دهیم. اینکه به عنوان یک تازهکار چه پیشنیازاتی را باید مطالعه و در نهایت چگونه و تحتِ چه منابعی این کتابخانهٔ قدرتمند را بیاموزیم. همچنین پاسخ برخی از سوالات شما را در این پُست به طور شفاف ارائه شده است که طیِ چندین سال سوال علاقه مندان بودهاند. معرفی سریع و سادهٔ کیوت (Qt) این ابزار (به انگلیسی: Qt) با آوای «Cute» به فارسی (کیوت) مجموعهای از کتابخانهها و سرآیندهای نوشتهشده به زبان سی++ است که به برنامهنویس امکان توسعه آسان نرمافزارهای کاربردی را میدهد. کیوت شامل چندین کلاس برای کار با واسط گرافیکی، چندرسانه، ابزارهای پایگاهداده، شبکه و … است. نرمافزارهای نوشته شده با ابزار کیوت قادرند تا با استفاده از یک کامپایلر زبان سیپلاسپلاس برای طیف وسیعی از سیستمعاملها از جمله گنو/لینوکس (نسخههای رومیزی و وسیلههای قابل حمل)، ویندوز، ویندوز CE، مکاواس و … همگردانی شوند. بدین ترتیب حمل نرمافزار نوشته شده بدون تغییر در متن کد نوشته شده امکانپذیر است. از کیوت در زبانهای برنامهنویسی متعددی مانند سی++ و جاوا و پایتون میتوان استفادهکرد. پیشنیازات برای یادگیری کتابخانه Qt دانش متوسط و به بالا در رابطه با زبان برنامهنویسی مُدرن سیپلاسپلاس نسخههای ۱۱ به بعد، (بنابراین اگر شما هیچ اطلاعی در رابطه با ساختار برنامههای سیپلاسپلاس و نحوهٔ عملکرد آن ندارید، شانس موفقیت شما بسیار پایین خواهد بود و ممکن است برنامهٔ تولید شدهٔ شما به بدترین شکل ممکن پیاده سازی شود و حتی مدام دست به کمک دیگران باشید). من پیشنهاد میکنم قبل از آن با زبان سیپلاسپلاس آشنا شوید. آشنایی با کامپایلر و نحوهٔ عملکرد آن در پلتفرمهای مختلف از جمله ویندوز، مکاواِس، لینوکس، اندروید و آیاواِس. مهم است بدانید تسلط کافی در زبان سی++ و ساختار برنامههای نوشته شده در این زبان بسیار موثر است. آشنایی و تسلط کافی به ابزارهای ساخت و ساز مانند CMake یا QMake و QBS. آشنایی با معماریهای مختلف مانند x86، x86-64، Arm و غیره... و پیکربندی پروژه و تهیهٔ خروجی. آشنایی با معماریِ سیستمعاملها، برخی از رابطهای برنامهنویسی (Api)، برای مثال اگر قرار است از خاصیت چند-سکویی کیوت استفاده کنید تا یک برنامهٔ تحت اندروید را توسعه دهید، در این صورت باید در نظر داشته باشید که همه چیز توسط کیوت حاضر و آماده نیست، شما بدون درکِ معماری سیستمعامل اندروید و پیکربندی برنامه در مراحل توسعه نمیتوانید به راحتی از پسِ این کار بر آیید و هر از گاهی نیاز است به شیوهٔ اختصاصی پلتفرم مورد نظر برنامهٔ خود را توسعه دهید. در پلتفرمهای اپل نیز تسلط کافی به Xcode و مدیریت حساب توسعه در Apple Developer مورد نیاز است، شما باید بدانید چطور یک پروفایل را برای پلتفرم آیاواس باید تنظیم کنید. اگر شما در پلتفرمهای مختلف کار میکنید، قطعاً نیاز به کار با کیتهای توسعه، رابطهای توسعه و همچنین ابزارهای ساخت هر پلتفرم خواهید داشت. بنابراین، در محیط ویندوز نیاز دارید محیط خود را با ابزارهای ساخت و ساز آن مانند Microsoft Visual Studio Build Tools که شامل کامپایلرها، دیباگر و برخی از ابزارهای برنامهنویسی است هماهنگ کنید، چرا که بدون آن امکان توسعه وجود ندارد (نیاز نیست نرمافزار محیط توسعهٔ یکپارچهٔ Visual Studio را نصب کنید، همان ابزار Build Tools کافی است). در محیط لینوکس نصب پیشنیازها و کامپایلرهای GCC و یا Clang مهم است و در مک نیز بهروز رسانی و نصب ابزارهای ساخت و ساز و همچنین نسخهٔ کامل Xcode از واجبات توسعه در کیوت خواهد بود. بنابراین داشتن تجربه و آشنایی کافی با این ابزارها متوسط به بالا به نفع شماست. آشنایی با اصطلاحات و مفاهیم تجربهکاربری و رابطکاربری جهت طراحی مناسب با فناوریهای Qt Widget و Qt Quick (در صورتی که علاقهمند به طراحی ظاهر برنامههای خلاقانه دارید). آشنایی Xml برای سبک سنتی و ویجت و JavaScript پیشنیاز خوبی برای درک مسائل مربوط به فناوری طراحی در کیوتکوئیک است که تحت QML رابطهای کاربری و اجزای مختلف و خلاقانه را پیاده سازی خواهید کرد. توجه کنید که مستندات کیوت به اندازهٔ کافی جهت آشنایی با پیشنیازات بهروز رسانی میشود و نسبت به نسخههای ۵ و حتی ۶ توضیحات لازم را ارائه میکند. با توجه به این مسائل، مراحل نصب و داشتن حساب کاربری در کیوت لازم است، اما به این معنا هم نیست که شما از نسخهٔ رایگان نمیتوانید استفاده کنید، توجه داشته باشید که تنها تفاوت بین نسخهٔ رایگان و تجاری در یک سری ویژگیهای اختصاصی شرکت کیوت است که در پشتیبانی از آنها اعمال شده و نه بیشتر. آیا کیوت یک زبان برنامهنویسی است؟ چرا نحوِ (Syntax) آن با سیپلاسپلاس استاندارد فرق میکند؟ خیر، کیوت ابتدا به عنوان یک کتابخانهٔ رابط گرافیکی کاربر توسعه داده شده است که بعدها برای توسعه اهدافِ بیشتری شامل کتابخانههای شبکه و غیره شده است که در قالب یک چهارچوب (فریموُرک) که تحت زبان برنامهنویسی سیپلاسپلاس برای این زبان توسعه یافته است و در زمینههای مختلفی کاربردهای فراوان دارد. دلیل زیبایی و ظاهر سادهٔ آن ساختار بسیار قدرتمند آن است که موجب شده همانند چهارچوبهای قدرتمند دیگری خودنمایی کند. (اما قول این ظاهر و سادگی آن را نخورید، چون با سیپلاسپلاس طرف هستیم) آیا کیوت از سرویسها و قابلیتهای اختصاصیِ اپلیکیشنهای اندروید و آیاواِس را به طور کامل پشتیبانی میکند؟ به صورت پیشفرض خیر، هیچ ابزاری به صورت چند-سکویی فعلاً (تاکید میکنیم - فعلاً تا به این تاریخ) وجود ندارد که تمامی امکانات اختصاصی این پلتفرمها را بدون کد نویسی اختصاصی پشتیبانی کند. اما این به این معنی نیست که جواب منفی خواهد بود، لذا شما در برنامهنویسی سیپلاسپلاس به راحتی میتوانید برای پلتفرمهای فوق با سرویسهای آنها ارتباط برقرار کنید. این کار کمی نیاز به دانش فنی بالایی خواهد داشت! برای مثال (دسترسی به سرویسهای اندروید یا آیاواس) با ترکیب کُدهای آبجکتیو-سی و جاوا امکانپذیر است و یا باید با توجه به SDKهای پلتفرمهای مورد نظر آنها را سفارشی نویسی کنید. این کار به راحتی قابل انجام خواهد بود و کافی است شما در رابطه با نحوهٔ ترکیب کُدهای آن آشنا باشید. کیفیت خروجی برنامههای تحت کیوت چگونه است؟ اگر شما واقعاً یک برنامهنویسِ ماهرِ سیپلاسپلاس باشید میتوانید برنامهای را تولید کنید که بسیار خوش دستتر و سریعتر از برنامههای پیشفرضِ پلتفرمها باشد. در بارهٔ دلایل آن به ساختار برنامههای نوشته شده توسط این زبان به این مقاله مراجعه کنید. اگر غیر از این باشد برنامهٔ شما بسیار بد و کُند عمل خواهد کرد و بهتر است سراغ زبانهای پیشنهادی (هر پلتفرم) بروید. هرچند سیپلاسپلاس یک زبان بومی برای تمامی پلتفرمها محسوب میشود اما این ریسک برای افراد مبتدی پیشنهاد نمیشود. معمولاً برنامههای گسترده و عظیم توسط سیپلاسپلاس توسعه داده میشوند که برنامهنویسان آن واقعا حرفهای و با قوانین این زبان آشنا هستند. آیا برای تولید برنامههای مک و آیاواس نیاز به سیستم خاصی داریم؟ بله، شما بدون وجود سیستمعامل مک نمیتوانید برنامهای را بر روی دستگاههای اپِل کامپایل کنید. این امر مستلزمِ سیستم عامل اختصاصی این شرکت بوده و باید توسعه دهنده دارای حساب کاربری معتبر سالانه باشد تا بتواند برنامهٔ خود را بر روی دستگاههای مورد نظر اجرا کند. در غیر این صورت تنها میتواند برنامهٔ خود را بر روی سیستم خود مورد آزمایش و خطا قرار دهد. آیا کیوت در ایران بازار کار مناسبی دارد، آیا ارزش دارد من این کتابخانه را یاد بگیرم؟ خوشبختانه کیوت بیشتر از ۲۰ سال است که در دنیا مورد استفاده قرار میگیرد و کشورهای پیشرفته از آن استقبال میکنند. در کشور ما مدتی است این کتابخانه مورد استقبال قرار گرفته و بسیاری از شرکتها مایل به ساخت و توسعهٔ برنامههای خود تحت این کتابخانه هستند که برخی از دلایل آن (بهره بردن از قابلیتهای زبان سی و سیپلاسپلاس و ویژگیهای خاص آن است). از طرفی کیوت به عنوان یک کتابخانهٔ چندسکویی، مناسب برای تولید و توسعهٔ محصولات در قالب اپلیکیشنهای موبایل و برنامههای کاربردی بر روی دسکتاپ است که در نوع خود کم نظیر است. استفاده از این کتابخانه، موجب سهولت و افزایش سرعت توسعهٔ تولید و طراحی نرمافزار میشود و شما میتوانید با توجه به حفظ کیفی کدهای خود از یک محیط مجهز به ابزارهای طراحی پیشرفته استفاده کنید. پشتیبانی بسیار خوب از زبان فارسی و به خصوص تاریخ شمسی و دیگر موارد، طراحی به شیوهٔ استاندارد راست به چپ و رعایت اصول در آن یکی از دلایلی است که میتوان تضمین کرد کیوت یک ابزار مناسب در طراحی و توسعهٔ برنامههای بومی به زبان فارسی است. چه کسانی یا شرکتهایی از این فریمورک استفاده میکنند؟ جالب است بدانید کتابخانهٔ کیوت محدود به فرد یا شرکت خاصی نیست، با توجه به دو نسخهٔ تجاری و رایگان آن، شرکتهای خصوصی، افراد و توسعهدهندگان بسیار هستند که از آن به عنوان یک فریمورک طراحی و تولید برنامه استفاده میکنند. معمولاً شرکتهای توسعهدهندهٔ تجهیزات سختافزاری، پزشکی، رباتیک، صنعتی و دیگر موارد از آن استفاده میکنند. همچنین بازار طراحی نرمافزارهای هوشمند موبایل، نرمافزارهای کاربردی و پرکاربرد از این کتابخانه استفاده میکنند. اما تبلیغات در این زمینه به دلیل عدم شناخت، تسلط و آشنایی به سی++ نسبت به دیگر ابزارها کمتر است. درآمد و هزینههایی که میتوان از انجام پروژههای کیوت دریافت کرد چگونه است؟ به طور کلی نمیتوان در مورد یک تعرفهٔ مشخص صحبت کرد، این بستگی به نوع مهارت شخصی و کیفیت کار دارد. اما در این مقاله میتوان به این اشاره کرد که برنامهنویسی سی++ و کیوت یکی از خوش درآمدترین مباحثی هستند که میتوان به آن اشاره کرد که البته بستگی به مهارت و تسلط کافی توسعهدهنده دارد. آیا کیوت از سکوی وِب پشتیبانی میکند؟ کیوت از تمامی پلتفرمها پشتیبانی میکند، مخصوصاً با پشتیبانی از ماژولهای QtWebEngine و QtWebAssembly این امر امکانپذیر است که برنامههای خود را تحت فناوریهای وِب نیز توسعه دهید. آیا من حتماً باید به زبان سیپلاسپلاس مسلط باشم؟ هرچند زبان سی++ یکی از الزامات کیوت است، اما همانطور که اشاره شد، آشنایی با هسته، کتابخانهٔ پیشفرض، سینتکس و روشهای برنامهنویسی رایج آن برای درکِ بهتر کیوت مهم هستند. من دانشجو یا متخصص رشتهٔ کامپیوتر نیستم، آیا میتوانم این کتابخانه را یاد گرفته و از آن در توسعه برنامههای مورد نظر خود استفاده کنم؟ بله، اما ممکن است در تجزیه و تحلیل رفتارهای سیستمعامل، مدیریت خطاها و پیکربندی ابزارهای تخصصی (برنامهنویسی) با مشکلاتی مواجه شوید که تنها متخصصات این رشته میتوانند آن را درک و حل کنند. آیا واقعاً حجم برنامههای کیوت نسبت به Net. یا Java بیشتر است !؟ خیر، به طور ذاتی برنامههای توسعه داده شده توسط سی++ دارای کمترین حجم برنامه هستند، معمولاً کتابخانههای استاندارد این زبان به صورت پیشفرض بر روی سیستم عاملها تعبیه شده و در دسترس قرار دارند. اما شما در ویندوز زمانی که با داتنت برنامهنویسی میکنید، فریمورک مربوطه از قبل بر روی سیستم عامل ویندوز نصب بوده و بدون آن هیچ برنامهٔ نوشته شده توسط داتنِت قابل اجرا نمیباشد. اما چون از قبل این کتابخانه بر روی سیستمعامل تعبیه شده است شما نیاز به تنها داشتن فایل اجرایی دارید و نیازی نیست فریمورک داتنت را در کنار فایل اجرایی خود مستقر کنید. بنابراین حجم مربوط به چهارچوب به چشم نیامده و اینطور به نظر میرسد که برنامههای تحت دات نت بسیار سبُکتر هستند! متاسفانه این تفکری اشتباه است برنامههای تحت سیپلاسپلاس نسبت به زبانهای دیگر کم حجمتر و سبُکتر بوده و شما کافی است فایلهای مربوط به کتابخانه را در کنار برنامهٔ خود داشته باشید. در رابطه با کتابخانهٔ Qt نیز باید گفت کیوت به عنوان یک چهارچوب مانند دات نت شامل کلاسها و ماژولهایی است که باید همانند دات نت بر روی سیستم عامل تعبیه شود اما چون اینکار به صورت جداگانه در کنار برنامهٔ شما قرار میگیرد اینگونه تصور میشود که برنامههای مبتنی بر کیوت نسبت به دات نت از حجم بیشتری برخوردار هستند. این کاملاً طبیعی بوده و به عنوان نکته ضعف نیست. من علاقهٔ خاصی به سیپلاسپلاس دارم و میخواهم کیوت را یاد بگیرم، از کجا و چه تحت منابعی باید شروع کنم؟ خوشبختانه کیوت از لحاظ مستندات بسیار جامع است و شما میتوانید از این آدرس به تمامی مستندات مورد نیاز خود دسترسی داشته باشید. همچنین اگر نگران اینترنت خود هستید و یا به آن دسترسی مداوم ندارید میتوانید از داخل محیط توسعهٔ کیوت کریتور از بخش Help آن مستندات مورد نیاز خود را به صورت آفلاین دریافت کنید. من دنبال کتاب آموزشی کیوت هستم، آیا کیوت کتابهای آموزشی مفیدی در این زمینه از مقدمه تا پیشرفته دارد؟ بله، در این بخش شما میتوانید کتابهایی را در این زمینه مشاهده کنید که مرجع رسمیِ کیوت آنها را تایید کرده است. من به زبان انگلیسی تسلط کافی ندارم، ترجیح میدهم که از مراجع فارسی معتبر استفاده کنم، آیا کیوت در این زمینه منابعی دارد که معتبر باشند؟ خوشبختانه کیوت به قدری طعمِ جذابی برای برنامهنویسی دارد که دو کتاب مقدماتی و پیشرفتهٔ این کتابخانه به زبان فارسی نوشته و در کتابخانهٔ ملی کشور به صورت رسمی به ثبت رسیدهاند و عبارتند از نسخههای مقدماتی برای Qt Widgets و نسخهٔ پیشرفته برای Qt Quick (این کتابها تجاری هستند) که در لیست کتابخانهٔ اصلی کیوت نیز تأیید و ثبت شدهاند. آیا مقالات یا کتابهای آموزشی رایگانی هم برای کیوت وجود دارد؟ تنها مرجع آموزشی که در این رابطه به زبان فارسی توضیح میدهد، آیاواستریم است، تقریباً هیچ مقاله یا کتاب جامع و کاملی به صورت رسمی به زبان فارسی خارج از مرجع آیاواستریم (به رایگان) وجود ندارد. اما وعدههایی میدهیم که در پلتفرم فانوکس آموزشهای جدی و با ارزشی برای کیوت ارائه شود که در دو هدف رایگان و تجاری برنامهریزی شدهاند. آیا لیستی برای مشاهدهٔ برنامههای توسعه یافته توسط Qt داریم؟ بسیاری از برنامههای قدرتمند و خارقالعادهای توسط سیپلاسپلاس توسعه داده میشوند که میتوان لیست عظیمی از آنها را نام برد. اما در این میان لیستی از برنامههایی که تحت کیوت توسعه داده شدهاند در این بخش آمده است. برای یادگیری استاندارد سیپلاسپلاس و تقویت مهارت خود در این زبان کدام مقالات و کتابها را پیشنهاد میکنید؟ علاوه بر این که شما میتوانید در مرجع به دنبال آموزشهای مرتبط با این زبان باشید، پیشنهاد ما این است که از مراجع رسمی آن نیز استفاده کنید. برخی از آنها به صورت زیر آمدهاند: cppreference.com http://www.cplusplus.com/ Learn C++ C++ Tutorial | SoloLearn: Learn to code for FREE! Learn C++ (Introduction and Tutorials to C++ Programming) Qt Documents Qt Quick & QML اگر سوالی داشته باشم کجا میتوانم آن را مطرح کرده و به پاسخ خود برسم؟ شما میتوانید برای سوال و پرسش در انجمنهای این مرجع اقدام کنید. اساتید و دوستان با تجربه سوالات شما را دریافت و مناسبترین پاسخها را ارائه خواهند داد. همچنین شما میتوانید ما را در گروه سیپلاسپلاس و کانال تلگرامی دنبال کنید. نکته (در این پُست بنابر اهداف فرهنگسازی برای حق چاپ) فایلهای مرتبط با کتابهای آموزشی زبان اصل و یا زبان فارسی قرار داده نشده است. کتابهای زیادی در رابطه با این زبان وجود دارند که به زبان اصلی میباشند اما برای احترام به نویسندهٔ آنها از ارسال چنین فایلهایی معذوریم. این پُست ممکن است ویرایش یا بهروز رسانی شود.
-
2 امتیازتوابع Image Filtering شاید در تصویرمان بخواهیم عملیات زوم کردن را انجام دهیم در این صورت ما از توابع pyrUp،pyrDownیا تابع buildPyramid استفاده کنیمکهتابع buildPyramid تا هر چند برابر که بخواهیم تصویر را دور میکند اما بیش از حد ان باعث نابودی پیکسل های تصویر میشود. تابع pyrUp: تصویر را نزدیک میکند(ZoomIn) این تابع الگوریتم متفاوتی دارد و باید طبق این الگوریتم پیش رفت تا مشکلی پیش نیاید الگوریتم این تابع به این صورت است که میگوید شما میخواهید تصویر را دوبرابر کنید پس باید در پارمتر سومی که سایز را از مامیخواهد سطر و ستون تصویر ضرب در2 شود اینگونه سطر و ستون دوبرابر خواهند شد و خروجی مورد نظر را میدهد اما اگر در مقداری به جز مقدار 2 ضرب یا بعلاوه شود در این صورت تصویر انقدر بزرگ میشود که امکان نمایش ان وجود ندارد البته هر چند برای دوبرابر کردن تصویر که سایز ضرب در 2 میشود هم محدودیت وجود دارد و تا حد مشخصی میشود تصویر را نزدیک کرد بعد از ان با خطا مواجه میشویم یک مثال از این تابع را مشاهده کنید: #include <stdio.h> #include <stack> using namespace cv; Mat output_image; Mat image_read; void Zoom_In() { pyrUp(image_read, output_image, Size(image_read.cols * 2, image_read.rows * 2)); imshow("Zoom In", output_image); image_read = output_image; } void Zoom_Out() { pyrDown(image_read, output_image, Size(image_read.cols / 2, image_read.rows / 2)); imshow("Zoom Out", output_image); image_read = output_image; } void ZoomIn_And_ZoomOut(int position, void* user) { std::cout << "Position: " << position << " " << " user data " <<(int)user<< std::endl; } int main() { void* userdata = (void*)10; TrackbarCallback zoom_in = (TrackbarCallback)Zoom_In; TrackbarCallback zoom_out = (TrackbarCallback)Zoom_Out; image_read = imread("C:\\Users\\Mohamad4030\\Desktop\\c9ac_d2ynkbk.jpg", IMREAD_COLOR); imshow("befor",image_read);//befor filtering ShowWindow(GetConsoleWindow(), SW_HIDE); createTrackbar("TrackBar1", "befor", 0, 10,zoom_in); waitKey(0); } تابع createTrackBar: یک اسلایدربار را به یک پنجره متصل میکند ورودی اول نام اسلایدر بار ورودی دوم نام پنجره برای متصل شدن ورودی سوم حداقل مقدار اسلایدربار ورودی چهارم حداکثر مقدار ورودی پنجم یک رویداد برای اینکه اگر موقعیت اسلایدربار تعغیر کرد چه کاری صورت گیرد که اینجا ما میتوانیم به دو صورت این ورودی را بدهیم با موقعیت و دیتاهای کاربر که باید بصورت اشارگر باشد و در خود تابع به نوع مناسب تبدیل شود یا اینکه یک TrackbarCallback تعریف کرده همونطور که در کد میبینید و تابع را نوشته و تبدیل میکنیم که تابع ما ZoomIn است ورودی اخر این تابع دیتای های کاربر هست که به پارامتر void* user منتقل میشود در تابع ZoomIn دقت کنید که باید بعد از عملیات زوم image_read برابر با output_image قرار بگیرد تا در عملیات بعد سایز image_read که در پارامتر سوم مورد نیاز است برای زوم بعدی مورد استفاده قرار گیرد. حاصل اجرای کد بالا بصورت زیر خواهد بود: تابع pyrDown: برای بتوانیم تصویر رادور کنیم(ZoomOut) از این تابع استفاده میکنیم برای اینکه از سطر و ستون تصویر بکاهیم و تصویر را تا اندازه ی مشخص دور کنیم باید اینجا سطر و ستون تقسیم بر 2 شود که اگر به عنوان مثال ضرب در 2 شود تصویر نزدیک میشود در همان حالت اگر تصویر تقسیم بر 2 شود به حالت اولیه خود برمیگردد یک مثال از این تابع را مشاهده کنید: #include <opencv2\opencv.hpp> #include <Windows.h> #include <iostream> #include <stdio.h> #include <stack> using namespace cv; Mat output_image; Mat image_read; void Zoom_In() { pyrUp(image_read, output_image, Size(image_read.cols * 2, image_read.rows * 2)); imshow("Zoom In", output_image); image_read = output_image; } void Zoom_Out() { pyrDown(image_read, output_image, Size(image_read.cols / 2, image_read.rows / 2)); imshow("Zoom Out", output_image); image_read = output_image; } void ZoomIn_And_ZoomOut(int position, void* user) { std::cout << "Position: " << position << " " << " user data " <<(int)user<< std::endl; } int main() { void* userdata = (void*)10; TrackbarCallback zoom_in = (TrackbarCallback)Zoom_In; TrackbarCallback zoom_out = (TrackbarCallback)Zoom_Out; image_read = imread("C:\\Users\\Mohamad4030\\Desktop\\c9ac_d2ynkbk.jpg", IMREAD_COLOR); imshow("befor",image_read);//befor filtering ShowWindow(GetConsoleWindow(), SW_HIDE); createTrackbar("TrackBar1", "befor", 0, 10,zoom_in); createTrackbar("TracBar2", "befor", 0, 10, zoom_out); waitKey(0); } حاصل اجرای کد بالا بصورت زیر خواهد بود: تابع buildPyramid: کار تابع pyrDown راانجام میدهد این کار توسط پارامتر سوم صورت میگیرد فقط تنها نکته ای که وجود دارد پارامتر دوم این تابع یک InputOutputOfArray که منظورش یک ورودی و خروجی از ارایه است دریافت می کند یعنی باید یک ارایه ای دریافت کند که ورودی و خروجی ان فقط از همان ارایه باشد در دو تابع ذکر شده ما امدیم وبعد از عملیات تصویر اصلی را برابر تصویر که عملیات روی ان صورت گرفته قرار میدادیم تا در عملیات بعدی نتیجه مطلوب را دریافت کنیم اما در اینجا فقط با دادن مقداری که میخواهیم عملیات ZoomOut را انجام دهیم تصویر را دور میکند یک مثال از این تابع مشاهده کنید: #include <opencv2\opencv.hpp> #include <Windows.h> #include <iostream> #include <stdio.h> #include <stack> using namespace cv; Mat output_image; Mat image_read; /*void Zoom_In() { pyrUp(image_read, output_image, Size(image_read.cols * 2, image_read.rows * 2)); imshow("Zoom In", output_image); image_read = output_image; } void Zoom_Out() { pyrDown(image_read, output_image, Size(image_read.cols / 2, image_read.rows / 2)); imshow("Zoom Out", output_image); image_read = output_image; } void ZoomIn_And_ZoomOut(int position, void* user) { std::cout << "Position: " << position << " " << " user data " <<(int)user<< std::endl; }*/ int main() { vector<Mat> vecmat; image_read = imread("C:\\Users\\Mohamad4030\\Desktop\\c9ac_d2ynkbk.jpg", IMREAD_COLOR); buildPyramid(image_read, vecmat,4); for (int i = 0; i < vecmat.size(); i++) imshow("ZoomIn"+i, vecmat[i]); ShowWindow(GetConsoleWindow(), SW_HIDE); waitKey(0); } دقت کنید که کلاس vector از خود کتابخانه ی OpenCV است و باید از همین کلاس برای این تابع استفاده کنید جز این با خطا مواجه میشوید. حاصل اجرای کد بالا بصورت زیر است:
-
2 امتیاز
-
2 امتیازقوانین و قالب اصول نگارشی در مرجع آی او استریم نسخهٔ 1.3.0 با توجه به اهداف مرجع، ارائه اسناد و محتوای معتبر رعایت اصول صحیح نگارشی در ترجمه، بازنشر و دیگر شرایط تولید محتوا نیاز است. بنابراین برای یادگیری شیوه نگارش و نحوهٔ صحیح نوشتن شما میتوانید شیوهٔ صحیح نوشتن و استفاده از علائم نگارشی را بیاموزید. متن زیر بر همین اساس آماده شده است و به مرور زمان تکمیل خواهد شد. توجه داشته باشید که شرایط زیر در سراسر سیستم نرمافزاری که شامل ماژولهای مختلفی چون (خبر، وبلاگ، پادکست، مستندات و ...) میشود. و عدم رعایت آن موجب عدم تایید و حتی لغو مقاله شما خواهد گردید. قبل از هر چیز به نمونه مثال زیر توجه کنید: عنوان آزمایشی متن (انتخاب سر نویس ۳) این متن آزمایشی است جهت نمایش یک پاراگراف از اندازه، چیدمان و دیگر موارد نگارشی که بدون اعمال هیچ گونه اندازه و سر نویسی نوشته شده است. برای اینکه پاراگرافهای زیب و یکدست در سرتاسر وب سایت داشته باشیم لازم است این قانون را رعایت نماییم. با توجه به اهداف مرجع ممکن است در آموزشهای شما در میان متن فارسی از متن انگلیسی یا کدهای برنامه نویسی استفاده کنید که برای مثال : کتابخانه STL یک کتابخانهٔ استاندارد کتابخانهای با نام iostream وجود دارد که با تکه کد #include <iostream> وارد میشود. برای حل این مشکل آن تگ < > کد را بر روی نوشته خود اعمال کنید#include <iostream>نتیجه به صورت یک تکه کد درون خطی نمایش داده میشود. در برخی موارد کاراکترهای خاص مانند C++ لازم است به صورت صحیح نوشته شود، معمولاً برای این کار آن را به صورت برعکس مینویسد اما این کار پیشنهاد نمیشود چرا که در بحث سئو تاثیر منفی خواهد گذاشت. ما برای حل این مشکل یک افزونه با عنوان L در نظر گرفته ایم که میتوانید کاراکترهای خود را انتخاب کنید و آن را بر روی آن اعمال نمایید. مثال : زبان برنامهنویسی C++ بدون اعمال تگ L مثال : زبان برنامهنویسی C++ تگ L اعمال شده است بنابراین نکاتی که همه ما به آن در تولید محتوا توجه میکنیم به صورت زیر هستند: قبل از شروع نگارش فارسی به «راست چین بودن» محیط ویرایشگر توجه میکنیم. برای نگارش صحیح فارسی از صفحه کلید استاندارد فارسی در ویندوز و گنو/لینوکس و مک استفاده میکنیم. این صفحه کلید به صورت پیشفرض در سیستم عامل گنو/لینوکس و مک نصب است. همینطور در نسخههای جدید ویندوز(از ۸ و به بعد) قابل فعالسازی در این سیستم عامل نیز است. در جملات از «میباشد» و «نمیباشد» استفاده نمیکنیم. معادل این کلمات به ترتیب «است» و «نیست» است. معادل واژهها بسیار مهم هستند، برای مثال کیبورد معادلش در فارسی صفحهکلید است و بهتر است از معادل فارسی استاندارد استفاده شود. در نگارش صحیح فارسی هیچگاه پیشوندها و پسوندها به صورت چسبیده نوشته نمیشوند. مثلاً: نمیشوند، میروم، جنگلها، پرندهگان، طراحیها، آنها و… همگی غلط هستند. برای نوشتن پیشوندها و پسوندها به صورت جداگانه، چنانچه حروف دو بخش به صورت پیشفرض احتمال چسبیدن به هم را داشته باشند برای جداسازی آنها از نیم فاصله استفاده میکنیم. مثلاً: نمیشود، میشود، توسعهدهنده، برنامهنویس، کسبوکار، میرسم، نمیخورم، گلهها، سبزهزارها، طراحیها، آنها و… همگی درست هستند. برای درج نیم فاصله در صفحه کلید استاندارد فارسی از Shift + Space که تقریبا در تمامی سیستمعاملها همین ترکیب را دارد استفاده میکنیم. در هنگام استفاده از کاراکترها (نظیر . ! ؟ ، … : ؛) باید به این نکته توجه کرد که آنها بدون هیچ فاصلهای به کلمه قبل از خود میچسبند. همینطور پس از آنها همیشه یک فاصله وجود دارد. چنانچه در متن از کلمات و یا عباراتی به زبانی دیگر استفاده شده بود حتماً در نخستین جایی که از آن کلمات و یا عبارات استفاده میکنیم باید معادل آن به زبان اصلی در درون پرانتز و بلافاصله پس از استفاده درج شود. مثلاً جملات زیر را در نظر بگیرید: پردازنده و رم (RAM) رایانه حتماً باید با هم سازگاری داشته باشند. زبان برنامهنویسی سیپلاسپلاس (++C) و فناوری کیوت کوئیک (Qt Quick). جی. کی. رولینگ (J. K. Rowling) خالق مجموعه داستانهای هری پاتر (Harry Potter) در مصاحبه اخیر خود با بی بی سی (BBC) از قصد خود در خصوص نوشتن سری جدیدی از داستانها خبر داد. نوروزبل (نؤرۊزبل) عید باستانی مردم خطه کاسپین است. به هیچ عنوان هیچ یک از اصطلاحات علمی را به فارسی نباید ترجمه و باز نشر کنیم، برای مثال : فناوری کیوت کوئیک (فناوری کیوت سریع) این غلط است. چنانچه در متن از کلمات و یا عبارتی به زبان فارسی استفاده شود که معادل غیر فارسی آن مفهوم را به شکل بهتری برساند، معادل غیر فارسی در هنگام نخستین استفاده در درون پرانتز نوشته میشود. مثلاً جملات زیر را در نظر بگیرید: راهنمای فایل (File Directory) یکی از روشهای رایج دسترسی به فایلها در سیستم عاملها است. طراحی رابط کاربری (UI) و تجربه کاربری (UX) دو مقوله جدا از هم هستند. چنانچه در متن از عبارات مخفف (فارسی و یا غیر فارسی) استفاده کرده باشیم در نخستین استفاده حتماً باید عبارت کامل در درون پرانتز درج شود. مثلاً جملات زیر را در نظر بگیرید: جهت استفاده از کتابخانههایی چون Qt باید (سطوح مقدماتی و متوسط زبان برنامهنویسی ++C) را به خوبی پشت گذاشته باشید. جَک JAC (Jangal Accounts)) سیستم یکپارچهای برای مدیریت حسابهای کاربری در سرویسهای گوناگون است که توسط شرکت جنگل ساخته شده و مورد استفاده قرار میگیرد. هرگاه در متن نیاز به درج توضیحات تکمیلی باشد از پرانتز استفاده میکنیم. مثلا: داتویوز (شرکت داتویوز (Dotwaves) با (مسئولیت محدود)) بزرگترین تولید کننده نرمافزار در شمال غرب کشور است. متن باید دارای افعالی یکپارچه باشد. این بدان معناست که فعلهای خبری متن همگی باید دارای یک نقش باشند. مثلاً اگر در حال نوشتن متن دستور پخت یک غذا باشیم، عبارت زیر غلط خواهد بود: برای طراحی یک نرمافزار تحت کیوت ابتدا باید محیط توسعه را نصب و راه اندازی کرد. سپس تحت زبان برنامهنویسی ++C و فناوری Qt Quick آن را طراحی و توسعه میدهیم. متن باید دارای لحنی یکپارچه باشد. مثلاً اگر در قسمتی از متن از زبان محاوره استفاده کردیم در جای دیگر نباشد از زبان کتابی صحبت کنیم. مثلاً ۲ جمله اول هر دو درست هستند ولی جمله سوم غلط است. قراره من در این آموزش برای شما بگم که چطور در رابطه با برنامهنویسی سطح پایین دانشتان را ارتقا دهید! (غلط) قراره من در این آموزش برای شما بگم که چطور در رابطه با برنامهنویسی سطح پایین دانشتون رو ارتقا بدین (صحیح) قرار است من در این آموزش برای شما نحوه ارتقا دانشتان در برنامهنویسی سطح پایین را توضیح دهم. (صحیح) در متن هرجا که لازم باشد به مهم بودن بخشی خاص اشاره شود آن را بلد (Bold) میکنیم. مثال: آوردن ماشین حساب در امتحان ریاضی مهندسی ممنوع نیست. در پاراگرافهای موجود در متن باید سعی شود که تا جایی که امکان دارد در جملات پشت سر هم از کلمات یکسان استفاده نشود. مثلاً متن زیر به خاطر تکرار کلمات یکسان (در این مثال جاوا اسکریپت و است) متن زیبایی نیست: جاوا اسکریپن یک زبان پر طرفدار است. جاوا اسکریپت پر کاربرد ترین زبان در لایه رابط کاربری است. جاوا اسکریپت ملقب به نام «JS» است. چنانچه در متن بخواهیم یکپارچگی عبارتی را نشان دهیم آن را درون «» قرار میدهیم. این کار برای سهولت خواندن متن انجام میشود. چنانچه در متن بخواهیم که جملهای را نقل قول کنیم آن را در درون «» قرار میدهیم. اگر متن نقل قول شده بیشتر از یک جمله بود به غیر از استفاده از علامت فوق از فونتی کوچکتر و یا اتالیک (Italic) استفاده میشود. البته برای راحتی کار و یکسان بودن بهتر است بر روی دکمه قالب روی ویرایستار کلیک کرده و از بخش بلوک (بلوک نقل قول) را انتخاب کنید. در محیط وب اگر در متن از کلمات و یا عباراتی استفاده شود که توضیحاتی مفصل از آن در جایی دیگر موجود باشد، آن کلمات و یا عبارات را به همان جایی که توضیحات مفصل آن وجود دارد پیوند (Link) میکنیم. در هنگام لینک کردن عبارات در وب چنانچه لینک مورد نظر خارج از آدرسی خارج از سایت خودمان باشد حتماً باید لینک در تبی (Tab) جداگانه باز شود. در هنگام لینک کردن عبارات حتماً برای آن عنوانی (Title) در نظر میگیریم. این عنوان زمانی که ماوس بر روی لینک قرار بگیرد نمایش داده میشود. این عنوان باید متنی باشد که توضیحات بیشتر را در مورد لینک بدهد. مثلاً اگر کلمه رشت را به صفحه ویکیپدیا فارسی رشت لینک کردهایم یکی از عنوانهای مناسب میتواند «در مورد رشت در ویکیپدیا فارسی بیشتر بخوانید.» باشد. چنانچه در محیط وب متنی را از جایی نقل و قول (و یا کپی) کردیم حتماً باید در صفحه خودمان به آن مطلب لینک بدهیم. این لینک میتواند درون متنی باشد و یا اینکه در انتهای متنمان به عنوان منبع ذکر شود. در وب چنانچه مایل به استفاده از تصاویر در متنمان بودیم حتماً مسأله اندازه (حجم)آن را در نظر میگیریم. معمولاً از تصاویر با حجم پایین در درون متن استفاده میشود و اگر لازم بود که خواننده به تصویر با اندازه اصلی دسترسی داشته باشد معمولاً این تصویر به تصویر کم حجم موجود در متن لینک میشود. در نوشتن مطالب از فونتهای عجیب و غیر استاندارد و یا اندازههای بسیار بزرگ/کوچک استفاده نمیکنیم. هر چند فونتهای استاندارد بر روی ویرایستار تعبیه شده است اما همینطور حتیالامکان رنگها و فونت و اندازههای پیشفرض را تغییر نمیدهیم. (مگر اینکه واقعاً در مواردی خاص نیاز به این کار باشد.) کاراکترهای اعداد در زبان فارسی با زبانهایی نظیر انگلیسی و عربی کاملاً متفاوت است. در نگارش فارسی فقط و فقط از کاراکترهای فارسی اعداد استفاده میکنیم. این کاراکترها ۱۲۳۴۵۶۷۸۹۰ هستند. تنها زمانی مجاز به استفاده از کاراکترهای اعداد انگلیسی و عربی هستیم که در حال ذکر معادلهای غیر فارسی باشیم. مثلا: فایل ام پی تری (MP3) یکی از فرمتهای رایج موسیقی است. ام فور (M4) یکی از اسلحههای رایج بازی کانتر است. در لیستها اعداد شمارهگذاری را به صورت دستی وارد نمیکنیم! برای این کار از ابزار تعبیه شده در محیط نگارش استفاده میکنیم. (همینطور در لیستهای غیر مرتب نیز کاراکترهای شروع کننده پاراگراف را دستی وارد نمیکنیم.) در نگارش جدید فارسی از ی مالکیت استفاده نمیشود. مثلاً عبارات زیر همگی غلط هستند: خانهٔ ما علاقهٔ مفرط پذیرندهٔ جدید برخی از کاراکترها نظیر ی و ک در فارسی متفاوت با عربی است. در نگارش فارسی دقت میکنیم که از کاراکترهای عربی استفاده نکنیم. برای خوانایی متن و بالا بردن درک مطلب از پاراگراف استفاده میکنیم. هر پاراگراف متشکل از یک یا چند جمله است که نزدیکی محتوایی دارند. پس از اتمام پاراگراف فارغ از اینکه جمله نهایی در کجا به پایان رسیده است به خط بعدی میرویم. پس از انتشار مطلب در محیط وب چنانچه پس از گذشت مدتی طولانی قسمتی از متن با حقایق روز متفاوت بود بر روی آن خط میکشیم. همچنین اگر لازم بود بخشی را به عنوان اصلاحیه اضافه میکنیم. متن زیر را در نظر بگیرید: سیستم عامل مَک او اِس ایکس (Mac OS X) در حال حاضر جدیدترین سیستم عامل ساخته شده توسط شرکت اپل (Apple) است. یکی از ویژگیهای جدید افزوده شده به این سیستم عامل ظاهر بسیار زیبای آن است. حال این متن را پس از گذشت چند سال به شکل زیر تغییر میدهیم: سیستم عامل مَک او اِس ایکس (Mac OS X) در حال حاضر جدیدترین سیستم عامل ساخته شده توسط شرکت اپل (Apple) است. (در حال حاضرسیستم عامل مَک او اِس سییرا (macOS Sierra) جدیدترین سیستم عامل اپل است.) یکی از ویژگیهای جدید افزوده شده به این سیستم عامل ظاهر بسیار زیبای آن است. اگر در متن در حال توضیح موضوع خاصی هستیم بهتر است که در جاهایی از معادلهای مترادف آن موضوع استفاده کنیم. مثلاً اگر در حال معرفی یک نرمافزار هستیم میتوانیم برای اشاره به آن از کلماتی نظیر نرم افزار، برنامه، اپ و اپلیکیشن استفاده کنیم. به طور کلی در متن از کلمات و عباراتی که از زبان دیگری آمدهاند استفاده نمیکنیم ولی این مسأله نباید باعث کاهش خوانایی و مفهوم متن شود. ساده نویسی یکی از اصول اصلی نگارش است. اینکه از چه مجموعه از کلمات و عباراتی در متنمان استفاده کنیم بستگی به سطح خوانندگانمان دارد. مثلاً اگر در حال نوشتن یک متن برای برنامه نویسان هستیم به راحتی میتوانیم از کلماتی نظیر UX و UI و.. استفاده کنیم ولی استفاده از این کلمات در یک متن عمومی توصیه نمیشود و در صورت استفاده حتماً باید معانی آنها به صورت کامل در درون پرانتز و یا پاورقی درج شود. روش ارسال کد در قالب مناسب برای درک بهتر مطلب توسط ابزار <> در صورتی که مقاله، سند یا مطلب خاصی را منتشر میکنید که دارای تکه کدی است آن را در داخل تگ کد قرار میدهیم که نمونه مثالهای آن به صورت زیر نمایان خواهند شد: نمونه مثال خروجی کد C //A Hello World! program in C. #include <stdio.h> int main() { // printf() displays the string inside quotation printf("Hello, World!"); return 0; } نمونه مثال خروجی کد ++C // A Hello World! program in C++. #include <iostream> using namespace std; int main() { cout << "Hello, World!"; return 0; } نمونه مثال خروجی کد در Java //A Hello World! program in Java. public class HelloWorld { public static void main( String[] args ) { System.out.println( "Hello World!" ); System.exit( 0 ); //success } } نمونه مثال خروجی کد در JavaScript // A Hello World! program in JavaScript. const btn = document.getElementById('button'); btn.addEventListener('click', function() { alert('Hello World!'); نمونه مثال خروجی کد در QML // A Hello World! program in QML. import QtQuick 2.0 Rectangle { id: page width: 320; height: 480 color: "lightgray" Text { id: helloText text: "Hello world!" y: 30 anchors.horizontalCenter: page.horizontalCenter font.pointSize: 24; font.bold: true } } نمونه مثال خروجی کد در PHP // A Hello World! program in PHP. $text = "Hello, World!"; $x = 5; $y = 4; echo "<h2>" . $text . "h2><br>"; echo $x + $y; نمونه مثال خروجی کد در Node.JS // A Hello World! program in Node.JS const express = require('express') const app = express() app.get('/', (req, res) => res.send('Hello World!')) app.listen(3000, () => console.log('Example app listening on port 3000!')) نمونه مثال خروجی کد در CSS p { text-align: center; color: red; } نمونه مثال خروجی کد در #C // A Hello World! program in C#. using System; namespace HelloWorld { class Hello { static void Main() { Console.WriteLine("Hello World!"); // Keep the console window open in debug mode. Console.WriteLine("Press any key to exit."); Console.ReadKey(); } } } نمونه مثال خروجی کد در Ruby #!/usr/bin/ruby print "Hello, World!\n" نمونه مثال خروجی کد در Python # This program prints Hello, world in Python! print('Hello, world!') و اما یک نکتهی اساسی در نشر محتوا این است که برای مخفی نگه داشتن بخشی از پاسخها که نیاز نیست برای همه قابل نمایش باشد از گزینه اسپویلر یا همان مخفی کردن با علامت چشم بر روی ادیتور استفاده میکنیم تا محتوا به صورت همین نمونه نمایان شود.