<?xml version="1.0"?>
<rss version="2.0"><channel><title>&#x635;&#x641;&#x62D;&#x647; &#x627;&#x635;&#x644;&#x6CC;: برنامه نویسی</title><link>https://sinajalalvandi.ir/blog/programming/page/2/?d=6</link><description>&#x635;&#x641;&#x62D;&#x647; &#x627;&#x635;&#x644;&#x6CC;: برنامه نویسی</description><language>fa</language><item><title>&#x632;&#x646;&#x62C;&#x6CC;&#x631;&#x647; &#x627;&#x62E;&#x62A;&#x6CC;&#x627;&#x631;&#x6CC; (Optional Chaining) &#x62F;&#x631; &#x62C;&#x627;&#x648;&#x627; &#x627;&#x633;&#x6A9;&#x631;&#x6CC;&#x67E;&#x62A;: &#x627;&#x646;&#x642;&#x644;&#x627;&#x628;&#x6CC; &#x62F;&#x631; &#x62F;&#x633;&#x62A;&#x631;&#x633;&#x6CC; &#x628;&#x647; &#x62F;&#x627;&#x62F;&#x647;&#x200C;&#x647;&#x627;</title><link>https://sinajalalvandi.ir/blog/programming/%D8%B2%D9%86%D8%AC%DB%8C%D8%B1%D9%87-%D8%A7%D8%AE%D8%AA%DB%8C%D8%A7%D8%B1%DB%8C-optional-chaining-%D8%AF%D8%B1-%D8%AC%D8%A7%D9%88%D8%A7-%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D9%BE%D8%AA-%D8%A7%D9%86%D9%82%D9%84%D8%A7%D8%A8%DB%8C-%D8%AF%D8%B1-%D8%AF%D8%B3%D8%AA%D8%B1%D8%B3%DB%8C-%D8%A8%D9%87-%D8%AF%D8%A7%D8%AF%D9%87%E2%80%8C%D9%87%D8%A7-r1/</link><description><![CDATA[
<p><img src="https://sinajalalvandi.ir/uploads/monthly_2025_03/optional-chaning.jpg.7c5445af064f8c02bd0252c9dac4be95.jpg" /></p>
<p>اگر توسعه‌دهنده وب باشید یا به دنیای برنامه‌نویسی جاوا اسکریپت علاقه داشته باشید، احتمالاً با چالش‌هایی مثل خطای undefined یا null هنگام دسترسی به خواص یک شیء مواجه شده‌اید. این مشکل معمولاً زمانی رخ می‌دهد که بخواهید به یک ویژگی عمیق در یک شیء دسترسی پیدا کنید، اما مطمئن نباشید که تمام زنجیره مسیر دسترسی به آن ویژگی وجود دارد یا نه. خوشبختانه، جاوا اسکریپت با معرفی <strong>Optional Chaining</strong> یا زنجیره اختیاری در نسخه ES11 (سال 2020) این مشکل را به شکلی زیبا و کارآمد حل کرده است. در این مقاله قصد دارم شما را با این قابلیت جدید، نحوه کارکرد آن، کاربردهایش و تأثیرش بر کدنویسی روزمره آشنا کنم.</p><h4>زنجیره اختیاری چیست؟</h4><p>زنجیره اختیاری که با عملگر ?. نشان داده می‌شود، به شما اجازه می‌دهد به خواص یا متدهای یک شیء دسترسی پیدا کنید، بدون اینکه نگران باشید که آیا مقدار آن شیء یا بخشی از زنجیره مسیرش null یا undefined است یا نه. اگر در هر مرحله از زنجیره، مقدار null یا undefined پیدا شود، به جای پرتاب خطا، به سادگی مقدار undefined برگردانده می‌شود. این ویژگی نه تنها کدنویسی را تمیزتر می‌کند، بلکه از بسیاری از خطاهای رایج که توسعه‌دهندگان با آن دست‌وپنجه نرم می‌کنند، جلوگیری می‌کند.</p><p>بیایید با یک مثال ساده شروع کنیم. فرض کنید یک شیء به شکل زیر دارید:</p><pre spellcheck="" class="ipsCode language-javascript" data-language="JavaScript"><code>const user = {
  name: "علی",
  address: {
    city: "تهران"
  }
};</code></pre><p>حالا اگر بخواهید به <code>user.address.city</code> دسترسی پیدا کنید، مشکلی نیست چون مسیر کامل وجود دارد. اما اگر شیء address وجود نداشته باشد چه؟ مثلاً:</p><pre spellcheck="" class="ipsCode language-javascript" data-language="JavaScript"><code>const user = {
  name: "علی"
};

console.log(user.address.city); // TypeError: Cannot read property 'city' of undefined</code></pre><p>در این حالت، چون address وجود ندارد، جاوا اسکریپت نمی‌تواند به city دسترسی پیدا کند و خطای TypeError پرتاب می‌شود. قبل از معرفی زنجیره اختیاری، توسعه‌دهندگان مجبور بودند با شرط‌های متعدد این مشکل را مدیریت کنند:</p><pre spellcheck="" class="ipsCode language-javascript" data-language="JavaScript"><code>const city = user &amp;&amp; user.address &amp;&amp; user.address.city;
console.log(city); // undefined</code></pre><p>این روش کار می‌کند، اما کد را شلوغ و خواندنش را سخت‌تر می‌کند. حالا با زنجیره اختیاری، همین کار را می‌توان به این شکل انجام داد:</p><pre spellcheck="" class="ipsCode language-javascript" data-language="JavaScript"><code>const city = user?.address?.city;
console.log(city); // undefined</code></pre><p>خیلی ساده‌تر و خواناتر، نه؟</p><h4>نحو و نحوه کارکرد</h4><p>عملگر <code>?.</code> در سه موقعیت اصلی استفاده می‌شود:</p><ol><li><p><strong>دسترسی به خواص شیء</strong>: مثل <code>obj?.prop</code></p></li><li><p><strong>دسترسی به آرایه‌ها</strong>: مثل<code> arr?.[index]</code></p></li><li><p><strong>فراخوانی متدها</strong>: مثل <code>obj?.method()</code></p></li></ol><p>هر وقت از این عملگر استفاده می‌کنید، جاوا اسکریپت ابتدا بررسی می‌کند که مقدار سمت چپ ?. آیا null یا undefined است یا نه. اگر باشد، فرآیند متوقف می‌شود و undefined برمی‌گرداند. اگر نه، به دسترسی یا فراخوانی ادامه می‌دهد.</p><p>مثال دیگر برای آرایه‌ها:</p><pre spellcheck="" class="ipsCode language-javascript" data-language="JavaScript"><code>const data = [1, 2, 3];
console.log(data?.[1]); // 2

const emptyData = null;
console.log(emptyData?.[1]); // undefined</code></pre><p>یا برای متدها:</p><pre spellcheck="" class="ipsCode language-javascript" data-language="JavaScript"><code>const user = {
  sayHello() {
    return "سلام!";
  }
};

