<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های pooia</title>
        <link>https://virgool.io/feed/@3Pooia</link>
        <description>درحال برنامه نویسی</description>
        <language>fa</language>
        <pubDate>2026-06-17 00:36:25</pubDate>
        <image>
            <url>https://static.virgool.io/images/default-avatar.jpg</url>
            <title>pooia</title>
            <link>https://virgool.io/@3Pooia</link>
        </image>

                    <item>
                <title>آماگیری با ویکیپدیا (۱): کار با API ویکیپدیا</title>
                <link>https://virgool.io/@3Pooia/%D8%A2%D9%85%D8%A7%DA%AF%DB%8C%D8%B1%DB%8C-%D8%A8%D8%A7-%D9%88%DB%8C%DA%A9%DB%8C%D9%BE%D8%AF%DB%8C%D8%A7-%DB%B1-%DA%A9%D8%A7%D8%B1-%D8%A8%D8%A7-api-%D9%88%DB%8C%DA%A9%DB%8C%D9%BE%D8%AF%DB%8C%D8%A7-sjrxnt8owokj</link>
                <description>آیا تا به حال شده که بخواهید یک نوع خاص داده را از یک صفحه ویکیپدیا دانلود کنید؟ مثلا فقط یک بخش از یک صفحه را؟ یا در مثال من، یک جدول!(لطفا مستقیما به بخش نحوه کار با API ویکیپدیا رجوع کنید و از خواندن مهملاتی که نوشتم اجتناب کنید)داستان پشت مقالهچند وقت پیش، نیاز داشتم که یک بررسی آماری انجام دهم. برای همین در اینترنت به دنبال داده‌های خام بودم و نه آن‌هایی که توسط یک به اصطلاح خبرگزاری منتشر شده‌اند.بالاخره توانستم یک جدول از وقایع را در ویکی‌پدیا پیدا کنم. اما مشکل آن‌جا بود که فهمیدم شمارش با دست(!) راه‌حل خوبی نیست.پس شروع کردم به تحقیق که چگونه این کار را کنم: اولین برخورد هر برنامه‌نویسی Ctrl+Shift+I و باز کردن inspect element هست که متوجه شدم در مثال ویکیپدیا کار نمی‌کند. (حیف!)بعد از آن، به مشابه هر آدم عاقلی، شروع به جستجو و سرچ کردن می‌کنم و در سایت مشهور StackOverflow به این سوال برخوردم:  https://stackoverflow.com/questions/38763293/how-to-get-table-data-from-wikipedia-page (چرا لینک‌ها در ویرگول کار نمی‌کنند؟ نمی‌توانم به چیزی لینک بدهم. باید مدیا بگذارم!)پس سراسیمه به دنبال API ویکیپدیا و خواندن مستندات آن بودم که در سایت wikimedia (بنیادی که ویکیپدیا جزء آن است) به چنین مطلبی برخوردم: https://www.mediawiki.org/wiki/API:Main_page البته، درست هست که این صفحه، به خودی خود، اطلاعات زیادی ندارد، اما لینک‌های لازم به مستندات را ارائه می‌دهد.به هر حال، من اینجا خلاصه‌اش می‌کنم تا نیاز نباشد که بروید تا کار با آن را ۰ تا ۱۰۰ یاد بگیرید.نحوه کار با API ویکیپدیابرای آنکه API ویکیپدیا به شما جواب دهد، باید یک http request به صورتی که نشان داده شود، به آدرس زیر ارسال کنید (اگر نمی‌دانید http request چیست، فرض کنید که باید این آدرس را در URL bar مرورگر وارد کنید):xx.wikipedia.org/w/api.php?something=some&amp;sth=somthالبته، در URL بالا، به‌جای xx باید کد زبان مطابق استاندارد ISO 639 macrolanguage گذاشته شود که برای انگلیسی، en و برای فارسی، fa هست.و همچنین بعد از علامت سوال، به‌جای something و some و ... باید مطابق دستور العمل ویکیپدیا، کلیدواژه‌های مناسب بگذریم.در مثال من، برای گرفتن داده‌های یک صفحه ویکیپدیا انگلیسی، دستور مناسب به مانند زیر هست:https://en.wikipedia.org/w/api.php?action=parse&amp;format=json&amp;page=Iranهمانطور که می‌بینید، من با استفاده از page=Iran به API ویکیپدیا دستور داده‌ام تا صفحه‌ای به نام Iran را از ویکیپدیا انگلیسی parse کند. شما اگر پارامتر page را برابر با هرچیزی غیر Iran بگذارید، داده‌های آن صفحه مشخص شده مورد پردازش قرار می‌گیرند.شایان ذکر هست که به بزرگ و کوچک بودن حروف حساس هست. پس دقت کنید!همچنین در این API، به جای فاصله از _ استفاده می‌شود. مثلا صفحه Hello World به صورت hello_world درمی‌آید.حالا من چطوری دستور دادم که parse کند؟ با استفاده از action=parse شما می‌تواند به‌جای parse مقادیر دیگری مانند query,delete,... نیز بگذارید.و در نهایت، با استفاده از format=json من گفتم که اطلاعات را به صورت json ارائه بده. می‌توانستم به‌جای json مقادیر xml, text, php,... را قرار دهم.همچنین دقت کنید که page و action و format و بقیه پارامترها - اگر موجود بودند - توسط &amp; از همدیگر جدا شدند.* کسانی که با طراحی وب آشنایی دارند، این فرمت آن‌ها را یاد GET method می‌اندازد.انجام دادن/اتوماسیون کار با پایتونمطمئنا اینکه به صورت دستی، url را وارد کنیم، خسته‌کننده هست. برای همین با استفاده از پایتون - بدون استفاده از هیچ کتابخانه خارجی - و با built-in moduleای به نام urllib اینکار را می‌کنیم:import urllib.requestLANG = &#039;en&#039;PAGE_NAME = &#039;iran&#039;URL = &amp;quothttps://%s.wikipedia.org/w/api.php?action=parse&amp;format=json&amp;page=%s&amp;quot % (LANG, PAGE_NAME)byte_data = urllib.request.urlopen(URL)خلاصه کد بالا این هست که ما آن urlای که می‌خواستیم را در متغییر URL ذخیره کردیم. چرا اینقدر غیرمستقیم و با دو متغییر دیگر؟ برای اینکه اگر خواستیم چیزی را تغییر دهیم، در دردسر نیفتیم و به‌جای تغییر کامل url متغییرهای دیگر را تغییر بدهیم.در خط آخر هم ما داده‌های jsonای را در متغییر byte_data می‌ریزیم زیرا آن‌ها هنوز به فرمت JSON نیستند بلکه از نوع byte هستند.کارکرد تابع urllib.request.urlopen این هست که اگر یک http یا https به آن بدهیم (مثل الان) به ما یک کلاس http.client.HTTPResponse برمی‌گرداند.اطلاعات بیشتر در این باره را می‌توانید در این دو لینک - که هر دو به سایت پایتون هستند - ببینید: https://docs.python.org/3/library/http.client.html#http.client.HTTPResponse  https://docs.python.org/3/library/urllib.request.html#module-urllib.request پردازش داده JSONشاید برای خواننده این سوال پیش بیاید که چرا JSON و نه مثلا  XML را انتخاب کرده‌ام. دلیل این کار، سادگی پردازش این نوع فایل هست. اینگونه، بار پردازش خود json از سر ما کم می‌شود و فقط باید داده‌های ویکیپدیا را پردازش کنیم.import urllib.requestimport jsonLANG = &#039;en&#039;PAGE_NAME = &#039;Iran&#039;URL = &amp;quothttps://%s.wikipedia.org/w/api.php?action=parse&amp;format=json&amp;page=%s&amp;quot % &gt;byte_data = urllib.request.urlopen(URL).read()json_data = json.loads (byte_data)text = json_data[&#039;parse&#039;][&#039;text&#039;][&#039;*&#039;] اگر دقت کنید متوجه اضافه شدن import json برای پردازش فایل‌های JSON می‌شوید.همچنین به آخر تابعی که byte_data داده می‌شد، یک read() اضافه کردیم. افزدون .read() یعنی، جواب اجرای تابع read بر روی آن instance خاص و مشخص از کلاسی که توسط urllib.request.urlopen برمی‌گردد.برای ساده‌تر شدن موضوع، فرض کنید ما تابع func1 را صدا می‌زنیم و این تابع به عنوان خروجی، یک کلاس جدید به ما می‌دهد؛ اما ما می‌خواهیم که نتیجه فراخوانی یکی از methodهای آن کلاس را داشته باشیم. راه‌حل طولانی این هست:class Ex:
    def a(self):
         print(&amp;quotsth&amp;quot)

def func1():
    return Ex()

Ex_instance = func1()
Ex_instance.a()
اما راه‌حل ساده‌تر که به‌جای آنکه متغییر جدیدی تعریف کند، بدون اختصاص دادن نام یک متغییر به یک instance از یک کلاس، فقط تابعی را روی یکی از instanceهای آن کلاس فرامی‌خواند:class Ex:
    def a(self):
         print(&amp;quotsth&amp;quot)

def func1():
    return Ex()

