چهارشنبه , ۲۴ مهر ۱۳۹۸
آخرین مطالب
LINK TABLES
خانه | برنامه‌نویسی | زبان C – تابع (جلسه ۱۱)

زبان C – تابع (جلسه ۱۱)

یه جلسه دیگه از زبان C هم شروع شد و مثل روزای قبل اومدیم که کلی مطلب جدید یاد بگیریم. آخرای جلسه قبل بود که در مورد توابع صحبت شد. طبق قولم جلسه امروز رو با توابع شروع می‌کنیم. پس محکم پشت لپ‌تاپ هاتون بشینید که با سرعت بریم 😀

سایر جلسات زبان C که تا کنون تدریس شده

معرفی چند مفهوم مهم در برنامه نویسی

جلسه اول = مقدمه                                      جلسه دوم = انواع داده

جلسه سوم = اشاره گر                                 جلسه چهارم = آرایه

جلسه پنجم = رشته                                     جلسه ششم = آرایه و اشاره گر

جلسه هفتم = ساختار (structure)                   جلسه هشتم = عملگرها

جلسه نهم = ساختارهای شرطی                    جلسه دهم = حلقه های تکرار

مفهوم تابع

اگر یک اتومبیل را در نظر بگیریم؛ از اجزای زیادی تشکیل شده که هر کدام وظیفه ی خاصی انجام می دهند. در واقع چیزی را تحویل گرفته و چیزی را تحویل می دهند. مثلا موتور خودرو سوخت، روغن و الکتریسیته را تحویل گرفته و نیرو مکانیکی تولید می کند. زبان C هم چنین شکلی دارد؛ یعنی از اجزایی ساخته شده که هر کدام وظیفه ای بر عهده دارند. این اجزا تابع نام دارند.

استفاده از توابع در برنامه‌نویسی مزایایی دارد که برخی از آن‌ها به ترتیب زیر هستند:

۱ – خرد کردن برنامه به اجزای کوچک‌تر جهت ساده‌تر شدن حل مساله

۲ – طراحی، تست و اشکال زدایی اجزای برنامه به طور مستقل

۳ – امکان استفاده دوباره از برنامه به طور مستقل

۴ – انجام پروژه به صورت تیمی

۵ – افزایش خوانایی برنامه و درک راحت‌تر آن

۶ – ساده‌تر شدن اشکال یابی برنامه

۷ – کاهش حجم برنامه

اجزای تابع

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

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

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

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

بله بسیار مهم است. اصولا در زبان C باید هر عضوی را در جای مشخصی تعریف کرد و گرنه دچار خطا می شویم. محل تعریف تمام اجزای زبان C به تابع main بستگی دارد. تابع main تابعی است که در تمام برنامه هایی که نوشته می شود حضور دارد و سایر توابع و بدنه اصلی برنامه درون این تابع اجرا می شود.

در زبان C، تابع‌ را می‌توان در ۳ ناحیه معرفی کرد:

  1. در بالای تابع main
  2. در پایین تابع main
  3. در فایل‌های کتابخانه (در مورد کتابخانه توضیح خواهیم داد.)
  • توابع را می‌توان در بالای تابع main تعریف کرد؛ بنابراین با شروع برنامه، توابع توسط برنامه رؤیت شده و می‌توان از آن‌ها در برنامه استفاده کرد.
  •  اگر توابع درون فایل‌های کتابخانه‌ای‌ تعریف شوند، هم‌چنان با شروع برنامه، فایل‌های حاوی توابع به برنامه ضمیمه (include) می‌شود.
  • اما اگر توابع در زیر تابع main تعریف شوند، باید قبل از شروع تابع main توسط اعلان (الگوی تابع)، به برنامه اطلاع داده شود که در زیر تابع main توابعی وجود دارد، زیرا وقتی یک برنامه آغاز می‌شود، فقط کدهایی که قبل و درون تابع main وجود دارد، برای برنامه قابل‌رؤیت هست.

پس ایجاد تابع شامل دو مرحله است: یکی تعریف تابع(function definition) و دیگری پیش‌تعریف یا الگوی تابع(function prototype).

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

حال قالب کلی الگوی تابع را مشاهده کنید:

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

