برنامه تبدیل دما از فارنهایت به سلسیوس
برنامهی بعدی از فرمول زیر استفاده میکند:
( F - 32 ) * 5 / 9 = C
و جدولی از دماهای فارنهایت و معادل آنها در سلسیوس چاپ میکند:
| فارنهایت | سلسیوس |
|---|---|
| 1 | -17 |
| 20 | -6 |
| 40 | 4 |
| 60 | 15 |
| 80 | 26 |
| 100 | 37 |
| 120 | 48 |
| 140 | 60 |
| 160 | 71 |
| 180 | 82 |
| 200 | 93 |
| 220 | 104 |
| 240 | 115 |
| 260 | 126 |
| 280 | 137 |
| 300 | 148 |
این برنامه نیز مانند برنامهی Hello, World شامل یک تابع به نام main است، اما طولانیتر بوده و مفاهیم جدیدی را معرفی میکند، از جمله:
-
کامنتها (Comments)
-
تعاریف و اعلان متغیرها (Declarations & Variables)
-
عبارات حسابی (Arithmetic Expressions)
-
حلقهها (Loops)
-
خروجی قالببندی شده (Formatted Output)
نمونه کد برنامه:
#include <stdio.h>
/* چاپ جدول فارنهایت-سلسیوس
برای fahr = 0, 20, ..., 300 */
main()
{
int fahr, celsius;
int lower, upper, step;
lower = 0; /* حد پایین دما */
upper = 300; /* حد بالا */
step = 20; /* اندازهی گام */
fahr = lower;
while (fahr <= upper) {
celsius = 5 * (fahr-32) / 9;
printf("%d\t%d\n", fahr, celsius);
fahr = fahr + step;
}
}
دو خط اول:
/* چاپ جدول فارنهایت-سلسیوس
برای fahr = 0, 20, ..., 300 */
یک کامنت هستند که توضیح کوتاهی دربارهی عملکرد برنامه میدهند. همهی متن بین /* و */ توسط کامپایلر نادیده گرفته میشود. کامنتها میتوانند در هر جایی که فاصله، تب یا خط جدید باشد، استفاده شوند و به فهم بهتر برنامه کمک میکنند.
در C، تمام متغیرها باید قبل از استفاده تعریف شوند، معمولاً در ابتدای تابع و قبل از دستورات اجرایی. تعریف متغیر مشخص میکند که متغیر چه نوع دادهای دارد و شامل نام و نوع متغیر است، مثل:
int fahr, celsius;
int lower, upper, step;
نوع دادهها و حلقهها در برنامه تبدیل دما
-
نوع int به این معناست که متغیرها اعداد صحیح هستند.
-
نوع float برای اعداد اعشاری استفاده میشود، یعنی اعدادی که قسمت کسری دارند. محدودهی اعداد صحیح و اعشاری به ماشین شما بستگی دارد؛ برای مثال، int های 16 بیتی معمولاً بین -32768 تا 32767 هستند و float معمولاً ۳۲ بیتی با حداقل ۶ رقم معتبر و بزرگی تقریبی بین 10^-38 تا 10^38 میباشد.
علاوه بر int و float، C چند نوع دادهی دیگر نیز دارد:
| char | یک کاراکتر (یک بایت) |
| short | عدد صحیح کوتاه |
| long | عدد صحیح بلند |
| double | عدد اعشاری با دقت بیشتر |
همچنین آرایهها، ساختارها، union ها، اشارهگرها و توابعی که این نوع دادهها را بازمیگردانند وجود دارند، که در درسهای بعدی با آنها آشنا میشویم.
شروع محاسبات
در برنامهی تبدیل دما، محاسبات با دستورات مقداردهی اولیه شروع میشوند:
lower = 0;
upper = 300;
step = 20;
هر خط از جدول با همان روش محاسبه میشود، بنابراین از حلقه استفاده میکنیم تا این کار برای هر خط جدول تکرار شود:
while (fahr <= upper) {
...
}
نحوه کار حلقه while: ابتدا شرط داخل پرانتز بررسی میشود. اگر درست باشد (مثلاً fahr کمتر یا مساوی upper باشد)، بدنه حلقه اجرا میشود. سپس شرط دوباره بررسی میشود و اگر درست بود، بدنه دوباره اجرا میشود. وقتی شرط نادرست شد (fahr بزرگتر از upper شد)، حلقه پایان مییابد و اجرای برنامه از دستور بعد از حلقه ادامه مییابد. بدنه حلقه میتواند یک یا چند دستور داخل { } باشد، یا یک دستور تک بدون { }. تورفتگی (Indentation) دستورات داخل حلقه کمک میکند ساختار منطقی برنامه به راحتی دیده شود و خوانایی بالا برود.
محاسبه دمای سلسیوس
بیشتر کارها در بدنه حلقه انجام میشود. دمای سلسیوس با دستور زیر محاسبه و در متغیر celsius ذخیره میشود:
celsius = 5 * (fahr-32) / 9;
-
دلیل استفاده از ضرب در ۵ و تقسیم بر ۹ به جای ضرب مستقیم در 5/9 این است که تقسیم اعداد صحیح در C قسمت کسری را حذف میکند. اگر میخواستیم مستقیماً 5/9 را استفاده کنیم، نتیجه صفر میشد.
این مثال نشان میدهد که printf چگونه کار میکند. printf یک تابع عمومی برای چاپ و قالببندی خروجی است که در ادامه بیشتر با آن آشنا میشویم.
-
آرگومان اول printf یک رشته از کاراکترهاست که قرار است چاپ شود.
-
هر % داخل این رشته مشخص میکند که یکی از آرگومانهای بعدی در آن محل قرار گیرد و چگونه چاپ شود.
مثال:
printf("%d\t%d\n", fahr, celsius);
-
%d مشخص میکند که آرگومان مربوطه یک عدد صحیح است.
-
این دستور باعث میشود که مقادیر دو عدد صحیح fahr و celsius چاپ شوند و بین آنها یک tab (\t) قرار گیرد.
نکته: هر % در رشته باید با آرگومان مربوطه از نظر شماره و نوع داده مطابقت داشته باشد، وگرنه خروجی اشتباه خواهد بود.
نکات مهم درباره printf
-
printf بخشی از زبان C نیست؛ زبان C خودش هیچ ورودی یا خروجی استانداردی تعریف نمیکند.
-
printf یک تابع مفید از کتابخانه استاندارد C است که معمولاً در برنامههای C در دسترس است.
-
رفتار printf مطابق استاندارد ANSI تعریف شده، بنابراین با هر کامپایلر و کتابخانهای که استاندارد را رعایت کند، عملکرد یکسانی دارد.
ورودی و خروجی در C
-
برای تمرکز روی خود زبان C، تا فصل ۷ درباره ورودی و خروجی زیاد صحبت نمیکنیم.
-
ورودی قالببندی شده (formatted input) نیز بعداً آموزش داده میشود.
-
اگر نیاز به گرفتن ورودی عددی داشتید، میتوانید به تابع scanf در بخش ۷.۴ مراجعه کنید.
-
scanf مشابه printf است، با این تفاوت که ورودی میخواند به جای چاپ خروجی.
-
مشکل ظاهر جدول و راه حل آن
یکی از مشکلات برنامه تبدیل دما این است که اعداد جدول مرتب چاپ نمیشوند، زیرا راستچین نیستند.
-
برای حل این مشکل میتوانیم عرض مشخصی برای هر عدد تعیین کنیم تا اعداد در ستونهای خود راستچین شوند.
مثال:
printf("%3d %6d\n", fahr, celsius);
-
این دستور عدد اول هر خط را در یک ستون سه رقمی و عدد دوم را در یک ستون شش رقمی چاپ میکند.
-
خروجی جدول مانند این خواهد شد:
0 -17
20 -6
40 4
60 15
80 26
100 37
...
با این کار جدول خواناتر و حرفهایتر به نظر میرسد.
نسخه دقیقتر برنامه تبدیل دما با اعداد اعشاری
یک مشکل جدیتر برنامه قبلی این بود که با توجه به استفاده از محاسبات اعداد صحیح (integer arithmetic)، دمای سلسیوس دقیق نبود.
-
برای مثال، دمای 0°F در واقع حدود -17.8°C است، نه -17.
-
برای داشتن دقت بیشتر، باید از اعداد اعشاری (floating-point) به جای اعداد صحیح استفاده کنیم.
نسخه دوم برنامه به این شکل است:
#include <stdio.h>
/* چاپ جدول فارنهایت-سلسیوس
برای fahr = 0, 20, ..., 300؛ نسخه اعداد اعشاری */
main()
{
float fahr, celsius;
float lower, upper, step;
lower = 0; /* حد پایین دما */
upper = 300; /* حد بالا */
step = 20; /* اندازه گام */
fahr = lower;
while (fahr <= upper) {
celsius = (5.0/9.0) * (fahr-32.0);
printf("%3.0f %6.1f\n", fahr, celsius);
fahr = fahr + step;
}
}
توضیح تغییرات
تفاوت اصلی با نسخه قبل در این است که متغیرهای fahr و celsius از نوع float هستند.
فرمول تبدیل دما نیز به شکل طبیعیتری نوشته شده است: (5.0/9.0) * (fahr - 32.0)
- قبلاً نمیتوانستیم از 5/9 استفاده کنیم، چون تقسیم اعداد صحیح در C قسمت کسری را حذف میکند و نتیجه صفر میشد.
- اضافه کردن .0 به اعداد (5.0 و 9.0) نشان میدهد که آنها اعداد اعشاری هستند و تقسیم صحیح نیست، بنابراین نتیجه دقیق خواهد بود.
اگر عملگر حسابی با اعداد صحیح باشد، عملیات صحیح انجام میشود.
اگر یک عملگر با یک عدد اعشاری و یک عدد صحیح مواجه شود، عدد صحیح به صورت خودکار به اعشاری تبدیل میشود.
- به عنوان مثال (fahr-32)، عدد 32 به صورت خودکار به float تبدیل میشود.
با این حال، نوشتن اعداد اعشاری با نقطهی اعشاری حتی وقتی عدد صحیح است، نشاندهنده ماهیت اعشاری آن برای خوانندهی انسان است و خوانایی کد را بالا میبرد.
تبدیل اعداد صحیح به اعشاری و تنظیم قالب چاپ
قوانین دقیق تبدیل اعداد صحیح به اعشاری در فصل ۲ توضیح داده شده است.
-
فعلاً توجه کنید که دستورات زیر نیز به شکل طبیعی کار میکنند:
fahr = lower;
while (fahr <= upper)
در اینجا، عدد صحیح به صورت خودکار به عدد اعشاری تبدیل میشود قبل از انجام عملیات.
قالببندی خروجی با printf
-
%3.0f به این معناست که یک عدد اعشاری (اینجا fahr) حداقل سه کاراکتر عرض داشته باشد، بدون نقطه اعشاری و بدون ارقام کسری.
-
%6.1f برای عدد دیگری (اینجا celsius) به کار میرود که حداقل شش کاراکتر عرض داشته باشد و یک رقم بعد از نقطه اعشاری چاپ شود.
نمونه خروجی جدول:
0 -17.8
20 -6.7
40 4.4
...
میتوان عرض و دقت را حذف کرد یا تغییر داد:
- %6f → حداقل ۶ کاراکتر عرض
- %.2f → دو رقم بعد از نقطه اعشاری، بدون محدودیت عرض
- %f → چاپ به صورت عدد اعشاری بدون محدودیت
مثالهای دیگر:
- %d → چاپ عدد صحیح
- %6d → چاپ عدد صحیح، حداقل ۶ کاراکتر عرض
- %f → چاپ عدد اعشاری
- %6f → چاپ عدد اعشاری، حداقل ۶ کاراکتر عرض
- %.2f → چاپ عدد اعشاری، ۲ رقم بعد از نقطه
- %6.2f → چاپ عدد اعشاری، حداقل ۶ کاراکتر عرض و ۲ رقم بعد از نقطه
printf همچنین فرمتهای دیگر را پشتیبانی میکند:
- %o → عدد در مبنای ۸ (Octal)
- %x → عدد در مبنای ۱۶ (Hexadecimal)
- %c → یک کاراکتر
- %s → رشتهای از کاراکترها
- %% → چاپ خود علامت %
تمرینها
-
برنامه تبدیل دما را طوری تغییر دهید که یک سرتیتر (heading) بالای جدول چاپ شود.
-
برنامهای بنویسید که جدول معکوس سلسیوس به فارنهایت را چاپ کند.