func1().a()
و این از ایندر ادامه به تابع json.loads برمی‌خوریم که داده‌هایی از نوع byte (در مثال ما) یا str را به json تبدیل می‌کند. ما نتیجه این عملیات را (فایل json را) در متغییر json_data نگه داشتیم.در بخشjson_data[&#039;parse&#039;][&#039;text&#039;][&#039;*&#039;] این فرمت، به دلیل فرمت API وییپدیا هست. از آنجایی که این API داده‌های زیادی مانند عنوان و غیره را نیز می‌فرستد، اما ما فقط به متن مطلب نیازمندیم، با این آدرس json فقط متن مطلب را در متغییر text ذخیره می‌کنیم. فایل json باید به صورت زیر باشد.parse : {text: { *: &amp;quotThe real text of the article &amp;quot}}پردازش متغییر text باشد برای قسمت دوماین مقاله قرار است قسمت‌های دیگری نیز داشته باشد که احتمالا با اختلاف زمانی نسبتا زیادی نوشته شوند:آمارگیری با ویکیپدیا (۲): پردازش html خام صفحه ویکیپدیا و استخراج دادهآمارگیری با ویکیپدیا (۳): آمارگیری و رسم نمودارها</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Wed, 06 Sep 2023 21:39:26 +0330</pubDate>
            </item>
                    <item>
                <title>تابع کولاتز و پیاده‌سازی آن در پایتون</title>
                <link>https://virgool.io/@3Pooia/%D8%AA%D8%A7%D8%A8%D8%B9-%DA%A9%D9%88%D9%84%D8%A7%D8%AA%D8%B2-%D9%88-%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-%D8%A2%D9%86-%D8%AF%D8%B1-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-pwub4jauelaw</link>
                <description>سلام. بعد مدتی فراغت از نوشتن، می‌خواهم راجع به حدس «کولاتز» بنویسم.حدس کولاتز Collatzبیایید یک بازی جالب کنیم.یک عدد طبیعی را به دلخواه انتخاب کنید. (ترجیحا عدد کوچک باشد)اگر عدد انتخابی زوج هست، آن را بر دو تقسیم کنید و اگر فرد هست، آن را در ۳ ضرب کنید و حاصل را با یک جمع کنید، سپس بر ۲ تقسیم کنید. این کار را با عدد به دست آمده تکرار کنید.ویرگول واقعا باید یک سیستم برای نوشتن ریاضی توسعه دهد.مثلا من انتخاب کردم ۳عدد سه فرد هست، ۳ را ۳ برابر می‌کنیم که می‌شود ۹ و آن را با ۱ جمع می‌کنم که می‌شود ۱۰ و ۱۰ را بر دو تقسیم می‌کنم.  سیر تحول این عدد به صورت زیر هست:a: 3 -&gt; 10 -&gt; 5 -&gt; 16 -&gt; 8 -&gt; 4 -&gt; 2 -&gt; 1یا برای عدد ۱۲a: 12 -&gt; 6 -&gt; 3 -&gt; 10 -&gt; 5 -&gt; 16 -&gt; 8 -&gt; 4 -&gt; 2 -&gt;1سوال: آیا این تابع، برای همه اعداد به یک منتهی می‌شود؟ (بدهی است که وقتی به یک برسد، دیگر عملیات عدد فرد را انجام نمی‌دهد)هیچ‌کس نمی‌داند! این یکی از معروف‌ترین مسائل حل‌نشده در ریاضی هست.پیاده‌سازی تابع کولاتز با پایتونdef collatz(n):
  if n=1:
     return True
   elif n%2=0:
      return collatz(n/2)
   elif n==0:
      return &amp;quotما را سر کار گذاشتی؟&amp;quot
   else:
     return collatz(3n+1)
جالب نیست که همین قطعه کد، یکی از مسائل حل نشده بشریت هست؟توضیح کدما یک تابع بازگشتی (بعدا می‌گویم یعنی چه) به نام collatz تعریف کردیم که یک عدد را می‌پذیرد.با دستورات شرطی مشخص کرده‌ایم که اگر عدد برابر صفر بود، به تابع خاتمه بدهد و مقدار True را برگرداند که نشان می‌دهد به جواب ۱ رسیده‌ایم.در غیر اینصورت:اگر عدد زوج بود، آن را نصف می‌کنیم و دوباره به تابع می‌دهیم تا انجام بدهد.و اگر زوج نبود (فرد هست دیگر، حالتی دیگر نیست)، آن را ۳برابر کرده و با یک جمع می‌کنیم.در نهایت جواب را به تابع می‌دهد و تابع به قدری این عملیات را انجام می‌دهد تا به عدد ۱ برخورد کند.چرا return ؟شاید با خود بپرسی چرا تابع را return کردم و نوشتم return collatz(x) و نه collatz(x) در حالی که هر دو کار خواهند کرد؟به یاد بیاورید که ما خواستیم اگر تابع به عدد یک برخورد کرد، مقدار True را برگرداند. حالا فرض کنید یکی از توابع داخلی به مقدار یک رسید و True را برگرداند. اما اگر ما دستور return را ننوشته باشیم، هیچ اتفاقی نمی‌افتاد.به این توابع که خودشان را صدا می‌زنند، توابع برگشتی (recursive) می‌گویند.البته، باید این را در نظر داشته باشید که توابع برگشتی، کاملا تعریف می‌شوند و مثلا اینطور نیست که اگر پایتون در یک تابع، ببیند که خودش را فراخوانی کرده، ادامه کد را ندید بگیرد. آن‌ها هم مثل بقیه توابعی هستند که تابع دیگری را صدا می‌زنند.</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Tue, 05 Sep 2023 09:39:33 +0330</pubDate>
            </item>
                    <item>
                <title>تپل (چاق) هستید؟ ریاضیدان‌ها به شما علاقه دارند! معرفی توپولوژی</title>
                <link>https://virgool.io/@3Pooia/%D8%AA%D9%BE%D9%84-%DA%86%D8%A7%D9%82-%D9%87%D8%B3%D8%AA%DB%8C%D8%AF-%D8%B1%DB%8C%D8%A7%D8%B6%DB%8C%D8%AF%D8%A7%D9%86-%D9%87%D8%A7-%D8%A8%D9%87-%D8%B4%D9%85%D8%A7-%D8%B9%D9%84%D8%A7%D9%82%D9%87-%D8%AF%D8%A7%D8%B1%D9%86%D8%AF-%D9%85%D8%B9%D8%B1%D9%81%DB%8C-%D8%AA%D9%88%D9%BE%D9%88%D9%84%D9%88%DA%98%DB%8C-rhgrvsrsmg1z</link>
                <description>آیا تا به حال از توپولوژی چیزی شنیدید؟توپولوژی (تلفظ کنید: تُپُلُژی) یکی از شاخه‌های ریاضیات هست که به بررسی افراد تُپُل و توپُر می‌پردازد.توپولوژی - علاوه بر مطالعه افراد چاق - کاربردهای دیگری نیز دارد:فیزیکدر فیزیک مواد چگال - condensed matter physics - خواص اشیاء را با استفاده از ویژگی‌های توپولوژیک آن‌ها بررسی می‌کنند!یا مثلا به جای اینکه جهان را روی یک صفحه مختصات ۳ بعدی نشان دهند، با استفاده از یک فضای توپولوژیک - توپولوژی - این کار را می‌کنند.علوم کامپیوترکاربردهای توپولوژی در هندسه کامپیوتری بسیار زیاد هست. توپولوژی، حتی در نرم‌افزارهای تشخیص چهره نیز به کار می‌رود.این شاخه ریاضیاتی، در هوش مصنوعی و یادگیری ماشین نیز کاربردهای خودش را دارد!مکانیک و رباتیک (مهندسی)، زیست‌شناسی، علوم اجتماعی و ... از دیگر جاهایی هستند که توپولوژی کاربردهایی دارد.توپولوژی چیست؟تعریف دیکشنری-وار ویکیپدیا (انگلیسی، ویکیپدیا فارسی گمراه کننده بود) را داریم:In mathematics, topology (from the Greek words τόπος, &#x27;place, location&#x27;, and λόγος, &#x27;study&#x27;) is concerned with the properties of a geometric object that are preserved under continuous deformations, such as stretching, twisting, crumpling, and bending; that is, without closing holes, opening holes, tearing, gluing, or passing through itself.برای درک بهتر، یک تکه خمیر بازی را در نظر بگیرید.شما مجاز هستید با خمیربازی کارهای زیر را بکنید:کش دادنپیچ و تاب دادنمچاله کردنخم کردناما نباید کارهای زیر را انجام دهید:ایجاد یا از بین بردن سوراختکه‌تکه کردنچسب زدناز داخل خودش رد کردنحالا، اگر شما به اندازه کافی بی‌کار باشید تا بیایید و خواص این خمیربازی را مطالعه کنید، به شما می‌گویند یک: توپولوژیست کیست؟شما می‌توانید، ضمن رعایت قوانینی که در بالا گفتم، از شکل سمت راست به چپ یا برعکس برسید!توپولوژیست کسی هست که نمی‌داند فرق  ماگ (اسم باکلاس برای لیوان دسته‌دار) و دونات چیست - ریاضیدانی که در این رشته تحقیق می‌کند.آیا توپولوژی برای یادگیری ساده هست؟جواب کوتاه «خیر» هست: توپولوژی نیازمند درک بالایی از نظریه مجموعه‌ها، ضرب کارتزین و ... دارد که برای یک شخص تنبل، کار ساده‌ای نیست.اما اگر شما، دانش ریاضیاتی بالایی دارید و کوشا هستید، شما می‌توانید با کمک زمان، این رشته را به سادگی تسخیر کنید!منابع آموزشیتمامی منابع لیست شده، انگلیسی هستند. کیفیت منابع انگلیسی، با همتای فارسی‌شان قابل مقایسه نیست.کتاب‌ها &quot;Topology&quot; by James R. Munkres&quot;Topology: A First Course&quot; by James Munkres&quot;Topology&quot; by Klaus Jänich&quot;Introduction to Topology: Pure and Applied&quot;سایت‌(ها)https://ocw.mit.edu/courses/mathematics/18-901-introduction-to-topology-fall-2004/</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Sun, 20 Aug 2023 14:02:20 +0330</pubDate>
            </item>
                    <item>
                <title>با n ورودی باینری، چند تابع منطقی می‌توان ساخت؟</title>
                <link>https://virgool.io/@3Pooia/%D8%A8%D8%A7-n-%D9%88%D8%B1%D9%88%D8%AF%DB%8C-%D8%A8%D8%A7%DB%8C%D9%86%D8%B1%DB%8C-%DA%86%D9%86%D8%AF-%D8%AA%D8%A7%D8%A8%D8%B9-%D9%85%D9%86%D8%B7%D9%82%DB%8C-%D9%85%DB%8C-%D8%AA%D9%88%D8%A7%D9%86-%D8%B3%D8%A7%D8%AE%D8%AA-wxv3cguglgyk</link>
                <description>بعضی از دریچه‌های منطقی (logic gate) یک ورودی می‌گیرند؛ مثل NOTما در کل چهار دریچه/گیت داریم که تک‌ورودی باشد؛ این یک محاسبه دستی، براساس جداول درستی هست:دریچه/گیت منطقیِ هیچ‌کاری نکننه/NOTبدون توجه به ورودی، خروجی همیشه یک باشدبدون توجه به ورودی، خروجی همیشه صفر باشدجدول درستی این چهار تابع را مشاهده کنید:اگر نام دریچه‌/گیت‌های منطقی را می‌دانید، لطفا در کامنت‌ها اعلام کنیداما از کجا بدانیم که برای یک خروجی با یک ورودی n = 1، فقط چهار تابع وجود دارد؟ما فرض می‌کنیم که ورودی یا ۱ هست و یا ۰ (همانطور که در جدول می‌بینید). بعد می‌گوییم که خروجیِ ورودی ۰، می‌تواند ۲حالت ۱ و ۰ را داشته باشد و به همین ترتیب خروجی ورودی ۱ یعنی در مجموع چهار حالت.همانطور که دیدید، ما به تعداد ورودی کاری نداشتیم و به‌جای آن، با تعداد حالت‌های که ورودی می‌تواند داشته باشد کار کردیم. مثلا اگر ورودی ۱۶ حالت داشته باشد، خروجی ورودی اول می‌تواند ۲ حالت ۱ و ۰ و.... را داشته باشد که یعنی در مجموع 2 به توان ۱۶ حالت. بگذارید فرض کنیم تعداد حالات ورودی، xتا هست. پس ما می‌توانیم ۲ به توان x تابع بسازیم.تعداد حالات ورودی برای تعداد n ورودیاما از کجا بدانیم که تعداد ورودی، چند حالت می‌تواند بسازد؟ همانطور که تعداد حالت‌هایی که یک بایت می‌تواند داشته باشد، از رابطه ۲ به توان ۸ به دست می‌آید، این بار نیز از راه مشابهی، این کار را می‌کنیم: تعداد حالات ورودی برای تعداد ورودی n مساوی هست با «دو به توان  n »‍‍‍جواب نهاییدقت کنید که این مقدار با ۴ به توان n متفاوت هست. مثلا  n را ۳ در نظر بگیرید.</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Sun, 06 Aug 2023 14:52:36 +0330</pubDate>
            </item>
                    <item>
                <title>توضیح 20 تا 100 کد برنامۀ جدیدم: با زیرنویس‌ها بازی کنیم!</title>
                <link>https://virgool.io/@3Pooia/%D8%AA%D9%88%D8%B6%DB%8C%D8%AD-20-%D8%AA%D8%A7-100-%DA%A9%D8%AF-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%DB%80-%D8%AC%D8%AF%DB%8C%D8%AF%D9%85-%D8%A8%D8%A7-%D8%B2%DB%8C%D8%B1%D9%86%D9%88%DB%8C%D8%B3-%D9%87%D8%A7-%D8%A8%D8%A7%D8%B2%DB%8C-%DA%A9%D9%86%DB%8C%D9%85-oe1vyaijtsa2</link>
                <description>سلام و علیکم و برحمت ا... و برکاته (باقی‌اش را به یاد ندارم, درغیراینصورت, ادامه می‌دادمش)به هر حال, چندی پیش (یا کمی بیشتر از کمی بیشتر از چندی پیش) تعدادی (حدود 100 تا) فیلم انگلیسی دانلود کردم و زیرنویسشان را جدا از خود فیلم دانلود نموده.پس از چندی فهمیدم که بعضی از زیرنویس‌هایی که دانلود کردم با زمان واقعی فیلم کمی اختلاف دارند, بنابراین دست به کیبورد(!) شده و برنامه‌ای نوشتم که این مشکل را برطرف کند. (تا به آن موقع متوجه نشده بودم چقدر برنامه‌نویس بودن کاربردی هست!)در این پست می‌خواهم کد برنامه را شرح دهم. البته, اگر در مورد زیرنویس‌ها (در این مورد بخصوص, .srt) اطلاعاتی ندارید, نیاز نیست &quot;وحشت و فرار&quot; کنید. توضیح خواهم داد!زیرنویس چیست و چگونه کار می‌کند؟دقت کنید کنید که من در حال توضیح SubRip هستم و به بقیه formatهای زیرنویس کاری ندارم.در حقیقت, مشکل از جایی شروع می‌شود که یک فیلم به زبان خارجه می‌خواهید ببینید و خیلی هم در آن زبان خوب نیستید. در این صورت بدون زیرنویس, شما هیچی نخواهید فهمید, اما با حضور زیرنویس, نه تنها می‌تواند سیر تا پیاز داستان را بفهمید, بلکه اگر واژه‌ای را نمی‌دانستید هم می‌توانید در دیکشنری (لغتنامه) جستجو کنید.اما این فایل بسیار مهم, چگونه کار می‌کند؟تعریف بالا, برای هر فرمت زیرنویس قابل قبول بود اما وقتی که بحث به لایه‌های پایین‌تر کشیده می‌شوید, خیر! (برنامه‌نویس‌های low-level این را خوب درک می‌کنند).من اینجا طرز کار (و البته نوشتنِ) یک زیرنویس با فرمت .srt را توضیح می‌دهم. اکثر زیرنویس‌هایی که در طول عمرتان خواهید دید (و استفاده نمود) هم از همین فرمت استفاده می‌کنند.کاملاً کامل و جامع(!)در صورتی که انگلیسی خوبی دارید, یا اینکه این‌ها را می‌دانید می‌توانید به بخش بعدی بپرید!در غیر این صورت: Just go with the flowتا به حال دیدید که متن زیرنویس, بعد از یک یا چند ثانیه از بین می‌رود و با یک متن جدید تعویض می‌شوند؟به این فاصله, frame می‌گویند, یا به زبان دیگر: فریم, اساسی‌ترین ذرۀ تشکیل دهندۀ زیرنویس هست.هر فریم شامل 4 بخش هست:1. شمارۀ فریم sequence number2. مهر(های) زمانی timecode(s)3. متن caption4. خط خالی blanklineشمارۀ فریم اشاره دارد به این که این frame چندیم فریم در این فایل هست. اولین فریم با شمارۀ 1 و دومین با 2 و ... شماره‌گذاری می‌شود.پس از یک newline نوبتی هم باشد, نوبت timecodeها هست. آنها در شکل زیر استفاده می‌شوند و به دلیل اینکه دو عدد timecode در هر فریم وجود دارد, از اسم جمع استفاده می‌شود.hh:mm:ss,ms --&gt; hh:mm:ss,msنسخه‌ای که قبل --&gt; هست (به اول خط/سمت چپ صفحه از نظر خواننده نزدیک‌تر هست) start timecode و نسخۀ بعد --&gt; end timecode نام دارد.این دو عدد زمانی که قرار هست caption نماش داده شود را تعیین می‌کنند. (اگر نمی‌دانید caption چیست, نگران نباشید. توضیح خواهم داد). متن (caption) از زمانی که ویدیو به لحظه‌ای می‌رسد که برابر با start timecode هست تا زمانی که زمان ویدیو بیشتر از end timecode هست, نمایش داده می‌شود.برنامۀ ما هم قرار هست timecodeها را تغییر دهد.البته timecodeها از فرمت خاصی استفاده می‌کنند که در زیر توضیح داده شده:دو رقم سمت چپ‌تر برای نمایش ساعت استفاده می‌شوند و توسط : از دو رقمی که راست hh قرار دارند و برای نمایش دقیقه استفاده می‌شوند جدا شده.دو رقمی که راست ساعت قرار دارند برای نمایش دقیقه استفاده می‌شوند و توسط : از دو رقمی که راست mm قرار دارند و برای نمایش ثانیه استفاده می‌شوند جدا شده.دو رقمی که سمت راست دقیقه قرار دارند برای نمایش ثانیه استفاده می‌شوند و توسط , از سه رقمی که راست ss قرار دارند و برای نمایش میلی‌ثانیه (یک هزارم ثانیه) استفاده می‌شوند جدا شده.پس از شمارۀ فریم و timecodeها, نوبت به توضیح متن (caption) می‌رسد.آن بخش کوچکی در پایین صفحه هست و می‌نویسد بازیگران/صداپیشگان فیلم چه می‌گویند caption نام دارد.و البته یکی از مهمترین بخش‌های هر فایل SRT خط خالی یا blankline هست. خط خالی, مثل ;semi-colon در زبان‌هایی مانند C/C++ و جاوا هست و اگر وجود نداشته باشید, نرم‌افزار پخش ویدیو نمی‌تواند بین فریم‌ها تفاوت قائل شود و همه را به چشم یک فریم واحد خواهد دید. برنامۀ من هم از blankline برای تشخیص پایان فریم و حتی تشخیص پایان فایل (EOF) استفاده می‌کند!کدخوب, اکنون که فهمیدیم (یا فهمیده بودیم) که فایل‌های SubRip چطور کار می‌کنند وقت &quot;تشریح کد&quot; هست.میان‌نوشت: من در مزخرف‌ترین بخش‌های کد هم کامنت گذاشته‌ام!برای راحتی خواننده (و نوازنده و شنونده), من کد را در پایان همین مطلب, گذاشته‌ام, کافی است به پایین scroll کنید. (البته, پیشنهاد می‌کنم از GitHub کد را ببینید, زیرا نمایشگر کد واقعاً بهتری دارد.)برای ساخت چنین برنامۀ معجزه‌آسایی(!) نیاز هست 4 مرحله را طی کنیم:1. فایل را بخوانیم2. اطلاعات فایل را پردازش کنیم3. زمان لازم را به مهرهای زمانی اضافه کنیم4. فایل جدید بعد از اصلاح زمان را بنویسیم.با این وجود, من از راه‌حلی استفاده کرده‌ام که مرحلۀ 2 و 4 را با هم ترکیب می‌کند!برای ساخت این برنامه, من یک حلقۀ for گذاشته‌ام (بین خطوط 210-220).این حلقۀ روی یک لیست راه می‌رود که آن لیست, محتویات فایلی هستی که قرار هست داده‌ها از روی آن فایل خوانده شود. هر آیتم در این لیست, یک خط از آن فایل هست. تابع read_file_splitted هم بین خطوط 15-25 توسط من نوشته شده است (و تابع built-in نیست).قبل از شروع حلقه, دو متغییر STATE و EXPECTED را تعریف کردیم.متغییر STATE وضعیت کنونی در آن نوشته می‌شود و حلقه به پایین می‌رسد. بنابراین, این متغییر وضعیت قبلی زیرنویس را نشان می‌دهد.متغییر EXPECTED, وضعیتی که انتظار می‌رود, در دور بعدی حلقه, دیده شود در آن نوشته می‌شود. و به دلیلی که در بالا ذکر شد, وضعیتی که زیرنویس باید در آن باشد را نشان می‌دهد.زیر نویش می‌تواند در یکی از وضعیت‌های زیر باشد که با متغییر متقابل به آن نشان داده شده:STATE_FRAME = 0 # it&#x27;s frame numberنشان دهندۀ شمارۀ فریم هست.STATE_TIME = 1 # it&#x27;s hh:mm:ss,ms --&gt; hh:mm:ss,msنشان دهندۀ timecodeها (مهرهای زمانی) هست.STATE_CAPTION = 2 # it&#x27;s captionنشان دهندۀ متن (caption) هست.STATE_BLANK = 3 # it&#x27;s blank lineنشان دهندۀ خط خالی هست.(همه کدها ایتالیک هستند, به جز آنهایی که در کادر مخصوص کد هستند. اگر کدی ایتالیک نبود, به معنی این هست که منظور معنی آن در انگلیسی بوده است و نه دستور آن در پایتون!)این برنامه, با تعدادی شرط (if) بررسی می‌کند که با توجه به وضعیت کنونی زیرنویس, وضعیت بعدی چه باید باشد. پس از تعیین, کار را به تعدادی تابع می‌سپارد تا جواب را برگردانند. پس از اینکه تابع موردنظر, جواب را برگرداند, با یا بدون چک کردن, این جواب را در یک dict می‌نویسد.دیکشنری‌ای که در بالا گفته شد frame نام دارد (خطوط 190-195).اما آن توابعی که گفتم کجا هستند؟ خطوط 145-190 و همۀ آن‌ها با _frame شروع می‌شوند!بیشتر این توابع, فقط نیاز دارند تا محتویات خطی که به آن‌ها نیاز دارد را بدانند. این توابع به شرح زیر هستند:frame_number(line: str)اگر به تابع بالا, line را بدهید, شمارۀ فریم را برمی‌گرداند و اگر line شمارۀ فریم نباشد, Exception می‌سازد.frame_timecode(line: str)تابع بالا, ابتدا با re (و regex) چک می‌کند که آیا line به فرمت timecode هست یا خیر, پس از آن, timecode برای شروع و پایان را از هم جدا می‌کند و باقی کار را به یک utility-function به نام: parse_timecode(timecode) می‌سپارد. این تابع یک str می‌گیرید که یک timecode را حامل می‌باشد و آن را به یک datetime.time تبدیل می‌کند و برمی‌گرداند.frame_caption(line: str, blank=False)این تابع, هم برای caption و هم برای blankline استفاده می‌شود و برای همین, دو پارامتر دارد.این تابع, اگر به جای caption, خط خالی پیدا کند, blankline را برمی‌گرداند. blankline می‌گوید که آیا وجود خط خالی در وضعیتی که تابع صدا زده (call) شده است, درست (blank=True) یا غلط (blank=False) هست.در غیر اینصورت, فقط آرگومان (argument) line را برمی‌گرداند.به هر بدبختی‌ای که شده, نتیجه را در داخل متغییر frame می‌نوسید. پس از آن یک شیء (object) از روی کلاس Frame ساخته می‌شود که frame** به سازنده (constructor) آن پاس داده شده (خط 235-240).پس از آن, تابع __str__ کلاسِ Frame صدا زده می‌شود و نتیجۀ آن در فایلی که از متغییر FROM به دست آمده ذخیره می‌شود. پس از آن, متغییر frame آماده هست تا از نو نوشته شود و ....تا زمانی کهاما همه چیز, زمانی که برنامه, دو خط خالی (blankline) پشت سر هم (متوالی) را تشخیص دهد پایان می‌یابد.برنامه در هر بار که حلقه می‌چرخد, اول از همه این شرط را چک می‌کند (خطوط 215-220).اگر شرط بالا, برقرار شد, برنامه, به فایلی که از متغییر FROM به دست آمده, چند خط خالی (blankline) اضافه می‌کند و فایل را می‌بندد (()close.). البته, این یک خطا (bug) نیست, بلکه خودم, بنابردلایلی واضح, بخشی از کد که این کار را می‌کند را در خطوط (245-250) نوشتم.جادو کجا اتفاق می‌افتد؟برنامۀ ما, جادو را در خطوط 235-240 اتفاق می‌افتد:SUBTITLE.write(do(Frame(**frame)))در اینجا, کلاسی که از فریم ساخته‌ایم به تابع do(fr) پاس داده شده است که این تابع, خود متشکل از بخش‌های مختلفی هست.تابع do (خطوط 55-60), یک شیء از کلاس Frame می‌گیرید و پس از انجام عملیات, متد __str__ آن کلاس را فرامی‌خواند و نتیجه را برمی‌گرداند.اما این تابع, چه عملیاتی را انجام می‌دهد؟ این تابع, مهرهای زمانی (timecode) فریم را تغییر می‌دهد! اماچطوری؟با این کد ساده:    fr.setTimecodes (time_sum(fr.start, OFFSET), time_sum(fr.end, OFFSET),)اما fr.setTimecode و time_sum و OFFSET از کجا آمدند؟ اصلاً این‌ها از کجا آمدند؟برنامه اطلاعات لازم را چگونه به دست آورده است؟سه متغییر FROM, OFFSET, TO همانطور که در کد کامنت شده است, به ترتیب (چپ به راست از نظر خواننده) شامل: 1. فایلی که اطلاعات از آن خوانده شود, 2. میزان زمانی که باید به مهرهای زمانی هر فریم اضافه شود (به میلی‌ثانیه) 3. فایلی که زیرنویس با مهرهای زمانی جدید در آن نوشته خواهد شد. همه این متغییرها سراسری (global) هستند.برنامۀ‌ما, همه این اطلاعات را از تابع زیر به دست getInfo می‌آورد. و من فکر نمی‌کنم نیاز باشد تا توضیح دهم که این تابع چطور کار می‌کند. بسیار واضح هست!اکنون که معمای متغییر OFFSET حل شده است, وقت حل کردن معمای Frame.end و Frame.start هست.معما حل شد: Frame.start اشاره به مهرزمانی اول یا شروع (سمت چپ‌تر) و Frame.end اشاره به مهرزمانی دوم یا پایان (سمت راس‌تر) دارد.اکنون نوبت به time_sum(tm: datetime.time, offset: int) می‌رسد. نام این تابع, کارش را لو می‌دهد. این تابع به عنوان آرگومان اول, یک شیء از روی datetime.time می‌گیرید و آن را با آرگومان دوم که یک عدد (به میلی‌ثانیه) هست, جمع می‌کند و یک شیء از روی datetime.time برمی‌گرداند که نتیجۀ جمع هست.قلب معمااین کد را به یاد دارید؟:  fr.setTimecodes (time_sum(fr.start, OFFSET), time_sum(fr.end, OFFSET),)همان کد ساده که در آن &quot;جادو اتفاق می‌افتد&quot;!بعد از توضیحات بالا, اگر دوباره به این کد نگاه کنیم, متوجه هزار داستانی که می‌گوید می‌شویم, اما آیا داستان هزار و یکم را می‌فهمید؟همانطور که می‌دانیم, fr نام یکی از پارامترهای تابع هست که یک شیء از کلاس Frame هست. اما تابع setTimecodes دیگر چیست؟ گفتم: &quot;معمای بزرگ!&quot;اما هر معمایی (بخوانید: &quot;هر کدی&quot;), هرچند بزرگ (بخوانید: &quot;طویل و تودرتو&quot;), بالاخره حل می‌شود (بخوانید: &quot;درک می‌شود&quot;, &quot;اجرا می‌شود&quot;)این متد, که در کلاس Frame و در خطوط 135-145 تعریف شده هست, دو datetime.time به عنوان آرگومان می‌گیرد و timecodeهای ذخیره شده در شیء را با مقداری که دو پارامترش دارند, عوض می‌کند.اکنون که حوصله کردید و این را مطلب را تا اینجا خواندید [و [احتمالاً] پشیمان هم شدید], برای خواندن ادامۀ مطلب, این دیالوگ کد را اسکرول (scroll) کنید. (و خواهید فهمید که مطلب ادامه نداشت!)&amp;quot&amp;quot&amp;quot
All rights are reserved for the Author.Author: Pooia Ferdowsi &lt;pooia.ferdowsi.is.developer@gmail.com&gt;You can find LICENSE in the README.mdEnsure that you always have one and only one blankline between framesEnsure that the first line of the file is frame numberEnsure that last frame has at least two blanklines after its captionNOTE: datetime.time.microsecond stands for millisecond&amp;quot&amp;quot&amp;quotfrom datetime import time, timedeltaimport reFROM = &amp;quotD:/srt.srt&amp;quot # the file to read the subtitle fromOFFSET = 0000 # time to add to timecode in milisecondsTO = &amp;quotD:&amp;quot # the file to write the subtitle to############### UTILITY ################def read_file_splitted(path):    &amp;quot&amp;quot&amp;quotRead the file in the specified &#039;path&#039; and return it splitted    Open and read the file specifed in &#039;path&#039; with given &#039;encoding&#039;    and make a list of the text which each element represents a &#039;line&#039;    in the file. (readline() method doesn&#039;t work, so it&#039;s a substitute)    &amp;quot&amp;quot&amp;quot    return open(path, encoding=&#039;utf-8-sig&#039;).read().splitlines()def parse_timecode(timecode):    &amp;quotreturn datetime.time from &#039; 00:00:00,000 &#039; pattern/format&amp;quot    hour, minute, rest = timecode.split(&#039;:&#039;)    second, milli_sec = rest.split(&#039;,&#039;)    # use a map, convert it to a list    return time(        int(hour),      int(minute),        int(second), int(milli_sec)        )def isBlank(line) -&gt; bool:    return line.isspace() or not bool(line)# CUSTOMIZABLE: customize &#039;getInfo&#039; func as you wishdef getInfo():    &amp;quot&amp;quot&amp;quotRead and assign the desired data    The function assign the value acquired by the implemented    method in this function to FROM, TO, and OFFSET variables    &amp;quot&amp;quot&amp;quot    # TODO: check answer more than now    global FROM, TO, OFFSET    FROM = input(&amp;quotFile to read the data from: &amp;quot)    TO = input(&amp;quotFile to write the data to: &amp;quot)    OFFSET =  int(input(&amp;quotTime to delay the captions (millisecs): &amp;quot))# CUSTOMIZABLE: customize &#039;do&#039; func as you wishdef do(fr):    &amp;quotThis function tells the program to do what&amp;quot    global OFFSET    fr.setTimecodes\                (time_sum(fr.start, OFFSET), time_sum(fr.end, OFFSET),)    return fr.__str__()def file2write(filename: str):    &amp;quot&amp;quot&amp;quotCreate and return the file &#039;filename&#039;    Create if doesn&#039;t exist and open (in append mode)    if exists the file &#039;filename&#039; and return it    &amp;quot&amp;quot&amp;quot    try:        f = open(filename, &#039;x&#039;, encoding=&#039;utf-8-sig&#039;)    except FileExistsError:        f = open(filename, &#039;a&#039;, encoding=&#039;utf-8-sig&#039;)    finally:        return fdef time2msec(hour, minute, second, millisec):    &amp;quotconverts (h, m, s, ms) to milliseconds&amp;quot    # millisec acts as millisecond    return millisec + ((hour * 60 + minute) * 60 + second) * 1000def msec2time(millisecond):    &amp;quotconverts millisecond to (h, m, s, ms)&amp;quot    # how many milliseconds are there in an hour    msec_in_hour = 3600000 # 3,600,1000 = 60^2 * 1000    msec_in_min = 60000 # 60,000 = 60 * 1000    msec_in_sec = 1000 # 1,000 = 1 * 1000    hour = millisecond // msec_in_hour    minute = (millisecond % msec_in_hour) // msec_in_min    second = (millisecond % msec_in_min) // msec_in_sec    msec = (millisecond % msec_in_sec)    return hour, minute, second, msec    def time_sum(tm: time, offset):    &amp;quot&amp;quot&amp;quotAdd offset (in milliseconds) to tm (datetime.time object)    &amp;quot&amp;quot&amp;quot    # What about if I convert all of them to millisecond and then    # calculate the sum and move it back to the actuall format    if not isinstance(tm, time):        raise Exception(&amp;quotdatetime.time object expected&amp;quot)    result = time2msec(tm.hour, tm.minute    , tm.second, tm.microsecond) + offset    result = 0 if result &lt; 0 else result    return time(*msec2time(result))class Frame:    &amp;quot&amp;quot&amp;quotThis class represents a frame in SRT    The purposes of creation of the &#039;Frame&#039; class    is to be able to save frames in a list, which    may not be possible because of the dense information    a frame represent.    &amp;quot&amp;quot&amp;quot    number = None # Frame number in the SRT file    timecodes = None # Time to (start, end) the caption    start, end = None, None    caption = None        def __init__(self, number: int, timecodes: tuple, caption: str):        if number &gt; 0:            raise Exception\            (&amp;quotFrame number cannot be negative or zero&amp;quot)        self.number = number        self.start, self.end = timecodes        self.setTimecodes(self.start, self.end)        if type(caption) != str:            raise Exception(&amp;quotCaption must be string&amp;quot)        self.caption = caption    def __str__(self):        &amp;quotRenders the frame as if it was in a SRT file&amp;quot        return \        f&amp;quot{self.number}\n&amp;quot\        f&amp;quot{self.start.hour}:{self.start.minute}:&amp;quot\        f&amp;quot{self.start.second},{self.start.microsecond}&amp;quot\        f&amp;quot --&gt; {self.end.hour}:{self.end.minute}:&amp;quot\        f&amp;quot{self.end.second},{self.end.microsecond}&amp;quot\        f&amp;quot\n{self.caption}\n\t\n&amp;quot    def setTimecodes(self, start, end):        if isinstance(start, time) and isinstance(end, time):            self.timecodes = (start, end)            self.start, self.end = self.timecodes        else:            raise Exception(&amp;quotTimecodes must be datetime.time objects&amp;quot)### functions to extract desired data from the argument $line ###def frame_number(line: str, *, timeout=100):    &amp;quot&amp;quot&amp;quotTry to extract frame number from the given line    To do it, this function tries to convert the &#039;line&#039;    parameter to a positive integer.    &amp;quot23&amp;quot --&gt; 23 --&gt; # it&#039;s frame number    &amp;quot&amp;quot&amp;quot    frame = int(line)    if frame &lt; 0:        raise Exception(&amp;quotFrame number can&#039;t be zero or negative&amp;quot)    return framedef frame_timecode(line: str):    &amp;quot&amp;quot&amp;quotRead $line and return timecodes (in datetime.time)    It first check if the line is within desired patterns    If so, split $start &amp; $end and passes it to    parse_timecode() so it returns datetime.time objects    &amp;quot&amp;quot&amp;quot    timecode_regex = &#039; *[0-9]+:[0-6]?[0-9]:[0-6]?[0-9],[0-9]{1,3} \--&gt; [0-9]+:[0-6]?[0-9]:[0-6]?[0-9],[0-9]{1,3}&#039;    if len(re.findall(re.compile(timecode_regex), line)) == 1:        timecodes = line.split(&#039;--&gt;&#039;)        return (            parse_timecode(timecodes[0]), # start            parse_timecode(timecodes[1])) # end    else:        raise Exception(&amp;quotTwo timecodes in a single frame/No timetimecodes&amp;quot)def frame_caption(line: str, *, blank=False):    &amp;quot&amp;quot&amp;quotRead the $line and return it as caption if it&#039;s no empty    If so, it refer to the $blank parameter and returns $blank    This help to know can the line be blank (end of frame) or    it&#039;s a bug.    Remember: &gt;&gt;&gt; &#039;str&#039; == True -- False    &amp;quot&amp;quot&amp;quot    if isBlank(line):        return blank # blankline found instead of caption    else:        return line# get FROM, TO, OFFSETgetInfo()# $frame saves each frame as a dictionary til it&#039;s valued newlyframe = {} #{&#039;number&#039;: int, &#039;timecodes&#039;: (,), &#039;caption&#039;: &#039;&#039;}&amp;quot&amp;quot&amp;quotVariable &#039;STATE&#039; contain the current (previous) state of the line.Variable &#039;EXPECTED&#039; contain the state which is expected to be onthe line at the point. it must be the current state of the line.Integer variable start with &#039;STATE_&#039; are used to define line states.&amp;quot&amp;quot&amp;quotSTATE_BEGIN = -1 # it&#039;s first time to do any process on the fileSTATE_FRAME = 0 # it&#039;s frame numberSTATE_TIME = 1 # it&#039;s hh:mm:ss,ms --&gt; hh:mm:ss,msSTATE_CAPTION = 2 # it&#039;s captionSTATE_BLANK = 3 # it&#039;s blank lineSTATE = STATE_BEGIN # default statusEXPECTED = STATE_FRAMESUBTITLE = file2write(TO)# Explore the file and append &lt;class &#039;Frame&#039;&gt; objects to# list $frames to represent the hole subtitle (SRT) file.for line in read_file_splitted(FROM):    if isBlank(line):        if STATE == STATE_BLANK:            break # tow contiguous blanlines mean EOF    # Find state of the line and do appropriate actions    if EXPECTED == STATE_FRAME:        frame[&#039;number&#039;] = frame_number(line) \        if STATE == STATE_BEGIN else frame_number(line, timeout=3)        STATE, EXPECTED = STATE_FRAME, STATE_TIME    elif STATE == STATE_FRAME and EXPECTED == STATE_TIME:        frame[&#039;timecodes&#039;] = frame_timecode(line)        STATE, EXPECTED = STATE_TIME, STATE_CAPTION    elif STATE == STATE_TIME and EXPECTED == STATE_CAPTION:            caption = frame_caption(line)            if caption == False:                raise Exception(&amp;quotCaption expected. Blankline found&amp;quot)            frame[&#039;caption&#039;] = caption            # It&#039;s first line of the caption and can&#039;t be blank            STATE, EXPECTED = STATE_CAPTION, STATE_CAPTION    elif STATE == STATE_CAPTION and EXPECTED == STATE_CAPTION: #        caption = frame_caption(line, blank=True)        if caption == True:            # it&#039;s blankline, so do something!            SUBTITLE.write(do(Frame(**frame))) # add it to the             STATE, EXPECTED = STATE_BLANK, STATE_FRAME        else:            frame[&#039;caption&#039;] += &amp;quot\n%s&amp;quot % captionSUBTITLE.write(&amp;quot\n\t\n\t\n&amp;quot)SUBTITLE.close()</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Fri, 29 Jul 2022 20:49:32 +0430</pubDate>
            </item>
                    <item>
                <title>تجربه‌ام در بازگشت به برنامه‌نویسی</title>
                <link>https://virgool.io/fboard/%D8%AA%D8%AC%D8%B1%D8%A8%D9%87-%D8%A7%D9%85-%D8%AF%D8%B1-%D8%A8%D8%A7%D8%B2%DA%AF%D8%B4%D8%AA-%D8%A8%D9%87-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-vctpoddffjun</link>
                <description>You sit down and start working.ساده‌ترین جواب, جواب بالا هست و برای من هم همین بوده, اما به این جواب به هیچ وجه جواب کاملی نیست(راستی, امتحان علوم را به تمام درسخوان‌ها تبریک و به همۀ تنبل‌ها تسلیت می‌گویم :)از نو شروع کنیدعالَم برنامه‌نویسی, چنان سریع تغییر می‌کند که بهترین برنامه‌نویس‌ها را نیز جا می‌گذارد.اگر دوباره, یادگیری را از صفر شروع نکنید (البته, نه صفر مطلق) مانند این هست که به جدّ بناءی من بگویید بیاید و یک برج خلیفه را برایتان بسازد. عالم برنامه‌نویسی هر روز به اندازۀ یک سال در, برای مثال, بنایی, تغییر می‌کند.اشتباهات گذشتۀ خود را تکرار نکنیدشاید می‌توانید به این ترک‌و‌بازگشت, به عنوان یک فرصت نگاه کرد و مسیر صد ساله را یک شبه طی کرد. فقط کافی هست به تجربیات قبلی خودمان تکیه کنیم.برای مثال, من هنگامی که برنامه‌‌نویسی را دوباره شروع کردم, هزار نرم‌افزار نریختم و فقط از مطمئن‌ترین‌ها استفاده کردم.چون یادگرفته بودم چطور جستجو کنم, کمتر مجبور به سوال پرسیدن می‌شدم, مستقل‌تر بودم و چون انگلیسی بهتری داشتم, documentationها را بهتر می‌فهمم.گام‌های کوچک اما زیادهنگام بازگشت به برنامه‌نویسی, ممکن هست مغرور شوید که من قبلاً این‌کار را کرده‌ام, پس بگذار به‌جای اینکه وقت‌ام را سر این‌ها تلف کنم, کارهای بزرگ کنم.البته که این تفکر, از پایه اشتباه هست اما تذکّر دادن آن را شایان دانستم زیرا ممکن هست که در دام غرور بیفتید. (شایان, به معنای شایسته هست. کسی را می‌شناسم که نام برادرش شایان هست. شما چطور؟)گام‌ها, پیوسته!ممکن هست شما هم مانند من نتوانید خیلی برنامه‌نویسی کنید, اما چیز مهم این هست که همیشه و در هر روز و هفته, زمان مشخصی را تعیین کنید و تحت هر شرایط به برنامه‌نویسی بپردازید.البته, این کار فقط برای برنامه‌نویسی نیست و خیلی از زمینه‌های دیگر هم این فعل را به رسمیت می‌شناسند.کار نیکو از پر کردن هستیادم می‌آید که یک صفحه دربارۀ ضرب المثل‌های زبان‌های جهان و معادل انگلیسی آن‌ها می‌خواندم. مطمئن نیستم, اما فکر می‌کنم این ضرب المثل فارسی را همراه با &quot;Practice make [a man] perfect&quot; نوشته بود.فکر نمی‌کنم نیاز به توصیح داشته باشد اما باید بدانید که &quot;تمرین&quot; در برنامه‌نویسی, تکرار هزاران بارۀ یک مسئله نیست, بلکه تکرار یکبارۀ هزاران مسئله هست. بنابراین به جای حل کردن سوالات معمول, کمی در الگوریتم‌ها غرق شوید و از مغز مبارک کار بکشد.هدف داشته باشیدهدف داشتن, برای پیشرفت یک چیز هست اما شما باید برای &quot;یادگیری&quot; برنامه‌ای داشته باشید که شما را دوباره, به نقطۀ اوج برگرداند, سپس می‌توانید اینکار را ادامه دهید و پرواز کنید.این نکته, بسیار مهم هست. و البته, سخت‌ترین نکته‌ای هست که یاد خواهید گرفت. برای همین توضیح اضافی دربارۀ این نکته را ضروری می‌دانم.برای این نوع برنامه‌ریزی, باید کارهایی که برای رسیدن به نقطه‌ای که می‌خواهید را مکتوب کرده.برنامه‌ریزی, بسیار فراتر از این خُردمقاله هست. بنابراین یادگیری آن را به شما واگذار می‌کنم.پی‌نوشت: این مطلب بسیار کوتاه بود و کامل نیست, اما نتوانستم بهتر از این بنویسمش.منابع:https://www.quora.com/How-do-you-return-to-programming-after-you-have-taken-a-long-break-away-from-practicehttps://forum.freecodecamp.org/t/how-would-you-return-to-programming-after-a-long-time/249433/3</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Wed, 25 May 2022 21:25:13 +0430</pubDate>
            </item>
                    <item>
                <title>از ترک تا بازگشت به برنامه‌نویسی</title>
                <link>https://virgool.io/@3Pooia/%D8%A7%D8%B2-%D8%AA%D8%B1%DA%A9-%D8%AA%D8%A7-%D8%A8%D8%A7%D8%B2%DA%AF%D8%B4%D8%AA-%D8%A8%D9%87-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-e3xxawwosncf</link>
                <description>فکر می‌کنم دو ماه پیش بود, شاید هم بیشتر, ولی خیلی دور نبود که به عللی مجبور به تعویض سیستم عامل کامپیوتر شدم. از اوبونتو به ویندوز.شاید چیز مهمی به نظر نرسد که باعث ترک برنامه‌نویسی شود, اما هزاران خط و هزاران بایت کد و اطلاعاتی که دیگر قرار نبود برگردند را از دست دادم. همین تاثیر بدی بر روحیه من گذاشت.می‌خواستم آن‌ها را در امثال DropBox ذخیره کنم, کاری که هیچ‌وقت نکردم! هنگامی که مادرم گفت, اطلاعات را می‌توانستی روی فلش بریزی, این درد بیشتر شد.البته که من می‌خواستم اطلاعات را در پارتیشن دیگری بگذارم (وگذاشتم) تا موقع نصب ویندوز, فضا وجود داشته باشد, اما خوب, وقتی که فهمید(او فهیمد!) برای نصب ویندوز باید تمام پارتیشن‌ها, درایورهاو... خالی باشد, و اینکه دایی‌ام جلویم بود و بنابر دلایلی نمی‌توانستم بگویم صبر کن تا اطلاعات را منتقل کنم. اساساً, کار از کار گذشته بود!از آنجایی که حرفۀ جدیدی برای خودم انتخاب کرده بودم, مشکلی با ترک برنامه‌نویسی نداشتم. پس همین کار را هم کردم.امااما, بعداً یک ایده به ذهنم رسید که مجبور بودم برنامه‌نویسی را دوباره شروع کنم. البته ایدۀ بسیار بزرگی بود و پیاده‌سازی‌اش نکردم.اما, چندی نَگُذشت که ایدۀ بسیار ساده‌ای به ذهنم آمد, هرچند کوچک نبود و در نهایت شامل 25 خط کد شد اما راه من را برای بازگشت به برنامه‌نویسی هموار کرد. کد این پروژه را همین امروز به گیت‌هاب آپلود کردم.اما, یکی از امیدبخش‌ترین‌ها, زمانی بود که در حین نوشتن پروژۀ بالا, برادرم به من گفت: «مگه تو از ناسا پیام نگرفته بودی؟», من آدم دروغ‌گویی نیستم, پس گفتم که نه, اشتباه به یاد می‌آوری. اما همین باعث شد تا زمانی که ایمیلم را باز کردم, عبارت NASA را سرچ کنم و شاید حدس زده باشید:بابت کیفیت کم عکس معذرت می‌خواهم. به ویندوز وارد نیستم.همین امید من را روشن کرد.بعد از آن, مطلب خوب سایت سیسوگ, به کمک من آمد و اگرچه برنامه را مدت‌ها پس از خواندن مطلب نوشته بودم, اما یک گام بسیار مهم بود. به علاوه این که یکی از کاربرهای گیتهاب, که نامشان را نبردم, شاید بتوان گفت فوراً, به آن ستاره دادند.البته که فقط همین دو نرم‌افزار, منبع امید من نبودند, بلکه پیدا کردن منابعی که می‌خواستم بخوانمشان اما نکردم نیز به من کمک کرد. به علاوۀ هزاران چیز دیگر.همین امروز, شروع به مرور کدهای قدیمی خودم کردم. کدهای پاندکس, پروژۀ من که قرار بود برای مدتی مثل 1 سال متوقف باشد, با توقف من نیز مُرد. اما, وقتی شروع به خواندنشان کردم, از کدهای خودم هیچ سر در نیاوردم! خوب به یاد می‌آورم که پاندکس از یک فایل با کمی بیشتر از 100 خط کد شروع شد و الان(در گذشته, البته) [داشت] به زبان برنامه‌نویسی‌ای تبدیل [می]شد که خودم از کدش سر در نمی‌آورم!خوب به یاد می‌آورم که حتی سینتکس آن را هم نوشته بودم! مانند زیر بود, بسیار شبیه اسمبی. من آن زمان سعی می‌کردم اسمبلی یاد بگیرم...main:
 var A, 10
move A, 10
print $Aو می‌گفتم که آن زمان چقدر موفق بودم! بله خیلی هم بودم و در اعماق چاه ناامیدی هم نبودم.اما, با خودم گفتم که پس بیا تلاش کنم تا به آن جایگاه دیرینۀ خودم برسم, الان که باتجربه‌تر و...تر هستم, چرا کار باید سخت‌تر باشد؟ راست می‌گویم؟؟البته, از موفقیت‌های قبلاً من فقط این نبود, بلکه امروز من فقط دوتا از موفقیت‌های گذشته خودم را در گیتهاب دیدم. یکی این و دیگری:پروژۀ ناتمامی که تنها یک کُلَنگ تا گنج داشتوقتی که تصمیم گرفتم کدی هزار خطه بنویسم, کدی 912 خطه را با lua نوشتم اما هیچ‌وقت هزار خطه نشد.این کد یک آموزش lua بود که وقتی الان کامنت‌هایم را می‌خوانم, نمی‌فهمم چه می‌گفتم!کد در زمانی که فایل فقط 912 خط داشتتصمیم گرفتمخیلی نگذشت که تصمیم گرفتم, اولین کد 1000 خطی خودم را کامل کنم.تصمیم گرفتم پاندکس را ادامه بدهم و کاملش کنیم.و کارهای دیگری که یا تصمیم گرفتم یا تصمیم خواهم گرفت...البته که مطميءن نیستم, اما تلاشم را خواهم کرد.یک مدت نبودم برای همین, آمورش ساخت ادیتور و... هم به همین علت متوقف شد.اگر از این پست استقبال بشوم, پستی از تجربیاتم در راه بازگشت خواهم نوشت.</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Sun, 30 Jan 2022 17:56:17 +0330</pubDate>
            </item>
                    <item>
                <title>حذف فایل ld-linux و مشکلاتش</title>
                <link>https://virgool.io/@3Pooia/%D8%AD%D8%B0%D9%81-%D9%81%D8%A7%DB%8C%D9%84-ld-linux-%D9%88-%D9%85%D8%B4%DA%A9%D9%84%D8%A7%D8%AA%D8%B4-qeaupqsg4am5</link>
                <description>چند روز پیش سعی داشتم که adobe flash player را در Ubuntu 20.4 نصب کنم. برای همین باید نصب اشتباه قبلی را حذف می‌کردم. وارد دایرکتوری lib64/ که شدم یک فایل بود و یک دایرکتوری به نام flash-plugin.من هم آن فایل را به نام ld-linux-...-2.so. را جز‌ءی از flash player در نظر گرفتم و آن هم حذف کردم. غافل از اینکه آن فایل مسئول کابخانه‌های پویا (dynamic libraries) سیستم بود. (اگر نمی‌دانید چیست جستجو کنید. ما در لینوکس فایل‌های اجرایی را یا به صورت static یا به صورت dynamic داریم)بعد از آن من فقط یک ترمینال داشتم و نمی‌توانستم ترمینال جدیدی باز کنم و همچنین به لطف خدا یک مرورگر که وقتی می‌خواستم با کلید میانبر ترمینال را باز کنم آن را بستم!اما اطلاعات خوبی به دست آوردم. می‌گفتند که از نسخه‌ی live استفاده کن تا فایل خراب را با فایل درست تعویض کنی اما من نمی‌دانستم چطور و چیزی از جستجو در وب نصیب من نشد.برای همین اقدام به نصب Ubuntu روی یک partition دیگری کردم و اطلاعات آن سیستم دیگر را با mount کردن روی Ubuntu جدید آوردم.چند روز بعد این فکر به ذهنم رسید که چرا نتوانم با Ubuntu سالم فایل خراب را تعمیر کنم؟ پس سیستم خراب را mount کردم و فایل ld-linux آن را در این گذاشتم (یا شاید این را در آن گذاشتم) و بعد... کار کرد.من در طی آن مشکل چند چیز را فهمیدم:فایل ld-linux فایل اشتراکی کتابخانه‌های dynamic هستحالت TTY نیاز به استفاده از کتابخانه‌های dynamic دارد.برنامه‌ی busybox به صورت static کار می‌کند.</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Sat, 20 Nov 2021 11:57:15 +0330</pubDate>
            </item>
                    <item>
                <title>گراف‌ها!</title>
                <link>https://virgool.io/TameshkGroup/%DA%AF%D8%B1%D8%A7%D9%81-%D9%87%D8%A7-ideriqz6me1s</link>
                <description>سلام. بعد از مدت کمی ناپیدایی، امرز به علل اجباری می‌خواهم در این پست گراف‌ها را توضیح بدهم!اول از همه ببینیم این گراف یا به انگلیسی Graph که می‌گوید چیست؟برای درک کردن گراف، کافی هست شکل زیر را به شما نشان دهم:گرافکاربردحالا که فهمیدیم گراف چیست، می‌خواهم کاربردهایش را بگوم.گراف‌ها برای مدل کردن روابط و پردازش‌ها در بسیاری از مسائل علومی مانند فیزیک، زیست‌شناسی و حتی زندگی روزمره به کار می‌روند.برای مثال شما می‌توانید کامپیوترهای متصل به یک شبکه را با گراف‌ها نمایش دهید.کاربردهای بی‌انتهای گراف‌ها را می‌توانید از لینک زیر مشاهده کنید...https://en.wikipedia.org/wiki/Graph_theory#Applications(لینک بالا به علت مشکل ویرگول هست، مشکل اصلا از من نیست!)گراف‌هادر این بخش از متن، قرار هست کمی راجع به گراف‌ها یاد بگیریم!در گراف‌ها ما دارای vertex (گاها point یا node) هستیم که معمولا vertices (جمع) نوشته می‌شوند!این نودها در عکس بالا به شکل یک دایره‌ی سفید که وسط آن‌ها یک عدد هست وجود دارند.علاوه بر vertices، گراف‌ها دارای edge هم هستند که با نام‌های link, line, arc هم شناخته می‌شوند.الان باید راجع به یک چیز دیگر با هم حرف بزنیم تا بتوانم یکی از نکات مهم درباره‌ی edgeهای گراف را بگوم:جهت‌دار با بی‌جهتگراف‌ها را می‌توان در دو دسته‌ی directed یا جهت دار و بی‌جهت یا undirected تقسیم کرد.گرافی که در بالا دیدید بی‌جهت یا undirected هست زیرا یال (6,4) با یال (4,6) برابر هست.اما اگر به گراف شماره‌ی b نگاه کنید، متوجه خواهید شد که این رابطه یک‌طرفه و جهت دار هست، بنابراین گراف b یک گراف directed هست!نکته‌ی مهم راجع به edgeها این بود که:در یک گراف جهت‌دار، (a,b) برابر با (b,a) نیست در حالی که در یک گراف بی‌جهت، (a,b) و (b,a) با هم برابرند.دو راه عمده برای پیاده‌سازی گراف‌ها هست:لیست‌های مجاور (adjacency list)ماتریس‌های مجاور (adjacency matrix)البته، مطمئنا می‌توان با روش‌های دیگر هم گراف‌ها را پیاده‌سازی کرد. و روش پیاده‌سازی بستگی به عملیات‌هایی که می‌خواهید روی گراف انجام بدهید دارد.در این پست فقط راه‌حل ماتریکس مجاور را بررسی می‌کنیم. (به علت سادگی بالا!)ماتریکس مجاور(ببخشید که تخت الفظی هست)در این روش ما یک آرایه دو بُعدی با سایز V x V داریم که V برابر با تعداد راس‌های گراف هست.در این روش ما اطلاعات را در یک آرایه می‌گذاریم که arr[i][j] نشان می‌دهد این گراف، دارای یک edge ازش i به j هست که دارای value یا weightای برابر با مقداری که در مکان arr[i][j] قرار دارد.شما نمی‌توانید با این روش، گراف‌های جهت‌دار را پیاده‌سازی کنید!برای درک بهتر :)مزایااین روش برای پیاده‌سازی راحت هستبرداشتن یک edge فقط O(1) زمان می‌برد.معایتحتی اگر تمام vertexها خالی باشند، باز هم V^2 تا حافظه اشغال می‌کند!اضافه کردن یک یال نیاز به O(V^2) زمان دارد.پیاده‌سازیبرای دیدن پیاده‌سازی، این لینک را توصیه می‌کنم. با پایتون.دوره آموزشی های تصویری ما را هم در یوتیوب دنبال کنید و حتما پیشنهاد میکنم پیج اینستاگرام تمشک رو دنبال کنید ، برای دسترسی به بعضی از کدهای آموزش ها هم به گیتهاب تمشک سر بزنید.اگر بازم از این آموزشها دوست داشتید یادتون نره دنبال کردن انتشارات ما رو ?.© منبع : تمشک، geeksforgeeks.org</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Mon, 27 Sep 2021 15:03:56 +0330</pubDate>
            </item>
                    <item>
                <title>ادیتور/ویرایشگر تحت کنسول خود را با C بسازید. (۹)</title>
                <link>https://virgool.io/@3Pooia/%D8%A7%D8%AF%DB%8C%D8%AA%D9%88%D8%B1%D9%88%DB%8C%D8%B1%D8%A7%DB%8C%D8%B4%DA%AF%D8%B1-%D8%AA%D8%AD%D8%AA-%DA%A9%D9%86%D8%B3%D9%88%D9%84-%D8%AE%D9%88%D8%AF-%D8%B1%D8%A7-%D8%A8%D8%A7-c-%D8%A8%D8%B3%D8%A7%D8%B2%DB%8C%D8%AF-%DB%B9-rbhcbdsviroe</link>
                <description>همانطور که در قسمت قبل چند تا از سیگنال‌هایی را که زمان فشرده شدن کلید به ترمینال فرستاده می‌شوند را غیرفعال (disable) کردیم، در این قسمت هم به همان کار خواهیم پرداخت.غیرفعال کردن Ctrl+Vدر بعضی از سیستم‌ها فشار دادن کلید Ctrl+V باعث می‌شود تا ترمینال صبر کند تا یک کاراکتر دیگر فشار دهید و سپس آن کاراکتر را می‌فرستد (شما بگیرد اساسا کار خاصی نمی‌کند (البته می‌دهد!) ولی شما همان کار خاصی نمی‌کند در نظر بگیرید).برای غیرفعال کردن این ویژگی باید IEXTEN را در c_lflag قرار دهیم. مانند زیر:struct termios raw = orig_terminal;
raw.c_iflag &amp;= ~(IXON) // for Ctrl+Q and Ctrl+S
raw.c_lflag &amp;= ~(ECHO /* disable character echoing */ | ISIG /*  disable Ctrl+C &amp; Ctrl+Z */
| ICANON /* disable CANONICAL mode */ | IEXTEN /* disable Ctrl+V */)ثابت IEXTEN هم مانند دیگر کانست‌های مربوطه از &lt;termios.h&gt; می‌آید و اگرچه با I شروع می‌شود اما یک local flag هست و در c_lflag جا می‌گیرد.تغییر Ctrl+Mکلید M^ آخرین کلیدی نیست که قرار هست غیرفعالش کنیم! آخرین کلیدی که قرار بر غیرفعال کردنش بود Ctrl+V بود که در بالا گفتم.اما اگر آخرین کلیدی که قرار بود خاموشش کنیم Ctrl+V بود، پس چه بلایی را برای M^ رقم بزنیم؟اگر عنوان این بخش را درست خوانده باشید، من از واژه تغییر به‌جای واژه غیرفعال استفاده کردم. پس ما قرار هست تغیری در سیگنالی که این کلید ارسال می‌کند انجام دهیم.الان اگر یکی به یکی امتحان کند Ctrl+$$ می‌بینید که ۲۵ حرف از ۲۶ حرف الفبای انگلیسی کار می‌کند اما Ctrl+M را ۱۰ می‌خواند در حالی که M حرف 13ام الفبای انگلیسی هست.کلیدهای Ctrl+J و ‌enter هم باعث به وجود آمدن سیگنال 10 می‌شونداین ویژگی باعث می‌شود که &#x27;r\&#x27; به &#x27;n\&#x27; تبدیل شود. الان هم می‌خواهیم این قابلیت را غیرفعال کنیم.نکته: carriage return نامی  برای&#x27;r\&#x27; هست.raw.c_iflag &amp;= ~(IXON | ICRNL);
raw.c_lflag &amp;= ~(ECHO | ISIG  | ICANON | IEXTEN )ثابت ICRNL از &lt;termios.h&gt; می‌آید.مثل ثابت‌هایی که در c_iflag هستند با I شروع می‌شود که خلاصه‌ی Input هست. همچنین CR به معنای carriage return هست و NL برای NewLine می‌باشد.الان هم M^ و هم enter برابر با ۱۰ هستند و معنی&#x27;r\&#x27; می‌دهند. ساخته شده توسط: https://carbon.now.sh
و خط جدید هم با Ctrl+C بسازیدقبول دارم خیلی دیر بود و آموزش کوتاهی بود. ولی (نا)خوشبختانه این را نوشتم.بدورد تا قسمت بعدی. راستی [تا یادم نرفته] لطفا به من بگویید که بهتر می‌شود تمام قسمت‌های این آموزش را در یک پست لینک دهم؟ یا ویرگول مسدودم می‌کند؟</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Wed, 15 Sep 2021 10:42:42 +0430</pubDate>
            </item>
                    <item>
                <title>ادیتور/ویرایشگر تحت کنسول خود را با C بسازید. (8)</title>
                <link>https://virgool.io/@3Pooia/%D8%A7%D8%AF%DB%8C%D8%AA%D9%88%D8%B1%D9%88%DB%8C%D8%B1%D8%A7%DB%8C%D8%B4%DA%AF%D8%B1-%D8%AA%D8%AD%D8%AA-%DA%A9%D9%86%D8%B3%D9%88%D9%84-%D8%AE%D9%88%D8%AF-%D8%B1%D8%A7-%D8%A8%D8%A7-c-%D8%A8%D8%B3%D8%A7%D8%B2%DB%8C%D8%AF-8-jwyofresrurr</link>
                <description>قسمت قبلتوی قسمت قبل، یک سیستم ساختیم که کلید فشار داده شده را نشان می‌داد، داشتیم می‌گتفیم Ctrl+A یک برمی‌گرداند، Ctrl+B دو برمی‌گرداند، ولی Ctrl+C چطور؟ نه برنامه را خاتمه می‌داد. البته ما تنها با Ctrl+C  مشکل نداشتیم، با کلیدهایی مثل  Ctrl+S هم مشکل داشتیم!توی این قسمت یکی به یکی این مشکلات را حل می‌کنیم.کلیدهای Ctrl+C و Ctrl+Zبه صورت معمول، Ctrl+C یک سیگنال SIGINT ارسال می‌کنند که باعث خاتمه یافتن برنامه‌می شود و همچنین Ctrl+Z باعث می‌شود تا یک سیگنال SIGTSTP به برنامه ارسال بشود که برنامه را معلق می‌کند.یعنی:Ctrl+C -- TerminateCtrl+Z -- Suspendحالا چطوری این دو را غیرفعال کنیم؟raw.c_lflag&amp;= ~(ECHO|ICANON|ISIG);می‌بینید که تنها فرق موجود اضافه کردنِ فلگ ISIG هست که از  &lt;termios.h&gt; می‌آید.خوب، حالا Ctrl+C و Ctrl+Z را امتحان کنید. ببینید، برنامه خاتمه نیافت!این، همچنین باعث می‌شود تا Ctrl+Y در مک‌او‌اس هم از کار بیافتد. Ctrl+Y در مک شبیه Ctrl+Z هست فقط با این تفاوت که صبر می‌کند تا برنامه ورودی را بخواند و بعد برنامه را suspend می‌کند.خاموش کردن Ctrl+S و Ctrl+Qداشتید می‌گفتید، Ctrl+A=1 و Ctrl+B=2 و Ctrl+C=3 و Ctrl+D=4  و ... اما یهو Ctrl+S اه هیچی تایپ نمی‌شود، چرا بعد از Ctrl+S هیچی تایپ نشد؟ بگذار بنویسم q تا از برنامه خارج بشوم. وای باز هم کار نکرد...+ استاپ+ برادر Ctrl+Q را بگیر- ممنون+ خواهش می‌کنم.ماجرا این هست که وقتی شما کلید ترکیبی Ctrl+S را می‌گیرید ترمینال وارد حالت freeze می‌شود و هیچ اتفاقی نمی‌افتد.هر چقدر تایپ کنید هیچ به هیچ، هیچ اتفاقی نمی‌افتد! اما اگر Ctrl+Q را بگیرید. تمام دکمه‌هایی که زده بودید اما کار نکردند دانه دانه نمایان می‌شود. بنابراین:وقتی که Ctrl+S رو فشار بدهید باعث می‌شود تا کلیدهایی که فشرده می‌شوند ضبط شوند و هنگامی که Ctrl+Q را فشار می‌دهید باعث اجرا شدن تمامی کلیدهای ضبط شده می‌شود.این قابیلت معمولا برای software flow control استفاده می‌شود.برای از بین بردن این قابلیت کافی هست تا قطعه کد زیر را به سورس کد اضافه (append) کنیم.raw.c_iflag &amp;= ~(IXON);اگر کد را کوچک می‌بینید یا اصلا نمی‌بینید، بدانید و آگاه باشید که مقصر ویرگول هست وگرنه من تصویر را با سایز مناسب از صفحه نمایش گرفتم ویرگول کوچک نشان می‌دهید. برای حل این مشکل: ۱. تصویر را دنلود کنید. ۲. با یک نرم‌افزار که قابلیت زوم دارد تصویر را باز کنید. (!) واقعا جز این چی انتظار داشتی؟ بیکار بودی این همه زیر نویش را خواندی؟شما می‌دانید چرا constantهای ECHO | ICANON | ISIG در c_lflag هستند اما IXON در c_iflag هست؟چون که c_lflag برای Local FLAGs هست و c_iflag برای Input FLAGs هست!بله، برعکس همه فلگ‌های تا اینجا با دیدم که با I شروع می‌شدند (که local flag بودند) این فلگ input flag هست!مثل بقیه فلگ‌های موجود IXON از termios.h می‌آیدand XON comes from the names of the two control characters that Ctrl-S and Ctrl-Q produce: XOFF to pause transmission and XON to resume transmission.اسم XO*[*] اسم کاراکترهای‌کنترلی Ctrl-S و Ctrl-Q هست!در این مثالی که در بالا زدم (می‌دانم چرا اینطوری نوشته می‌شود اما نمی‌توان خط را عوض کنم، به هر حال قشنگ هست :) XOFF برای stop کردن ترمینال یا معادل Ctrl+S به کار می‌رود و Ctrl+Q سیگنال XON که باعث ادامه دادن فعالیت ترمینال می‌شود.خوب امیدوارم تا الان بی مشکل این متن را خوانده باشید، باید عرض کنم که هنوز هم تعدادی کلید دیگر باقی مانده که حوصله‌ام سر رفت و عرض نمی‌کنم.شما اگر عمر این پیشنویس را بدانید، یک ضربه در سر [مبارک] من می‌زدید که بچه چه کارت بوده در دو هفته نتونستی یک پیشنویس ۴ دقیقه‌ای بنویسی؟خداحافظخدا یار و نگه‌دارت</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Thu, 19 Aug 2021 13:05:21 +0430</pubDate>
            </item>
                    <item>
                <title>ادیتور/ویرایشگر تحت کنسول خود را با C بسازید. (6)</title>
                <link>https://virgool.io/@3Pooia/%D8%A7%D8%AF%DB%8C%D8%AA%D9%88%D8%B1%D9%88%DB%8C%D8%B1%D8%A7%DB%8C%D8%B4%DA%AF%D8%B1-%D8%AA%D8%AD%D8%AA-%DA%A9%D9%86%D8%B3%D9%88%D9%84-%D8%AE%D9%88%D8%AF-%D8%B1%D8%A7-%D8%A8%D8%A7-c-%D8%A8%D8%B3%D8%A7%D8%B2%DB%8C%D8%AF-6-aptiay4f2mam</link>
                <description>قسمت قبلی/ قسمت ۵ام‌نشان دادن کلید فشرده شدهسوال «ورودی چطوری در حالت Raw کار می کند» بهانه خوبی هست تا برنامه‌ای بسازیم که کاراکتر خوانده شده توسط تابع ()read را نشان در صفحه نمایش یا Screen نشان دهدما هم کد ASCII کاراکتر را نشان خواهیم داد و هم اگر کارکتر قابل چاپ باشد (یعنی مثلا CTRL یا NULL یا DEL نباشد) آن را به صورت کاراکتر چاپ کنیم.کد از این قرار هست:کد کامل پایین‌تر در دسترس می باشداین هم کد کامل:#include &lt;unistd.h&gt;
#include &lt;termios.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;ctype.h&gt;

struct termios orig;

void disableRawMode();

void enableRawMode(){
        tcgetattr(STDIN_FILENO , &amp;orig);
        atexit(disableRawMode);
        struct termios raw = orig;
        raw.c_lflag &amp;= ~(ECHO | ICANON);
        tcsetattr(STDIN_FILENO , TCSAFLUSH, &amp;raw);
}

void disableRawMode(){
        tcsetattr(STDIN_FILENO , TCSAFLUSH ,&amp;orig);
}

int main() {
        enableRawMode();
        char c;
        while (read(STDIN_FILENO, &amp;c, 1) == 1 &amp;&amp; c != &#039;q&#039;) {
                if(iscntrl(c)){
                        printf(&amp;quot%d\n&amp;quot, c);
                }else{
                        printf(&amp;quot%d (&#039;%c&#039;)\n&amp;quot, c, c);
                }
        }
  return 0;
}همانطور که می بینید دو هدر ctype برای تابع iscntrl و هدر stdio برای تابع printf به برنامه اضافه شد.تابع iscntrl چک می کند آیا کاراکاتر داده شده یک کاراکتر کنترلی هست (درست بر می گرداند/ غیر صفر) یا یک کاراکتر printable (قابل چاپ).کد های اسکی بین ۰-۳۱ کاراکتر های کنترلی هستند و کد های بین ۳۲ تا ۱۲۶ کاراکتر های قبل چاپ. البته کاراکتر ۱۲۷ هم کاراکتر کنترلی هست.تابع printf هم که دیگر نیاز به گفتن ندارد. دارد؟قبل از آزمایش کردن برنامه ...این یک برنامه خیلی کارآمد هست که به ما نشان می دهد چطوری کلید فشرده شده به بایت هایی تبدیل می شود که ما می خوانیم.بیشتر کلید های معمولی مستقیما به کاراکتری تبدیل می شوند که نشان می دهند (علامت کاراکتر روی صفحه کلید هست) اما این را روی کاراکتر مثل جهت ها (اهل بازی هستید؟) یا esc یا Backspace یا DEL انجام دهید. کلید ها رو با Ctrlبهتر هست چند چیز را به یاد داشته باشید:همه کلید ها جهت دار، Page up و Page down کلید‌های HOME و END سه یا ۴ بایت را روی ترمینال خواهند به نمایش گذاشت: ۲۷ یا esc و بعد ] و ۱ یا ۲ کاراکتر بعد از آن (اگر تجربه داشته باشید به احتمال زیاد دیدید که:\033[1mکه اگر عدد ۳۳ رو از مبنای ۸ به مبنای ۱۰ بر گردانیم. به عدد ۲۷ خواهیم رسید که معادل ۲۷ هست.)این به عنوان escape sequence شناخته می شود. همه escape sequence ها با ۲۷ یا ۰۳۳ یا 0x1b شروع می شود.Backspace is byte 127. Delete is a 4-byte escape sequence.کلید enter شماره ۱۰ دارد که id‌ی کاراکتر &#x27;\n&#x27; یا newline هستکلید ctrl+A یک هست و Ctrl+B دو اما Ctrl+C باعث می شود تا برنامه متوقف شود.اگر تنظیمات مرتبط را انجام دهیم. ترکیب کلید ها انگلیسی با ctrl باعث تولید کد های اسکیِ ۱ تا ۲۶ می شود (البته بین حروف کوچک و بزرگ فرقی نیست)الان می توانید برنامه را اجرا کنید. اما خواندن متن را از دست ندهید.اگر در این حالت شما Ctrl+S رو فشار دهید، ترمینال یخ می زند. اطلاعات بیشتر اینجا برای خارج کردن از حالت یخ زده (آن را در دمای ۳۰۰ میلیون درجه سانتی گراد قرار دهید تا مستقیما از جامد به گاز تبدیل شود | میعان‌اش کنید) کلید Ctrl+Q را فشار دهید. البته بعد از فشار دادن دکمه Ctrl+Q کلید‌هایی که بعد از Ctrl+S به برنامه پاس داده شدند نیز چاپ می شوند.این هم از متن با ترجمه ‌اش در پایین:Also, if you press Ctrl-Z (or maybe Ctrl-Y), your program will be suspended to the background. Run the fg command to bring it back to the foreground. (It may quit immediately after you do that, as a result of read() returning -1 to indicate that an error occurred. This happens on macOS, while Linux seems to be able to resume the read() call properly.)همچنین اگر کلید های Ctrl+Z (شاید Ctrl+Y باشد) را فشار دهید، برنامه به background می رود.دستور fg رو اجرا کنید تا به foreground بر گردد. از خروجی عکس نگذاشتم چون ...... جذابیت خود را از دست می دهدبدرود</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Sun, 01 Aug 2021 18:03:50 +0430</pubDate>
            </item>
                    <item>
                <title>ادیتور/ویرایشگر تحت کنسول خود را با C بسازید. (5)</title>
                <link>https://virgool.io/@3Pooia/%D8%A7%D8%AF%DB%8C%D8%AA%D9%88%D8%B1%D9%88%DB%8C%D8%B1%D8%A7%DB%8C%D8%B4%DA%AF%D8%B1-%D8%AA%D8%AD%D8%AA-%DA%A9%D9%86%D8%B3%D9%88%D9%84-%D8%AE%D9%88%D8%AF-%D8%B1%D8%A7-%D8%A8%D8%A7-c-%D8%A8%D8%B3%D8%A7%D8%B2%DB%8C%D8%AF-5-nc0x3qxavqtm</link>
                <description>این قسمت هم کوتاه هست، تصمیم گرفتم قسمت ها رو کوتاه کنم ولی به جای یک هفته یک هفته، یک روز یک روز بنویسمخاموش کردن حالت CANONICALما با استفاده از فلگِ ICANON می توانیم اقدام/مبادرت به خاموش یا روشن کردن حالت کانونیکال کنیم. که یعنی ما ورودی را کاراکتر به کاراکتر/بایت به بایت بجای خط به خط می بینیم.کد!برای همین کد را به مانند زیر/بالا تغییر می دهیم:#include &lt;unistd.h&gt;
#include &lt;termios.h&gt;
#include &lt;stdlib.h&gt;

struct termios orig;
void disableRawMode();
void enableRawMode(){
        tcgetattr(STDIN_FILENO , &amp;orig);
        atexit(disableRawMode);
        struct termios raw = orig;
        raw.c_lflag &amp;= ~(ECHO | ICANON);
        tcsetattr(STDIN_FILENO , TCSAFLUSH, &amp;raw);
}
void disableRawMode(){
        tcsetattr(STDIN_FILENO , TCSAFLUSH ,&amp;orig);
}
int main(){
        enableRawMode();
        char ch;
        while( read(STDIN_FILENO , &amp;ch , 1) &amp;&amp; ch != &#039;q&#039;);
        return 0;
}و این هم کد تغییر یافته، حالا بگرد و پیدا کن ??اگر کد قبل رو اجرا می کردید. بعد از زدن q باید enter یا خط جدید می زدید اما حروف بعد از q به ترمینال پاس داده نمی شد.الان شما مستقما q رو بزنید برنامه بسته می شود.</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Fri, 30 Jul 2021 13:48:57 +0430</pubDate>
            </item>
                    <item>
                <title>ادیتور/ویرایشگر تحت کنسول خود را با C بسازید. (4)</title>
                <link>https://virgool.io/@3Pooia/%D8%A7%D8%AF%DB%8C%D8%AA%D9%88%D8%B1%D9%88%DB%8C%D8%B1%D8%A7%DB%8C%D8%B4%DA%AF%D8%B1-%D8%AA%D8%AD%D8%AA-%DA%A9%D9%86%D8%B3%D9%88%D9%84-%D8%AE%D9%88%D8%AF-%D8%B1%D8%A7-%D8%A8%D8%A7-c-%D8%A8%D8%B3%D8%A7%D8%B2%DB%8C%D8%AF-4-gzyztsjezdje</link>
                <description>سلام! این بار که دیر نرسیدم نه؟ ۶ روز از قسمت ۳ این آموزش می گذرد و من در حال نوشتن اولین خط قسمت بعد هستم!از آنجایی که خیلی بی حوصله شدم فقط کار با تابع atexit رو یاد می دهم بنابراین قرار نیست پُست بلندی بشودقسمت سوم virgool.io | vrgl.irغیر فعال کردن حالت raw هنگام خروجدوست من، یکی از برنامه نویسان این کره آبی (اشتباه نکنید ۷۰٪ معادل ۳/۵ و یا تقریبا ۲/۳ رو از ::سطح:: {باز هم اشتباه نکنید، ۷۰٪ از سطح کره زمین رو آب تشکیل داده، مثلا هسته زمین از آب هست؟ (باز دوباره هم اشتباه نکنید، هسته زمین از خاک نیست! بلکه از نیکل و آهن هست!)} بنابراین کل زمین رو که آب نپوشانده!)&lt;چقدر حرف اضافه زدم&gt;خود نویسنده آموزش به انگلیسی می گوید:بیایید با کاربر خوب باشیم (منظورش این هست که و روی کاربر کخ هایمان را خالی نکنیم) و خودمون اتوماتیک هر وقت برنامه خارج شد، ترمینال این بنده خدا را reset کنیم (تو قسمت قبلی راجع به دستور reset گفتم)قبلش بیایید یکم اصولی تر برنامه نویسی کنیم! دو تابع اضافه کن به نام های enableRawMode که وظیفه فعال کردن حالت raw را دارد و دیگری به نام disableRawMode که مسئول خاموش کردن این حالت هست، به برنامه اضافه می کنیمهمچنین یک struct termios دیگر به برنامه اضافه می کنیم که مسئول نگه داشتن یک کپی ا وضعیت معمولی ترمینال هست#include &lt;unistd.h&gt;
#include &lt;termios.h&gt;
#include &lt;stdlib.h&gt;

struct termios orig_termios;
void enableRawMode(){
tcsetattr(STDIN_FILENO, TCSAFLUSH, &amp;orig_termios);
}
void disableRawMode(){
   tcgetattr(STDIN_FILENO, &amp;orig_termios);
  atexit(disableRawMode);
 structtermios raw = orig_termios;
  raw.c_lflag &amp;= ~(ECHO);
  tcsetattr(STDIN_FILENO, TCSAFLUSH, &amp;raw);
}

int main(){
        char ch;
        enableRawMode();
        while(read(STDIN_FILENO,&amp;ch,1) == 1 &amp;&amp; ch != &#039;q&#039;);
        return 0;  
}این تابع atexit از هدر stdlib.h می آیدما یک عدد struct termios به نام orig_termios رو با مقدار اولیه یا معمولیترمینال ذخیره می کنیم تا هر وقت خواستیم از برنامه خارج بشویم این متغییر رو به عنوان حالت ترمینال تنظیم کنیم. ما یک struct دیگر به نام raw از روی همین می سازیم و از raw به عنوان struct termiosای استفاده می کنیم که قرار هست حالت raw را داشته باشه اما atexit چی کار می کنه؟این declaration تابع هست:int atexit(void (*function)(void));این تابع، function داده شده را ثبت می کند تا فراخوانی/اجرا شود هر وقت که برنامه kill شد، چه با تابع exit و چه با برگرداندن مقدار از تابع main.شما می توانید توابع مختلفی به این تابع پاس دهید و همه آنها هنگام kill برنامه اجرا شوند.استاندارد POSIX حداکثر می تواند ATEXIT_MAX تابع برای اجرا هنگام خروج را قبول کند که معمولا ATEXIT_MAX برابر با ۳۲ هست.من به شخصه ماکرو ATEXIT_MAX رو نداشتم، همچنین باید بگویم اگر از  ()abort استفاده کنید ایت تابع اجرا نمی شوندخوب خلاصه اش عکس زیر هست:همین؟ خوب نه، هنوز یکم ادامه دارد ولی فقط یکم!احتمالا متوجه شدید که حروف اضافه به shell پاس داده نشده؟ مثل عکس زیر:(لازم به ذکر هست من عبارت سبز رنگ رو بعد اجرا کردن برنامه s نوشتم)نگاه نگاه!دلیل اش همون TCSAFLUSH بود که در قسمت دوم{virgool.io | vrgl.ir} گفتم!</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Mon, 19 Jul 2021 11:07:42 +0430</pubDate>
            </item>
                    <item>
                <title>دو محاسبه برنامه نویسی در یک پست</title>
                <link>https://virgool.io/fboard/%D8%AF%D9%88-%D9%85%D8%AD%D8%A7%D8%B3%D8%A8%D9%87-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D8%AF%D8%B1-%DB%8C%DA%A9-%D9%BE%D8%B3%D8%AA-potyge7b3ine</link>
                <description>درورد ، پس از نمایش پست قبلی ، و سبک شدن از احساس «بر باد رفتن زحمت ها» تصمیم به نوشتن پست جدیدی کردم تا دو کار ریاضی را انجام دهیم ، یکی مربوط به برنامه نویسی و دیگری مربوط به برنامه نویسیاین هم لیست کار ها:محاسبه تعداد حالت های ممکنهندسه در برنامه نویسی(راستی من اولین پست ام رو در ۱۶ اسفند نوشتم)و یا در زبانی دیگرکوتاه کننده لینک vrg.ir برای چند پست می تواند کار کند؟چاپ یک شکل سه بعدی با پایتون :)کوتاه کننده لینک vrgl.ir چند برای چند پست به درد می خورد؟برایfor: 52**3 + 52**3 + 52**4 + 52**5
is equal to: 387656256
or 387,656,256برای ۳۸۷ میلیون پست آآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآآاما چطور می توان حساب کرد؟اگر شما هم مثل من کمی مسائل ریاضی علم کامپیوتر را حل کرده باشید ، این موضوع برای شما مسخره باشد ، اما همه که نمی دانند.برای درک کردن موضوع ، بگویید اگر برنامه ای از شما یک حرف از الفبای انگلیسی خواست، چند حرف می توانید به آن بدهید؟نمی دانم!۲۶غیرهاگر «نمی دانم!» انتخاب شما هست و مثال را واضح فهمیدید و همچنین سواد ابتدایی دارید ، همین الان بروید بیروناگر «۲۶» را گفتید ، سواد ابتدایی دارید ،‌اما زیرکی پایه ندارید ،‌ در صفحه بمانید اما علم خود را بیشتر کنید.و اگر «غیره» را گفتید دو حالت پیش می آید:شما ۲۶*۲ و یا 52 را گفتید: افرین ، این پست برای شما هست :)هر چیزی دیگر: همان کار هایی را  که کسانی که گزینه «نمی دانم!» را انتخاب کردند ، انجام دادند انجام دهید:انگلیسی ۲۶ حرف دارد که می توانند در ۲ حالت بزرگ یا کوچک باشند ، بنابراین ۲۶*۲ و یا ۵۲ حالت ممکن هستخوب بنابراینvrgl.ir/&lt;englishWord&gt;
52 states۵۲ حالت ممکن هست.اما کوتاه ترین لینکی که من دیدیم ۳ تا بیشتر نداشت.بنابراین :vrgl.ir/&lt;3EnglishWords&gt;
52 * 52 * 52اما چرا ضرب و نه جمع؟خوب ما یک a داریم و بعدش ۵۲ حالت ممکن هست. پس ما ۵۲+۱ حالت ممکن داریم و یا ۵۲*۱ حالت ممکن؟واضح هست که ۱*۵۲ جواب درست هست.حالت اگر بگوییم ما یا a و یا b داریم و بعدش ۵۲ حالت ممکن هست. پس ما ۲+۵۲ حالت ممکن داریم یا 2*52 حالت ممکن؟واضح هست که جواب 52*2 هستدر ادامه ، می توانvrgl.ir/&lt;3EnglishWords&gt; 
states: 52 * 52 * 52رو برابر با :vrgl.ir/&lt;3EnglishWords&gt;
states: 52 ** 3قرار داد و به جای ۳ بار ضرب ، یک بار از توان استفاده کنیم.52**3 + 52**3 + 52**4 + 52**5این که عبارت بالا چه کار می کند بر عهده خودتان! باید در ذهنتان جایی برای خلاقیت باشد یا نه؟بنابراین کوتاه کننده لینک vrgl.ir به شرطی که نهایت از جمله ای به طول ۵ و حداقل از جمله ای به طول ۳ استفاده کند باید 387656256 حالت موجود باشد.اکنون فرض می کنیم که حداقل طول جمله ۱ حرف و این شامل حروف بزرگ و کوچک به همراه اعداد ۰ تا ۹ می شود و حداکثر طول جمله را ۵ در نظر می گیریم.62**1+62**2+62**3+62**4+62**5که برابر با :931151402 و یا 931,151,402 (تقریبا یک میلیارد! )و اگر تنها یکی به طول جملخ اضافه شود یعنی عبارت به :62**1+62**2+62**3+62**4+62**5+62**6که برابر هست با57,731,386,986 (پنجاه و هفت میلیارد!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!۱۱۱۱۱۱۱!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)نتیجه گیری ها:۱) ریاضی علم کامپیوتر (محاسبه تعداد حالت های موجود) خودمون رو بهتر کنیم۲) کوتاه کننده لینک vrgl.ir به این زودی ها کم نمی آورد.ساخت شکل سه بعدی با پایتوناین یکی بعد کاملا ساده هست!تقریبا هیچ چیزی ندارداول از همه سوس کد که در ادیتور nano هست (و بعد نتیجه) : کد!و در آخر ، پاسخ را می بینیم:پاسخ !-)چرا پایتونتنها دو دلیل دارد ، آن هم پشتیبانی خوب پایتون از  string های چند خطی هست و اینکه تنها زبانی با این ویژگی هست که یاد دارمنتیجه گیری۱) ساخت یک شکل سه بعدی با کامپیوتر خیلی هم سخت نیست!</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Sun, 11 Jul 2021 18:24:23 +0430</pubDate>
            </item>
                    <item>
                <title>فلگ های بدرد بخور NASM</title>
                <link>https://virgool.io/@3Pooia/%D9%81%D9%84%DA%AF-%D9%87%D8%A7%DB%8C-%D8%A8%D8%AF%D8%B1%D8%AF-%D8%A8%D8%AE%D9%88%D8%B1-nasm-p8vg1pvsktlr</link>
                <description>در این پست می خواهم فلگ هایی مهمی را که از سایت nasm پیدا کردم را خلاصه کنم.البته ، این به معنی این نیست که تمام flag های اسمبلر محبوب nasm را در اینجا ذکر کردم (البته می توانید از طریق اینجا مستندات سایت رسمی درباره تمام flag های این اسمبلر را ببینید) ، و یا تمامی برنامه های nasm تنها از این آپشن ها استفاده می کنند و یا تمام آپشن های در این لیست مهم و بدردبخور هستند (بدرد بخور درست هست یا بدرد بخور - فاصله دارد یا نه؟؟ لطفا کامنت کنید)نکته : در اسمبلر  nasm پیش پردازنده ها با % یا percent شروع می شوند برعکس اسمبلر gnu یا gas که با . یا dot شروع می شوند و برعکس زبان محبوب C/C++ که با # یا sharp شروع می شوند.گفتم که تعجب نکنید چرا از % به جای # استفاده شده .-h و --helpتوضیحاتی کوچکی را درباره ی برنامه می دهد.nasm --help