تا این جا آموختیم که تابع چیست و چه اجزایی دارد و چگونه باید تعریف شود و الگوی تابع برای چه کاری استفاده می شود. اما می‌توان توابع را از دیدگاه ورودی و خروجی به ۴ دسته تقسیم کرد:

  1. تابع با ورودی، با خروجی
  2. تابع با ورودی، بدون خروجی
  3. تابع بدون ورودی، با خروجی
  4. تابع بدون ورودی، بدون خروجی

 

۱ – تابع با ورودی، با خروجی

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

قالب یک تابع دارای ورودی و خروجی را در زیر مشاهده می‌کنید:

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

به مثال زیر توجه کنید. تابعی بانام fx که دو مقدار را در ورودی دریافت می‌کند و ضرب دو مقدار را به خروجی تابع بازمی‌گرداند.

  • نوع داده خروجی تابع از نوع int، نام آن fx و دارای دو ورودی از نوع unsigned char هست.
  • درون تابع یک متغیر محلی از نوع int بانام s معرفی‌شده است که نتیجه عمل ضرب دو ورودی x و y را در خود نگه می‌دارد.
  • در خط انتهایی تابع، متغیر s توسط دستور return به خروجی تابع منتقل می‌شود.
  • این تابع را می‌توان در بالای تابع main یا در فایل‌های سرآمد (Header) و یا در زیر تابع main تعریف کرد. اگر تابعی در زیر تابع main تعریف شود، باید الگوی تابع قبل از تابع main قرار گیرد. اعلان تابع به بخش ابتدایی معرفی تابع گفته می‌شود.

اعلان تابع تعریف‌شده در مثال بالا را، در زیر مشاهده می‌کنید:

بخش ابتدایی تابع به همراه یک ; در انتهای آن، اعلان تابع نامیده می‌شود که قبل از تابع main قرار داده می‌شود. به هر تعداد تابع که در زیر تابع main تعریف شود، باید اعلان آن‌ها را در بالای تابع main قرار گیرد.

مثال زیر نحوه استفاده از تابع تعریف‌شده در بالا را که دارای ورودی و خروجی است، در خطوط اصلی برنامه نشان می‌دهد:

  • در خط یک کتابخانه استاندارد ورودی خروجی زبان C به برنامه include یا ضمیمه شده است. برای کار با ورودی خروجی ها به این فایل نیاز است، چرا که پارامترهای لازم برای کار با ورودی خروجی ها در این فایل نوشته شده است.
  • در خط سه الگوی تابع fx معرفی شده است.
  • در خط ۴ و ۵ متغیرهای عمومی (global) که در تمام طول برنامه قابل شناسایی هستند تعریف شده اند.
  • خطوط ۷ تا ۱۰ مربوط به تابع main و دستورات آن است. این تابع نه ورودی دارد و نه خروجی. می دانید چرا؟
  • خطوط ۱۲ تا ۱۷ هم که تعریف تابع fx است.
  • چون محدوده دید کدها از ابتدای include ها تا پایان تابع main است، اگر الگوی تابع fx در بالا نوشته نشود کامپایلر تعریف تابع fx را نخواهد دید.
  • به عنوان تمرین دقیق بررسی کنید که بعد از اجرای این کد متغیرها چه مقداری خواهند داشت. صحت آن را در کامپایلر هم بررسی کنید.

۲ – تابع با ورودی، بدون خروجی

تابع با ورودی بدون خروجی تابعی است که مقادیر عددی را از ورودی دریافت کرده، اما مقداری را به خروجی باز‌نمی‌گرداند. برای مثال این نوع تابع می‌تواند مقادیر دریافت شده از ورودی را بر روی رجیستر های موردنظر قرار دهد.

قالب یک تابع با ورودی، بدون خروجی را در زیر مشاهده می‌کنید:

چون این تابع دارای خروجی نیست، در خروجی آن از کلمه void استفاده شده است.

به مثال زیر توجه کنید. تابعی بانام gx که دو مقدار را در ورودی دریافت می‌کند و مقدار and بیتی آن‌ها را بر روی یک رجیستر قرار می‌دهد:

  • در خروجی تابع عبارت void قرارگرفته است و دارای خروجی نیست.
  • تابعی که دارای خروجی نیست، فاقد دستور return است، زیرا مقداری به خروجی بازگردانده نمی‌شود.

