ORANGEPRO

ORANGEPRO

فناوری آینده رو ما به پیش می بریم....
ORANGEPRO

ORANGEPRO

فناوری آینده رو ما به پیش می بریم....

رفع خطا در C++-2

[Warning] overflow in conversion from 'int' to 'std::map<char, char>::mapped_type' {aka 'char'} changes value from '55463' to '-89' [-Woverflow] 

این خطا یعنی چی ؟

این خطای [Warning] overflow in conversion from 'int' to 'char' یک هشدار جدی در مورد مدیریت حافظه و بازه اعداد (Range) است. بیاییم این مسئله را به صورت دقیق و فنی کالبدشکافی کنیم.


تحلیل فنی خطا
در سی‌plus-plus، نوع داده char معمولاً یک سایز (1 byte) دارد و بازه عددی آن (اگر signed باشد) بین 127- تا 127 است.
در کد خود سعی کرده‌اید  یک عدد بسیار بزرگ یعنی 55463 را در یک متغیر از نوع char (که در اینجا مقدار mapped_type در std::map<char, char> است) ذخیره کنی.
چه اتفاقی افتاده است؟
وقتی عدد 55463 را به char تبدیل می‌کنی، چون این عدد از ظرفیت (Capacity) یک بایت فراتر رفته، رخ دادن یک پدیده به نام Integer Overflow (بیش‌سرریز) باعث می‌شود که سیستم فقط بیت‌های پایین‌تر (Lower bits) آن را نگه دارد.
اگر محاسبات را از نظر باینری بررسی کنیم:
    عدد 55463 در سیستم باینری (به صورت 16بیتی) برابر است با: 11011001 10111111
    چون char فقط ? بیت می‌گیرد، سیستم فقط 8بیت سمت راست را برمی‌دارد: 10111111
    در سیستم علامت‌دار (Signed) برای char (که بیت اول نشان‌دهنده علامت است)، مقدار 10111111 برابر با 89- می‌شود.

به همین دلیل کامپایلر به تو می‌گوید:
    “مقدار از 55463 به 89- تغییر کرد.”


کجای کد مشکل دارد؟

با توجه به فایل Test.cpp که فرستادی، احتمالاً کدی شبیه به این داری:

myMap['a'] ='گ';   در این صورت من خطا میگیرم


یا شاید در حال استفاده از یک مقدار عددی به عنوان “مقدار” (Value) در مپ هستی که قرار بوده کد اسکی (ASCII) باشد، اما به اشتباه یک عدد بزرگ به آن پاس داده شده است.
راه‌حل‌های پیشنهادی (Solutions)

اگر قرار است فقط کاراکترهای استاندارد (ASCII) ذخیره شوند:
باید بررسی کنی که چرا عدد 55463 تولید می‌شود. احتمالاً در محاسبات منطقی یا در حلقه‌ات (Loop) یک خطا وجود دارد که باعث می‌شود یک ایندکس یا مقدار محاسباتی از محدوده استاندارد خارج شود.
 استفاده از unsigned char (اگر نیاز به بازه مثبت داری):
اگر مقادیر تو بین 0 تا 255 هستند، از unsigned char استفاده کن. اما باز هم عدد 55463 بسیار بزرگتر از 255 است و باز هم با Overflow مواجه می‌شوی.
این خطا یعنی تو داری سعی می‌کنی یک “غول” (عدد بزرگ) را در یک “جعبه کوچک” (char) جا بدهی! جعبه از شدت فشار تغییر شکل می‌دهد و محتویاتش (مقدار عددی) کاملاً تغییر می‌کند.
تحلیل ریشه‌ای مشکل (The Root Cause)
دلیل اصلی این است که نوع داده char در C++ به شدت محدود است. در اکثر سیستم‌ها، char فقط 8-bit است و می‌تواند فقط یک کاراکتر از خانواده ASCII یا Extended ASCII را ذخیره کند.
کاراکتر ‘گ’ جزو کاراکترهای چندبایتی (Multi-byte) است. در استاندارد UTF-8 (که استاندارد جهانی برای نمایش متون است)، کاراکترهای فارسی معمولاً 16بایت یا بیشتر فضا اشغال می‌کنند.

وقتی تو می‌نویسی myMap['a'] = 'گ';

    کامپایلر سعی می‌کند کاراکتر ‘گ’ را که مثلاً دو بایت است (مثلاً 0xD8 0xAF در UTF-8)، در یک ظرف یک‌بایتی (char) جا دهد.
    این باعث می‌شود فقط بایت اول (یا بخشی از آن) برداشته شود که یک عدد بزرگ (مثل همان 55463 که در خطای قبلی دیدی) ایجاد می‌کند.
    در نتیجه، آن عدد بزرگ سعی می‌کند در char ذخیره شود و با خطای Overflow مواجه می‌شوی.

بسته به اینکه پروژه تون چقدر حساس است، سه راه پیش رو داری:

 استفاده از wchar_t (راه سریع برای تست)
اگر می‌خواهی فقط با کاراکترهای پهن (Wide characters) کار کنی، باید از wchar_t استفاده کنی که فضای بیشتری برای ذخیره کاراکترها دارد.
cpp
#include <iostream>
#include <map>

int main() {
    // استفاده از wchar_t به جای char
    std::map<wchar_t, wchar_t> myMap;

    // استفاده از L قبل از کاراکتر برای نشان دادن Wide Character
    myMap[L'a'] = L'گ';

    std::wcout << L"Value: " << myMap[L'a'] << std::endl;
    return 0;
}

 استفاده از std::string به جای char (بهترین راه برای پروژه‌های واقعی)

به عنوان یک توسعه‌دهنده، این روش را به شدت توصیه می‌کنم. در دنیای مدرن، ما کاراکترهای فارسی را به عنوان یک “رشته” (String) می‌بینیم، نه یک کاراکتر تک‌بایتی. std::string می‌تواند رشته‌های UTF-8 را که شامل چندین بایت هستند، به راحتی ذخیره کند.
cpp
#include <iostream>
#include <map>
#include <string>
int main() {
    // کلید و مقدار هر دو از نوع string باشند
    std::map<std::string, std::string> myMap;
    myMap["a"] = "گ"; // استفاده از کوتیشن دوتایی برای رشته
    std::cout << "Value: " << myMap["a"] << std::endl;
    return 0;
}

نکته: در این حالت، std::string تمام بایت‌های مربوط به کاراکتر ‘گ’ را به درستی در خود نگه می‌دارد و دیگر خبری از Overflow نیست.


خلاصه تغییرات:
    تغییر std::map<char, char> به std::map<std::string, std::string>.
    استفاده از " " (Double Quotes) به جای ' ' (Single Quotes).

لیست محبوب‌ترین زبان‌های برنامه‌نویسی در بین دولوپرهای خانم

لیست محبوب‌ترین زبان‌های برنامه‌نویسی در بین دولوپرهای خانم گزارشی تحت عنوان زنان در حوزه تکنولوژی در سال 2018 منتشر شد که در آن بیش از 14000دولوپر حرفه‌ای مشارکت داشتند و از میان ایشان حدود 2000نفر خانم بودند. در راستای مشاهده  تغییرات جالبی که در صنعت تکنولوژی در حال شکل‌گیری است،اجازه دهید لیستی از زبان‌های برنامه‌نویسی را که بیشتر دولوپرهای خانم از آن‌ها استفاده می‌کنند، بررسی کنیم:

1. Java
2. JavaScript
3. C
4. C++
5. Python
6. PHP
7. C#
8. Ruby
9. R
10. Perl
11. TypeScript
12. Swift
13. Scala
14. Go
15. Haskell

توابع پرکاربرد در C++-9