nasm -h # shorter-fاین فلگ برای تشخیص format فایل خروجی استفاده می شود. برای مثالnasm -f bin hello.asmو یا nasm -f elf hello.asmاگر می خواهید لیست کامل و خلاصه شده ای از فرمت های موجود داشته باشید ، قسمت -hf را ببینید.-hfبا این آپشن می توانید فرمت های خروجی قابل دسترس را ببینید. help formatusr@dev:~ $ nasm -hf
usage: nasm [-@ response file] [-o outfile] [-f format] [-l listfile]
            [options...] [--] filename
    or nasm -v (or --v) for version info


Response files should contain command line parameters,
one per line.

    -t            assemble in SciTech TASM compatible mode
    -E (or -e)    preprocess only (writes output to stdout by default)
    -a            don&#039;t preprocess (assemble only)
    -M            generate Makefile dependencies on stdout
    -MG           d:o, missing files assumed generated
    -MF file      set Makefile dependency file
    -MD file      assemble and generate dependencies
    -MT file      dependency target name
    -MQ file      dependency target name (quoted)
    -MP           emit phony target

    -Z file        redirect error messages to file
    -s            redirect error messages to stdout

    -g            generate debugging information

    -F format     select a debugging format

    -gformat      same as -g -F format

    -o outfile    write output to an outfile
    -f format     select an output format

    -l listfile   write listing to a listfile

    -Ipath        add a pathname to the include file path
    -Oflags...    optimize opcodes, immediates and branch offsets
       -O0        no optimization
       -O1        minimal optimization
       -Ox        multipass optimization (default)
       -Ov        display the number of passes executed at the end
    -Pfile        pre-include a file &#40;also --include&#41;
    -Dmacro[=str] pre-define a macro
    -Umacro       undefine a macro
    -Xformat      specifiy error reporting format (gnu or vc)
    -w+foo        enable warning foo (equiv. -Wfoo)
    -w-foo        disable warning foo (equiv. -Wno-foo)
    -w[+-]error[=foo]
                  promote [specific] warnings to errors
    -h            show invocation summary and exit (also --help)

   --pragma str   pre-executes a specific %pragma
   --before str   add line (usually a preprocessor statement) before the input
   --prefix str   prepend the given string to all the given string
                  to all extern, common and global symbols (also --gprefix)
   --postfix str  append the given string to all the given string
                  to all extern, common and global symbols (also --gpostfix)
   --lprefix str  prepend the given string to all other symbols
   --lpostfix str append the given string to all other symbols
   --keep-all     output files will not be removed even if an error happens
   --no-line      ignore %line directives in input
   --limit-X val  set execution limit X
                     passes          total number of passes (default unlimited)
                     stalled-passes  number of passes without forward progress (default 1000)
                     macro-levels    levels of macro expansion (default 1000000)
                     rep             %rep count (default 1000000)
                     eval            expression evaluation descent (default 1000000)
                     lines           total source lines processed (default 2000000000)