مثال زیر نحوه استفاده از تابع تعریف‌شده در بالا را که دارای ورودی و بدون خروجی است، در خطوط اصلی برنامه نشان می‌دهد:

  • تابع gx قبل از تابع main تعریف شده، به همین دلیل نیازی به استفاده از الگوی تابع وجود ندارد.
  • در تابع gx مقادیر دریافت شده، پس از عمل And بیتی بر روی رجیستر PORTD قرار می‌گیرد.
  • چون تابع gx خروجی ندارد، وقتی در تابع main فراخوانی می شود به هیچ متغیری نسبت داده نشده است.

  ۳ – تابع بدون ورودی، با خروجی

تابع بدون ورودی، با خروجی تابعی است که مقادیری را از ورودی دریافت نمی‌کند، اما مقداری را به خروجی بازمی‌گرداند. برای مثال این نوع تابع می‌تواند مقادیر قرارگرفته بر روی رجیستر مای موردنظر را بخواند و به خروجی بازگرداند. در این نوع تابع، کلمه void در ناحیه ورودی تابع قرار می‌گیرد.

قالب یک تابع بدون ورودی، با خروجی را در صفحه بعد مشاهده می‌کنید:

به مثال زیر توجه کنید. تابعی بانام kx که دو مقدار را از دو رجیستر دریافت می‌کند و مقدار Or بیتی آن‌ها را به خروجی بازمی‌گرداند:

  • در ورودی تابع، کلمه void قرارگرفته است که بیانگر آن است که تابع فاقد ورودی است. این تابع رجیسترها را می خواند اما از برنامه چیزی به عنوان ورودی تحویل نمی گیرد.
  • چون تابع kx دارای خروجی است، از دستور return استفاده شده است.

۴ – تابع بدون ورودی، بدون خروجی

تابع بدون ورودی، بدون خروجی تابعی است که نه مقادیر را از ورودی دریافت می‌کند و نه مقادیری را به خروجی بازمی‌گرداند. معمولاً توابعی که فقط عملیاتی را بر روی رجیسترها انجام می‌دهند از این قبیل هستند. در این نوع تابع، کلمه void هم در ورودی و هم خروجی تابع قرار می‌گیرد.

قالب یک تابع بدون ورودی بدون خروجی را در زیر مشاهده می‌کنید:

به مثال زیر توجه کنید. تابعی بانام dx که مقدار باینری ۰۰۰۰۱۱۱۱ را بر روی دو رجیستر قرار می‌دهد:

  • در ناحیه ورودی و خروجی تابع کلمه void قرارگرفته است که بیانگر آن است که تابع فاقد ورودی و فاقد خروجی است.
  • خودتان برای تمرین این تابع را به همراه تابع main به کار ببرید. چون از PORT هم استفاده شده به راحتی می توانید برای میکروکنترلر AVR از آن استفاده کنید.

چند نکته مفید در ارتباط با توابع:

  • توابع با هر نامی که معرفی شوند (حروف‌های بزرگ و کوچک) با همان نام باید در برنامه مورداستفاده قرار گیرند.
  • ورودی توابع می‌تواند متغیر، آرایه، رشته و… باشد.
  • نوع داده‌هایی که توابع به خروجی بازمی‌گردانند باید به‌گونه‌ای انتخاب شود که نتیجه محاسبات را با بیشترین مقدار در خود حفظ کنند. به‌عنوان‌مثال تابعی را در نظر بگیرید که دو مقدار از نوع unsigned char را در ورودی دریافت می‌کند و ضرب آن‌ها را به خروجی تابع منتقل می‌کنند. همان‌طور که می‌دانیم، نوع داده unsigned char از نوع ۸ بیتی بدون علامت بوده و می‌تواند مقادیر عددی ۰ تا ۲۵۵ را در خود حفظ کند. اگر این دو ورودی بیشترین مقدار خود (۲۵۵) را داشته باشند، ضرب این دو عدد ۸ بیتی نتیجه‌ای با طول ۱۶ بیت را به همراه خواهد داشت؛ بنابراین خروجی این تابع باید از نوع unsigned int تعریف شود تا خطایی در زمان اجرا رخ ندهد.
  • توابع را می‌توان در قالب فایل‌های کتابخانه‌ای در برنامه‌های مختلف مورداستفاده قرارداد. کتابخانه ها مجموعه ای از توابع هستند که در کنار هم قرار گرفته اند و این مزیت را دارند که جابه جایی آن ها بین کامپیوترها ساده بوده و انجام پروژه ها ار استاندارد می کنند و …
  • توابع معرفی‌شده را می‌توان در توابع دیگر نیز استفاده کرد.