clearviewport :
 clearviewport در زبان C++ مستقیماً به عنوان یک تابع یا کلمه کلیدی استاندارد وجود ندارد. اما در چارچوب‌های گرافیکی یا بازی‌سازی (مانند OpenGL، DirectX، یا موتورهای بازی مثل Unity و Unreal Engine)، این مفهوم به پاک کردن یا بازنشانی ناحیه نمایش (viewport) اشاره دارد.
به طور خلاصه، clearviewport در این بافت‌ها به معنای پاک کردن بافر رنگ و/یا عمق با یک رنگ یا مقدار مشخص است تا بتوان صحنه جدیدی را در آن ترسیم کرد. این کار قبل از شروع رندر کردن فریم جدید انجام می‌شود تا از تداخل تصاویر قبلی با تصویر جدید جلوگیری شود.

linerel :
 linerel به صورت مستقیم یک تابع یا مفهوم استاندارد در زبان C++ یا کتابخانه‌های رایج آن نیست. احتمالاً منظور شما یکی از موارد زیر است:
    line (تابع ترسیم خط): در کتابخانه‌های گرافیکی مانند BGI (Borland Graphics Interface) یا OpenGL، تابعی به نام line یا مشابه آن وجود دارد که برای ترسیم یک خط مستقیم بین دو نقطه استفاده می‌شود.
    یک تابع سفارشی: ممکن است linerel نام یک تابع سفارشی در پروژه‌ای باشد که شما با آن کار می‌کنید و وظیفه‌ی آن ترسیم خطی با توجه به یک موقعیت نسبی (relative) باشد.در هر صورت، این تابع یا مفهوم به ترسیم یک خط مستقیم در محیط گرافیکی اشاره دارد.


converttorgb :
 converttorgb به طور کلی به فرآیند تبدیل یک مقدار رنگی از یک فرمت (مانند HSL، HSV، CMYK، یا کد هگزادسیمال) به فرمت RGB (قرمز، سبز، آبی) اشاره دارد. این تبدیل برای نمایش رنگ‌ها در صفحه نمایش یا استفاده در توابع گرافیکی که ورودی RGB می‌پذیرند، ضروری است.


getdisplaycolor :
 getdisplaycolor به طور کلی به تابعی اشاره دارد که رنگ نمایش داده شده در یک پیکسل خاص روی صفحه نمایش را برمی‌گرداند. این تابع معمولاً در برنامه‌هایی که نیاز به تحلیل یا تعامل با رابط کاربری گرافیکی (GUI) دارند، استفاده می‌شود.

palettetype *getdefaultpalette:
 PaletteType *getdefaultpalette( ); در C++ به یک تابع اشاره دارد که یک اشاره‌گر به یک ساختار داده از نوع PaletteType را برمی‌گرداند که نمایانگر پالت رنگ پیش‌فرض سیستم یا برنامه است.

رفع خطا در C++-1

    [Error] expected primary-expression before '<<' token

 این خطا معمولاً به این معنیه که کامپایلر در جایی که انتظار یه “عبارت” (expression) رو داشته، یه توکن << دیده و نمی‌دونه چطور اون رو تفسیر کنه. این معمولاً به خاطر یکی از این دلایل اتفاق می‌افته:
    جای اشتباه <<: گاهی اوقات << رو جایی گذاشتی که نباید باشه، مثلاً بعد از یه دستور if یا for بدون اینکه دستور کامل باشه، یا بین دو عبارت که نباید با هم ترکیب بشن.
    سینتکس اشتباه در cout: شاید یه خطای تایپی در استفاده از cout یا توکن << وجود داشته باشه. مثلاً ممکنه یه << اضافه یا کم گذاشته باشی، یا قبل از << یه نیم‌کُلون (;) قرار گرفته باشه.

 ترکیب اشتباه عبارات: مثلاً اگر بخوای یه متغیر رو با یه رشته ترکیب کنی، باید حواست به سینتکس باشه.

TRY CATCH در C++

بلوک try-catch در C++ برای مدیریت استثناءها (Exceptions) استفاده می‌شود. این مکانیسم به شما اجازه می‌دهد که کدی را که ممکن است باعث خطا یا استثناء شود، در یک محیط کنترل‌شده اجرا کنید و در صورت وقوع خطا، برنامه به جای کرش کردن، بتواند به صورت کنترل‌شده به خطا واکنش نشان دهد.

ساختار کلی به این صورت است:

    try: کدی که احتمال وقوع استثناء در آن وجود دارد، درون بلوک try قرار می‌گیرد.
    catch: اگر استثنایی در بلوک try رخ دهد، اجرای آن متوقف شده و کنترل به بلوک catch مربوطه منتقل می‌شود. شما می‌توانید چندین بلوک catch برای مدیریت انواع مختلف استثناءها داشته باشید.


#include <iostream>
#include <stdexcept> // برای std::runtime_error

int main() {
    int numerator = 10;
    int denominator = 0;
    int result;

    try {
        if (denominator == 0) {
            // پرتاب یک استثناء از نوع runtime_error
            throw std::runtime_error("Error: Division by zero is not allowed.");
        }
        result = numerator / denominator;
        std::cout << "Result: " << result << std::endl; // این خط اجرا نخواهد شد
    }
    catch (const std::runtime_error& e) {
        // مدیریت استثناء
        std::cerr << "Caught exception: " << e.what() << std::endl;
    }
    catch (...) {
        // مدیریت هر استثناء دیگری که نوع آن مشخص نشده باشد (Catch-all)
        std::cerr << "Caught an unknown exception." << std::endl;
    }

    std::cout << "Program continues execution." << std::endl;
    return 0;
}


نکات کلیدی:

    throw: کلمه کلیدی است که برای ایجاد (پرتاب کردن) یک استثناء استفاده می‌شود.
    انواع استثناء: می‌توانید انواع مختلفی از استثناءها را پرتاب و مدیریت کنید، مانند:
    استثناءهای استاندارد کتابخانه (مانند std::out_of_range, std::invalid_argument).
    کلاس‌های استثناء سفارشی که از کلاس پایه std::exception ارث‌بری می‌کنند.
    catch(...): این یک گیرنده عمومی است که هر نوع استثنایی را که قبلاً توسط گیرنده‌های خاص مدیریت نشده باشد، می‌گیرد. بهتر است این را همیشه به عنوان آخرین catch قرار دهید.
    اجرای کد پس از خطا: پس از مدیریت موفقیت‌آمیز یک استثناء در بلوک catch، اجرای برنامه از ادامه‌ی بلوک try-catch (بعد از آخرین catch) دنبال می‌شود، نه از ابتدای بلوک try.

توابع پرکاربرد در C++-8

تابع sleep() یکی از مفاهیم بنیادی در برنامه‌نویسی هم‌روند (Concurrent Programming) و مدیریت زمان در سیستم‌عامل‌هاست.


تشریح تابع sleep() در C/C++
تابع sleep() برای متوقف کردن اجرای یک ریسه (Thread) یا فرآیند (Process) برای یک مدت زمان مشخص استفاده می‌شود. این کار باعث می‌شود که منابع CPU به طور موقت آزاد شده و برای کارهای دیگر در دسترس قرار گیرند.
۱. استانداردها و کتابخانه‌ها
نحوه استفاده از sleep() بستگی به سیستم‌عامل و استانداردی دارد که از آن استفاده می‌کنید:
    استاندارد POSIX (سیستم‌های شبه یونیکس مانند لینوکس و macOS):
    تابع: sleep(unsigned int seconds)
    کتابخانه: <unistd.h>
    واحد زمان: ثانیه (integer).

    استاندارد ویندوز (Windows API):
    تابع: Sleep(DWORD dwMilliseconds)
    کتابخانه: <windows.h>
    واحد زمان: میلی‌ثانیه (DWORD یک عدد صحیح بدون علامت ۳۲ بیتی است).

    استاندارد C++ مدرن (C++11 به بعد):

    توصیه می‌شود از این روش استفاده کنید چون پلتفرم-مستقل (Platform-Independent) است.
    تابع: std::this_thread::sleep_for(const chrono::duration& rel_time)
    کتابخانه: <thread> و <chrono>
    واحد زمان: هر واحد زمانی دلخواه (مثلاً نانوثانیه، میکروثانیه، میلی‌ثانیه) که توسط std::chrono::duration مشخص می‌شود.

۲. مکانیسم کارکرد (در سطح سیستم‌عامل)

هنگامی که یک ریسه تابع sleep() را فراخوانی می‌کند، هسته سیستم‌عامل (Kernel) کار زیر را انجام می‌دهد:
    انتقال به حالت انتظار (Waiting State): ریسه فراخواننده از لیست ریسه‌های “آماده اجرا” (Runnable) خارج شده و به لیست ریسه‌های “در انتظار” (Waiting/Sleeping) منتقل می‌شود.
    آزادسازی زمان‌بند: زمان‌بند سیستم‌عامل (Scheduler) متوجه می‌شود که این ریسه فعلاً نیازی به منابع CPU ندارد و می‌تواند به ریسه‌های آماده دیگر فرصت اجرا دهد.
    تایمر و بیدار شدن: هسته یک شمارنده زمانی داخلی برای آن ریسه تنظیم می‌کند. پس از سپری شدن مدت زمان مشخص شده، هسته ریسه را از حالت انتظار خارج کرده و آن را به لیست “آماده اجرا” برمی‌گرداند.


. تفاوت با تأخیر فعال (Busy Waiting)

تأخیر فعال (Active Waiting/Busy Waiting): شامل حلقه‌هایی است که به طور مداوم شرطی را بررسی می‌کنند .

   while (true) {
    // CPU به طور مداوم در اینجا مشغول چک کردن است.
}
این روش باعث می‌شود CPU ۱۰۰٪ برای یک کار بی‌فایده مصرف شود.

استفاده از sleep(): این تابع به ریسه اجازه می‌دهد تا کاملاً از اجرای CPU خارج شود و تنها زمانی مجدداً فعال شود که زمان مقرر فرا برسد. این رویکرد بسیار کارآمدتر و استاندارد است، خصوصاً در سیستم‌های چندوظیفه‌ای (Multitasking).



نماد (n)O بزرگ چیست؟

Big O Notation یک ابزار ریاضی برای توصیف نحوه رشد (Scaling) زمان اجرای یک الگوریتم (یا مصرف حافظه آن) با افزایش حجم ورودی (nn) است. به زبان ساده، این نماد به ما می‌گوید که الگوریتم چقدر “کند” می‌شود وقتی ورودی آن خیلی بزرگ می‌شود.

نکته کلیدی: Big O بر بدترین حالت (Worst-Case Scenario) تمرکز دارد و با نادیده گرفتن ضرایب ثابت (Constants) و مراتب پایین‌تر (Lower Order Terms)، صرفاً بر روی مرتبه غالب (Dominant Term) تمرکز می‌کند. این کار باعث می‌شود بتوانیم الگوریتم‌ها را بر اساس مقیاس‌پذیری آن‌ها مقایسه کنیم، بدون اینکه وابسته به سخت‌افزار خاصی باشیم.


چرا O(n) خوب است؟

در پروژه‌هایی با داده‌های حجیم (Big Data) یا سیستم‌های بلادرنگ (Real-Time Systems) مانند رباتیک، ما همیشه به دنبال الگوریتم‌هایی با پیچیدگی پایین هستیم. O(n)معمولاً نشان‌دهنده یک الگوریتم بسیار کارآمد است، زیرا اجرای آن با افزایش حجم داده‌ها قابل پیش‌بینی و کنترل باقی می‌ماند.