Warnings for the -W/-w options: (default in brackets)
    macro-params            macro calls with wrong parameter count [on]
    macro-selfref           cyclic macro references [off]
    macro-defaults          macros with more default than optional parameters [on]
    orphan-labels           labels alone on lines without trailing `:&#039; [on]
    number-overflow         numeric constant does not fit [on]
    gnu-elf-extensions      using 8- or 16-bit relocation in ELF32, a GNU extension [off]
    float-overflow          floating point overflow [on
    float-denorm            floating point denormal [off]
    float-underflow         floating point underflow [off]
    float-toolong           too many digits in floating-point number [on]
    user                    %warning directives [on]
    lock                    lock prefix on unlockable instructions [on]
    hle                     invalid hle prefixes [on]
    bnd                     invalid bnd prefixes [on]
    zext-reloc              relocation zero-extended to match output format [on]
    ptr                     non-NASM keyword used in other assemblers [on]
    bad-pragma              empty or malformed %pragma [off]
    unknown-pragma          unknown %pragma facility or directive [off]
    not-my-pragma           %pragma not applicable to this compilation [off]
    unknown-warning         unknown warning in -W/-w or warning directive [off]
    negative-rep            regative %rep count [on]
    phase                   phase error during stabilization [off]
    label-redef             label redefined to an identical value [off]
    label-redef-late        label (re)defined during code generation [error]
    other                   any warning not specifially mentioned above [on]
    all                     all possible warnings

valid output formats for -f are (`*&#039; denotes default):
  * bin       flat-form binary files (e.g. DOS .COM, .SYS)
    ith       Intel hex
    srec      Motorola S-records
    aout      Linux a.out object files
    aoutb     NetBSD/FreeBSD a.out object files
    coff      COFF (i386) object files (e.g. DJGPP for DOS)
    elf32     ELF32 (i386) object files (e.g. Linux)
    elf64     ELF64 (x86_64) object files (e.g. Linux)
    elfx32    ELFX32 (x86_64) object files (e.g. Linux)
    as86      Linux as86 (bin86 version 0.3) object files
    obj       MS-DOS 16-bit/32-bit OMF object files
    win32     Microsoft Win32 (i386) object files
    win64     Microsoft Win64 (x86-64) object files
    rdf       Relocatable Dynamic Object File Format v2.0
    ieee      IEEE-695 (LADsoft variant) object file format
    macho32   NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (i386) object files
    macho64   NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files
    dbg       Trace of all info passed to output stage
    elf       ELF (short name for ELF32)
    macho     MACHO (short name for MACHO32)
    win       WIN (short name for WIN32)

-oبرای فایل خروجی نامی انتخاب کنید. outputبه صورت پیش فرض nasm نام فایل اسمبلی را بدون .asm به عنوان خروجی پیش فرض در نظر می گیرد.برای واضح تر شدن موضوع$ nasm -f elf hello.asm
$ ls
hello.asm hello.oشما می توانید با آپشن -o نامی را برای output انتخاب کنید$ nasm -f elf hello.asm -o output.o
$ ls
hello.asm output.o-ZZ بزرگبردن خروجی به یک فایل. به عنوان مثال$ ls
hello.s
$ nasm -f bin hello.asm -Z nasm_errors_file
$ cat nasm_errors_file
nasm: fatal: unable to open input file `hello.asm`-s هدایت جریان به stdout به جای stderr.توضیح نمی دهم چون خیلی کاربردی نیست.-iدقیقا کاربر -I درc|gcc را دارد . البته -i در nasm با حروف کوچک نوشته می شود ، برعکس  gccاگر بخواهید با %include فایلی را وارد برنامه کنید . و فایل شما در مسیر ~/asm قرار داشته باشد شما برای دسترسی به ~/asmlib باید به صورت زیر از این پیش پردازنده استفاده کنید%include &amp;quot../asmlib/file.asm&amp;quotاما اگر از این آپشن استفاده کنیم می توانیم مسیری را که به آن می دهیم اضافه کنیم ، یعنی nasm علاوه بر جایی که هست ، مسیری که این آپشن داده را هم جستجو می کند.برای مثال من می خواهم در  ~/asm یک کتابخانه و در ~/asmlib دو ماژول داشته باشم ، اگر فایل اصلی من در مسیر ~/asm باشد . و من بخواهم بدون آپشن -i انها را وارد برنامه کنم باید به صورت زیر عمل کنم :%include &amp;quotlib1.asm&amp;quot
%include &amp;quot../asmlib/lib2.asm&amp;quot
%include &amp;quot../asmlib/lib۳.asm&amp;quotاین که مدام به صورت relative مسیر (path) فایل ها را بدهیم خسته کننده هست و احتمال خطا را بالا می آورد ، اینجا آپشن/ flag ای به نام -i به داد ما می رسد و به nasm می گوید ، علاوه بر جایی که فایل هست ، جایی که این flag اعلام می کند را می گردد ، مثلا کد بالا را با این flag بازسازی می کنیم%include &amp;quotlib1.asm&amp;quot
%include &amp;quotlib2.asm&amp;quot ; without -i flag %include &amp;quot../asmlib/lib2.asm&amp;quot
%include &amp;quotlib3.asm&amp;quot ; without -i flag %include &amp;quot../asmlib/lib3.asm&amp;quotو در هنگام اسمبل کردن به جایnasm -f &lt;format&gt; file.asmاز روش زیر استفاده می کنیمnasm -f &lt;format&gt; -i ../asmlib file.asm-pاین flag برگرفته از نام pre include هست ، با این آپشن شما فایلی را بدون این که در فایل وارد کنید ، در برنامه  include می کند.برای درک بهتر ، کد زیر را در نظر بگیرید.%include &amp;quotfile.s&amp;quot
global _start
_start:
همانطور که در کد می بینید ، ما با استفاده از %include فایلی به نام file.s را قبل از اسمبل کردن برنامه ، وارد برنامه می کنیم ، اما ما می توانیم به جای کد بالا از کد زیر استفاده کنیم/از %include استفاده نکنیم . و در هنگام اسمبل کردن نیزglobal _start 
_start:
 و در هنگام اسمبل کردن نیز به جای روش معمول ، مثل زیر عمل کنیم :nasm -p file.s -f &lt;format&gt; source.asmهمانطور که دیدید ، با استفاده از آپشن -p توانستیم بدون استفاده از پیش پردازنده %include فایلی را در برنامه include کنیم .یعنی این آپشن قبل همانند پیش پردازنده %include کار می کند.-dاین flag همانند آپشن -p کار می کند ، اما آپشن -p کاربر %include دارد ، در حالی که این آپشن کابرد %define را دارد . به معنی آنکه .وقتی شما در هنگام اسمبل کردن ، در کنسول می نویسید.nasm file.asm -f &lt;format&gt; -d ONE=1بخش -d ONE=1 حکم اضافه کردن کد زیر به source را دارد .%define ONE 1-uاین هم همانند -d و -p  یک پیش پردازنده ای را در خط فرمان به کد اضافه می کند. این پیش پردازنده %undef را به کد اضافه می کند.nasm -d XC=1 -u XCدستور بالا ، هیچ اثری ندارد :| چون که کد زیر را به برنامه اضافه می کند.%define XC 1