فراخوانی تابع

تا این جای بحث درباره انواع توابع و خصوصیات و نحوه تعریف آن ها صحبت کردیم. اما این ها کافی نیستند چرا که نیاز داریم از توابع استفاده کنیم. در واقع میخواهیم توابع را صدا بزنیم تا بیایند و برایمان کاری انجام بدهند. سوال این است که چطور توابع را صدا بزنیم؟

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

  1. فراخوانی تابع با مقدار(call by value)
  2. فراخوانی تابع با ارجاع(call by reference)

در فراخوانی تابع با مقدار یک کپی از مقدار آرگومان‌های تابع روی پارامترهای آن نوشته می‌شود، بنابراین تغییر کردن آرگومان تاثیری روی مقدار پارامتر نمی‌گذارد.

به مثال زیر دقت کنید:

  • در این مثال تابع tempconv تبدیل دما برحسب سانتیگراد به فارنهایت را انجام می دهد.
  • تعریف و الگوی تابع را بر اساس مثال هایی که بررسی شد توضیح دهید.
  • متغیرهای f و c از نوع متغیر عمومی یا global هستند و در تمام برنامه و توابع قابل استفاده هستند. چون مقدار اولیه به آن ها داده نشده، به صورت پیش فرض صفر خواهند بود.
  • متغیر i یک متغیر محلی است که فقط در محدوده ی تابع tempconv تعریف شده است و بعد از خروج از تابع از بین می رود.
  • اگر بخواهیم متغیر i با خروج از تابع از بین نرود باید قبل از تعریف متغیر از کلمه static استفاده کنیم
  • در زبان C متغیرهای عمومی مقدار اولیه صفر دارند در حالی که متغیرهای محلی مقدار اولیه نامشخصی دارند.
  • خط هفت جایی است که تابع tempconv فراخوانی یا صدا زده شده است. مقدار متغیری که به عنوان ورودی به تابع داده شده ( متغیر C آرگومان تابع است) روی ورودی تابع ( متغیر centigrade پارامتر تابع است) کپی می شود.
  • بعد از انجام این کپی، هر تغییری روی آرگومان C انجام شود هیچ اثری روی مقدار پارامتر centigrade ندارد. چرا که فقط یک کپی از آن به تابع تحویل داده شده و نه آدرس آن.

 

اما حالت دیگری هم در زبان c وجود دارد که در آن بدنه تابع مستقیما دستری به آرگومان‌ها داشته باشد. این قابلیت مفیدی است که به آن فراخوانی با ارجاع می‌گویند. در این روش آدرس آرگومان روی پارامتر کپی می‌شود. در بدنه تابع از آدرس ارسال شده برای دسترسی به آرگومان استفاده می‌شود، به این ترتیب تغییرات ایجاد شده در متغیر پارامتر، روی آرگومان نیز تاثیر می‌گذارد.

به مثال زیر دقت کنید:

  • در این برنامه دما بر حسب سانتیگراد دریافت شده و بر حسب فارنهایت و کلوین تحویل داده می شود.
  • تابع tempconv مسئول انجام این تبدیل است.
  • این تابع هیچ گونه خروجی ندارد و در عوض سه پارامتر دارد.
  • پارامترهای این تابع متغیر اعشاری centigrade و اشاره گرهای farenheit و kelvin هستند که به نوع اعشاری اشاره می کنند.
  • اگر نیاز به مطالعه بحث اشاره گر دارید حتما از قسمت یادآوری در ابتدای همین پست اقدام کنید.
  • آرگومان هایی که به این تابع در زمان فراخوانی تحویل داده می شود، مقدار متغیر C (فراخوانی با مقدار) و آدرس متغیرهای f و k (فراخوانی با ارجاع) است.
  • می توانید دلیل استفاده از اشاره گر به عنوان پارامترهای تابع را توضیح دهید؟
  • چون از فراخوانی با ارجاع استفاده شده است می توان مقدار متغیرهای f و k را که خروجی های این تابع هستند، از درون تابع تغییر داد. چیزی که در فراخوانی با مقدار ممکن نبود.

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

توابع printf و sprintf