console.log(user?.sayHello?.()); // "سلام!"
console.log(null?.sayHello?.()); // undefined</code></pre><h4>چرا زنجیره اختیاری مهم است؟</h4><p>حالا که با نحوه کارش آشنا شدید، بیایید ببینیم چرا این قابلیت اینقدر مورد استقبال قرار گرفته است:</p><ol><li><p><strong>کاهش خطاها</strong>: دیگر نیازی نیست نگران خطاهای غیرمنتظره باشید. اگر داده‌ای که از API یا منبع خارجی می‌آید ناقص باشد، زنجیره اختیاری به شما کمک می‌کند بدون دردسر از آن عبور کنید.</p></li><li><p><strong>کد تمیزتر</strong>: به جای نوشتن شرط‌های طولانی و پیچیده، با یک عملگر ساده می‌توانید همان نتیجه را بگیرید. این یعنی خوانایی بیشتر و نگهداری آسان‌تر.</p></li><li><p><strong>انعطاف‌پذیری با داده‌های پویا</strong>: در دنیای واقعی، داده‌ها همیشه طبق انتظار ما نیستند. مثلاً وقتی با یک API کار می‌کنید، ممکن است بعضی فیلدها گاهی وجود داشته باشند و گاهی نه. زنجیره اختیاری این عدم قطعیت را به خوبی مدیریت می‌کند.</p></li><li><p><strong>سازگاری با فریم‌ورک‌ها</strong>: در کتابخانه‌هایی مثل React یا Vue که با داده‌های پویا زیاد سر و کار دارید، این قابلیت به شدت زمان توسعه را کاهش می‌دهد.</p></li></ol><h4>کاربردهای عملی</h4><p>بیایید چند سناریوی واقعی را بررسی کنیم که زنجیره اختیاری در آن‌ها می‌درخشد:</p><h5>1. کار با API‌ها</h5><p>فرض کنید از یک API اطلاعاتی درباره کاربر دریافت می‌کنید:</p><pre spellcheck="" class="ipsCode language-javascript" data-language="JavaScript"><code>fetch("https://api.example.com/user")
  .then((response) =&gt; response.json())
  .then((data) =&gt; {
    const street = data?.user?.address?.street || "خیابان نامشخص";
    console.log(street);
  });</code></pre><p>اگر هر یک از این فیلدها وجود نداشته باشد، به جای خطا، مقدار پیش‌فرض نمایش داده می‌شود.</p><h5>2. مدیریت تنظیمات اختیاری</h5><p>تصور کنید یک تابع دارید که تنظیماتی را به صورت اختیاری می‌پذیرد:</p><pre spellcheck="" class="ipsCode language-javascript" data-language="JavaScript"><code>function configure(options) {
  const timeout = options?.timeout ?? 5000; // اگر timeout نباشد، 5000
  console.log(`تنظیم زمان: ${timeout} میلی‌ثانیه`);
}

configure({ timeout: 3000 }); // "تنظیم زمان: 3000 میلی‌ثانیه"
configure({}); // "تنظیم زمان: 5000 میلی‌ثانیه"</code></pre><p>اینجا از عملگر <code>??</code> (Nullish Coalescing) هم کنار ?. استفاده شده که فقط در صورت null یا undefined مقدار پیش‌فرض را برمی‌گرداند.</p><h5>3. بررسی توابع اختیاری</h5><p>اگر بخواهید متدی را فراخوانی کنید که ممکن است وجود نداشته باشد:</p><pre spellcheck="" class="ipsCode language-javascript" data-language="JavaScript"><code>const plugin = {
  init: () =&gt; console.log("شروع شد!")
};