%undef XCکه در عمل هیچ تاثیری در کد ندارد.عکسی از این اسمبلر محبوب ، برای این که پست بی عکس نماند.پی نوشت ۰ :                    من خیلی کم اسمبلی یاد دارم ، خواستم اسمبلی یاد بگیرم ، رفتم سر مستندات سایت رسمی که این دستگیرم شد ، گفتم بد نیست ترجمه کنم .پی نوشت i :                   اسمبلی زبان سختی نیست ، فقط یکم حال به هم زن هست . همین .پی نوشت ii :                    پی نوشتی نمانده که بخواهم بگم ، فقط خواستم بدونید از سیستم اعداد رومی استفاده کردم اما چون اعداد رومی صفر ندارند ، صفر بد بخت رو عربی نوشتم :|</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Tue, 22 Jun 2021 19:47:48 +0430</pubDate>
            </item>
                    <item>
                <title>ادیتور/ویرایشگر تحت کنسول خود را با C بسازید. (۱)</title>
                <link>https://virgool.io/@3Pooia/%D8%A7%D8%AF%DB%8C%D8%AA%D9%88%D8%B1%D9%88%DB%8C%D8%B1%D8%A7%DB%8C%D8%B4%DA%AF%D8%B1-%D8%AA%D8%AD%D8%AA-%DA%A9%D9%86%D8%B3%D9%88%D9%84-%D8%AE%D9%88%D8%AF-%D8%B1%D8%A7-%D8%A8%D8%A7-c-%D8%A8%D8%B3%D8%A7%D8%B2%DB%8C%D8%AF-lg7467l38hb7</link>
                <description>ترجمه ی مطالبی که در viewsourcecode.org نوشته شد.سایت ذکر شده IP ایرانی را تحریم کرده لطفا از پروژه وطنی shecan.ir استفاده کنیدالبته کلا این مطلب ، موضوعات و چیز های بدردنخور را حذف کرده و یا در بخش هایی دیگر توضیح داده ، همچنین من در این پست چیز هایی را توضیح می دهم که پست انگلیسی آن ها را توضیح نداده است :)آماده سازیبرنامه ما تنها نیاز به یک کامپایلر زبان C دارد . ( و همچنین محیط POSIX )(استاندارد POSIX همان استانداردی هست که unix - linux - BSD از آن پیروی می کنند )نصب کامپایلر Cبرای نصب در debian ها ( توزیع های خانواده دبیان ) ترمینال را باز کنید و بنویسیدsudo apt install gcc # or
sudo apt install clang # or
sudo apt install $c_compiler # or in past versions
sudo apt-get install gcc # or
...و خلاصه که نصب کنیددر Windows( توی مطب نگفته بود ، اما کاربران ویندوز ۹۰٪ مواقع با مشکل رو به رو هستند )برای ساخت این ادیتور ما از هدر هایی مانند unistd.h و termios.h استفاده می کنیم ، که در ویندوز نیستند.راه حل هاBash On WindowsCygwinکه من توضیح نمی دهم ، وظیفه بر دوش کابران ویندوز { ویندوزی های بیچاره :(  }و اما make یا makefileبنیاد gnu پروژه make را که توسط Stuart Feldman ساخته شده را بازسازی کرده.این برنامه فایل هایی که نیاز به recompile و لینک کردن دوباره ، دارند را تشخیص می دهد ، همچنین اگر این فایل ها به فایلی دیگر وابسته باشند ، وجود داشتن فایل را چک می کند ، و اگر به targetای دیگر آن target را هم اجرا می کند.مسلما است که نوشتن خطوط زیر در ترمینال ، برای هر تغییر بسیار خسته کننده استcc -c editor.c \
-Wall -Werror -Wextra
cc editor.o -o myowneditorپس چرا هنگامی که می توانیم از کامند زیر به جایی این همه دستور بالا استفاده کنیم ، این کار را نکنیمmakeفقط لازم هست تا به make بگوییم ، برنامه من را چطور کامپایل کن .(بنده که در ویرگول این پست را می نویسم ، کد هایی با cmake و meson دیدم ، در این دو تا build شما دست بازی ندارید ، اما کار راحتی دارید ، دقیق مثل اسمبلی که دست شما باز هست ، اما همه چیز را خودتان باید بگویید ، بنابراین در make قرار نیست نام پروژه را بگویید )دست خود را به کد آلوده کنیداز نظر من که این ترجمه رو می نویسیم ، برنامه نویس بدون کد همانند زنبور بدون جان هست . اشتباه نکنید! برنامه نویس بدون پروژه همانند زنبور بی عسل هست ، هنگامی که کد ننوشته باشد ، مرده ای بیش نیست { اگر کد ننوشتید ، بفرما کد پایین رو بنویسید که بیجان نباشید دگر}اول از همه فایلی به نام editor.c بسازید و کد زیر را در آن قرار دهید (‌ put کنید )int main(){
     return 0;
}این هم عکس از کد با vim(توجه : من تابع main را برای افرادی که آشنا نیستند ، توضیح می دهم )تابعی به نام main در کد موجود هست. این تابع جایی هست که برنامه شروع به اجرا شدن می کند ، به عنوان مثال اگر با زبانی مانند پایتون کار کرده باشید ، فرض کنید که تابعی به اسم start در برنامه دارید . وقتی که به زبان تان می گویید، این فایل را بخوان پایتون ، زبان شما ( در اینجا C ) دنبال تابع start می گردد و به جایی خواندن فایل از اول فایل ، تابع start ( در اینجا main ) را اجرا می کند .خوب ، حالیا در ترمینال دستور زیر را بنویسید تا برنامه شما کامپایل شودcc=gcc # or clang , cc
$cc editor.c -o editorو با کامند زیر در لینوکس :./editorاجرا اش کنید .( ویندوز رو نمی گویم، چون اگر با ویندوز کار کنید به مشکل می خورید )بعد از اجرا برنامه شما هیچ چیزی نخواهید دید ، اما مقداری که این تابع بر می گرداند ،  تاثیر گذار هست ! باور نمی کنید ؟؟ پس می توانید دستور زیر را اجرا کنید. ( در محیط bash در POSIX )echo $?و چه جوابی می گیرید ؟؟؟ بله ۰ یعنی مقداری که تابع برگشت داده ! هنوز هم باور نمی کنید ؟ پس بیاید چیزی که تابع بر می گرداند را تغییر بدهیم و نتیجه را ببینیم . اما قبل از آناو آمده تا Don&#x27;t repeat Yourself او make یا makefile هست( از کی تا حالا سرتیتر ها هم نقطه {.} می خواهنید؟؟ )(این بخش برای کسانی هست که make یاد ندارند - البته چون که دارای نکاتی طریف هست پیشنهاد می کنم حتی در صورت دانشتن make این بخش را بخوانید )من make را بسیار استفاده می کنم . این یک build system سبک و کارآمد هست ، که بسیار ساده هست ، در حدی که با چند بار خواندن چند makefile می تونید سینتکس این سیستم ساخت را یاد بگیرید! چه عالی :)گول آموزش های موجود در YouTube رو نخورید . به صورت پیش فرض make دنبال چیزی همانند all , default , output نیست. بلکه بر طبق مستندات سایت رسمی gnu ، این نرم افزار اولین target ( بعدا با آن آشنا خواهید شد ) را به عنوان نقطه شروع برنامه و یا target پیش فرض در نظر می گیرد.target: prerequisites
           recipe
           recipeاگر شما به جای prerequisites در آن جایی که آموزش دیدید dependency را دیدید ،‌ بدونید که در سایت رسمی gnu این به عنوان prerequisite یاد شده! پس بهتر است که از مستندات سایت رسمی استفاده کنیم و نه آموزش های YouTube .و همچنین recipe که دستور العملی هست که {بر طبق سایت رسمی gnu }این برنامه (make) دستورات و یا recipe هایی که به آن داده شده را هشدار می دهد ( چاپ می کند ) و آن ها را اجرا می کند .پس در بخش recipe ها ، شما می توانید دستورات bash که محیط شل پیش فرض گنو هست و یا shell های دیگر ، را (در بخش recipe ) بنویسید. همانند mkdir - rm -rf و خیلی چیز هایی دیگر. البته  make این ها را چک می کند و مثلا اگر از متغییر ای  استفاده کنید ، make متغییر را تشخیص داده و مقدار متغیر را با خود آن عوض می کند.در بخش prerequisite ها ، شما می توانید نام فایل هایی که target به آن وابسته هست و یا نام target هایی که این  target برای اجرا شدن نیاز دارد آنها اجرا شوند.و در بخش recipe ها هم دستورات محیط shell را می توانید قرار دهید ، البته به همراه دستورات make .تارگت ها را می توانید مانند توابع در نظر بگیرید و target اول را همانند تابع main تصور کنید.وقت ، وقت عمل است خوب بریم make رو بسازیمeditor: editor.c
          $(CC) editor.c -o editor \
         -Wall -Wextra -pedantic \
         -std=c99ممکن هست همینجا با دیدن $(CC) تعجب کنید و از ادامه راه منصرف شوید ، اما ساده هست. این یک متغییر در make هست که به صورت پیش فرض ، وجود دارد.آپشن/flag های داده شده با کامپایلر-Wall : هر چیز یک کوکچولو مشکوکی که دیدی رو به ما اعلام کن-Wextra: بعضی از انواع هشدار ها که آپشن اول آن ها را فعال نکرده را ، این یکی فعالشون می کند-std: استاندارد زبان را تعیین می کند ( فکر نکنم نیاز به توضیح باشه ؟ )-padantic: شبیه -Wallاین هم از makefile. و در نهایت ما build می گیریم ، برای اینکار کافی هست دستور make را بنویسید. تصویر پایین گویا ماجرا هست.من رو ببینید ، من گویا ماجرا هستم ، من من مناول با دستور cat محتویات فایل editor.c رو نمایش دادم . و بعد از آن توسط make کد را کامپایل کردم. و در نهایت با دستور echo $? آمدم و وضعیت را فهمیدیم و وضعیت 100 یا همان چیزی که تابع اصلی بر می گرداند بود.و در نهایت دوباره آمدم و make را اجرا کردم ، اما چون این برنامه باهوش هست ، فهمید که من فایلی را تغییر ندادم که بعد بخواهد باز دوباره make بگیرد؟؟؟اما چطور این کار را انجام می دهد ؟؟ در کدام حافظه ثبت می کند?? نگران نباشید ، هیچ چیز عجیبی در کار نیست ، make به طرز عجیبی این کار را انجام می دهد ، اگر آخرین تغییر فایل اجرایی editor نزدیکتر بود ، یعنی عمر editor.c از عمر editor بیشتر بود ، آنگاه make فکر می کند که همه چیز سر جایش هست .چقدر حرف می زنی ،‌ برو سر اصل مطلبممنون از دوستان که به من یاد اوری کردند.دوستان و همراهان گرامی ، لفطا این بخش را کامل بخونید ، بعد انجام بدهید. چون اگر بدون این که کامل بخونید ، این بخش رو انجام بدید ممکن هست بترسید !! (سیستم خراب شود و شما ندانید چی کار کنید)ما به هدر unistd.h نیاز مندیم ، این هدر در ویندوز موجود نیست .فایل editor.c را به کد زیر تغییر دهید :#include &lt;unistd.h&gt;
int main(){
     char ch;
     while( read(STDIN_FILENO , &amp;ch , 1) == 1);
     return 0;
}همانطور که در این فایل می بینید . ما تا زمانی که تابع read مقدار ۱ رو بر گرداند ، متغییر ch را برابر با کاراکتر ورودی کابر می کنیم. من تابع read رو بیشتر توضیح خواهم داد.اول از همه باید به شما بگویم STDIN_FILENO یک متغییر ثابت (constant) هست که مقداری برابر با ۰ دارد و در هدر unistd.h موجود هست.این سوال در stackoverflow مورد پسند من هست./* Standard file descriptors.  */#define STDIN_FILENO    0       /* Standard input.  */#define STDOUT_FILENO   1       /* Standard output.  */#define STDERR_FILENO   2       /* Standard error output.  */تابع read دارای سه آرگامون | آرگومنت هست.linux manual pagessize_t read(int fd, void *buf, size_t count);
read() attempts to read up to count bytes from file descriptor fd into the buffer starting at bufتابع read() تلاش می کند تا بخواند count بایت از توصیف کننده ی فایل fd درون بافری که با buf شروع می شود .به زبان آدمی زاد : این تابع count بایت از fd می خواند و توی buf می گذارد.همانطور که در کد می بینید ، ما یک while با بدنی تهی ( خالی ) داریم که ۱ بایت از ورودی می خواند و مقدارش را در ch می ریزد و اگر مقداری که تابع برگشت داد ، برابر با ۱ نبود از برنامه خارج می شود.الان make بگیرید . و امتحان کنید . اما قبلش یادتون باشد اگر خواستید خارج بشوید باید حالت eof و یا End Of File بسازید که در لینوکس با Ctrl+D و در ونیدوز با Ctrl+Z ساخته می شود.برای خارج شدن Ctrl+D را بگیریدبرای خارج شدن Ctrl+D را بگیرید.برنامه را طوری بسازیم که برای خارج شدن نیاز باشد  q رو فشار دهیم#include &lt;unistd.h&gt;
int main(){
      char ch;
      while( read(0 , &amp;ch , 1 ) == 1 &amp;&amp; ch != &#039;q&#039;);
      return 0;
}همانطور که در کد هست بخش &amp;&amp; ch != &#x27;q&#x27; به کد اضافه شده. یعنی اگر ch مقدار q داشت ، شما خارج شو- quitاما مشکلی هست :\  که بعدا با آن رو به رو خواهید شد ( نیم فاصله در اوبونتو چطوری هست ؟؟)خوب اول make و بعد مشکل را خواهید دید.الان ادیتور را باز کنید . و در آن یک چیزی بنویسید . برای خارج شدن نیاز هست تا کلید q را در متن بنویسید ، اما تا قبل از اینکه enter بزنید ، این پارامتر ها به تابع پاس داده نمی شوند.خوب حالا شما متنی را که دارای q هست بنویسید و بعد از  q هم چند حرف اضافه بنویسید .خواهید دید که حرف های بعد q به عنوان دستورات ترمینال در نظر گرفته شده و نه به عنوان متنی که در ادیتور نوشتید.با دقت نگاه کنید - شما for quit را که بعد از q آمده را دارید می بینیدنگاه کنید . بعد از q من نوشته بودم  for quit و دقیقا همان بخش به عنوان کامند bash در نظر گرفته شده.اما چرا ادیتور به محض فشار دادن q متوقف نشد؟همانطور که گفتم تا قبل از وارد کردن کلید enter هیچ اطلاعاتی به تابع داده نمی شود بنابراین اگر شما بنویسید q تا قبل از فشردن کلید enter هیچ اطلاعاتی به برنامه داده نمی شود . خوب ، حالا ما enter را زدیم و اطلاعاتی یکی یکی به برنامه داده شدند ، برنامه q را دید و متوقف شد. بنابراین برنامه به محض دیدن q متوقف شده و ادیتور چیز های بعد q را نمی خواند ، بنابراین آنها به ترمینال پاس داده می شوند و دستورات bash در نظر گرفته می شوند.چرا ادیتور نمی تواند بدون صبر برای وارد کردن کلید enter اطلاعات را بخواند؟زیرا ترمینال در حالت معمول بر روی حالت cooked mode و یا کانونیکال مود می باشد .برای این کار ما به raw mode نیاز داریم که اگر خدا قسمت کرد در پست های بعد توضیح می دهم .از آنجایی که دیگر کار با ویرگول راحت نیست ( نمی دونم چرا وقتی مطلب طولانی می شود ، لپتاپ من کندتر می شود و به سرعت اول تایپ نمی کند ،هر چه مطلب طولانی تر سرعت تایپ کمتر {البته اگر الان برم تو یک تب دیگر باز سرعت می گیرد ، مشکل از ویرگول هست}) و دیگر خسته شدم و شما هم احتمالا خسته شدید ، بقیه اش برای پست های بعدی موفق باشید :-) قسمت دوم ،ویرگول.آی/اوvirgool.io به امید دیدار دوباره {}خداحافظ :\</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Fri, 18 Jun 2021 10:52:55 +0430</pubDate>
            </item>
                    <item>
                <title>یک پروژه اسپرینگ بوت رو بدون تامکت اجرا کنید</title>
                <link>https://virgool.io/coderlife/%DB%8C%DA%A9-%D9%BE%D8%B1%D9%88%DA%98%D9%87-%D8%A7%D8%B3%D9%BE%D8%B1%DB%8C%D9%86%DA%AF-%D8%A8%D9%88%D8%AA-%D8%B1%D9%88-%D8%A8%D8%AF%D9%88%D9%86-%D8%AA%D8%A7%D9%85%DA%A9%D8%AA-%D8%A7%D8%AC%D8%B1%D8%A7-%DA%A9%D9%86%DB%8C%D8%AF-u4mngzzuq8mf</link>
                <description>همان طور که می دانید اگر بخواهید از جاوا در وب استفاده کنید باید تامکت یاد بگیرید  یا jetty که من تامکت رو ترجیح می دهم.( دلیل استفاده از تامکت پیچیده هست. اما در ساده ترین شکل = چون تامکت از اینترفیس servlet پشتیبانه )البته یک پروژه spring-boot رو می توان روی تامکت اجرا کرد ( به کمک فایل WAR)اما نمی شود بدون هیچ چیزی یک پروژه بهاری رو استفاده کرد؟؟؟ چرا می شود . ابتدا به فایل .JAR تبدیل کنید.جاوا را آماده کنیدتبدیل به .JARیادتون هست ما کجا می نوشتیم ./mvnw spring-boot:run -quietو یا mvn spring-boot:run -quiet
کجا ؟؟ همان جایی که فایل pom.xml رو پیدا می کنید.برید دقیقا همان جا.و اکنون بستگی به Maven و یا Gradle دارد. ( البته چقدر هم زیاد بستگی دارد )Maven :./mvnw clean install # ormvn clean installGradle :./gradlew clean buildgradle clean buildاگر با maven هستید بروید به دایرکتوری target و اگر از gradle استفاده می کنید در دایرکتوری build به دنبال آن بگردید .هر وقت که پیدا کردید . ترمینال را همانجا باز کنید. و بنویسیدjava -jar ${filename}و بدون هیچ وابستگی ای . به جز جاوا spring-boot راه می افتد. ویژگی مور علاقه من در spring-boot</description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Tue, 15 Jun 2021 13:26:36 +0430</pubDate>
            </item>
                    <item>
                <title>حس خوب رای دادن در PSF | Pyton پایتون</title>
                <link>https://virgool.io/@3Pooia/%D8%AD%D8%B3-%D8%AE%D9%88%D8%A8-%D8%B1%D8%A7%DB%8C-%D8%AF%D8%A7%D8%AF%D9%86-%D8%AF%D8%B1-psf-pyton-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-plhvszdiuyu3</link>
                <description>داستان از آنجایی شروع می شود که من در سال ۲۰۲۱ برای پایتون یک پول ریکویست در گیتهاب فرستادم . ( که خیلی مضخرف بود ) اما از روی مهمان نوازی یا مهربانی ، آنها من را عضو Python Software Foundation کردند و از من پرسیدند آیا می خواهم رای بدهم . گفتم بله. الان که این بند رو نوشتم یاد انتخابات های ناعادلانه ای می افتم که افراد -۱۸ سال نمی توانند در آن رای دهند . به هر حال برای من ایمیل به شکل زیر آمدنظر سنجی حدودا ساعت ۵ عصر = ۱۷ برگذار شد در تاریخ ۸ Jun و تا ۱۷ یا ۱۸ ام Jun دامه دارد . Vote: Python Software Foundation Board of Directors Election 2021Inbox?Helios Voting Bot &lt;no-reply@mail.heliosvoting.org&gt;4:40 PM (1 hour ago)??to me?Dear Pooia Ferdowsi,The 2021 election for the Board of Directors of the Python Software Foundation is open. The full list of candidates is available at https://python.org/nominations/elections/2021-python-software-foundation-board/nomineesVoting will close at the end of June 17th, 2020 AoE (https://timeanddate.com/time/zones/aoe) as previously announced. See https://www.timeanddate.com/countdown/election?iso=20210618T12&amp;amp;p0=1440&amp;amp;msg=PSF+Board+Election+2021+Voting+Deadline for a countdown.Election URL:  https://vote.heliosvoting.org/helios/e/psf-board-2021/voteElection Fingerprint:  بازم به شما چهYour voter ID: به شما چهYour password: این هم به شما چه--Heliosخواستم بگم که پایتون به حمایت شما نیاز منده . اگر عضو PSF هستید ، رای بدهید اگر هم نیستید دم به دقیق برای https://github.com/python/cpython ایشو و پول ریکویست بفرستید . البته فراموش نکنید که اکانت bpo درست کنید .تو به کی رای دادی ؟ چرا ؟به یک اسپانیایی به اسم Cristián Maureira-Fredesاما چرا ؟ اولا دولیلا - توی شرکت معتبر  Qt کار می کرد بجز اون تنها یکی دیگر بود که توی IBM کار می کرد که ممن از IBM بدم می آید و فکر می کنم کارمند های خیلی بدی دارند و اگر رییس پایتون شوند انتقام همه بلا هایی که آبی بزرگ سرشان آورد را روی ما خالی می کنند ( # واقعیت-غیر-محض )داکیومنت خوبی برای معرفی خودش ساخته بود ، فکر می کنم با این آدم پایتون مستنداتش بهتر می شود .می خواهد در برای اسپانیایی ها تلاش کند - ( خوب که چی ؟ هیچی ) واقعا دنیا به کسانی نیاز داره که به زبان های غیر از انگلیسی هم کمک کنند ، حالا اگر خواستند به انگلیسی هم کنند . اما دنیا به این جور آدم ها نیاز داره .البته هر کی یک سلیقه و یک نامزدی داره . باید به PSF vote هر کسی احترام گذاشت .منظور از احترام = آزار ندادن </description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Tue, 08 Jun 2021 17:57:03 +0430</pubDate>
            </item>
                    <item>
                <title>کیورد register در سی</title>
                <link>https://virgool.io/@3Pooia/%DA%A9%DB%8C%D9%88%D8%B1%D8%AF-register-%D8%AF%D8%B1-%D8%B3%DB%8C-h1lixji4azgs</link>
                <description>در مقاله ای دیگر گفتم که این کیورد از سی++ بر داشته شده است . اما همچنان در سی باقی هست.تا به حال شنیدید می گویند که سی زبانی سیستمی یا سخت افزاری هست . ( جزو زبان های MOHOL : Middle  Order Hardware Oriented Language توسط ادستخر دیکسترا ) . اما اگر با سی کار کذه باشید چیزی ندیدید.در حالی که اگر کمی حرفه ای تر بشید مثل من روی گذاشتن unsigned , short , long تعصب دارید :)اما یکی دیگر از کیورد های سخت افزاری register نام دارد این کیورد همانند متغییر های کلاس auto بعد از پایان تابع از بین می رود اما .اگر به datasheet یک  CPU  برای اسمبلر نگاه کرده باشید ( منظور من رو با ax , bx , eax اشتباه نگیرید . منظورم PC , LINK  و این ها هست ) . می بینید که بجز  ALU ( arithmetic Login Unit ) جایی دیگر به نام register هست که حافظه CPU هست . متغییر های کلاس register در آنجا ذخیره می شوند اما بسته به کامپایلر شما ممکن هست در RAM  هم باشید .متغییر های این کلاس معمولا سرعت دسترسی بالاتری دارند.  </description>
                <category>pooia</category>
                <author>pooia</author>
                <pubDate>Sun, 06 Jun 2021 15:37:37 +0430</pubDate>
            </item>
            </channel>
</rss>