در جلسه امروز چندین بار به کتابخانه اشاره شد و با توضیحاتی که داده شد توانستید یک درک نسبی به دست آورید. حال از کتابخانه استاندارد C چند تابع مهم و پرکاربرد خصوصا برای میکروکنترلر را بررسی می کنیم. توابعی مانند sprintf، scanf، printf و … که در فایل header با نام stdio.h قرار گرفته اند.

 این توابع به ترتیب برای چاپ بر روی صفحه‌نمایش، دریافت اطلاعات از صفحه‌کلید و ساخت رشته‌ها به کار می‌رود؛ اما در برنامه‌نویسی برای میکروکنترلر ها، به شکل دیگری استفاده می شوند. برای مثال از تابع printf برای ارسال یک رشته از طریق ارتباط سریال به کامپیوتر استفاده می‌شود یا تابع sprintf برای ساخت یک رشته حاوی متن و مقادیر عددی به کار می‌رود.

به‌عنوان‌مثال برای نمایش متغیری که مدام در حال تغییر است، باید آن را توسط تابع sprintf درون یک‌رشته قرار دهیم و سپس رشته ساخته‌شده را برای نمایش، به یک نمایشگر یا یک کامپیوتر ارسال کنیم. در هر حالت قالب استفاده از این توابع ثابت است. در زیر به بررسی دو تابع printf و sprintf می‌پردازیم.

قالب استفاده از تابع printf را در زیر می‌بینید:

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

  • در ناحیه ورودی تابع printf، ابتدا یک عبارت درون ” و ” قرارگرفته است.
  • حروف و کاراکترهای قرارگرفته در این عبارت تا قبل از علامت d% عیناً در محل موردنظر چاپ می‌شود.
  • در محلی که d% قرار دارد، مقدار متغیر i به‌جای آن قرار می‌گیرد. کاراکتر بعد از علامت % را اصطلاحاً کاراکتر فرمت می‌نامند.
  • این کاراکترها مشخص می‌کنند که نوع نمایش مقدار متغیر مربوطه در محل موردنظر به چه شکل باشد. کاراکترهای فرمت مشخص می‌کنند که مقدار متغیر i به‌صورت اعداد مبنای ۱۰، بدون علامت، اعشاری، کدهای اسکی یا … باشد.
  • مثلاً اگر به‌جای d% کاراکتر فرمت f% قرار گیرد، نمایش مقدار متغیر i به‌صورت اعشاری می شود.
  • کاراکتری که بعد از علامت \ قرار دارد را اصطلاحاً کاراکتر کنترلی می‌نامند. کاراکترهای کنترلی شکل نمایش جایگاه عبارات را مشخص می‌کنند که عبارات در یک سطر بافاصله قرار گیرند یا هر عبارت در یک سطر قرار گیرد و یا … . در مثال بالا n\ باعث می‌شود نمایش هر بار در یک سطر جدید انجام شود.
  • قرار دادن کاراکتر کنترلی اجباری نیست. انواع کاراکترهای فرمت در جداول زیر قابل مشاهده می‌شود. نتیجه مثال بالا را در زیر مشاهده کنید:

قالب تابع sprintf مشابه تابع printf است. با این تفاوت که تابع sprintf به‌جای نمایش در محل خاصی، یک رشته تولید می‌کند. این رشته می‌تواند برای نمایش به هر محلی همچون صفحه‌نمایش، کامپیوتر یا … ارسال شود. درون این تابع باید یک آرایه با تعداد عضو متناسب با طول عبارت قرار گیرد.

قالب تابع sprintf را در زیر مشاهده می‌کنید:

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

  • ساختار ورودی تابع sprintf مشابه تابع printf است با این تفاوت که یک آرایه نیز در ورودی تابع sprintf قرار می‌گیرد و این تابع این آرایه را تبدیل به رشته‌‌ای با آرایش موردنظر کاربر می‌کند.
  • در این مثال دو متغیر وجود دارد، این توابع می‌توانند متغیرهای زیادی را نمایش دهند.
  • در تابع sprintf اول به ترتیب متغیر i در محل ۴d% و متغیر j در محل f% قرار می‌گیرد. نمایش مقدار متغیر j به‌صورت اعشاری خواهد بود.
  • می‌توان تعداد ارقام قابل‌نمایش را با قرار دادن عددی بین علامت% و کاراکتر فرمت، مشخص کرد.
  • در تابع sprrintf دوم، عبارت ۴٫۴d  به معنای چاپ حداقل ۴ رقم و ۲٫۱f به معنای دو رقم برای عدد صحیح و یک رقم برای اعشار است. در ادامه توضیح کاملی درباره این اعداد داه می شود.
  • آرایش رشته str1 و str2 نتیجه‌ایی به شکل زیر خواهد داشت:

در این‌جا لازم است در رابطه با عددی که بین کاراکتر فرمت و علامت % قرار می‌گیرد توضیحی داده شود. در این راستا سه مورد مهم را تعریف می‌کنیم:

طول میدان

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

جداکننده

یک علامت .(نقطه) برای جداکردن طول میدان که پیش‌تر توضیح داده شد از دقت مقدار که در ادامه بیان خواهد شد.

دقت مقدار

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

دقت مقدار برای اعداد صحیح، حداقل تعداد رقمی که باید چاپ شود را تعیین می‌کند. اگر تعداد رقم‌ها از این عدد( دقت مقدار ) کمتر باشد به تعداد لازم در سمت چپ صفر اضافه می‌گردد و سپس چاپ می‌شود.

بحث خیلی خیلی مهم توابع هم تموم شد. اول از همه بهتون یه خسته نباشید میگم و بعدش یه تبریک جانانه چون دیگه چیزی نمونده بتونید به زبان C کد نویسی کنید و میکروکنترلر مورد نظرتون را راه اندازی کنید. اما یه نکته کوچولو و یه خواهش دوستانه. برای تهیه این مطالب وقت و انرژی زیادی صرف می شه تا شما بتونید ازشون لذت و استفاده کافی را ببرید. اگه شما زیر مطالب نظر بدید یا از لینک شبکه های اجتماعی که همین جا زیر پست اومده، ما رو به دوستاتون هم معرفی کنید خستگی از تنمون در میاد و تشویق می شیم تا مطالب بهتری که شایسته ی مخاطبانمون هست تولید کنیم. 🙂 جلسه بعد با بحث دستورات پیش‌‌پردازنده ادامه میدیم. یا حق

درباره ی احسان عبداللهی

احسان عبداللهی هستم | کارشناسی الکترونیک خوندم و کارشناسی ارشد مخابرات |در سال 94 وب سایت میکرولرن را راه اندازی کردم | سعی کردم هر چیزی را به صورت کاربردی دنبال کنم، برای همین از کارشناسی کار با میکروکنترلرهای AVR و ARM، برنامه نویسی C و طراحی PCB را به صورت تخصصی کار کردم و از کارشناسی ارشد برنامه نویسی پایتون ، Computer vision و deep learning را به صورت تخصصی و کاربردی شروع کردم | الان هم سعی میکنم همیشه خودم را به روز نگه دارم و لذت کار کردن با دنیای برنامه نویسی و امبدد سیستم ها را به دیگران انتقال بدم