plugin?.init?.(); // "شروع شد!"
const noPlugin = null;
noPlugin?.init?.(); // هیچ خطایی نمی‌دهد، فقط undefined</code></pre><h4>محدودیت‌ها و نکات مهم</h4><p>هرچند زنجیره اختیاری فوق‌العاده است، اما محدودیت‌هایی هم دارد که باید به آن‌ها توجه کنید:</p><ul><li><p><strong>پشتیبانی مرورگر</strong>: این قابلیت در مرورگرهای قدیمی (مثل IE) پشتیبانی نمی‌شود. اگر پروژه‌تان نیاز به سازگاری با مرورگرهای قدیمی دارد، باید از ابزارهایی مثل Babel استفاده کنید.</p></li><li><p><strong>استفاده بیش از حد</strong>: اگر در هر خط کد از <code>?.</code> استفاده کنید، ممکن است کدتان بیش از حد دفاعی شود و اشکال‌زدایی سخت‌تر شود.</p></li><li><p><strong>تفاوت با عملگرهای دیگر</strong>: <code>?.</code> با <code>&amp;&amp;</code> یا <code>||</code> فرق دارد. مثلاً <code>0 &amp;&amp; "something"</code> مقدار 0 را برمی‌گرداند، اما <code>0?.something</code> خطا نمی‌دهد و undefined می‌دهد.</p></li></ul><h4>جمع‌بندی</h4><p>زنجیره اختیاری (?.) یکی از بهترین قابلیت‌هایی است که جاوا اسکریپت در سال‌های اخیر به خودش دیده است. این ویژگی نه تنها زندگی توسعه‌دهندگان را آسان‌تر کرده، بلکه به ما اجازه می‌دهد کدهایی بنویسیم که هم ایمن‌ترند و هم خواناتر. اگر هنوز از این قابلیت استفاده نکرده‌اید، پیشنهاد می‌کنم همین حالا آن را در پروژه بعدی‌تان امتحان کنید. مطمئنم بعد از چند بار استفاده، دیگر نمی‌توانید بدون آن کدنویسی کنید!</p><p>نظر شما چیست؟ آیا تجربه‌ای با زنجیره اختیاری دارید؟ در بخش نظرات وبلاگم برام بنویسید و اگر سوالی دارید، خوشحال می‌شم کمکتون کنم!</p><p></p>]]></description><guid isPermaLink="false">1</guid><pubDate>Sun, 05 Jan 2025 16:00:50 +0000</pubDate></item><item><title>Lifetime &#x62F;&#x631; Rust &#x686;&#x6CC;&#x633;&#x62A; &#x648; &#x686;&#x631;&#x627; &#x628;&#x627;&#x6CC;&#x62F; &#x628;&#x647; &#x622;&#x646; &#x627;&#x647;&#x645;&#x6CC;&#x62A; &#x628;&#x62F;&#x647;&#x6CC;&#x645;&#x61F;</title><link>https://sinajalalvandi.ir/blog/programming/lifetime-%D8%AF%D8%B1-rust-%DA%86%DB%8C%D8%B3%D8%AA-%D9%88-%DA%86%D8%B1%D8%A7-%D8%A8%D8%A7%DB%8C%D8%AF-%D8%A8%D9%87-%D8%A2%D9%86-%D8%A7%D9%87%D9%85%DB%8C%D8%AA-%D8%A8%D8%AF%D9%87%DB%8C%D9%85%D8%9F-r15/</link><description><![CDATA[
<p><img src="https://sinajalalvandi.ir/uploads/monthly_2025_03/lifetimes.png.8917e85dd1dba3b39bfee11bedb50a65.png" /></p>
<p>زبان برنامه‌نویسی Rust به خاطر ویژگی‌های منحصربه‌فردش مثل ایمنی حافظه و عملکرد بالا، حسابی سر زبون‌ها افتاده. یکی از مفاهیم کلیدی که Rust رو از بقیه زبان‌ها متمایز می‌کنه، چیزیه به اسم <strong>Lifetime</strong> (طول عمر). اگه تازه با Rust آشنا شدید یا می‌خواهید عمیق‌تر این زبون رو بشناسید، این مقاله قراره شما رو با این مفهوم مهم آشنا کنه و نشون بده چرا توی نوشتن کدهای امن و کارآمد انقدر نقش داره. پس بیاید با هم وارد این موضوع بشیم و ببینیم Lifetime چیه، چرا مهمه و چطور توی عمل کار می‌کنه.</p><h4>Lifetime دقیقاً چیه؟</h4><p>توی Rust، وقتی از Lifetime صحبت می‌کنیم، داریم به یه قانون اساسی اشاره می‌کنیم که به مدیریت حافظه ربط داره. به زبان ساده، Lifetime مشخص می‌کنه که یه <strong>مرجع</strong> (Reference) توی کدتون تا چه زمانی معتبره و می‌تونید ازش استفاده کنید. مرجع همون چیزیه که با علامت <code>&amp;</code> توی کد نشون داده می‌شه، مثل <code>&amp;x</code> که به یه متغیر یا داده اشاره می‌کنه بدون اینکه مالکیتش رو بگیره.</p><p>Rust با این سیستم مطمئن می‌شه که هیچ‌وقت به داده‌ای که دیگه توی حافظه وجود نداره (مثلاً پاک شده) اشاره نکنید. این کار از خطاهایی مثل <strong>Dangling Pointer</strong> (اشاره‌گر معلق) جلوگیری می‌کنه که توی زبان‌هایی مثل C یا C++ خیلی دردسرسازن. به عبارت دیگه، Lifetime مثل یه نگهبان هوشمنده که نمی‌ذاره کدتون به جاهای خطرناک حافظه سرک بکشه.</p><h4>چرا Lifetime انقدر توی Rust مهمه؟</h4><p>بیاید یه لحظه به این فکر کنیم که چرا Rust همچین سیستمی رو طراحی کرده. توی زبان‌های برنامه‌نویسی دیگه مثل Python یا Java، مدیریت حافظه معمولاً با یه <strong>Garbage Collector</strong> انجام می‌شه. این ابزار خودش می‌گرده و حافظه‌ای که دیگه لازم نیست رو آزاد می‌کنه. اما Rust راه دیگه‌ای رو انتخاب کرده: اینجا خبری از Garbage Collector نیست! در عوض، با قوانین سخت‌گیرانه‌ای مثل <strong>Ownership</strong> (مالکیت) و Lifetime، مدیریت حافظه رو توی زمان کامپایل انجام می‌ده.</p><p>مزیتش چیه؟ اول اینکه برنامه‌هاتون سریع‌تر اجرا می‌شن چون سربار Garbage Collector رو ندارید. دوم اینکه خیلی از خطاهایی که توی زبونای دیگه موقع اجرا (Runtime) پیداشون می‌شه، توی Rust همون اول، موقع کامپایل، گیر می‌افتن. Lifetime اینجا نقشش پررنگ می‌شه چون تضمین می‌کنه هر مرجعی که استفاده می‌کنید، به داده‌ای اشاره داره که هنوز زنده‌ست.</p><h4>Lifetime توی کد چطور کار می‌کنه؟</h4><p>حالا بیاید یه نگاه عملی‌تر به موضوع بندازیم. توی Rust، Lifetime با یه علامت خاص به اسم <strong>Lifetime Annotation</strong> نشون داده می‌شه که معمولاً یه حرف مثل 'a یا 'b هست. این علامت به کامپایلر می‌گه که یه مرجع تا چه مدت معتبره و باید بهش توجه کنه.</p><p>یه مثال ساده رو ببینیم:</p><pre spellcheck="" class="ipsCode language-rust" data-language="Rust"><code>fn longest&lt;'a&gt;(x: &amp;'a str, y: &amp;'a str) -&gt; &amp;'a str {
    if x.len() &gt; y.len() {
        x
    } else {
        y
    }
}</code></pre><p>اینجا چی داریم؟ یه تابع به اسم longest که دو رشته (String) رو به‌عنوان مرجع می‌گیره و بلندترینش رو برمی‌گردونه. علامت <code>'a</code> به کامپایلر می‌گه که مرجع خروجی تابع (یعنی چیزی که برگردونده می‌شه) باید به داده‌ای اشاره کنه که حداقل به اندازه کوتاه‌ترین Lifetime بین x و y زنده می‌مونه. اینجوری مطمئن می‌شیم خروجی همیشه به یه حافظه معتبر اشاره داره.</p><p>اگه این <code>'a</code> نبود، کامپایلر نمی‌تونست بفهمه که مرجع برگشتی تا کی قراره معتبر باشه و ممکن بود خطا بده یا بدتر، یه اشاره‌گر معلق بسازیم که به داده پاک‌شده اشاره کنه.</p><h4>یه مثال پیچیده‌تر: Lifetime توی ساختارها</h4><p>فرض کنید یه ساختار (Struct) دارید که داخلش یه مرجع هست. توی Rust، وقتی یه مرجع توی یه ساختار استفاده می‌شه، باید Lifetime اون رو مشخص کنید. مثلاً:</p><pre spellcheck="" class="ipsCode language-rust" data-language="Rust"><code>struct Book&lt;'a&gt; {
    title: &amp;'a str,
    author: &amp;'a str,
}

fn main() {
    let title = String::from("The Rust Journey");
    let author = String::from("Jane Doe");
    let book = Book {
        title: &amp;title,
        author: &amp;author,
    };
    println!("{} by {}", book.title, book.author);
}</code></pre><p>توی این کد، ساختار Book دو مرجع داره: title و author. علامت <code>'a</code> به کامپایلر می‌گه که این مرجع‌ها به داده‌هایی اشاره می‌کنن که حداقل تا یه مدت مشخص (یعنی Lifetime 'a) توی حافظه زنده هستن. اگه title یا author قبل از استفاده از book از حافظه پاک بشن، کامپایلر خطا می‌ده و نمی‌ذاره کد اجرا بشه.</p><h4>انواع Lifetime و قوانینش</h4><p>توی Rust، Lifetime‌ها همیشه به‌صورت دستی نوشته نمی‌شن. خیلی وقت‌ها کامپایلر خودش می‌تونه بفهمه که Lifetime چیه و نیازی به مشخص کردنش نیست. به این می‌گن <strong>Lifetime Elision</strong>. مثلاً توی این کد:</p><pre spellcheck="" class="ipsCode language-rust" data-language="Rust"><code>fn first_word(s: &amp;str) -&gt; &amp;str {
    s.split(' ').next().unwrap()
}</code></pre><p>نیازی به نوشتن<code> a'</code> نیست چون کامپایلر می‌فهمه که مرجع خروجی به ورودی s وابسته‌ست و تا وقتی s زنده‌ست، خروجی هم معتبره.</p><p>اما وقتی موضوع پیچیده‌تر می‌شه (مثل تابع longest یا ساختارها)، باید خودتون دست به کار بشید و Lifetime رو مشخص کنید. قانون اصلی اینه: هر مرجعی که برمی‌گردونید یا توی یه ساختار استفاده می‌کنید، باید به داده‌ای اشاره کنه که هنوز توی حافظه وجود داره.</p><h4>Lifetime و ایمنی حافظه</h4><p>یکی از بزرگ‌ترین مزیت‌های Lifetime اینه که جلوی خطاهای حافظه رو می‌گیره. مثلاً توی C، ممکنه یه اشاره‌گر به حافظه‌ای اشاره کنه که دیگه آزاد شده و برنامه‌تون کرش کنه. اما توی Rust، کامپایلر با چک کردن Lifetime‌ها مطمئن می‌شه که همچین چیزی اتفاق نیفته. این یعنی شما به‌عنوان برنامه‌نویس، خیالتون راحته که کدتون از نظر حافظه امن و قابل‌اعتماده.</p><h4>چطور Lifetime رو یاد بگیریم؟</h4><p>اگه تازه با Rust شروع کردید، ممکنه اولش Lifetime یه کم گیج‌کننده به نظر بیاد. اما نگران نباشید! با تمرین و نوشتن کد، کم‌کم دستتون میاد که کجا باید ازش استفاده کنید. یه راه خوب برای یادگیری اینه که با مثال‌های ساده شروع کنید و بعد سراغ پروژه‌های پیچیده‌تر برید. مثلاً یه تابع بنویسید که چند مرجع رو مدیریت می‌کنه و ببینید کامپایلر چه خطاهایی می‌ده. این خطاها بهترین معلم شما توی یادگیری Rust هستن!</p><h4>کاربرد Lifetime توی پروژه‌های واقعی</h4><p>Lifetime فقط یه مفهوم تئوری نیست؛ توی دنیای واقعی هم حسابی به کار میاد. مثلاً فرض کنید دارید یه سرور وب با Rust می‌نویسید (مثل پروژه‌هایی که با فریم‌ورک Actix-Web ساخته می‌شن). توی همچین برنامه‌ای، مدیریت دقیق مرجع‌ها و حافظه خیلی مهمه تا سرور پایدار بمونه و کرش نکنه. Lifetime اینجا کمک می‌کنه که مطمئن بشید هیچ مرجعی به داده نامعتبر اشاره نمی‌کنه.</p><p>یا مثلاً توی توسعه سیستم‌عامل‌ها (مثل پروژه Redox که با Rust نوشته شده)، جایی که عملکرد و ایمنی حرف اول رو می‌زنه، Lifetime یه ابزار قدرتمند برای کنترل حافظه‌ست.</p><p>Lifetime توی Rust مثل یه سپر محافظه که نمی‌ذاره کدتون به دردسر بیفته. این سیستم نه‌تنها باعث می‌شه برنامه‌هاتون امن‌تر باشن، بلکه بهتون کنترل بیشتری روی منابع می‌ده و کمک می‌کنه کدی بنویسید که هم سریع باشه و هم قابل‌اعتماد. اگه دنبال زبانی هستید که بهتون قدرت و امنیت رو با هم بده، Rust و مفهوم Lifetime‌ش چیزیه که نباید ازش غافل بشید.</p>]]></description><guid isPermaLink="false">15</guid><pubDate>Wed, 30 Oct 2024 22:01:00 +0000</pubDate></item><item><title>&#x648;&#x628;&#x200C;&#x627;&#x633;&#x6A9;&#x631;&#x67E;&#x6CC;&#x646;&#x6AF; &#x628;&#x627; &#x67E;&#x627;&#x6CC;&#x62A;&#x648;&#x646;: &#x686;&#x6AF;&#x648;&#x646;&#x647; &#x62F;&#x627;&#x62F;&#x647;&#x200C;&#x647;&#x627; &#x631;&#x627; &#x627;&#x632; &#x648;&#x628; &#x627;&#x633;&#x62A;&#x62E;&#x631;&#x627;&#x62C; &#x6A9;&#x646;&#x6CC;&#x645;&#x61F;</title><link>https://sinajalalvandi.ir/blog/programming/%D9%88%D8%A8%E2%80%8C%D8%A7%D8%B3%DA%A9%D8%B1%D9%BE%DB%8C%D9%86%DA%AF-%D8%A8%D8%A7-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-%DA%86%DA%AF%D9%88%D9%86%D9%87-%D8%AF%D8%A7%D8%AF%D9%87%E2%80%8C%D9%87%D8%A7-%D8%B1%D8%A7-%D8%A7%D8%B2-%D9%88%D8%A8-%D8%A7%D8%B3%D8%AA%D8%AE%D8%B1%D8%A7%D8%AC-%DA%A9%D9%86%DB%8C%D9%85%D8%9F-r5/</link><description><![CDATA[
<p><img src="https://sinajalalvandi.ir/uploads/monthly_2025_03/scrap.png.06f44f5e6ba8791328a2060d465c671d.png" /></p>
<p>در دنیای امروز که داده‌ها حرف اول رو می‌زنن، توانایی استخراج اطلاعات از وب یه مهارت فوق‌العاده ارزشمنده. چه بخواهید قیمت محصولات یه فروشگاه آنلاین رو جمع‌آوری کنید، چه اخبار رو تحلیل کنید یا داده‌های تحقیقاتی رو از سایت‌ها بکشید بیرون، <strong>وب‌اسکرپینگ (Web Scraping)</strong> راه‌حل شماست. توی این مقاله قراره با وب‌اسکرپینگ، ابزارهای پایتون برای این کار و مراحل انجامش آشنا بشید. اگه به پایتون و داده علاقه دارید، تا آخر با من همراه باشید!</p><h4>وب‌اسکرپینگ چیه؟</h4><p>وب‌اسکرپینگ به فرآیند خودکار جمع‌آوری داده‌ها از صفحات وب گفته می‌شه. به جای اینکه دستی برید و اطلاعات رو کپی کنید، یه برنامه می‌نویسید که این کار رو براتون انجام بده. پایتون به خاطر سادگی، کتابخانه‌های قدرتمند و انعطاف‌پذیریش، یکی از بهترین زبان‌ها برای وب‌اسکرپینگه.</p><h4>چرا پایتون؟</h4><ul><li><p><strong>کتابخانه‌های آماده</strong>: ابزارهایی مثل Beautiful Soup، Requests و Scrapy کار رو خیلی راحت می‌کنن.</p></li><li><p><strong>خوانایی کد</strong>: حتی اگه تازه‌کار باشید، می‌تونید با چند خط کد شروع کنید.</p></li><li><p><strong>جامعه بزرگ</strong>: هر سوالی داشته باشید، جوابش توی انجمن‌های پایتون پیدا می‌شه.</p></li></ul><h4>ابزارهای اصلی وب‌اسکرپینگ با پایتون</h4><p>بیاید با چند ابزار کلیدی که توی این مسیر نیاز دارید آشنا بشیم:</p><ol><li><p><strong>Requests</strong>: برای ارسال درخواست HTTP و دریافت محتوای صفحه وب.</p></li><li><p><strong>Beautiful Soup</strong>: برای تجزیه (parse) کردن HTML و پیدا کردن داده‌های مورد نظر.</p></li><li><p><strong>Scrapy</strong>: یه فریم‌ورک کامل برای پروژه‌های بزرگ‌تر و پیچیده‌تر (اختیاری).</p></li></ol><h4>یه مثال ساده: استخراج عنوان صفحه</h4><p>بیاید با یه مثال عملی شروع کنیم. فرض کنید می‌خواهیم عنوان یه صفحه وب رو بگیریم:</p><pre spellcheck="" class="ipsCode language-python" data-language="Python"><code>import requests
from bs4 import BeautifulSoup

# آدرس صفحه‌ای که می‌خواهیم اسکرپ کنیم
url = "https://example.com"

# درخواست به صفحه
response = requests.get(url)

# چک کردن اینکه درخواست موفق بوده
if response.status_code == 200:
    # تجزیه HTML
    soup = BeautifulSoup(response.text, "html.parser")
    # پیدا کردن تگ عنوان
    title = soup.find("title").text
    print(f"عنوان صفحه: {title}")
else:
    print("خطا در اتصال به صفحه")</code></pre><p>خروجی چیزی شبیه اینه:</p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>عنوان صفحه: Example Domain</code></pre><p>اینجا با requests محتوای صفحه رو گرفتیم و با BeautifulSoup تگ <code>&lt;title&gt;</code> رو پیدا کردیم. ساده بود، نه؟</p><h4>مراحل وب‌اسکرپینگ</h4><p>برای یه پروژه وب‌اسکرپینگ موفق، این مراحل رو دنبال کنید:</p><ol><li><p><strong>شناسایی هدف</strong>: اول مشخص کنید چه داده‌ای می‌خواهید (مثلاً قیمت‌ها، نظرات کاربران، یا لینک‌ها).</p></li><li><p><strong>بررسی ساختار صفحه</strong>: ابزار توسعه‌دهنده مرورگر (Inspector) رو باز کنید و HTML صفحه رو نگاه کنید تا بفهمید داده‌ها کجا هستن.</p></li><li><p><strong>نوشتن کد</strong>: با پایتون درخواست بفرستید و داده‌ها رو استخراج کنید.</p></li><li><p><strong>ذخیره داده‌ها</strong>: اطلاعات رو توی فایل CSV، JSON یا دیتابیس ذخیره کنید.</p></li><li><p><strong>اتوماسیون (اختیاری)</strong>: اگه نیازه، کدتون رو طوری تنظیم کنید کi (مثلاً روزانه) اجرا بشه.</p></li></ol><h4>یه پروژه واقعی: استخراج قیمت محصولات</h4><p>فرض کنید می‌خواهید قیمت یه محصول رو از یه سایت فروشگاهی بکشید بیرون:</p><pre spellcheck="" class="ipsCode language-python" data-language="Python"><code>import requests
from bs4 import BeautifulSoup

url = "https://fake-shop.com/product/sample"  # آدرس فرضی
response = requests.get(url)

if response.status_code == 200:
    soup = BeautifulSoup(response.text, "html.parser")
    price = soup.find("span", class_="price").text  # فرض بر اینکه قیمت توی این تگ هست
    print(f"قیمت محصول: {price}")
else:
    print("اتصال ناموفق")</code></pre><p>توی این کد، ما دنبال تگ &lt;span&gt; با کلاس price گشتیم. اگه سایت واقعی باشه، باید کلاس یا تگ دقیق رو از HTMLش پیدا کنید.</p><h4>نکات مهم و چالش‌ها</h4><p>وب‌اسکرپینگ به همین سادگیا هم نیست! یه سری نکته و چالش هست که باید حواستون باشه:</p><ul><li><p><strong>قوانین سایت</strong>: قبل از اسکرپ کردن، فایل robots.txt سایت رو چک کنید و مطمئن شید که اجازه این کار رو دارید. بعضی سایت‌ها اسکرپینگ رو ممنوع کردن.</p></li><li><p><strong>بلاک شدن</strong>: اگه درخواست‌های زیادی بفرستید، ممکنه IPتون بلاک بشه. برای این کار می‌تونید از تأخیر (delay) بین درخواست‌ها یا پراکسی استفاده کنید.</p></li><li><p><strong>تغییر ساختار سایت</strong>: اگه سایت HTMLش رو عوض کنه، کدهاتون ممکنه خراب بشه. باید آماده به‌روزرسانی باشید.</p></li><li><p><strong>داده‌های پویا</strong>: بعضی سایت‌ها با جاوا اسکریپت لود می‌شن. توی این موارد، ابزارهایی مثل <strong>Selenium</strong> یا <strong>Playwright</strong> که مرورگر رو شبیه‌سازی می‌کنن، به کارتون میاد.</p></li></ul><h4>ذخیره داده‌ها توی فایل</h4><p>بعد از استخراج، می‌تونید داده‌ها رو توی یه فایل CSV ذخیره کنید:</p><pre spellcheck="" class="ipsCode language-python" data-language="Python"><code>import csv

data = {"title": "محصول نمونه", "price": "100,000 تومان"}
with open("products.csv", "w", newline="", encoding="utf-8") as file:
    writer = csv.DictWriter(file, fieldnames=["title", "price"])
    writer.writeheader()
    writer.writerow(data)</code></pre><p>حالا داده‌هاتون توی یه فایل مرتب ذخیره شدن!</p><h4>چرا وب‌اسکرپینگ یاد بگیریم؟</h4><ul><li><p><strong>تحلیل بازار</strong>: قیمت‌ها و محصولات رقبا رو مقایسه کنید.</p></li><li><p><strong>تحقیقات</strong>: داده‌های علمی یا خبری رو جمع‌آوری کنید.</p></li><li><p><strong>اتوماسیون</strong>: کارای تکراری مثل چک کردن موجودی انبار رو خودکار کنید.</p></li></ul><h4>جمع‌بندی</h4><p>وب‌اسکرپینگ با پایتون یه مهارت قدرتمنده که با چند خط کد ساده شروع می‌شه، اما می‌تونه به پروژه‌های پیچیده و حرفه‌ای تبدیل بشه. ابزارهایی مثل Requests و Beautiful Soup نقطه شروع عالی‌ای هستن و اگه بخواهید حرفه‌ای‌تر بشید، می‌تونید سراغ Scrapy یا Selenium برید. فقط یادتون باشه با مسئولیت‌پذیری و رعایت قوانین پیش برید.</p>]]></description><guid isPermaLink="false">5</guid><pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate></item><item><title>&#x628;&#x631;&#x631;&#x633;&#x6CC; Ownership &#x648; Borrowing &#x62F;&#x631; Rust: &#x6A9;&#x644;&#x6CC;&#x62F; &#x627;&#x645;&#x646;&#x6CC;&#x62A; &#x62D;&#x627;&#x641;&#x638;&#x647; &#x648; &#x639;&#x645;&#x644;&#x6A9;&#x631;&#x62F; &#x628;&#x647;&#x6CC;&#x646;&#x647;</title><link>https://sinajalalvandi.ir/blog/programming/%D8%A8%D8%B1%D8%B1%D8%B3%DB%8C-ownership-%D9%88-borrowing-%D8%AF%D8%B1-rust-%DA%A9%D9%84%DB%8C%D8%AF-%D8%A7%D9%85%D9%86%DB%8C%D8%AA-%D8%AD%D8%A7%D9%81%D8%B8%D9%87-%D9%88-%D8%B9%D9%85%D9%84%DA%A9%D8%B1%D8%AF-%D8%A8%D9%87%DB%8C%D9%86%D9%87-r14/</link><description><![CDATA[
<p><img src="https://sinajalalvandi.ir/uploads/monthly_2025_03/Rust-56874.png.8a9dc5f1219f432112cf823800545a0f.png" /></p>
<p>زبان برنامه‌نویسی <strong>Rust</strong> به دلیل رویکرد نوآورانه‌اش در مدیریت حافظه و ایمنی کد، در سال‌های اخیر توجه بسیاری از توسعه‌دهندگان را به خود جلب کرده است. یکی از مهم‌ترین ویژگی‌های این زبان که آن را از رقبا متمایز می‌کند، سیستم <strong>Ownership</strong> (مالکیت) و <strong>Borrowing</strong> (امانت‌دهی) است. در این مقاله، به صورت عمیق و پیشرفته به این مفاهیم می‌پردازم، نحوه کارکرد آن‌ها را بررسی می‌کنیم و نشان می‌دهیم که چرا این قابلیت‌ها، Rust را به انتخابی ایده‌آل برای پروژه‌های پیچیده و حساس تبدیل کرده‌اند. اگر به دنبال یادگیری پیشرفته Rust یا بهبود مهارت‌های برنامه‌نویسی خود هستید، تا انتها همراه من باشید.</p><h4>Ownership در Rust چیست و چرا اهمیت دارد؟</h4><p>در هسته زبان Rust، مفهومی به نام <strong>Ownership</strong> قرار دارد که به معنای مالکیت داده‌ها توسط یک متغیر خاص است. هر تکه داده در حافظه فقط یک صاحب دارد و وقتی این صاحب از دسترس خارج شود (مثلاً با پایان یافتن محدوده یا scope)، حافظه به صورت خودکار آزاد می‌شود. این مکانیزم بدون نیاز به <strong>Garbage Collector</strong> عمل می‌کند و به همین دلیل، Rust عملکردی نزدیک به زبان‌هایی مثل C++ ارائه می‌دهد، اما با ایمنی بیشتر.</p><p>برای مثال، کد زیر را در نظر بگیرید:</p><pre spellcheck="" class="ipsCode language-rust" data-language="Rust"><code>fn main() {
    let s = String::from("Hello, Rust");
    println!("{}", s);
} // حافظه متعلق به s اینجا آزاد می‌شود</code></pre><p>این سیستم ساده به نظر می‌رسد، اما وقتی بحث انتقال مالکیت (Move) پیش می‌آید، قدرت واقعی آن مشخص می‌شود.</p><h4>انتقال مالکیت (Move) و جلوگیری از خطاهای حافظه</h4><p>در Rust، وقتی یک متغیر به متغیر دیگری اختصاص داده می‌شود، مالکیت داده منتقل می‌شود و متغیر اولیه دیگر معتبر نیست. این رفتار که به <strong>Move</strong> معروف است، از دسترسی همزمان چند متغیر به یک حافظه جلوگیری می‌کند و خطاهایی مثل <strong>dangling pointer</strong> یا <strong>double free</strong> را حذف می‌کند. مثال زیر این موضوع را روشن‌تر می‌کند:</p><pre spellcheck="" class="ipsCode language-rust" data-language="Rust"><code>fn main() {
    let s1 = String::from("Rust");
    let s2 = s1; // مالکیت به s2 منتقل می‌شود
    // println!("{}", s1); // خطا: s1 دیگر معتبر نیست
    println!("{}", s2); // خروجی: Rust
}</code></pre><p>این قانون سخت‌گیرانه تضمین می‌کند که در هر لحظه فقط یک متغیر کنترل داده را در اختیار داشته باشد، که برای برنامه‌نویسی امن و بدون باگ حیاتی است.</p><h4>Borrowing: انعطاف‌پذیری در کنار امنیت</h4><p>گاهی اوقات نیازی به انتقال مالکیت نیست و فقط می‌خواهید به داده دسترسی پیدا کنید یا آن را تغییر دهید. اینجا <strong>Borrowing</strong> وارد میدان می‌شود. Rust دو نوع امانت‌دهی ارائه می‌دهد:</p><ol><li><p><strong>Reference غیرقابل تغییر (&amp;)</strong>: امکان خواندن داده بدون تغییر آن.</p></li><li><p><strong>Reference قابل تغییر (&amp;mut)</strong>: امکان تغییر داده با رعایت قوانین ایمنی.</p></li></ol><p>مثال:</p><pre spellcheck="" class="ipsCode language-rust" data-language="Rust"><code>fn main() {
    let mut s = String::from("Hello");
    let r1 = &amp;s; // امانت غیرقابل تغییر
    println!("Reference: {}", r1);
    
    let r2 = &amp;mut s; // امانت قابل تغییر
    r2.push_str(", Rust!");
    println!("Updated: {}", s); // خروجی: Hello, Rust!
}</code></pre><p>قانون کلیدی Borrowing در Rust این است: می‌توانید چندین امانت غیرقابل تغییر داشته باشید، اما فقط یک امانت قابل تغییر در هر لحظه مجاز است و این دو نمی‌توانند همزمان وجود داشته باشند. این محدودیت از <strong>Data Race</strong> (رقابت داده) جلوگیری می‌کند و ایمنی را تضمین می‌کند.</p><h4>کاربرد Ownership و Borrowing در برنامه‌نویسی چندنخی</h4><p>یکی از حوزه‌هایی که این سیستم واقعاً می‌درخشد، برنامه‌نویسی <strong>چندنخی (multi-threaded)</strong> است. در زبان‌های سنتی مثل C++، مدیریت دسترسی thread ها به داده‌های مشترک نیازمند استفاده از قفل‌ها (locks) و هماهنگی دستی است. اما Rust با قوانین Ownership و ابزارهایی مثل <strong><abbr title="یکی از ابزارهای قدرتمند در زبان برنامه‌نویسی Rust هست که برای مدیریت امن حافظه توی برنامه‌های چندنخی (multi-threaded) استفاده می‌شود">Arc</abbr></strong> و <a rel="external nofollow" href="https://en.wikipedia.org/wiki/Lock_(computer_science)"><strong>Mutex</strong></a>، این پیچیدگی را به حداقل می‌رساند.</p><p>مثال پیشرفته:</p><pre spellcheck="" class="ipsCode language-rust" data-language="Rust"><code>use std::sync::{<abbr title="یکی از ابزارهای قدرتمند در زبان برنامه‌نویسی Rust هست که برای مدیریت امن حافظه توی برنامه‌های چندنخی (multi-threaded) استفاده می‌شود">Arc</abbr>, <a href="https://en.wikipedia.org/wiki/Lock_(computer_science)" rel="external nofollow">Mutex</a>};
use std::thread;

fn main() {
    let data = <abbr title="یکی از ابزارهای قدرتمند در زبان برنامه‌نویسی Rust هست که برای مدیریت امن حافظه توی برنامه‌های چندنخی (multi-threaded) استفاده می‌شود">Arc</abbr>::new(<a href="https://en.wikipedia.org/wiki/Lock_(computer_science)" rel="external nofollow">Mutex</a>::new(vec![1, 2, 3]));
    let mut threads = vec![];

    for i in 0..3 {
        let data = <abbr title="یکی از ابزارهای قدرتمند در زبان برنامه‌نویسی Rust هست که برای مدیریت امن حافظه توی برنامه‌های چندنخی (multi-threaded) استفاده می‌شود">Arc</abbr>::clone(&amp;data);
        threads.push(thread::spawn(move || {
            let mut num = data.lock().unwrap();
            num.push(i);
            println!("Thread {}: {:?}", i, num);
        }));
    }

    for t in threads {
        t.join().unwrap();
    }
}</code></pre><p>در این کد، <strong><abbr title="یکی از ابزارهای قدرتمند در زبان برنامه‌نویسی Rust هست که برای مدیریت امن حافظه توی برنامه‌های چندنخی (multi-threaded) استفاده می‌شود">Arc</abbr></strong> (Atomic Reference Counting) امکان اشتراک داده بین thread ها را فراهم می‌کند و <a rel="external nofollow" href="https://en.wikipedia.org/wiki/Lock_(computer_science)"><strong>Mutex</strong></a> تضمین می‌کند که فقط یک thread در لحظه به داده دسترسی تغییرپذیر داشته باشد. نتیجه؟ کدی امن، بدون Data Race و با عملکرد بالا.</p><h4>مزایای استفاده از Ownership و Borrowing در Rust</h4><ol><li><p><strong>ایمنی حافظه</strong>: حذف خطاهای رایج مثل استفاده از اشاره‌گرهای نامعتبر.</p></li><li><p><strong>عملکرد بهینه</strong>: عدم نیاز به Garbage Collector و مدیریت دستی حافظه.</p></li><li><p><strong>کنترل دقیق</strong>: توسعه‌دهنده با قوانین مشخص، کنترل بهتری بر رفتار برنامه دارد.</p></li></ol><p>البته، این سیستم در ابتدا ممکن است برای برنامه‌نویسان تازه‌کار چالش‌برانگیز باشد، اما با تسلط بر آن، می‌توانید پروژه‌هایی پایدار و قابل اعتماد بسازید.</p>]]></description><guid isPermaLink="false">14</guid><pubDate>Wed, 02 Oct 2024 15:38:00 +0000</pubDate></item><item><title>&#x645;&#x62F;&#x6CC;&#x631;&#x6CC;&#x62A; &#x62F;&#x633;&#x62A;&#x6CC; &#x62D;&#x627;&#x641;&#x638;&#x647; &#x62F;&#x631; &#x632;&#x628;&#x627;&#x646; C</title><link>https://sinajalalvandi.ir/blog/programming/%D9%85%D8%AF%DB%8C%D8%B1%DB%8C%D8%AA-%D8%AF%D8%B3%D8%AA%DB%8C-%D8%AD%D8%A7%D9%81%D8%B8%D9%87-%D8%AF%D8%B1-%D8%B2%D8%A8%D8%A7%D9%86-c-r4/</link><description><![CDATA[
<p><img src="https://sinajalalvandi.ir/uploads/monthly_2025_03/clang.png.2abe7ce95928076af2ea167d525ebb16.png" /></p>
<p>زبان برنامه‌نویسی C به عنوان یکی از پایه‌ای‌ترین و قدرتمندترین زبان‌های برنامه‌نویسی شناخته می‌شه که هنوز هم در توسعه سیستم‌عامل‌ها، نرم‌افزارهای Embedded و برنامه‌های با کارایی بالا حرف اول رو می‌زنه. یکی از قابلیت‌های خاص و برجسته این زبان، <strong>مدیریت دستی حافظه</strong> هست که به برنامه‌نویس اجازه می‌ده به طور مستقیم کنترل کاملی روی تخصیص و آزادسازی حافظه داشته باشه. این ویژگی، هم یه مزیت بزرگه و هم یه چالش مهم که درک عمیقش برای هر برنامه‌نویس C ضروریه.</p><h4>مدیریت دستی حافظه چیه؟</h4><p>در C، برخلاف زبان‌های مدرن‌تر مثل Java یا Python که از Garbage Collector برای مدیریت خودکار حافظه استفاده می‌کنن، برنامه‌نویس خودش مسئول تخصیص و آزادسازی حافظه‌ست. این کار با استفاده از توابعی مثل <code>malloc()، calloc()، realloc() و free()</code> انجام می‌شه. به عنوان مثال، وقتی نیاز به یه آرایه پویا دارید، می‌تونید با<code> malloc()</code> حافظه مورد نیاز رو تخصیص بدید و بعد از استفاده، با <code>free() </code>اون رو آزاد کنید. این کنترل دستی به شما اجازه می‌ده دقیقاً بفهمید چه مقدار حافظه در چه زمانی استفاده می‌شه و کی آزاد می‌شه.</p><h4>چرا این قابلیت خاصه؟</h4><p>مدیریت دستی حافظه به برنامه‌نویس قدرت بی‌نظیری می‌ده. اول اینکه، بهینه‌سازی عملکرد برنامه‌ها در C خیلی بهتر از زبان‌هایی با مدیریت خودکار حافظه‌ست. چون هیچ پروسه اضافی مثل Garbage Collection وجود نداره که به صورت غیرقابل پیش‌بینی اجرا بشه و منابع سیستم رو مصرف کنه. این ویژگی برای برنامه‌هایی که نیاز به سرعت بالا دارن، مثل سیستم‌عامل‌ها یا بازی‌های ویدیویی، حیاتیه. دوم اینکه، شما می‌تونید حافظه رو دقیقاً به شکلی که نیاز دارید مدیریت کنید؛ مثلاً یه ساختار داده پیچیده بسازید و فقط همون مقدار حافظه‌ای که لازمه رو تخصیص بدید.</p><h4>مثال عملی</h4><p>فرض کنید می‌خواید یه لیست پویا از اعداد بسازید. در C، می‌تونید این کار رو با یه اشاره‌گر و تخصیص حافظه انجام بدید:</p><pre spellcheck="" class="ipsCode language-c" data-language="C"><code>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

int main() {
    int *numbers;
    int size = 5;
    numbers = (int *)malloc(size * sizeof(int)); // تخصیص حافظه برای 5 عدد
    if (numbers == NULL) {
        printf("خطا در تخصیص حافظه!\n");
        return 1;
    }
    for (int i = 0; i &lt; size; i++) {
        numbers[i] = i + 1;
    }
    for (int i = 0; i &lt; size; i++) {
        printf("%d ", numbers[i]);
    }
    free(numbers); // آزادسازی حافظه
    return 0;
}</code></pre><p>این کد نشون می‌ده که چطور حافظه تخصیص داده می‌شه، استفاده می‌شه و بعد آزاد می‌شه. اگه <code>free()</code> رو فراموش کنید، با مشکل <strong>Memory Leak</strong> مواجه می‌شید که حافظه به طور بیهوده اشغال می‌مونه.</p><h4>چالش‌ها و مسئولیت‌ها</h4><p>با این همه قدرت، یه مسئولیت بزرگ هم میاد. مدیریت نادرست حافظه می‌تونه به مشکلاتی مثل <strong>Memory Leak</strong>، <strong>Dangling Pointers</strong> (اشاره‌گرهایی که به حافظه آزادشده اشاره می‌کنن) یا <strong>Segmentation Fault</strong> منجر بشه. برای همین، برنامه‌نویس باید دقت زیادی داشته باشه و همیشه مطمئن بشه که هر حافظه‌ای که تخصیص داده، در زمان مناسب آزاد می‌شه.</p><h4>نتیجه‌گیری</h4><p>مدیریت دستی حافظه در C مثل یه شمشیر دو لبه‌ست: هم قدرت فوق‌العاده‌ای به برنامه‌نویس می‌ده و هم نیاز به دقت و مهارت داره. این قابلیت باعث شده C همچنان انتخاب اول برای پروژه‌هایی باشه که نیاز به کنترل سطح پایین و بهینه‌سازی دقیق دارن. اگه دنبال زبانی هستید که شما رو مجبور کنه عمیق‌تر به عملکرد سیستم فکر کنید و در عین حال انعطاف‌پذیری بالایی بهتون بده، C و مدیریت دستی حافظه‌ش یه گزینه بی‌رقیبه.</p>]]></description><guid isPermaLink="false">4</guid><pubDate>Wed, 18 Sep 2024 09:13:50 +0000</pubDate></item><item><title>&#x622;&#x634;&#x646;&#x627;&#x6CC;&#x6CC; &#x628;&#x627; GMP &#x62F;&#x631; PHP: &#x627;&#x628;&#x632;&#x627;&#x631; &#x642;&#x62F;&#x631;&#x62A;&#x645;&#x646;&#x62F; &#x628;&#x631;&#x627;&#x6CC; &#x645;&#x62D;&#x627;&#x633;&#x628;&#x627;&#x62A; &#x627;&#x639;&#x62F;&#x627;&#x62F; &#x628;&#x632;&#x631;&#x6AF;</title><link>https://sinajalalvandi.ir/blog/programming/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-gmp-%D8%AF%D8%B1-php-%D8%A7%D8%A8%D8%B2%D8%A7%D8%B1-%D9%82%D8%AF%D8%B1%D8%AA%D9%85%D9%86%D8%AF-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%85%D8%AD%D8%A7%D8%B3%D8%A8%D8%A7%D8%AA-%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF-%D8%A8%D8%B2%D8%B1%DA%AF-r2/</link><description><![CDATA[
<p><img src="https://sinajalalvandi.ir/uploads/monthly_2025_03/php_gmp_9f80ad063b.webp.86051fa741010a7a1f41af6398a74661.webp" /></p>
<p>در دنیای برنامه‌نویسی، گاهی نیاز داریم با اعدادی کار کنیم که از حد معمول بزرگ‌تر یا پیچیده‌تر هستند. مثلاً اعداد بسیار بزرگ در رمزنگاری، محاسبات ریاضی پیشرفته یا حتی مسائل علمی. زبان برنامه‌نویسی PHP به‌صورت پیش‌فرض برای کار با اعداد معمولی طراحی شده، اما وقتی پای اعداد بزرگ یا محاسبات دقیق به میان میاد، نیاز به ابزاری قوی‌تر احساس می‌شه. اینجا GMP (مخفف GNU Multiple Precision) وارد صحنه می‌شه. تو این مقاله قراره به‌طور کامل با GMP در PHP آشنا بشیم، کاربردهاش رو بررسی کنیم و ببینیم چطور می‌تونیم ازش استفاده کنیم.</p><h4>GMP چیه و چرا مهمه؟</h4><p>GMP یه کتابخونه متن‌باز (open-source) هست که برای انجام محاسبات دقیق روی اعداد بزرگ و اعداد صحیح با دقت بالا طراحی شده. این کتابخونه ابتدا به زبان C نوشته شده، اما PHP از طریق افزونه‌ای به نام GMP (که باید نصب بشه) این امکان رو به برنامه‌نویسا می‌ده که از قابلیت‌هاش استفاده کنن. فرق اصلی GMP با روش‌های معمولی PHP اینه که محدودیت‌های اعداد صحیح یا اعشاری رو دور می‌زنه و اجازه می‌ده با اعدادی کار کنیم که شاید صدها یا هزاران رقم داشته باشن.</p><p>تو PHP، اعداد صحیح (integer) یه محدوده مشخص دارن (مثلاً در سیستم‌های ۶۴ بیتی از -2^63 تا 2^63-1). اگه بخواید یه عدد بزرگ‌تر از این محدوده رو محاسبه کنید، یا به مشکل سرریز (overflow) برمی‌خورید یا نتیجه‌تون دقیق نیست. GMP این مشکل رو حل می‌کنه و به شما اجازه می‌ده بدون نگرانی از محدودیت، محاسبات رو انجام بدید.</p><h4>نصب GMP در PHP</h4><p>برای استفاده از GMP، اول باید مطمئن بشید که این افزونه روی سرورتون نصب شده باشه. اگه از PHP روی لینوکس استفاده می‌کنید، می‌تونید با دستور زیر GMP رو نصب کنید:</p><pre spellcheck="" class="ipsCode language-plaintext" data-language="‏متن ساده ‏"><code>sudo apt-get install php-gmp</code></pre><p>بعد از نصب، باید چک کنید که تو فایل php.ini فعال باشه. برای این کار، خط زیر رو تو فایل اضافه کنید یا مطمئن بشید که وجود داره:</p><pre spellcheck="" class="ipsCode language-plaintext" data-language="‏متن ساده ‏"><code>extension=gmp</code></pre><p>اگه سرور ویندوزی دارید، باید فایل DLL مربوط به GMP رو دانلود کنید و تو تنظیمات PHP فعالش کنید. بعد از ری‌استارت سرور، با اجرای تابع phpinfo() می‌تونید ببینید که GMP فعال شده یا نه.</p><h4>کار با GMP در PHP</h4><p>حالا که GMP رو نصب کردیم، بیایم چندتا از تابع‌های مهمش رو بررسی کنیم. GMP تو PHP به‌صورت شیءگرا (object-oriented) و رویه‌ای (procedural) قابل استفادست. تو این بخش چند مثال ساده می‌زنم که بتونید سریع دست به کد بشید.</p><p><strong>   1.جمع و تفریق اعداد بزرگ:</strong> فرض کنید می‌خواهیم دو عدد خیلی بزرگ رو جمع کنیم:</p><pre spellcheck="" class="ipsCode language-php" data-language="PHP"><code>$num1 = gmp_init("12345678901234567890");
$num2 = gmp_init("98765432109876543210");
$sum = gmp_add($num1, $num2);
echo gmp_strval($sum); // خروجی: 111111111011111111100</code></pre><p>تابع gmp_init یه عدد بزرگ رو به فرمت GMP تبدیل می‌کنه. بعد با gmp_add جمع رو انجام می‌دیم و با gmp_strval نتیجه رو به رشته تبدیل می‌کنیم تا نمایش داده بشه.</p><p>   <strong>2.ضرب و تقسیم:</strong> برای ضرب از gmp_mul و برای تقسیم از gmp_div استفاده می‌کنیم:</p><pre spellcheck="" class="ipsCode language-php" data-language="PHP"><code>$product = gmp_mul($num1, $num2);
echo gmp_strval($product); // یه عدد خیلی بزرگ!</code></pre><p><strong>  3.توان و ریشه:</strong> اگه بخواید یه عدد رو به توان برسونید، از gmp_pow استفاده کنید:</p><pre spellcheck="" class="ipsCode language-php" data-language="PHP"><code>$power = gmp_pow($num1, 3); // num1 به توان 3
echo gmp_strval($power);</code></pre><p><strong>   4.مقایسه اعداد:</strong> برای مقایسه دو عدد بزرگ، تابع gmp_cmp به کار می‌ره:</p><pre spellcheck="" class="ipsCode language-php" data-language="PHP"><code>$result = gmp_cmp($num1, $num2);
if ($result &gt; 0) {
    echo "عدد اول بزرگ‌تره";
} elseif ($result &lt; 0) {
    echo "عدد دوم بزرگ‌تره";
} else {
    echo "برابرن";
}</code></pre><h4>کاربردهای GMP</h4><p>GMP فقط برای جمع و تفریق اعداد بزرگ نیست. تو زمینه‌های مختلفی مثل رمزنگاری (مثلاً الگوریتم RSA)، محاسبات علمی، و حتی بازی‌سازی که نیاز به دقت بالا داره، استفاده می‌شه. مثلاً تو RSA، شما باید با اعداد اول خیلی بزرگ کار کنید که GMP این کار رو راحت می‌کنه.</p><h4>مزایا و معایب</h4><p>مزایای GMP واضحه: دقت بالا، پشتیبانی از اعداد بزرگ، و انعطاف‌پذیری. اما یه سری معایب هم داره. مثلاً سرعتش نسبت به عملیات معمولی PHP کمتره، چون محاسبات پیچیده‌تری انجام می‌ده. همچنین نیاز به نصب جداگانه داره که ممکنه برای همه پروژه‌ها عملی نباشه.</p><h4>جمع‌بندی</h4><p>GMP تو PHP یه ابزار قدرتمنده که به برنامه‌نویسا اجازه می‌ده از محدودیت‌های اعداد معمولی عبور کنن و با خیال راحت محاسبات پیچیده انجام بدن. اگه تو پروژه‌تون نیاز به کار با اعداد بزرگ یا دقت بالا دارید، GMP می‌تونه بهترین دوستتون باشه. با نصب ساده و توابع کاربردی، این افزونه به شما کمک می‌کنه پروژه‌هاتون رو به سطح بالاتری ببرید.</p><p></p>]]></description><guid isPermaLink="false">2</guid><pubDate>Fri, 19 Jul 2024 08:05:48 +0000</pubDate></item></channel></rss>