۴۰ دیدگاه

  1. عالی بود ، استادمون هم انقدر کامل توضیح نداده بود

  2. با سپاس از شما. مفید بود

  3. با سلام. توضیحاتتون در مورد مبحث تابع خیلی خوب و موثر بود و برای بنده مفید واقع شد. خیلی ممنونم بابت این آموزش خوبتون.

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

  5. عالی بود ، کامل و کاربردی . ممنون و خسته نباشید

  6. سلام.
    سپاس فراوان بابت این مطلب آموزشی.
    در زبان برنامه نویسی C جهت {ویرایش/حذف/جستجوی} اطلاعات بعنوان مثال اطلاعات دانشجویان(نام و نام خانوادگی و شماره دانشجویی و نمرات دروس همراه واحد ها) که توسط کاربر قبلا وارد برنامه شده اند از چه دستوری استفاده می شود؟
    سپاس بابت توجه شما.

  7. خسلس عالی وبد
    امیدوارم بازم به اموزش های عای تون ادامه بدید و ما استفاده کنیم

  8. سلام
    خداقوت
    قسمت آخر که یاد میداد در یک تابع چطور چند تا خروجی داشته باشیم عالی بود

  9. خیلی عالی بود خدا قوت

  10. عرفان تازه کندی

    سلام.
    ممنون عالی بود

  11. این هم عالی بود.

    در مورد این بخش:
    ” همان‌طور که می‌دانیم، نوع داده unsigned char از نوع ۸ بیتی بدون علامت بوده و می‌تواند مقادیر عددی ۰ تا ۲۵۵ را در خود حفظ کند. اگر این دو ورودی بیشترین مقدار خود (۲۵۵) را داشته باشند، ضرب این دو عدد ۸ بیتی نتیجه‌ای با طول ۱۶ بیت را به همراه خواهد داشت؛ بنابراین خروجی این تابع باید از نوع unsigned int تعریف شود تا خطایی در زمان اجرا رخ ندهد.”

    در کدام بخش از آموزش به این موارد اشاره شده ؟

    • با سلام
      در خطوط بالاتر همین بخش توضیح داده شده:
      “به‌عنوان‌مثال تابعی را در نظر بگیرید که دو مقدار از نوع unsigned char را در ورودی دریافت می‌کند و ضرب آن‌ها را به خروجی تابع منتقل می‌کنند.”

  12. ممنون خیلی عالی بود خسته نباشید

  13. مهندس سلام من خیلی سوال میپرسم میدونم ببخشید
    مهندس توی فراخوانی تابع با ارجاع اونجا که گفتین در فراخوانی با ارجاع میشه از چند خروجی استفاده کرد
    میشه یک مثال بزنید

    • سلام
      سوال پرسیدن مشکلی نداره. ولی شما چیزی را که داخل متن کامل توضیح دادیم باز میاید همونو میپرسید. مثالی که میخواهید داخل متن وجود داره. همون تابعی که داره ورودی سانتیگراد میگیره و خروجی کلوین و فارنهایت میده.

  14. سلام.
    من هرچی از دستور printf استفاده میکنم کار نمیکنه و روی lcd چیزی نشون داده نمیشه.ایا باید تنظیمات خاصی را در کدویژن انجام بدم؟
    مثلا من این دستور رو مینویسم اما کار نمیکنه:
    printf(“adad = %d”,student1.avrage)
    در ضمن student1 یک structure هست.
    میشه راهنمایی کنید. واقعا گیج شدم.

  15. سلام دوست عزیز
    اول ممنون بابت آموزش های جامع و کامل شما
    و دوم اینکه در مثالی که برای فراخوانی تابع با مقدار زدین در خط ۶ ,c=38.7 یک مقدار دلخواه است که در خط ۷ در f ذخیره شده؟میشه این دو خط رو بیشتر توضیح بدین؟ممنون

  16. سلام
    من دانشجوی رشته Computer Science در لهستان هستم.
    مطالبتون به من خیلییییییییییی کمک کرده تا حالا.
    واقعا ازتون ممنونم و واقعا خسته نباشید.

    • سلام و عرض ادب
      خیلی خوشحالیم که مطالب برای شما مفید بوده. حتما آموزش های ما را دنبال کنید و نظرات خودتون را بفرمایید.

  17. سلام
    ممنون از مطلب فوقالعادتون
    من میخام برنامه نویسی رو در حد کاربردی برای کار مثلا شرکت یا کارخونه یاد بگیرم برای برنامه ریزی
    آیا این مطالب کافیه؟
    اگه کافی نیست باید چیکار کنم ؟

    • با سلام و درود خدمت شما دوست عزیز
      قطعا هیچ موقع مطالعه یک کتاب یا شرکت در یک دوره برای برنامه نویس شدن کافی نیست. حتی برنامه نویس های حرفه ای هم بعد از چند سال کار هنوز با نکات جدید روبه رو میشن. اما برای اینکه شما بتونید به یک حد قابل قبول برای شروع کار برسید میتونید از کتاب های برنامه نویسی استفاده کنید و یا در دوره های آموزش برنامه نویسی شرکت کنید. میکرولرن دوره های آموزشی به صورت آموزش خصوصی و تضمینی برگذار میکنه. برای اطلاع از کم و کیف این دوره ها میتونید با شماره زیر تماس بگیرید. در ضمن روی این شماره ایدی تلگرام هم فعال هست.
      ۰۹۰۱-۷۰۵۸۲۳۶

  18. عالی بود… عالی

  19. عالی بود دستتون درد نکنه

  20. با عرض سلام

    من تازە می خواهم برنامە نوسی زبان س را شروع کنم و میخواهم مرا راهنمایی کنید از کجا شروع کنم در ضمن اگر کتاب بە صورت پی دی اف دارید برام ایمیل کنید ممنون میشم
    شاهین از کردستان

    • سلام به شاهین عزیز 🙂
      در مرحله اول برای شروع زبان سی توصیه می کنم که ۱۲ جلسه ای که در سایت میکرولرن تهیه شده را مطالعه کنید تا دید کلی و خوبی نسبت به این زبان به دست آورید.
      لینک جلسات آموزش زبان سی :http://microlearn.ir/category/programming/c
      اما یک سوال : می خواید زبان سی را فقط در حد میکروکنترلرها یاد بگیرید یا برای کامپیوتر هم نیاز دارید باهاش کار کنید؟
      جواب این سوال رو بدید تا بهتر شما را راهنمایی کنم.

  21. دمتون گرم
    کاش زودتر سایتتون رو پیدا میکردم

  22. دمت گرم مهندس جان
    واقعا ممنونم بخاطر این سایت بی نظیرتون از همه نظر عالیه
    اگه امکان داره برای ARM هم دقیقا مثله AVR کار کنید

    با تشکر

    • لطف داری دوست خوبم. با این همه سوالای چالشی که شما می پرسی 😀 انگیزه ما هم بیشتر از قبل شده. حتما برای ARM هم در آینده آموزش های لازم ار قرار می دیم.

  23. ببخشید در مثال فراخوانی تابع با ارجاع همانطور که گفتین برای چندین خروجی بکار میرود
    همان طور که در ابنجا از اشارگر استفاده شده است یعنی تایع میره از آدرس مشخص f& , &d مقدار رو برمیدارد و نتیجه خروجی رو در کجا ذخیره میکند؟

    • سلام.
      من ابتدا به شما توصیه می کنم که بحث اشاره گرها را از آدرس زیر با دقت بخونید:
      http://microlearn.ir/199/c-pointers.html
      اما در باره سوالتون :
      در فراخوانی تابع با ارجاع، تعدادی از پارامترهای تابع اشاره گر هستند ولی هنگامی که می خواهیم تابع را فراخوانی کنیم باید به این اشاره گرها یک سری آدرس اختصاص بدیم. این آدرس ها همون f& و k& هستند. داخل بدنه تابع داریم با اشاره گرها کار می کنیم که حاوی آدرس این متغیرها هستند و هنگامی که مقداری را به اشاره گر داریم اختصاص می دیم در واقع داخل همون متغیرهای f و k ذخیره میشه. به این ترتیب شما می تونید قبل از تابع هر تuداد متغیر که دوس داشتی تعریف کنید و آدرسشون را به تابع بدید. با اجرای تابع نتیجه در این متغیرها ذخیره میشه چون تابع آدرسشون را داره. حالا با این توضیحات یک بار دیگه مثال فراخوانی با ارجاع را بررسی کن. 🙂

  24. چیزی که شما نتیجه رو به این صورت نوشتید بنظر من باید sprintf هم به این صورت تعریف شود

    Str1–> value1=75 value2=12.78900
    Str1–> value1=0075 value2=12.7
    ——————————————————–
    ;(sprintf (str1,”value1=%d value2=%f “ , i , j
    ;(sprintf (str2 , “value1 = %4d value2 = %2.1f “ , i, j

    • برای spirintf اول حرفتون درست بود و اصلاح شد. اما برای دومی درسته و مشکلی خاصی نداره. در واقع ۴ که بعد از جدا کننده اومده میگه ۴ تا رقم اعشار می تونم داشته باشم ولی خب چون عدد اعشاری نیست چیزی هم نمایش داده نمیشه دیگه.

      • در واقع اگر اعشاری بود به این صورت نمایش داده میشد
        ۰۰۷۵٫۰۰۰۰

        • اگه به جای ۷۵ یک عدد اعشاری داشتیم و می نوشتیم ۴٫۴f اون موقع ۴ تا رقم برای اعشار در نظر می گرفت. اما در این حالت اصلا درست نیست که از f استفاده کنیم چون خروجی ۰ بر می گرده و باید از d استفاده کنید.
          یه توصیه برات دارم: این بحث یکمی نیاز به تمرین داره. تا الان که به صورت دستی تمرین کردی. الان داخل یک کامپایلر زبان C برو همین کدها را بنویس و تست کن تا بهتر متوجه بشی که چی به چی هست.

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *