PDA

توجه ! این یک نسخه آرشیو شده میباشد و در این حالت شما عکسی را مشاهده نمیکنید برای مشاهده کامل متن و عکسها بر روی لینک مقابل کلیک کنید : برنامه نویسی c



آبجی
24th May 2010, 11:56 PM
برنامه نویسی c جلسه اول فصل 1
کليات و مفاهيم
هدف کلی
آشنایی با مفاهیم اولیه و ویژگیهای کلی زبانC
هدفهای رفتاری
پس از مطالعة این فصل انتظار می‌رود دانشجو بتواند:
1. تاریخچة پیدایش زبان C را بگوید.
2. ویژگیهای اصلی این زبان را شرح دهد.
3. کاراکترهای این زبان را تشخیص دهد.
4. ویژگی شناسه‌های C را بیان کند.
5. متغیرها را شناسایی کند.
6. قسمتهای مختلف برنامة نوشته شده به این زبان را شرح دهد.
مقدمه
در اوايل دهة 1970 ميلادی، «دنيس ريچي» در آزمایشگاه كمپاني بل زبان C را برای برنامه‌نويسي سيستمها طراحي کرد. اين زبان از دو زبان پيشين به نامهاي BCPL و B منتج شده است که ‌اين دو نيز در همين آزمایشگاه نوشته شدند. زبان C تا سال 1978 منحصر به استفاده در همين آزمایشگاه بود تا اينکه «ريچی» و «کرنيه» نسخة نهايي اين زبان را منتشر کردند. به سرعت مفسرهاي متعددي از C تهیه شد، ليکن براي جلوگيری از ناسازگاريهای ايجاد شده و نيز حفظ قابليت حمل زبان، استاندارد ANSI تعاريف متحدالشکلي مطرح کرد. آنچه در اين کتاب مطرح می‌شود بر اساس همين استاندارد است. مفسر خود برنامه‌اي کامپيوتري است که برنامة سطح بالا دادة ورودي آن و برنامة ‌ايجاد شده به زبان ماشين خروجي آن را تشکیل می‌دهد.
به طور كلي ويژگيهاي مهم زبان C به اختصار به شرح زير است:
زبان C به طور گسترده‌اي در دسترس است. مفسرهاي تجارتي آن در بيشتر کامپيوترهاي شخصي، ميني‌‌کامپيوترها و نيز در کامپیوترهای بزرگ قابل استفاده‌اند.
C زباني است همه ‌منظوره، ساخت‌يافته سطح بالا (مانند زبان پاسکال و فورترن) و انعطاف‌پذير كه برخي از خصوصيات زبانهاي سطح پايين را نیز كه معمولاً در اسمبلي يا زبان ماشين موجود است داراست. در عين حال اين زبان براي كاربردهاي ويژه طراحي نشده و مي‌توان از آن در همة زمينه‌ها، بخصوص به دليل نزديكي آن به زبان ماشين در برنامه‌نويسي سيستم، استفاده کرد. بنابراين C بين زبانهاي سطح بالا و سطح پايين قرار دارد و در نتيجه اجازه مي‌دهد كه برنامه‌‌نويس خصوصيات هر دو گروه زبان را به كار برد. از اين رو در بسياري از كاربردهاي مهندسي به طور انحصاري زبان C به كار مي‌برند. (زبانهاي سطح بالا، دستورالعملهايي شبيه زبان انسان و پردازش فکري او دارند، همچنين يک دستورالعمل زبان سطح بالا معادل چند دستورالعمل به زبان ماشين است.)
برنامه‌هاي نوشته شده به زبان C به طور كلي مستقل از ماشين يا نوع كامپيوتر است و تقريباً تحت كنترل هر سيستم عاملي اجرا مي‌شود.
مفسرهاي C معمولاً فشرده و كم ‌حجم‌اند و برنامه‌هاي هدف ايجاد شده با آنها در مقايسه با ساير زبانهاي برنامه‌سازي سطح بالا، خيلي كوچك و كارآمدند.
برنامه‌هاي C در مقايسه با ساير زبانهاي برنامه‌سازي سطح بالا، به ‌راحتي قابل انتقال‌‌اند. دليل آن اين است كه C خيلي از ويژگيهاي وابسته به نوع كامپيوتر را در توابع كتابخانه‌اي خود منظور داشته است. بنابراين هر نسخه از C با مجموعه‌اي از توابع كتابخانه‌اي مخصوص به خود همراه است كه براساس ويژگيهاي كامپيوتر ميزبان مربوط نوشته شده است. اين توابع كتابخانه‌اي تا حدودي استاندارد است و معمولاً هر تابع كتابخانه‌اي در نسخه‌هاي متعدد C به شکل يكسان در دسترس است.
C روش برنامه‌سازي ماژولار را پشتيباني مي‌كند. همچنين از نظر عملگرها نيز زبانی قوي است که عملگرهاي گوناگوني براي دستكاري روي داده‌ها در سطح بیت داراست.
به طور کلي جامعيت، عموميت، خوانايي، سادگي، کارآيي و پيمانه‌اي بودن که همگي از مشخصات برنامه‌ای ‌ايده‌‌آل‌اند در زبان C پياده‌‌سازي مي‌‌شوند.
ويژگيهاي فوق موجب شده زبان C يکي از قوي‌ترين و محبوب‌ترين زبانهاي برنامه‌‌سازي در دنيا مطرح شود.
كاراكترها
زبان برنامه‌نويسي C مجموعه‌اي خاص از كاراكترها را شناسايي مي‌كند. اين مجموعه که در حکم مصالح اوليه جهت شکل دادن به اجزای اصلي برنامه‌اند عبارت‌اند از:
- حروف بزرگ و حروف كوچك. زبان C برخلاف زبان پاسكال بين حروف بزرگ و كوچك فرق مي‌گذارد. مثلاً FOR با for يكسان نيست.
- ارقام دهدهي. شامل 0 تا 9
- جاي خالي يا Blank
-كاراكترهاي مخصوص. شامل ^ % $ # @ ! + - = / \ * ? ( ) < > { } [ ] ~ ;. ,&
- كاراكترهاي فرمت‌بندی. که براي بيان حالتهای ويژه‌اي به کار مي‌روند و عبارت‌اند از كاراكترHorizontal Tab يا \t، كاراكترVertical Tab يا \v، كاراكتر خط جديد يا \n ، كاراكتر برگشت به عقب (Back Space) يا \b، كاراكتر تغذية فرم (Form Feed) يا \f، كاراكتر ابتداي سطر يا \r، كاراكتر تهي يا \0، و جز آن كه آنها را کاراکترهاي فرمان نيز مي‌نامند. لازم به توضيح است که هر کاراکتر فرمان بيان‌‌کنندة تنها يک کاراکتر است هر چند که با دو يا چند کاراکتر نوشته مي‌شود.
شناسه‌ها
شناسه‌ها نشانه‌‌هاي سمبوليكي‌اند كه براي مراجعه به انواع داده‌ها مانند مقادير ثابت، متغيرها، نوعها و توابع به كار می‌روند. به عبارتي ديگر شناسه‌ نامي است كه به عناصر مختلف برنامه مانند متغيرها، توابع، آرايه‌ها، اشاره‌‌گرها و جز آن اختصاص می‌یابد. يك شناسة C دنباله‌اي است از حروف، ارقام يا علامت زيرخط که با هر ترتيبي مي‌توانند قرار گيرند. اما اولين کاراکتر بايد حرفی باشد. در شناسه‌‌ها هر دو شکل حروف بزرگ و کوچک مجاز شناخته مي‌شوند. برحسب قرارداد شناسه‌هايي كه با علامت زيرخط‌ شروع مي‌شوند فقط در برنامه‌هاي سيستم كاربرد دارند و در برنامه‌هاي كاربردي قابل استفاده نيستند. در مورد تعداد کاراکترها در اسامي از نظر C محدوديتي وجود ندارد گرچه هر مفسر ويژگيها و محدوديتهاي خاص خودش را به كار مي‌برد. طول اسامي در زبان C استاندارد تا 31 كاراكتر مجاز است.
v مثال 1ـ1 اسامي زير شناسه‌‌هاي معتبرند.

x1 , sum , payam_noor , maximum
v مثال 1ـ2 اسامي زير شناسه‌‌هاي غیرمعتبرند.

book-5 , 4s , $tax , "p" , number one
متغيرها
متغيرها در زبان C شناسه‌هايي‌اند كه محلهايي از حافظه را به خود اختصاص مي‌دهند. به عبارت ديگر متغير شناسه‌اي است که در ميان بخشی از برنامه براي نسبت دادن نوع تعيين شده‌اي از اطلاعات مورد استفاده قرار مي‌گيرد. در ساده‌‌ترين حالت هر متغير جانشين يک قلم داده می‌شود. متغير تركيبي است از ارقام، حروف و علامت زيرخط ( _ ). لازم به ذكر است متغيرهايي كه با علامت زيرخط شروع مي‌شوند براي متغيرهاي داخلي سيستم رزرو شده‌اند. طول هر متغير در استاندارد ANSI تا 31 كاراكتر است، ولي در بعضي از مفسرهاي قديمي محدود به 8 كاراكتر است. تمامي متغيرهايي که در برنامه‌‌هاي C به کار می‌روند بايد تعريف يا اعلان شوند. به يک متغير مي‌توان داده‌‌هاي مختلفي در محلهاي گوناگون برنامه نسبت داد. بنابراين مقدار متغير در طول اجراي برنامه ممکن است تغيير کند.
بعضي از شناسه‌هاي زبان C كلمات رزرو شده يا كليدي‌‌اند. يعني معني و مفهوم آن از قبل در زبان تعريف و پيش‌بيني شده است. بنابراين شناسه‌هاي تعريف شدة برنامه‌نويس نیستند. متداول‌ترين كلمات كليدي زبان Cدر زير نشان داده شده است.



for

goto

else

If

Char

float

int

main

enum

register

return

signed

default

while

do

double

sizeof

static

struct

auto

Case

short

coutinue

const

union

unsigned

extern

typedef

Void

switch

long

break


البته در بعضي از مفسرهاي زبان C ممكن است كلمات كليدي ديگري نيز وجود داشته باشد كه بايد به كتاب راهنماي مربوط مراجعه کرد. همچنين توجه داشته باشيد كه همة كلمات كليدي با حروف كوچك نوشته مي‌شوند. پس main كلمة كليدي است درحالي كه Main كلمة كليدي نیست زيرا حرف اول آن بزرگ است. همين طور void کلمة کليدي است اما VOID کلمة کليدي نيست.
علامت توضيح
در زبان C هر عبارتي كه بين دو علامت */ و /* قرار گيرد صرفاً توضيح محسوب مي‌شود. مثلاً اگر بخواهيم در مورد دستوری توضيح دهيم كه چه كاري انجام مي‌دهد در هر جاي برنامه كه فضاي خالي مجاز باشد مي‌توان براي توضيح از علامت فوق استفاده كرد. (در اغلب نسخه‌‌ها علامت // هم مجاز است.)
v مثال 1ـ3 در برنامة زير از علامت توضيح استفاده شده است.


کد:


#include main () { int j , k ; for (j =1 ; j <= 10 ; j+ +) /* outer loop */ { printf("%5d ", j) ; for (k=1; k<=10; k+ +) /* inner loop */ printf("%5d", j * k) ; printf("\n") ; } }






ساختار برنامه‌‌هاي C
در زبان C برنامه‌‌ها با فرمت خاصي نوشته مي‌شوند. همة برنامه‌هاي C شامل يك يا چندين تابع‌اند كه فقط يكي از آنها تابع اصلي يا main ناميده مي‌شود. بنابراين هر برنامه فقط يك تابع اصلي دارد. برنامه هميشه با اجراي تابع اصلي آغاز مي‌گردد. معرفي توابع ديگر ممكن است قبل و يا بعد از تابع اصلي قرار گيرد. به طور كلي مي‌توان گفت كه هر برنامه به زبان C حداقل داراي اجزاي مقدماتي به ترتيب زير است.
دستورالعملهاي اجرايي
در هر برنامه دستورالعملهاي اجرايي بايد بعد از تعريف متغيرها درج شوند. دستوري قابليت اجرا دارد كه در پايان آن دستور، علامت سميكولون (;) نوشته شود. براي فهم بهتر اين موضوع به مثال زير توجه کنيد.
v مثال 1ـ4 برنامه‌اي بنويسيد كه مساحت مستطيلي به طول 6 و عرض 3 را محاسبه و چاپ كند.


کد:

#include main() { int length , width , S ; /* variable declaration */ length = 6 ; width = 3 ; S = length * width ; printf ("area = %d", S) ; }




پس از اجراي برنامه، خروجي برنامه به صورت زير نمايش داده مي‌شود.
area = 18
توضیح. برنامه با حروف کوچک تايپ شده است. توضيحات نيز معمولاً با حروف کوچک تايپ مي‌شوند. در زبان C حروف بزرگ و کوچک معادل يکديگر نیستند. خط اول برنامه اعلان مي‌كند كه كتابخانة مربوط به توابع ورودي و خروجي براي دستيابي به توابع آن آماده شود. در واقع ارجاع به فايلي است که شامل اطلاعاتي است که هنگام تفسیر بايد در برنامه قرار گيرند. C يكي از زبانهايي است كه به لحاظ داشتن توابع توكار يا از پيش‌فرض شده بسيار غني است. هر مجموعه از توابع كه عمليات ويژه‌اي را انجام مي‌دهد در مجموعه‌ای با عنوان كتابخانه يا library قرار مي‌گيرد. توابعي كه عمليات ورودي و خروجي را انجام مي‌دهند در كتابخانه‌اي به نام stdio.h قرار دارند كه در آن stdio به معني standard input output (ورودي و خروجي استاندارد) و h نيز معرف header يا عنوان است. تابع printf نيز يكي از توابع خروجي است.
حال به توضيح #include مي‌پردازيم. برنامه‌هاي نوشته شده به زبان C قبل از اينكه به‌وسيلة مفسر ترجمه شوند در اختيار برنامة ديگري با عنوان پيش‌پردازنده يا preprocessor قرار مي‌گيرند. يكي از كاربردهاي اصلي اين برنامه آن است كه كتابخانه‌هاي مورد نياز برنامة منبع را يعني كتابخانه‌هايي را كه توابع به كار رفته در برنامة منبع را شامل است براي استفاده آماده می‌کند. اين كار با دستور include كه در ابتداي آن علامت # و به دنبال آن نام كتابخانه در داخل علامت <> يا " " مي‌آيد انجام مي‌گيرد. اولين عبارت در برنامة بالا همين كار را براي ما انجام مي‌دهد.
در خط بعد تابع اصلي تعريف شده است. پرانتز خالي به دنبال نام تابع بيان مي‌کند که ‌اين تابع آرگوماني ندارد. چند خط بعدي، متن برنامة اصلي را تشكيل مي‌دهند كه از پنج دستور ساده تشكيل شده است. پايان هر دستور را علامت سميكولون (;) مشخص مي‌نمايد. چون متن برنامه بيش از يك دستور است مجموع آنها که دستور مركب يا بلاك را تشکیل می‌دهند در داخل يك زوج آكولاد قرار می‌گیرند. در واقع هر آكولاد چپ براي مفسر C به معني شروع بلاك و هر آكولاد راست معرف پايان آن است. البته در بعضي مواقع برحسب مورد آكولادها را مي‌توان به صورت تودرتو نيز به كار برد.
اولين دستور در متن برنامه يا همان شروع آكولاد، توصيف متغيرهاست. سه دستور بعدي دستورات محاسباتي و جايگزيني‌اند و در آخر نيز دستور خروجي است كه در آن تابع printf براي چاپ فرمت‌‌‌دار است. اولين آرگومان تابع مذكور متن داخل گيومه است كه تابع آن را به همان صورت در خروجي چاپ مي‌كند. البته بعضي از قسمتهاي متن كه شامل علامت % باشد مانند %d به مفسر اطلاع مي‌دهد كه اولين متغير بعد از بسته ‌شدن گيومه كه در اين مثال S است مقادير صحيح مي‌پذيرد. در اينجا d معرف decimal است و %d فرمت متغير در خروجي را تعريف مي‌كند. در فصلهاي بعدي به طور كامل به بحث فرمت متغيرها خواهيم پرداخت.

v مثال 1ـ5 برنامة زير طول و عرض مستطيلي را از طريق ورودي استاندارد مي‌خواند و با فراخواندن تابعي به نام Rectangle مساحت آن را محاسبه می‌کند و سپس طول و عرض و مساحت را در دستگاه استاندارد خروجي نمايش مي‌دهد. طول با a و عرض با b و مساحت با area مشخص می‌شود.
کد:

کد:

# include main () { int a , b , area ; int Rectangle (int a , int b) ; scanf ("%d %d" , &a , &b) ; area = Rectangle (a , b); printf ("\n length = %d width = %d area = %d" , a , b , area) ; } int Rectangle (int a , int b) ; { int s ; s = a * b ; return (s) ; }








اگر 5 = a و 4 = b، خروجي برنامة مذكور به صورت زير خواهد بود.
length = 5 width = 4 area = 20
توضيح. خط اول ارجاع به فايل کتابخانه‌اي، خط دوم تعريف تابع اصلي، خط سوم شروع تابع اصلي، و خط چهارم اعلان متغيرهاست. در خط پنجم تابع فرعي Rectangle اعلان شده است كه مقدار صحيح برمي‌گرداند و آرگومانهاي آن نيز a و b‌اند كه مقادير صحيح‌اند. در خط ششم، تابع ورودي استاندارد scanf به كار رفته است. اين تابع كه جزء كتابخانة stdio.h است، اطلاعات را از طريق ورودي استاندارد كه صفحه كليد است دريافت مي‌كند. فرمت و ساز و كار اين گونه توابع را در فصلهای بعد بررسي می‌کنیم. در اينجا يادآور مي‌شويم كه فرم كلي تابع مزبور به صورت زیر است.

scanf (control string , argl , arg2 , … , argn) ;
كه در آن رشتة كنترل كه در داخل گيومه ("") می‌آید، اطلاعات مورد نياز دربارة فرمت اقلام داده‌هاي ورودي را شامل می‌شود و عناصر arg1 , arg2 ,... argn نيز آرگومانهايي‌اند كه اقلام داده‌‌هاي ورودي را معرفي مي‌کنند. در اين دستور کاراکتر "&" عملگر آدرس است. در رشتة كنترلي نيز كه در داخل گيومه قرار دارد، از چپ به راست %d اول معرف فرمت اولين آرگومان يا دادة ورودي به عنوان عدد صحيح است و به دنبال آن %d دوم نيز معرف فرمت دومين آرگومان به عنوان عدد صحيح است. علامت \n در رشتة كنترلي تابع printf، موجب انتقال به سطر جديد مي‌گردد. بنابراين اطلاعات بعدي در سطر جديد چاپ خواهد شد.
خودآزمایی 1
1. كدام يك از اسامي زير مجاز است به عنوان نام متغيردر برنامه به كار رود؟
Integer, -19, Lesson four, Unit_25, define, Loop2, Star565void, Please?, Payam_noor, C+ +, S#, Five$
2. برنامة‌ زير مساحت مربعي به ضلع 5 سانتی‌متر را محاسبه و چاپ مي‌كند. قسمتهاي مختلف آن را شرح دهيد.





کد:

کد:

#include
main() { int x , S ; x = 5 ; S = x * x ; printf ("area = %d", S) ; }




3. ويژگيهاي برنامة ‌ايده‌‌آل را شرح دهيد.
4. چند نمونه از زبانهاي سطح بالا، سطح پايين و سطح مياني را نام ببريد.

آبجی
25th May 2010, 12:00 AM
فصل 2
انواع داده‌ها
هدف کلی
آشنایی با انواع داده‌های زبان برنامه‌نویسی C و کاربردها و شیوه‌های معرفی آنها
هدفهای رفتاری
از دانشجو انتظار می‌رود پس از خواندن این فصل:
1. انواع داده‌های زبان C را نام برد.
2. مقادیر متغیر و ثابت داده‌ها را بشناسد.
3. انواع مقادیر ثابت را نام برد و تشریح کند.
4. داده‌های اسکالر و مجموعه‌ای را بشناسد.
5. چگونگی اعلان متغیرها در زبان C را بداند.
6. ویژگیهای داده‌های صحیح و شیوه‌های معرفی آنها را بداند.
7. ویژگیهای مقادیر ثابت صحیح بر مبنای 8، 10 و 16 و چگونگی معرفی آنها را بداند.
8. در داده‌های‌اعشاری، روشهای‌نوشتن‌ثابتهای‌با ممیزشناور را شرح‌دهدوکاربرد هریک‌را بداند.
9. در داده‌های کاراکتری کد اسکی و ebedic را تعریف کند.
10. تفاوت بین عدد و کاراکتر را در زبان C بداند.
11. طریقة شناساندن ثابتهای حرفی به مفسر را بداند.
12. طریقة شناسایی حروف کوچک و بزرگ را در کد اسکی بداند.
13. رشته یا ثابت رشته‌ای و طریقة معرفی آن را به مفسر بداند.
14. تفاوت ثابت حرفی و ثابت رشته‌ای تک‌حرفی را بداند.
15. مقداردهی اولیة متغیرها را بداند.
16. وظیفة‌ عملگر cast را شرح دهد.
17. داده‌های تهی و void را بشناسد.
18. پیش‌پردازنده و شیوة معرفی آن را بشناسد.
19. وظیفة فرمان #include و چگونگی تعریف آن را بداند.
20. وظیفة‌ فرمان #define و فواید آن را بداند.
مقدمه
دسته‌بندي داده‌ها به انواع مختلف، يكي از تواناييهاي جدید زبانهاي برنامه‌نويسي است. زبان C مجموعة کاملي از انواع داده‌ها را پشتیباني مي‌كند که عبارت‌اند از:
- داده‌هاي صحيح (integer)
- داده‌هاي اعشاري (floating point)
- داده‌هاي کاراکتری (character).
همچنين داده‌ها در زبانهاي برنامه‌‌‌نويسي به صورت مقادير ثابت و مقادير متغير به كار می‌روند. متغيرها در طول اجراي برنامه، مقادير مختلفي از داده‌ها را می‌پذيرند. اما مقادير ثابت مقاديري‌اند كه در طول برنامه تغيير نمي‌كنند. در زبان C چهار نوع ثابت وجود دارد که عبارت‌اند از ثابتهاي صحيح، ثابتهاي با مميز شناور، ثابتهاي کاراکتري و ثابتهاي رشته‌اي.
مقادير صحيح ثابت را مي‌توان علاوه بر روش معمول دهدهي، در مبناهاي هشت و شانزده نيز نوشت. مجموعه داده‌هاي از نوع صحيح و اعشاري را داده‌هاي از نوع محاسباتي يا arithmeticمي‌نامند. دو نوع ديگر از داده‌ها، نوع اشاره‌گر يا pointer و نوع شمارشي ياenumerated است، كه همراه با نوع محاسباتي، داده‌هاي نوع اسكالر ناميده مي‌شود. اين نوع داده‌ها را از اين لحاظ اسكالر مي‌نامند كه قابل مقايسه يا قابل سنجش با همنوع خودند. علاوه بر داده‌هايي از نوع اسكالر، داده‌هايي از نوع مجموعه‌اي وجود دارند از جمله آرايه‌، ركورد، ساختار و اجتماع كه در سازماندهي متغيرهايي مفیدند كه به طور منطقي به يكديگر مرتبط‌اند. اين نوع داده‌ها را نيز در فصلهای بعدي بررسي می‌کنیم.
اعلان متغيرها
اعلان، گروهي از متغيرها را به نوع داده خاصي مربوط مي‌سازد. در زبان C هر متغير، پيش از آنكه در دستوري از برنامه به كار رود، بايد تعريف شود. دستورهای مربوط به تعريف متغيرها، اطلاعات لازم در مورد نوع داده‌هايي را كه متغيرهاي مورد نظر مي‌پذيرند و اينكه چند بايت حافظه اشغال مي‌كنند و چگونگي تفسير آنها را در اختيار كامپايلر قرار مي‌دهند. اعلان شامل نوع داده و به همراه آن نام يک يا چند متغير است و به سميکولون ختم مي‌شود. براي اعلان يا تعريف متغيرهايي از نوع صحیح (integer) كلمة كليدي int و به دنبال آن اسامي متغيرهاي مورد نظر را كه با كاما از يكديگر تفكيك مي‌شوند مي‌نويسيم.
int a , b , c ;
البته مي‌توان هريك از متغيرها را در دستوري جداگانه و يا در سطري جداگانه معرفي كرد.
int a ;
int b ; int c ;
كه در سطر اول يک متغير اعلان شده و در سطر دوم با دو دستور جداگانه متغير دوم و سوم اعلان شده است. واضح است روش اول كه در آن هر سه متغير در يك سطر و با يك دستور اعلان شده ساده‌تر است. كلمات كليدي براي اعلان داده‌هايي از نوع اسكالر در جدول 2ـ1 نشان داده شده است.
جدول 2ـ1 كلمات كليدي در اعلان متغيرها

اصلي
اصلاح/توصیف‌‌کننده
int
float
char
double
enum
Short
long
signed
unsigned


<!--[if !vml]--><!--[endif]-->پنج كلمة ستون اول نوع اصلي يا پايه‌اي‌اند. چهار كلمة ستون دوم را اصلاح‌كننده<!--[if !supportFootnotes]-->[1]<!--[endif]-->یا توصيف‌كننده<!--[if !supportFootnotes]-->[2]<!--[endif]--> نامند كه به طريقي پنج نوع اصلي را توصيف مي‌كنند. به عبارت ديگر مي‌توان پنج نوع اصلي را اسم و چهار نوع توصيف‌كننده را صفت براي آن اسامي تصور كرد.
هرگونه اعلان متغيرها در داخل بلاك بايد قبل از اولين دستور اجرايي قرار گيرد. اما ترتيب اعلان آنها فرق نمي‌كند. برای مثال دو روش اعلان زير از نظر نتيجه يكسان‌‌اند.

روش اول

روش دوم
float x , y;

int a , b ;
float z ;

float x , y , z ;
int a ;


int b ;



داده‌‌هاي صحيح
زبان C از لحاظ بزرگي عناصر و همچنين از نظر نمايش داخلي آنها استاندارد ويژه‌اي به كار نمي‌برد. به طور کلي اعداد صحيح مثبت، منفي و صفر و نيز متغيرهايي كه مقادير صحيح را مي‌پذيرند، 16 يا 32 بيت حافظه اشغال مي‌كنند. فرم اولية داده‌هايي از نوع صحيح، يا همان int مقدار صحيح در نظر گرفته مي‌شود. اما اندازه يا بزرگي آن برحسب نوع ماشين و كامپايلر فرق مي‌كند.
در هنگام تعريف متغيرهاي از نوع int توصيف‌كننده‌هايshort ،long ، signed، unsigned و يا تركيبي از آنها نيز ممكن است به كار رود.
داده‌هايي كه با اين كلمات توصيف مي‌شوند، ممكن است از كامپايلري به كامپايلر ديگر تفسير متفاوت داشته باشند، ولي اساس آنها يكسان است. اگر مقادير صحيح در كامپايلری در حالت عادي 2 بايت باشد، بين short int و int فرقي نخواهد بود و هر دو 16 بيت يا 2 بايت حافظه اشغال می‌کنند. در ضمن short int را مي‌توان فقط به صورت short نيز به كار برد (يعني پيش‌ فرض آن است كه short همان short int است). در چنين حالتي long int نيز 4 بايت حافظه اشغال خواهد كرد كه آن را هم مي‌توان فقط به صورت long به كار برد (يعني در اينجا نيز پيش ‌فرض آن است كه long همان long int است). ولي چنانچه مقادير صحيح در حالت عادي 4 بايت حافظه اشغال کنند، short int يا فقط short 2 بايت حافظه به كار خواهد برد. اما بين long int و int (يا فقط long) تفاوتي وجود نخواهد داشت و هر دو 4 بايت حافظه اشغال خواهند کرد.
در مواردي متغيرها، فقط داراي مقادير غيرمنفي خواهند بود. مثلاً متغيري كه براي شمارش به كار می‌رود، يكي از اين موارد و هميشه مثبت است. زبان C اجازه مي‌دهد كه‌اين گونه متغيرها را با به كار بردن توصيف‌كنندة unsigned، بدون علامت اعلان كنيم. يك مقدار صحيح بدون علامت از نظر ميزان حافظة اشغالي با مقدار صحيح معمولي فرقي ندارد. تفاوت ميان آنها در بيت سمت چپ است كه بيت علامت ناميده مي‌شود و در مورد مقادير صحيح بدون علامت، اين بيت نيز مثل ساير بيتها براي نمايش مقدار عدد به كار مي‌رود و در نتيجه مقادير صحيح بدون علامت هميشه غيرمنفي است و بزرگي آن ممکن است تقريباً تا دو برابر مقدار صحيح معمولي باشد. براي مثال عدد صحيح معمولي از 32768- تا 32767+ (در مورد مقادير صحيح دو بايتي) تغيير مي‌كند، بنابراين مقدار صحيح بدون علامت از صفر تا 65535 تغيير خواهد كرد.
در استاندارد ريچي توصيف‌‌‌كنندة signedوجود ندارد. ولي استاندارد ANSI آن را پشتيباني مي‌كند. در اغلب موارد به صورت پيش‌فرض، متغيرها signedاند. بنابراين، به استفاده از توصيف‌كنندة‌ signed در آنها نیازی نخواهد بود. در اغلب مفسرها پيش‌فرض براي داده‌هاي كاراكتری signed char است.
متغيرهايي كه معرف اعداد صحيح‌‌اند به صورتهاي زير توصيف می‌شوند.
short int
int
unsigned int
signed int
long int
unsigned long int
unsigned short int
مثال 2ـ1 در زير نمونه‌‌هايي از نحوة معرفي متغيرهايي از نوع مقادير صحيح نمايش داده شده است.


کد:





1) long int temp , Pnoor ;2) short int y1 , y2 , y3 ;3) unsigned int m , n ;4) unsigned long sum , average ;5) unsigned short pt , qt ;









تعريف متغيرها از نوع long int و long هم‌ارز است، بنابراين مثال 1 را مي‌توان به صورت long temp , Pnoor ; نوشت. همچنين intshort و short نيز معادل هم‌اند. پس مثال 2 را مي‌توان به صورت short y1 , y2 , y3 ; نوشت. مثال 3 را نيز مي‌توان اين طور نوشت: unsigned m , n ;.


مقادير ثابت صحيح
در زبان C يکي ديگر از انواع داده‌‌ها، مقادير ثابت صحيح است. يك مقدار ثابت صحيح عدد و يا دنباله‌اي از ارقام است كه در مبناي 8، 10 و يا 16 تعريف شده باشد. اعداد زير نمونه‌هايي از اعداد با مقادير ثابت صحيح در مبناي 10 اند.
36925 , 9999 , +835 , 512 , 0
در C به طور پيش فرض اعداد صحيح در مبناي 10 تعريف شده‌‌اند. اما مبناهاي 8 و 16 نيز كاربرد زيادي دارند، زيرا 8 و 16 توانهايي از مبناي 2 اند و اين گونه سيستمهاي عددنويسي براي كامپيوترها مناسب‌‌تر است. براي مثال عدد 65536 در يك ماشين 16 بيت همان عدد 10000 در مبناي 16 است.
حال ببينيم كامپيوتر چگونه تشخيص مي‌دهد كه عددي در مبناي 8 يا 10 يا 16 تعريف شده؟ براي مشخص ساختن آن از پيشوندهاي 0 براي مبناي 8 و 0x براي مبناي 16 استفاده مي‌شود. مبناي 10 هم که پيش فرض است و پيشوند ندارد.بنابراين در مورد اعداد


+04163 , -0326 0751 , 0666

صفر سمت چپ به معناي آن است كه اعداد مزبور در مبناي 8 اند، لذا اگر عدد در مبناي 10 باشد، اولين رقم سمت چپ آن نمي‌تواند صفر باشد. بديهي است در مبناي 8 فقط هشت نشانة صفر تا 7 در ارقام به كار مي‌روند. همچنين در مبناي 16 نيز، شانزده نشانة مختلف به كار مي‌رود كه ده نشانة آن همان نشانه‌هاي متداول در مبناي 10 يعني صفر تا 9 است و شش نشانة ديگر حروف A , B , C , D , E , F است كه به ترتيب معادل 10 , 11 , 12 , 13 , 14 , 15 در مبناي 10 اند. مثالهاي زير نمونه‌اي از اعداد مبناي 16 اند.
0xF1E6 , 0x5AB , 0x327 , 0x99
اگر طول هر كلمه در ماشين مورد نظر 16 بيت باشد، طول آن از -32k تا +32k يعني از -32768 تا +32767 تغییر خواهد کرد كه معادل 215-1 و يا معادل 077777 مبناي 8 و يا 7FF مبناي 16 است. ولي اگر طول هر كلمه 32 بيت باشد، طول آن از -2G تا +2G خواهد بود يعني از-2, 147,483, 648 تا 2, 147, 483,647 كه معادل 231-1 است.
مقادير ثابت صحيح بدون علامت يا unsigned integer constantsبا قرار دادن u، حرف اول كلمة unsigned، و همين‌طور مقادير ثابت صحيح طولاني يا long integer constantsبا قراردادن حرف l، حرف اول كلمه long، در سمت راست آنها مشخص مي‌گردد كه l و u را می‌توان به هر دو صورت بزرگ يا كوچك نوشت. همچنين اگر عددي هر دو صفت مذكور را داشته باشد (يعني هم بدون علامت و هم به‌صورت طولاني باشد)، با دو حرف ul (u در سمت چپ، l در سمت راست آن) متمايز مي‌شود.
مثال 2ـ2 جدول زير مثالهايي از انواع مقادير ثابت صحيح را نشان مي‌دهد.


مقدار ثابت صحيح
سيستم عددي


546780u



مبناي 10 (بدون علامت)



1234567l



مبناي 10 (طولاني)



1234567ul



مبناي 10 (بدون علامت و طولاني)



0123456u



مبناي 8 (بدون علامت)



0123456ul



مبناي 8 (بدون علامت و طولاني)



0563214l



مبناي 8 (طولاني)



02677u



مبناي 8 (بدون علامت)



0x12545678l



مبناي 16 (طولاني)



0xABCDEFu



مبناي 16 (بدون علامت)



0xEF1A3Abul



مبناي 16 (بدون علامت و طولاني)



<!--[if !supportMisalignedColumns]-->

<!--[endif]-->
توابع scanfو printfدر فرمت مربوط به خواندن و نوشتن مقادير صحيح در مبناي 8 و 16 به ترتيب حروف o و x را مشخص‌كنندة فرمت در رشته كنترل فرمت به كار مي‌برند.


مثال 2ـ3برنامة زير عددي در مبناي 16 (با پيشوند 0x يا بدون آن) را از طريق ترمينال مي‌خواند و معادل آن را در مبناهاي 10 و 8 چاپ مي‌كند.
کد:





# include main () { int n ; printf ("Enter a hexadecimal constant: \n") ; scanf ("%x",&n) ; printf ("The decimal equivalent of %x is: %d ", n , n) ; printf ("\n The octal equivalent of %x is: %o\n", n , n) ; }






داده‌هاي اعشاري
در زبان C اعداد اعشاري نيز قابل نمايش است. داده‌‌هاي صحيح در بسياري موارد مناسب است. اما براي مقادير خيلي بزرگ و براي مقادير كسري كوچك كه در اغلب زمينه‌هاي علمي کاربرد دارد، به داده‌هاي از نوع مميز شناور يا floating point نیاز است. براي نوشتن ثابتهاي با مميز شناور دو روش به كار می‌رود.
روش اول كه ساده‌ترين راه است، آن است كه از علامت مميز (كه در انگليسي "." است) استفاده كنيم. مثالهاي زير از اين نوع است.


0.996 , 15.0 , 3.1415 , 7. ,.275

روش دوم كه نمايش علمي<!--[if !supportFootnotes]-->[3]<!--[endif]--> نيز ناميده مي‌شود، روش كوتاه‌نويسي مفيدی است. در اين روش هر مقدار شامل دو جزء است: يك قسمت عددي كه آن را مانتيس نامند و به‌دنبال آن يك قسمت نما يا توان مي‌آيد كه قسمت مانتيس بايد در 10 به توان نما ضرب شود. بين اين دو قسمت حرف E يا e (كه حرف اول exponent است) به مفهوم نما يا توان به كار می‌رود. براي مثال3E2 به مفهوم 3*102 و -125.7E-3 به مفهوم -125.7*10-3است. در واقع يك مقدار ثابت با مميز شناور، عددي است در مبناي 10 كه شامل يك مميز يا علامت اعشار يعني "." يا شامل يك نما يا هر دو است؛ مانند مثالهاي زير
0. , 0.0 , 1. , 0.92 182.25 , -3.1415 , 5E-5 , 0.775E-3
<!--[if !vml]--><!--[endif]--> البته قسمت نما نمي‌تواند يك عدد كسري باشد، پس 29.5E3.4 درست نيست. در بعضي نسخه‌‌هاي C براي اينكه مشخص كنند كه مقادير مورد نظر يك كلمه اشغال كرده است حرف F (یا f) را به آخر آن اضافه مي‌كنند، مانند 6.125E5F .
همچنين براي مشخص كردن اينكه مقادير مورد نظر فضايي به طول دو كلمه را اشغال كرده است، حرف L (يا l) به آخر آن اضافه مي‌شود مانند0.123456789E-25L .
دقت مقادير ثابت با مميز شناور ممكن است برحسب نسخه‌هاي مختلف تغيير كند، ولي همة آنها حداقل 6 رقم با معني را مي‌پذيرند.
براي اعلان متغيرهايي از نوع floating point از دو كلمة كليدي "float" و "double" استفاده مي‌شود، مانند
float a , b , c ;
double x , y , z ;
که در آن كلمه "double" به مفهوم دقت مضاعف يا double precesion است و در اغلب ماشينها طول فضايي كه براي متغيرهاي توصيف شده با آن رزرو مي‌شود، دو برابر "float" است. يك متغير توصيف شده با "float" به‌طور متعارف 4 بايت در حافظه اشغال مي‌كند، پس در "double" اين فضا 8 بايت خواهد شد و نمايش دروني مقادير floating-point نيز از ويژگيهاي معماري سخت‌افزار كامپيوتر است و هنوز كاملاً استاندارد نیست. در مورد ميزان دقت float و double نيز بايد به مستندات كامپايلر مربوط مراجعه كرد. در برخي كامپايلرها براي اعلان متغيرهاي از نوع double نيز مي‌توان آنها را به صورت long float تعريف كرد. بنابراين دو روش اعلان زير معادل‌اند.

double a , b , c ;
long float a , b , c ;

به هرحال اگر كلمة توصيف‌كنندة long به تنهايي جلوي متغيري به كار رود، آن متغير به صورت پيش‌فرض از نوع مقادير صحيح خواهد بود. بنابراين با دستور long a , b , c ; سه متغير c , b , a از نوع صحيح خواهند بود.

داده‌‌هاي كاراكتري
يکي از انواع داده‌‌هايي که در برنامه‌‌نويسي استفاده مي‌شود داده‌‌هاي کاراکتري است. در بسياري از زبانهاي برنامه‌‌‌سازي داده‌هاي عددي و داده‌هاي كاراكتري با يکديگر تفاوت دارند. مثلاً عدد 2 داده‌ای عددی و حرف A داده‌ای كاراكتري است. در عمل هم، كاراكترها به صورت عدد در حافظة كامپيوتر ذخيره مي‌شوند، و هر كاراكتر داراي يك كد عددي است. كدهاي مختلفي وجود دارد كه دو نوع آن عبارت‌اند از اسکی (ascii)<!--[if !supportFootnotes]-->[4]<!--[endif]--> یا كد استاندارد آمريكايي براي تبادل اطلاعات و ديگري ebcdic<!--[if !supportFootnotes]-->[5]<!--[endif]--> یا كد توسعه‌‌يافتة bcd كه آی‌بی‌ام روي سيستم بزرگ خود به كار مي‌برد و بيشتر متداول است. البته در زبان C، كد اسکی متداول است. در همة كدگذاريها براي هر كاراكتر نماد عددي وابسته‌ای وجود دارد كه در كدگذاري اسكي به آن ascii code گويند و مقدار آن از صفر تا 255 است.
در زبان C تفاوت بين اعداد و كاراكتر ناچيز است. در اين زبان يكي از انواع داده‌ها char ناميده مي‌شود، اما در حقيقت كاراكتر مقدار صحيح يك بايتي است كه هم براي نگهداري اعداد و هم براي نگهداري كاراكترها به كار می‌رود.
ثابتهاي حرفي در داخل يك زوج گيومه قرار مي‌گيرد. اين گيومه‌ها به كامپايلر اعلان مي‌كند كه كد عددي كاراكتر مورد نظر را به دست آورد. براي مثال در دستورهاي
char a , b ;
b = 5 ;
a = ‘5’;
مقدار a برابر 53، يعني برابر کد اسكي كاراكتر ’5’ و مقدار b برابر 5 خواهد بود.
v مثال 2ـ4 برنامة زير كاراكتری را از ورودي‌ می‌خواند و كد عددي آن را نمايش مي‌دهد.


کد:



#include main() { char ch ; scanf ("%c", &ch) ; printf (" The numeric code is: %d \n ", ch) ; }




<!--[if !vml]-->file:///C:%5CDOCUME%7E1%5CMilad%5CLOCALS%7E1%5CTemp%5Cmsoh tml1%5C01%5Cclip_image003.gif<!--[endif]--> همچنين در توابع printf و scanf نماد %c فرمت متغيرهاي كاراكتري است مانند %d كه براي متغيرهاي مقادير صحيح و %f كه براي متغيرهاي مقادير اعشار به كار می‌رود (توابع ورودي و خروجي و فرمت متغيرها را در فصل 3 بررسي می‌کنیم).


در مجموعه كاراكتر اسكي، ترتیب كد كاراكترها براساس ترتيب كاراكترهاست. براي مثال، كد حرف ’A’ برابر 65، ’B’ برابر 66، ...، و ’Z’ برابر 90 است. كد حروف كوچك از 97 تا 122 است. با توجه به ارزش كد حروف، تابع زير حروف بزرگ را به حروف كوچك تبديل مي‌كند (توابع را در فصل 6 بررسي مي‌کنیم).
کد:



char Up-to-low (ch) char ch ; { return ch + 32 ; }




تابع مذکور به کد اسكي هر كاراكتر دريافتي 32 واحد اضافه مي‌كند كه درنتيجه حروف بزرگ به حروف كوچك تبديل مي‌شود. مثلاً کد اسكي حرف ’A’ (65) 32 واحد از کد اسكي حرف ’a’ (97) كوچك‌تر است. مشابه آن مي‌توان تابعي براي تبديل حروف كوچك به بزرگ تعريف كرد كه در اين حالت بايد از کد اسكي حرف مورد نظر 32 واحد كسر گردد تا به حرف بزرگ مشابه خود تبديل شود.
در سيستم كدگذاري غير اسکی، مانند ebcdic، تفاوت عددي كد حروف بزرگ و كوچك 32 نیست. بنابراين در چنين حالتي تابع تعريف شدة بالا نتيجة مطلوب را نمي‌دهد. براي جلوگيري از چنين اشتباهي زبان C داراي توابع كتابخانه‌اي به اسامي toupper و tolower است كه به ترتيب عمل تبديل كاراكترها را از بزرگ به كوچك و از كوچك به بزرگ انجام مي‌دهند.
ثابتهاي رشته‌اي
رشته يا ثابت رشته‌اي از تعدادي کاراکتر متوالي تشکيل می‌شود که بين دو گيومه قرار می‌گیرند. به عبارت ديگر شامل دنباله‌اي از كاراكترهاست كه در بين دو گيومه قرار دارند، مانند نمونه‌‌هاي زير.


کد:

"university" , "256" , "payam noor" , "1380-02-06" , "five$" , "p4"

همچنين بايد توجه داشت كه " " نيز رشته‌ای تهي (empty) يا null است.
مثال 2ـ5 ثابت رشته‌اي زير شامل سه کاراکتر مخصوص است كه با escape sequence متناظرشان نشان داده شده‌اند.


کد:

"\t to continue , press the \"RETURN\" KEY\n"

که در آن نشانه‌ها يا كاراكترهاي مخصوص عبارت‌اند از
horizontal tab \t،
\" گيومه يا quotation mark دوبل كه دو بار به كار رفته است،
\n خط جديد يا new line.


كامپايلر به طور خودکار يك كاراكتر (\0) null در پايان هر ثابت رشته‌اي قرار مي‌دهد كه آخرين كاراكتر در داخل رشته (قبل از بسته شدن گيومه) خواهد بود. اين كاراكتر وقتي كه رشته نمايش داده شود رؤيت‌پذیر نیست. به هرحال مي‌توان هريك از كاراكترها را در داخل رشته امتحان كرد كه آيا كاراكتر null است يا نه. در خيلي موارد مشخص ساختن پايان يك رشته با يك كاراكتر مخصوص مانند كاراكتر null نياز به تعيين حداكثر طول براي رشته را از بين مي‌برد. به عنوان مثال رشتة فوق 38 كاراكتر دارد كه شامل پنج فضاي خالي و چهار كاراكتر مخصوص است كه با escape sequence معرفي شده‌اند و در پايان كاراكتر null است كه انتهاي رشته را مشخص مي‌سازد.
يك ثابت حرفي مانند ‘P’ با يك ثابت رشته‌اي تك‌‌حرفي متناظر آن مانند "P" هم‌ارز نیست. همچنين به‌خاطر داشته باشيد كه در جدول كد اسكي، هر كاراكتر داراي يك مقدار عددي است، ولي يك رشتة تك‌‌‌حرفي اين‌طور نيست. در واقع يك رشتة تك‌حرفي متشكل از دو كاراكتر است كه كاراكتر دوم همان كاراكتر null است كه پايان رشته را مشخص مي‌سازد.
باز هم توجه داشته باشيد كه يك رشتة n كاراكتري به آرايه 1+n عنصري نياز خواهد داشت، زيرا كاراكتر null نيز به طور خودکار به عنوان كاراكتر پاياني در آن قرار داده خواهد شد. براي مثال اگر رشتة "COMPUTER" در يك آراية يك بعدي كاراكتري به نام book ذخيره گردد، خانه اول آن، يعنيbook[0]، شامل كاراكتر C و خانة آخر، يعني book[8] شامل كاراكتر null خواهد بود كه معرف پايان رشته است.
دربارة رشته‌ها و آرايه‌ها و كاربرد آنها در فصل جداگانه‌اي به طور مشروح بحث خواهیم کرد.
مقداردهی اولية متغيرها
در صورتي که از پيش مقدار شروع متغير را بدانيم مي‌توانيم به هنگام تعريف، مقدار اولية مورد نظر را نيز به آن اختصاص دهيم. براي اين كار در تعريف متغيرها، به دنبال نام آن، اپراتور جايگزيني '=' را همراه با مقدار اوليه به كار مي‌بريم. برای مثال هر يك از روشهاي زير متغيرهاي a , b , c را توصيف می‌کنند و به ترتيب مقادير 12 , 13 , -25 را به آنها اختصاص مي‌دهند.


روش اول

روش دوم

روش سوم
int a =12;

int a =12 , b =13 ;

int a =12 , b =13 , c = -25 ;
int b =13 ;

int c = -25 ;


int c = -25 ;





اما در دستور زير فقط به b مقدار اوليه داده شده است.
int a , b = 15 , c ;
در اين گونه موارد براي جلوگيري از اشتباه بهتر است متغيرهايي را كه مقدار اوليه مي‌پذيرند جدا از ساير متغيرها توصيف کرد، مانند مثال زير.
int a =12 , b =13 , c =25 ;
int d , e , f ;
مثال 2ـ6 چند نمونة ديگر از مقداردهی اولية متغيرها در زير نشان داده شده است.
کد:





int sum = 5 ;
char Str = ' # ' ;
float tmp = 10.2 ;
double p1 = 0.1234E-6 ;


عملگر cast
مي‌توان تبديل يك نوع به نوع ديگر را به صورت صريح انجام داد. اين كار به كمك عملگر cast انجام مي‌گيرد. پس ساختار cast نوع ديگر از تبديل است. براي اين كار كافي است نوع جديد داده مورد نظر را در داخل پرانتز مستقيماً جلوي عبارت قرار دهيم؛ براي مثال
k = (float)2 ;
مقدار صحيح 2 را قبل از اختصاص‌دادن به k به float تبديل مي‌كند و سپس آن را به k اختصاص مي‌دهد. بنابراين، اپراتور cast اپراتور یکانیاست؛ يعني فقط يك اپراند دارد.
در موارد متعددي روش casting خيلي مفيد است. براي مثال حالت زير را درنظر بگيريد.
int i =2 , k =3 ;
float h = k / i ;
در اينجا مقدار k / i (يعني 3 / 2) برابر 1.5 خواهد شد. سپس نتيجه به float يعني 1.0 تبديل و به h نسبت داده مي‌شود. حال می‌خواهيم مقدار 1.5 را كه نتيجة واقعي عبارت رياضي 3/2 است به k و iيا هر دوي آنها را با cast به float تبديل كنيم، مثلاً
(float) k / i ;
در اينجا به‌طور صريح k به float تبديل مي‌گردد، پس نتيجه برابر 1.5 خواهد شد. عبارت مزبور را مي‌توان به صورت k / (float) i ; يا (float) k / (float) i ;نيز نوشت كه نتيجه باز هم 1.5 مي‌گردد، يعني نتيجه سه روش مزبور هم‌ارز است.
از مثالهاي بالا نتيجه مي‌شود كه به كمك casting مي‌توان در وسط جمله نوع داده را به نوع ديگري تبديل كرد. بنابراين اپراتور cast به‌عنوان نوع يا type عمل مي‌كند؛ يعني type conversion است و فرمت آن به‌اين طريق است كه نوعجديد متغير يا عبارت مورد نظر جلوي آن متغير يا عبارت در داخل پرانتز نوشته شود. براي مثال دستور (int)d1+d2 يعني اول d1 به int تبديل مي‌شود بعد با d2 جمع مي‌شود. درحالي كه دستور (int)(d1+d2)يعني نتيجة d1+d2 به int تبديل مي‌شود.
بنابراين فرمت اپراتور cast به صورت زير است.
(data type) expression
حال براي آنكه نقش اپراتور cast را بهتر متوجه شويد، به نتيجه و عملكرد دو مجموعه دستورهای زير توجه كنيد.
کد:





مثال اول

مثال دوم
float x ;

short int x ;
printf ("%d\n",(int)x) ;

printf ("%s\n",(char)x) ;




در مثال اول براي متغير x كه از نوع float اعلان شده است، 4بايت حافظه پيش‌بيني مي‌شود. ولي در نتيجة اجراي دستور printf سطر دوم، به دليل دستور (int)x مقدار آن به نوع intتبديل مي‌گردد و نمايش داده مي‌شود. بنابراين، اگر براي مثال محتواي حافظه به‌صورت

0.26 E+7

باشد، مقدار 2600000 نمايش داده خواهد شد.
همين‌طور در مثال دوم براي متغير x كه از نوع short int اعلان شده است، 2 بايت حافظه پيش‌بيني مي‌شود، ولي درنتيجة اجراي دستور printf سطر دوم، به دليل (char)x مقدار آن به نوع كاراكتر تبديل مي‌گردد و محتواي دو بايت حافظة مزبور به‌صورت يك رشتة دوبايتي نمايش داده مي‌شود. به همين دليل است كه در فرمت چاپ مقدار متغير مزبور، از فرمت "%s" كه براي رشته است استفاده شده است. حال اگر براي مثال محتواي حافظة مربوط به متغير x به صورت1 2 3 4باشد، موقع نوشتن به صورت رشتة "1 2 3 4"چاپ مي‌شود.
در اينجا به اختصار يادآور مي‌شویم كه فرمتهاي "%s", "%c", "%f", "%d"به ترتيب براي متغيرهاي از نوع مقادير صحيح، اعشار، كاراكتر و رشته به كار می‌روند.
نوع void
داده از نوع void (تهي) در استاندارد ريچي وجود نداشت و بعد به استاندارد ANSI افزوده شد. از اين نوع داده هدف مهمي مورد نظر است و آن در مورد معرفي توابعي است كه مقداري را برنمي‌گردانند، بلكه فقط عمل خاصي را انجام مي‌دهند.
مثال 2ـ7 تابعي به نام FF1 كه داراي دو آرگون x و y است به صورت زير تعريف شده است
. کد:

کد:

void FF1(x , y) int x , y ; { -------------- -------------- -------------- }
قرار گرفتن void در جلوي نام تابع مزبور به‌اين ‌دليل است كه‌ اين تابع چيزي را برنمي‌گرداند.


پيش‌‌پردازنده
پيش‌پردازنده را مي‌توان برنامة جداگانه‌اي در نظر گرفت كه قبل از كامپايلر واقعي اجرا مي‌گردد. هنگامي كه برنامه‌ای را كامپايل مي‌كنيد، پيش‌پردازنده به طور خودکار اجرا مي‌گردد. تمام فرامين پيش‌پردازنده با علامت " # " شروع مي‌گردند كه بايد اولين كاراكتر خط باشد. وظيفة اصلي و مهم پيش‌پردازنده آن است كه فايل درخواستي را آماده سازد و وارد برنامه كند. برخلاف دستورهای C كه به سميكولون ختم مي‌شوند، پايان جمله‌های آن با خط جديد مشخص مي‌گردد. دو دستور متداول از پيش‌‌پردازنده‌‌ها را در ادامه بررسي مي‌کنیم.
فرمان #include
فرمان #include موجب مي‌گردد كه كامپايلر همزمان با فايلي كه ترجمه مي‌كند، يك متن را نيز از فايل ديگر بخواند. اين عمل شما را قادر مي‌سازد كه بتوانيد قبل از شروع ترجمه، محتواي يك فايل را در فايل ديگر بريزيد (درج كنيد)، ضمن اينكه فايل اوليه تغيير نمي‌يابد. اين عمل به‌ ويژه در حالتي كه بيش از يك فايل مبنا، اطلاعاتي يكسان را سهيم شوند و به كار ببرند مفيد است. با اين كار به جاي اينكه اطلاعات مشترك دو فايل را به صورت دوبله در هر دو منظور کنيد، آن را فقط در يك فايل قرار مي‌دهيد، سپس هر موقع آن اطلاعات در فايل دوم مورد نياز باشد، به‌ طريق مذكور آن را براي استفادة فايل دوم نيز آماده مي‌كنيد.
تعريف فرمان #include به دو شکل زير است.

شکل اول

شکل دوم
# include < filename >


# include "filename"

در شکل اول، پيش‌پردازنده فقط محل خاصي را كه با عامل مشخص شده است نگاه مي‌كند. اين محل جايي است كه include fileهاي سيستم، مانند header files براي كتابخانة زمان اجرا يا Runtime Library نگهداري مي‌شوند. اگر شکل دوم به كار رود، پيش‌پردازنده فهرست يا دايركتوري را كه شامل فايل مبناست نگاه مي‌كند. اگر فايل include file را در آنجا پيدا نكند، پس از آن مشابه شکل اول، محل خاص مورد نظر را جستجو مي‌كند. اسامي include fileها بر حسب قرارداد، به پسوند "h" ختم مي‌شوند.
حال ببينيم وقتي كه پيش‌پردازنده با فرمان # include مواجه مي‌شود، چه پيش‌ مي‌آيد؟ پيش‌پردازنده فهرست تعريف شده در سيستم را براي فايلي به نام stdio.h جستجو مي‌كند. سپس فرمان #include را با محتواي فايل جايگزين مي‌كند.
براي اينكه بدانيد فرمان #include چگونه كار مي‌كند، فرض كنيد كه فايلي به نام file1.h داريد كه محتواي آن فقط دو دستور زير است.
int st-no ;
char name ;
سپس در فايل مبنا، فرمان #include را به صورت زير به كار مي‌بريد.
کد:



#include "file1.h" main() { ----------- ----------- }




حال وقتي كه برنامة مزبور را ترجمه مي‌كنيد، پيش‌پردازنده به جاي فرمان #include محتواي فايل مشخص شده را قرار مي‌دهد. بنابراين فايل مبنا به صورت زير درمي‌آيد.


کد:



int st-no ; char name ; main() { ------------ ------------ }




فرمان #define
همان طور كه مي‌توان با توصيف يا اعلان متغير، اسمي را به يك محل از حافظه وابسته كرد و به آن محل با آن نام (كه همان متغير مورد نظر است) مراجعه کرد، به همان طريق مي‌توان اسمي را به يك مقدار ثابت وابسته كرد و آن را با همان اسم كه ثابت سمبوليكي ناميده مي‌شود مشخص و هنگام نياز به آن مراجعه كرد. اين گونه متغيرها را كه معمولاً با حروف بزرگ معرفي مي‌شوند ثابتهاي سمبوليكي يا symbolic constants گويند و اين عمل با دستور #define انجام مي‌گيرد.
براي مثال با دستور # define book 15مي‌توان در هر جاي برنامه به جاي 15 از book استفاده کرد. بنابراين دو دستور زير هم‌ارزند.
k = 12 + 15 ;
k = 12 + book ;
هر دو دستور مقدار (12 +15 = 27) 27 را به متغير k نسبت مي‌دهند.
براساس دستور define مقدارbookدر حافظه به صورت مقدار ثابت 15 است كه در طول برنامه تغيير نمي‌كند. انتخاب نام براي مقادير ثابت چند فايدة مهم دارد.
اول آنكه به بعضي مقادير ثابت مي‌توان اسم با معني اختصاص داد. مثلاً مي‌توان عدد معروف «پي» را كه تا 4 رقم اعشار معادل 3.1415 است، در آغاز به صورت
#define Pi 3.1415
تعريف كرد و سپس در سرتاسر برنامه، به جاي عدد مزبور در تمام محاسبات وابسته به آن Pi را به كار برد.
دوم آنكه اگر مجبور باشيم در برنامه‌ای يك مقدار ثابت طولاني نامأنوس را چندين بار به كار بريم، ساده‌تر آن خواهد بود كه با دستور #define نامی مناسب براي آن انتخاب كنيم و به جاي ثابت مزبور از آن نام استفاده كنيم. مثلاً اگر مجبور باشيم همان عدد پي را با 6 رقم اعشار در قسمتهاي متعددي از برنامه به كار بريم، اين عمل هم پردردسر و هم اشتباه‌زا خواهد بود. لذا بهتر است، مثل حالت قبل، يك اسم براي آن انتخاب كنيم.
سوم آنكه ممکن است طبيعت مقدار ثابت طوري باشد كه در زمانهاي مختلف تغيير كند، مثل نرخ ماليات، يا اجرت ساعت كار و يا درصدي كه به عنوان سود در بانكها به پس‌اندازهاي پولي يا سرمايه‌گذاري تعلق مي‌گيرد كه هميشه ثابت نيست و ممكن است برحسب مقررات، قوانين و ساير شرايط مقدار آن عوض شود. در چنين مواردي بايد در سرتاسر برنامه مقدار ثابت موردنظر را عوض كنيم. درحالي كه اگر با دستور #define اسمي براي آن انتخاب كرده باشيم كافي است فقط در همان يك دستور تغيير مورد نظر را اعمال كنيم. مثلاً اگر براساس قوانين، نرخ جديد ماليات بر درآمد برابر 2 درصد باشد، كافي است به آن قبلاً نام TAX را اختصاص داده باشيم و با دستور #define TAX 0.02 مقدار جديد را جايگزين قبلي کنيم و ديگر نيازي نيست كه در داخل برنامه تغييراتي انجام دهيم. از مثال بالا مشخص مي‌گردد كه يك ثابت سمبوليكي نامي است كه جايگزين دنباله‌اي از كاراكترها مي‌گردد. كاراكترها ممكن است يك ثابت عددي، يك ثابت كاراكتري، و يك ثابت رشته‌اي باشند. بنابراين يك ثابت سمبوليكي اجازه مي‌دهد كه در يك برنامه به جاي يك مقدار ثابت (عددي، حرفي يا رشته‌اي) يك اسم قرار گيرد. وقتي كه برنامه ترجمه مي‌گردد، در هر محلي از برنامه كه ثابت سمبوليكي قرار گرفته باشد، دنبالة كاراكترهاي متناظر آن جايگزين مي‌گردد. ثابتهاي سمبوليكي معمولاً در آغاز برنامه تعريف مي‌گردند و شکل آنها به صورت زير است.
#define name text
كه در آن name معرف نام سمبوليك است كه معمولاً با حروف بزرگ نوشته مي‌شود. text نيز دنباله‌اي از كاراكترها را كه بايد به نام سمبوليك اختصاص داده شود معرفي مي‌نمايد. توجه داشته باشيد كه text به سميكولون ختم نمي‌گردد، زيرا تعريف ثابت سمبوليك دستور واقعي C نیست.
v مثال2ـ8 در زير نمونه‌هاي ديگري از ثابتهاي سمبوليكي نشان داده شده است.


کد:



#define Temp 524 #define Pi 3.1415 #define true 1 #define Name " payam noor " #define f(x) x + 1

خصيصة #define كه براي تعريف ثابتهاي سمبوليك به كار می‌رود يكي از چندين خصيصه‌اي است كه در پيش‌پردازنده وجود دارد.
v
خودآزمایی 2
1.برنامه‌اي بنويسيد كه مساحت دايره‌اي به شعاع Rرا محاسبه کند و نمايش دهد.
2. برنامه‌اي بنويسيد كه کاراکتري را از ورودي بخواند و کد اسکي آن را چاپ کند.
3. برنامه‌اي بنويسيد كه مجموع 100 جملة اول سري زير را محاسبه و چاپ كند.
y = 1 + 1/2 + 1/3 + 1/4 + …
4. برنامه‌اي بنويسيد كه ضرايب معادله‌های درجه دوم را بخواند، جوابهاي آن را به دست آوردو چاپ كند. اگر معادله ريشة حقيقي نداشته باشد، پيغام مناسب نمايش دهد.
5. خروجي برنامة زير چيست ؟


6. خروجي برنامة زيرچيست ؟
کد:


main () { unsigned char c ; c = 100 * 4 ; printf ("%d" , c) ; } __________________

آبجی
25th May 2010, 12:05 AM
فصل 3
توابع ورودي و خروجي
هدف کلی
آشنایی با هشت تابع ورودی و خروجی زبان C
هدفهای رفتاری
انتظار می‌رود پس از مطالعة این فصل دانشجو:
1. با کاربرد و ویژگیهای تابع خروجی printf() آشنا شود.
2. فرامین فرمت را در تابع آرگومان‌دار ‌printf() بشناسد.
3. با کاربرد و ویژگیهای تابع ورودی scanf() آشنا شود.
4. تفاوت و تشابه توابع printf() و scanf() را بداند.
5. با کاربرد و ویژگیهای تابع ورودی getchar() آشنا شود.
6. با کاربرد و ویژگیهای تابع خروجی putchar() آشنا شود.
7. با کاربرد و ویژگیهای تابع ورودی getche() آشنا شود.
8. با کاربرد و ویژگیهای تابع ورودی getch() آشنا شود.
9. با کاربرد و ویژگیهای تابع ورودی ـ خروجی gets() و puts() آشنا شود.
مقدمه
زبان C با مجموعه‌اي از توابع كتابخانه‌اي همراه است كه تعدادي از آنها تابع ورودي و خروجي‌اند. برخي از اين توابع متداول را كه اغلب در كتابخانه يا فايل stdio.h قرار دارند در اين فصل بررسي می‌کنیم.
توابع فرمت‌‌دار scanf و printf امکان انتقال اطلاعات ميان كامپيوتر و دستگاههاي ورودي و خروجي استاندارد را فراهم می‌کنند. در واقع این توابع فرمت‌‌دار روي داده‌‌هايي که به شکل پيش‌‌فرض براي کامپایلر شناخته شده‌اند عمل مي‌کنند. دو تابع getchar وputchar موجب انتقال يك كاراكتر به حافظه و بالعكس مي‌گردند. دو تابع gets و puts نيز ورود و خروج رشته‌ها را ساده‌تر مي‌سازند.برخي از توابع ورودي و خروجي به آرگومان نیاز ندارند. بعضي از اين توابع مقداري را برنمي‌گردانند. برخي به صورت مستقل به كار می‌روند و برخي ممكن است در داخل عبارات و دستورها به كار روند.
تابع printf()
داده‌‌هاي خروجي استاندارد در کامپيوتر با استفاده از اين تابع نوشته می‌شود. اين تابع به تعداد دلخواه آرگومان می‌پذيرد كه آرگومان اول داراي مفهوم خاص است و رشتة فرمت يا رشتة كنترل[2 (http://pnu-club.com/redirector.php?url=http%3A%2F%2Fwww.blogfa.com%2FD esktop%2F%23_ftn2)ناميده مي‌شود. رشتة كنترل در داخل زوج گيومه قرار مي‌گيرد و شامل اطلاعات قالب‌‌بندي است؛ يعني، مشخص مي‌كند كه بايد چند قلم آرگومان داده چاپ شود و فرمت آنها چگونه است. فرم كلي اين تابع به صورت زير است.
کد:

printf ("control string", arguments list) ;
يا
کد:

printf ("control string", arg1, arg2,…, argn) ;
رشتة كنترل دربردارندة دو نوع اقلام داده است. نوع اول شامل رشته يا كاراكترهايي است كه به همان صورت روي صفحه نمايش داده خواهد شد. نوع دوم شامل فرامين فرمت است كه با علامت "%" آغاز مي‌گردد و به دنبال آن كد فرمت يا مشخص‌كنندة فرمت مي‌آيد. فرمان فرمت، قالب يا فرمت و تعداد متغيرها يا آرگومانهايي را كه بايد چاپ شوند مشخص مي‌سازد و به آن type conversion نيز مي‌گويند و در آن براي مشخص ‌ساختن فرمت هر آرگومان يك گروه از كاراكترها كه با "%" آغاز مي‌گردند به كار مي‌رود.
برخي مؤلفان كد فرمت را فرامين فرمت نيز مي‌گويند. فهرست كد يا فرامين فرمت كه در فرمان printfبه كار می‌روند در جدول 3ـ1 نشان داده شده است.

جدول 3ـ1 فرامين فرمت در تابع printf ()

مفهوم فرمان فرمت
كد تبديل
داده‌ به صورت تك‌كاراكتر نمايش داده مي‌شود.


%c

داده به صورت عدد صحيح دهدهي علامت‌دار نمايش داده مي‌شود.


%d

داده‌ به صورت عدد صحيح علامت‌دار نمايش داده مي‌شود.


%i

داده به صورت عدد اعشاري، مميز شناور بدون نما يا توان نمايش داده مي‌شود.


%f

داده به صورت floating-point ولي به فرم نمايي يا علمي نمايش داده مي‌شود.


%e

داده به صورت floating-point به فرم %f يا %e (هركدام كوتاه‌‌تر باشد) نمايش داده مي‌شود.


%g

داده‌ به صورت عدد صحيح دهدهي بدون علامت نمايش داده مي‌شود.


%u

داده‌ به صورت رشته نمايش داده مي‌شود.


%s

داده به صورت عدد صحيح در مبناي 8 نمايش داده مي‌شود.


%o

داده به صورت عدد صحيح در مبناي 16 و بدون علامت‌ نمايش داده مي‌شود.


%x

پيشوندي كه با %o , %x , %u , %d براي معرفي مقدار صحيح بلند يا طولاني به كار می‌رود (مثل ld).


L

در مورد داده‌‌هاي از نوع اشاره‌گر به كار می‌رود.


%p

علامت % چاپ مي‌كند.


%%



v مثال3ـ1در برنامة زير مقادير متغيرهايي از نوعهاي مختلف در خروجي چاپ مي‌شود.
کد:

#include
main ()
{
int x =31 ;
float y =148.5 ;
char z[10] = {"PayamNoor"};
printf(" %d %f %s " , x , y , z) ;
}


اولي عدد صحيح دهدهي، دومي از نوع اعشاري و سومي رشته است كه به ترتيب با فرمان فرمت %s ,%f , %d مشخص شده‌اند. خروجي دستور مزبور به صورت زير خواهد بود.
کد:

31 148.5 PayamNoor
در برنامة مذكور به‌علت وجود يك محل خالي بين فرامين فرمت در رشتة كنترل، بين مقادير چاپ شده نيز فضاي خالي ايجاد شده است.

v مثال 3ـ2 به‌اين برنامه توجه کنيد.

کد:


#include
main ()
{
float x=2.0 , y=3 ;
printf("%f %f %f %f %d", x , y , x+y , x*y, x) ;
}
خروجي برنامه به صورت زير خواهد بود.
2.000000 3.000000 5.000000 6.000000 2
در اينجا آرگومانهاي اول و دوم تك‌متغيرند. ولي آرگومانهاي سوم و چهارم عبارات محاسباتي‌اند كه اول مقدار آنها محاسبه مي‌گردد و سپس نتيجه براساس كد فرمت مربوط چاپ مي‌شود. آرگومان آخر به شکل عدد صحيح چاپ مي‌شود.





مثال 3ـ3 به برنامة زير توجه کنيد.





کد:

#include
main ()
{
double x=50.0 , y=0.25 ;
printf(" %f %f %f %f\n ", x , y , x*y , x / y) ;
printf(" %e %e %e %e ", x , y , x*y , x / y) ;
}


هر دو دستور printf داراي آرگومانهاي يكسان‌اند ولي يکي با فرمان فرمت %f و در ديگري با فرمان فرمت %e چاپ شده‌اند. همچنين علامت "\n" موجب چاپ خروجي در سطر بعدي مي‌گردد.
خروجي اين برنامه به صورت زير خواهد بود.
50.000000 0.250000 12.500000 200.000000
5.000000e+01 2.500000e-01 1.250000e+01 2.000000e+02
در سطر اول مقادير x/y , x*y , y , x به فرم استاندارد floating point نشان داده شده، درحالي‌كه در سطر دوم همان مقادير به‌ دليل استفاده از فرمان فرمت "%e" به فرم نمايش علمي چاپ شده است.
ملاحظه می‌كنيد كه هر مقدار تا 6 رقم دقت، پس از نقطة اعشار نمايش داده شده است. به هرحال اين تعداد ارقام را مي‌توان با قرار دادن ميزان دقت در رشتة كنترلي تغيير داد.
در فرمان فرمت مي‌توان حداقل پهناي ميدان و تعداد ارقام اعشار، يعني ارقام بعد از مميز، را نيز مشخص كرد. همچنين مي‌توان تعيين كرد كه اطلاعات خروجي از سمت چپ ميدان چاپ (يعني فضاي تعيين‌‌شده براي چاپ) تراز گردند (در حالت عادي اطلاعات رشته‌اي از طرف چپ و اطلاعات عددي از سمت راست ميدان تراز مي‌شوند). حداقل طول ميدان را مي‌توان با قرار دادن يك عدد صحيح (به عنوان مشخص‌كنندة حداقل فضاي لازم) بين علامت % و كد فرمت مشخص كرد. اين كار موجب مي‌گردد كه اگر طول ميدان بيشتر از طول مورد نياز براي اطلاعات خروجي باشد، فضاي اضافي خالي باقي بماند. ولي اگر طول رشته يا عدد بزرگ‌تر از طول پيش‌بيني‌‌شده براي آن باشد، طول پيش‌بيني‌‌شده ناديده گرفته می‌شود و اطلاعات به طور كامل نمايش می‌یابد. اگر بخواهيد در مورد اطلاعات عددي فضاي اضافي با صفر پر شود، سمت چپ عدد m رقم "0" را قرار دهيد. براي مثال %04d موجب مي‌گردد كه اگر مقدار چاپ شده از چهار رقم كمتر باشد، سمت چپ آن به تعداد لازم صفر قرار گيرد به طوري كه مقدار چاپ شده چهار‌رقمي باشد.
در مورد مقادير floating point براي مشخص ساختن تعداد ارقام بعد از مميز، بايد پس از عدد مشخص‌كنندة طول ميدان، علامت مميز "." و پس از آن نيز يك عدد كه معرف تعداد ارقام اعشار خواهد بود قرار داد. براي مثال كد فرمت %10.4f عدد را با حداقل ده كاراكتر پهناي ميدان و با چهار محل براي ارقام اعشار نمايش خواهد داد.

مثال 3ـ4به برنامة زير دقت کنيد.

کد:

#include
main ()
{
int x = 12345 ;
float y =345.125 ;
printf("3d %5d %8d\n\n", x , x , x) ;
printf("%3f %10f %13f\n", y , y , y) ;
printf("%3e %10e %13e\n", y , y , y) ;
printf("%g %10g %13g \n", x , x , x) ;
printf("%3g %10g %13g ", x , x , x) ;
}


خروجي اين برنامه به صورت زير خواهد بود.
12345 12345 12345
345.125000 345.125000 345.125000
3.45125e+02 3.45125e+02 3.45125e+02
345.125 345.125 345.125
345.125 345.125 345.125
در سطر اول، خروجي با استفاده از مينيمم پهناي فيلد (به طول سه كاراكتر، پنج كاراكتر و هشت كاراكتر) چاپ شده است. در هر فيلد تمامي عدد به طور كامل نمايش داده شده است، اگرچه طول ميدان پيش‌بيني شده كمتر از عدد مورد نظر است (مانند فيلد اول كه مينيمم طول پيش‌بيني شده سه كاراكتر است ولي عدد مورد نظر 5 رقمي است).
دومين خروجي در سطر اول با يك محل خالي شروع شده است. اين محل خالي به‌علت وجود يك محل خالي بين فرمان فرمت فيلد اول و دوم در رشتة كنترلي است.
سومين خروجي در سطر اول داراي چهار محل خالي يا blank در سمت چپ است كه يك محل آن به سبب وجود يك محل خالي بين فرمان فرمت فيلد دوم و سوم در رشتة كنترلي است. سه محل خالي ديگر نيز براي پركردن حداقل فضاي پيش‌بيني شده براي ميدان مورد نظر است (كه در اينجا هشت كاراكتر براي يك عدد پنج رقمي است).
شرايط مشابهي در سطر دوم و سوم خروجي وجود دارد. فقط بايد توجه كرد كه كد فرمت در سطر دوم از نوع f و در سطر سوم از نوع e است.
در سطر چهارم و پنجم همان مقادير با استفاده از کد فرمت %g چاپ شده است. اين فرم نتيجه را كوتاه‌تر نشان مي‌دهد. فواصل بين مقادير چاپ شده نيز براساس درنظر گرفتن حداقل پهناي پيش‌بيني شده در رشتة كنترلي براي آرگومانهاي مورد نظر است.
مي‌توان ماكزيمم تعداد ارقام اعشار در مورد مقادير floating point يا ماكزيمم تعداد كاراكتر براي يك رشته را نيز مشخص كرد. مشخصة مورد نظر براي اين عمل، precision يا دقت ناميده مي‌شود. دقت مورد نظر، يك عدد صحيح بدون علامت است كه قبل از آن نيز يك علامت مميز "." قرار مي‌گيرد. اگر علاوه بر precision حداقل طول ميدان نيز مشخص شده باشد (كه معمولاً نيز همين طور است)، طول ميدان قبل از precision قرار مي‌گيرد و علامت مميز "." بين آن دو درج مي‌شود و كد فرمت پس از اين مجموعه كاراكترها مي‌آيد.
در مورد مقادير floating point اگر دقت پيش‌بيني شده براي ارقام اعشار كوچك‌تر از تعداد ارقام اعشار باشد، جزء اعشار گرد مي‌شود، به طوري كه تعداد ارقام آن با دقت يا precision پيش‌بيني شده مطابقت نمايد.

مثال 3ـ5 به‌اين برنامه توجه کنيد.



کد:

#include
main ()
{
float x =123.456 ;
printf("%7f %7.3f %7.1f\n", x , x , x) ;
printf("%12e %12.5e %12.3e", x , x , x) ;
}


خروجي اين برنامه به صورت زير خواهد بود.
123.456000 123.456 123.5
1.234560e+02 1.23456e+02 1.235e+02
سطر اول با ‌كد فرمت fايجاد شده است. در اينجا عدد سوم به دليل وجود مشخصة دقت كه يك رقم اعشار در نظر گرفته شده گرد شده است. همچنين با درنظر گرفتن حداقل طول ميدان (هفت كاراكتر) در سمت چپ عدد سوم، دو محل فضاي خالي به دليل حداقل طول ميدان و يك محل فضاي خالي نيز به دليل وجود يك محل خالي بين فرمان فرمت فيلدهاي دوم و سوم ايجاد شده است.
سطر دوم با كد فرمت نوع e ايجاد شده و داراي مشخصه‌هاي مشابه سطر اول است. در اينجا هم عدد سوم گرد شده است تا با دقت پيش‌بيني‌‌شده، يعني 3 رقم اعشار، تطابق یابد. همچنين چهار فضاي خالي نيز با در نظر گرفتن حداقل طول ميدان (دوازده كاراكتر) و وجود يك محل خالي بين فرمان فرمت فيلدهاي دوم و سوم در سمت چپ آن ايجاد شده است.
v
ضرورتي ندارد كه مشخصة دقت با حداقل طول ميدان توأم به كار رود، بلكه مي‌توان مشخصة دقت را بدون ذكر حداقل طول ميدان نيز به كار برد. ولي به هرحال نقطة معرف اعشار بايد در جلوي آن به كار رود، مانند دستور زير.
printf(" %.4f ", x) ;
علاوه بر كاراكترهاي تبديل و پهناي ميدان و شاخص دقت، رشته كنترل يك نشانه يا flag نيز دارد كه در شكل ظاهري خروجي اثر مي‌گذارد. flagبلافاصله بعد از علامت (%) قرار مي‌گيرد. بعضي كامپايلرها اجازه مي‌دهند كه دو flag پشت سر هم درون يک مشخصة تبديل به كار روند. flagهاي متداول در زبان C در جدول 3ـ2 نمايش داده شده‌اند.

جدول 3ـ2Flag هاي متداول

مفهوم و کاربرد
Flag
داده‌ها در داخل ميدان از سمت چپ تراز مي‌شوند. فضاهاي خالي لازم براي پركردن حداقل پهناي ميدان نيز از طرف راست يعني بعد از داده افزوده مي‌شود.


_

در مورد داده‌‌هاي عددي، علامت آن (+ يا -) نيز در جلوي آن ظاهر مي‌گردد. بدون استفاده از اين flag فقط در مورد مقادير منفي علامت آنها در خروجي ظاهر مي‌شود.


+

در مورد داده‌‌هاي عددي موجب مي‌شود كه فضاي خالي سمت چپ به جاي blank با صفر پرشود. البته فقط در مورد داده‌‌هايي به کار می‌رود كه از سمت راست تراز مي‌شوند.


0

در مورد هر داده عددي علامت‌دار و مثبت يك blank در جلوي آن ظاهر مي‌شود. اين نشانه اگر با نشانة (+) به کار رود آن را لغو مي‌كند.


▪ ▪



blankspace

باعث مي‌شود كه در جلوي داده‌‌هاي اكتال 0 و داده‌‌هاي هگزادسيمال 0x ظاهر شود.


#



(با نوع تبديل 0- و x-)

باعث مي‌شود كه در تمام اعداد floating-point علامت مميز "." ظاهر شود، حتي اگر عدد مورد نظر جزء اعشار نداشته باشد. همچنين در مورد نوع تبديل g از ناديده گرفته شدن صفرهاي بدون معني سمت راست جلوگيري مي‌كند.


#



(با نوع تبديل e-g-, f-,)



مثال 3ـ6 كاربرد فلاگها در مورد مقادير صحيح و اعشاري در برنامة زير نمايش داده شده است.



کد:

#include
main ()
{
int x =123 ;
float y =45.0 , z = -6.7 ;
printf(": %5d %7.0f %10.1e: \n", x , y , y) ;
printf(": %-5d %-7.0f %-10.1e: \n", x , y , z) ;
printf(": %+5d %+7.0f %+10.1e: \n", x , y , z) ;
printf(": %7.0f %#7.0f %7g %#g: " , y , y , z , z) ;
}


با اجراي برنامه خروجي زير حاصل مي‌شود كه در آن علامت ":"آغاز ابتداي ميدان و پايان انتهاي ميدان را نمايش مي‌دهد.
: 123 45 -6.7+00:
: 123 45 -6.7e+00:
: +123 +45 -6.7e+00:
:+123 +45 -6.7e+00:
: 45 45. -6.7 -6.500000:
خط اول خروجي را بدون استفاده از فلاگ نمايش مي‌دهد كه در آن هر عدد درون ميدان مشخص‌‌شده براي آن، از طرف راست تراز شده است. خط دوم همان اعداد را با استفاده از همان كاراكترهاي تبديل با پيش‌بيني يك فلاگ در هر گروه از رشته فرمت نمايش مي‌دهد، و ملاحظه مي‌كنيد كه‌اين بار به علت وجود فلاگ "-" همة اعداد از سمت چپ تراز شده‌اند. در خط سوم از فلاگ "+" استفاده شده است. در اين حالت اعداد مانند خط اول از سمت راست تراز مي‌شوند. اما علامت مربوط نيز (در هر دو حالت مثبت و منفي‌) در جلوي آنها ظاهر شده ‌‌است. در خط چهارم تركيب دو فلاگ "-" و "+" به کار رفته است. در اينجا ضمن اينكه اعداد به دليل وجود فلاگ "-" از سمت چپ تراز شده‌اند، علامت مربوط نيز به‌علت وجود فلاگ "+" در جلوي آنها ظاهر شده است. در خط پنجم دو مقدار مميز شناور را يكبار بدون وجود فلاگ و بار ديگر با استفاده از فلاگ "#" نمايش مي‌دهد و همان طور که ملاحظه مي‌شود نقش اين فلاگ آن است كه در مورد عدد 45 علامت مميز را نيز منظور داشته است و در مورد عدد دوم صفرهاي بدون ارزش بعد از مميز را نيز در كد فرمت "g" نمايش مي‌دهد.

مثال 3ـ7 برنامة زير چاپ اعداد را در مبناي 8 و 10 و 16 نمايش مي‌دهد.



کد:

#include
main ()
{
int x = 1234 , y = 0155 , z = 0xa06b ;
printf(": %6u %6o %6x: \n", x , y , z) ;
printf(": %-6u %-6o %-6x: \n", x , y , z) ;
printf(": %#6u %#6o %#6X: \n" , x , y , z) ;
printf(": %06u %06o %06X: ", x , y , z) ;
}


خروجي برنامه به صورت زير خواهد بود که در اينجا نيز علامت ":" ابتداي ميدان و پايان ميدان را در هر خط نمايش مي‌دهد.
: 1234 155 a06b:
:1234 155 a06b:
: 1234 0155 0XA06B:
:001234 000155 00A06B:
خط اول بدون استفاده از فلاگ، اعداد را بدون علامت و به ترتيب در مبناهاي 10، 8 و 16 در خروجي نمايش مي‌دهد. خط دوم همان داده‌ها را با همان كاراكتر تبديل و با استفاده از فلاگ "-" نشان مي‌دهد كه درنتيجه اعداد در فضاي پيش‌بيني‌‌شده براي آنها از سمت چپ تراز شده‌اند. در خط سوم از فلاگ "#" استفاده شده است. اين فلاگ موجب مي‌گردد كه در جلوي اعداد در مبناي 8 و 16 به‌ترتيب "0" و "0x" ظاهر شود. همچنين به سبب استفاده از حرف بزرگ "X"در كاراكتر تبديل، حروف موجود در اعداد مبناي 16، در خروجي به صورت حروف بزرگ (يعني 0XA06B) ظاهر شده‌اند. خط آخر نقش استفاده از فلاگ "0" را نمايش مي‌دهد. اين فلاگ موجب مي‌گردد كه سمت چپ اعداد به تعداد لازم با صفر پر شود. در اينجا نيز به علت استفاده از حروف بزرگ "X" در كاراكتر تبديل، حروف موجود در اعداد مبناي 16، در خروجي به صورت حروف بزرگ ظاهر شده‌اند.

آبجی
25th May 2010, 12:09 AM
تابع scanf()
در زبان C داده‌هاي ورودي مي‌توانند به كمك تابع كتابخانه‌اي scanfاز طريق دستگاه ورودي استاندارد وارد كامپيوتر شوند. تابع scanfنيز تابع فرمت‌دار و مشابه تابع printfاست ولي در جهت عكس عمل مي‌كند. به كمك اين تابع مي‌توان داده‌هاي عددي، كاراكترها، رشته‌ها يا تركيبي از آنها را وارد كامپيوتر كرد. فرمت اين تابع مشابه فرمت تابع printfو فرم كلي آن به صورت زير است.

کد:

scanf ("control string", arguments list) ;
يا
scanf ("control string", argl , arg2 ,…, arg n) ;

در اينجا نقش رشتة كنترل مشابه تابع printfو شامل اطلاعات قالب‌‌بندي خاص است. مشابه printfاين تابع نيز مي‌تواند هر تعداد آرگومان را دارا باشد، كه در آن اولين آرگومان رشتة فرمت يا رشتة كنترل است. همچنين اين تابع، اغلب همان كد فرمت تابع printf را به كار مي‌برد؛ براي مثال كدهاي فرمت %s, %c , %f , %d که به ترتيب براي خواندن داده‌هايي از نوع مقادير صحيح، اعشاري، كاراكتر و رشته به كار می‌روند. تفاوت مهم بين اين دو تابع آن است كه در جلوي آرگومانها، اپراتور آدرس يعني "&" نيز قرار مي‌گيرد.
البته اگر بخواهيد مقداري را براي متغير رشته‌اي بخوانيد، نيازي به اپراتور "&" نخواهد بود زيرا رشته‌ها در زبان ِC به صورت آرايه‌اي از نوع كاراكتر معرفي مي‌گردند و نام آرايه نيز معرف آدرس آرايه (يعني آدرس اولين عنصر آن) است.
مثال 3ـ8 برنامة زير نحوة کاربرد عملگر & را در تابع scanf نشان مي‌دهد.



کد:

#include
main ()
{
int x ;
char name[6] ;
scanf("%d" , &x) ;
scanf("%s", name) ;
printf("%d %s", x , name) ;
}

دستور scanf اول سيستم را هدايت مي‌كند كه داده ورودي را به صورت عدد صحيح از طريق ترمينال دريافت كند و اين مقدار را در متغير x ذخيره کند. دستور scanf دوم به دليل استفاده از آرايه، بدون عملگر & به کار می‌رود و اگر در اين برنامه براي متغير name رشتة "book" را وارد كرده باشيم، خروجي آن كلمة book خواهد بود.

جدول 3ـ3 فرامين يا کاراکترهاي فرمت براي داده‌هاي ورودي را كه کاراکترهاي تبديل نيز ناميده مي‌شوند نشان می‌دهد.
جدول 3ـ3 كاراكترهاي فرمت در تابع scanf ()

شـــرح
كد فرمت
داده ورودي به صورت تك‌كاراكتر تعبير مي‌شود.


%c

داده ورودي به صورت عدد صحيح علامت‌دار (در مبناي 10) تعبير مي‌شود.


%d

داده ورودي به صورت عدد صحيح علامت‌دار تعبير مي‌شود.


%i

داده ورودي به صورت عدد صحيح بدون علامت دهدهي تعبير مي‌شود.


%u

داده ورودي به صورت عدد صحيح اعشاري با مميز شناور (floating_point) تعبير مي‌شود.


%f , %e, %g

داده ورودي به صورت عدد صحيح كوتاه (short integer) تعبير مي‌شود.


%h

داده به صورت رشته تعبير مي‌شود. ورودي با يك كاراكتر non_white_space آغاز مي‌گردد و با اولين كاراكتر white_space خاتمه مي‌پذيرد (به پايان رشته به طور خودكار كاراكتر "\0" افزوده خواهد شد).


%s

داده ورودي به صورت عدد صحيح در مبناي 8 تعبير مي‌شود.


%0

داده ورودي به صورت عدد صحيح در مبناي 16 تعبير مي‌شود.


%x , %X

داده ورودي اشاره‌گر تعبير مي‌شود.


%p


مثال 3ـ9 برنامة‌ زير يك خط متن حداكثر به طول 79 كاراكتر را مي‌خواند و آن را به همان صورت چاپ مي‌كند.


کد:

#include
main () /* read a line of text */
{
char line[80] ;
int count , k ;
/* read in the line */
for (k=0 ; line[k]=getchar ()!=’\n’ ; + +k)
count = k ;
for (k=0 ; k
putchar(line[k]) ;
}

در حلقة for، شمارندة k از صفر شروع مي‌شود و مقدار آن در هر تكرار يك واحد افزايش مي‌يابد و در هر تكرار يك كاراكتر با تابع getchar از طريق ورودي استاندارد دريافت مي‌شود و به line[k] نسبت داده مي‌شود و وقتي كه كاراكتر خط جديد (يعني \n) وارد شد، عمل ورود كاراكترهاي رشته خاتمه مي‌يابد كه در اين لحظه مقدار k برابر تعداد كاراكترهاي واقعي رشته خواهد بود. سپس در حلقة بعدي محتواي آراية line[ ] كه دربردارندة رشتة دريافت شده است چاپ مي‌گردد (دو تابع getchar و putchar دوباره بررسي خواهد شد). راه ديگر براي ورود رشته‌ها به حافظة كامپيوتر استفاده از تابع gets است كه در مبحث رشته‌ها بحث می‌کنیم.
براي خواندن رشته‌هايي كه در آنها فضاي خالي (space يا blank) وجود داشته باشد، مي‌توان به طريقي از تابع scanfنيز استفاده کرد. براي اين كار مي‌توان به جاي كاراكتر تبديل نوع s در رشتة كنترلي، دنباله‌اي از كاراكترها را در داخل كروشه به صورت [...]قرار داد كه در اين صورت رشتة مورد نظر هريك از كاراكترهاي موجود در داخل كروشه ازجمله blank را شامل می‌شود.
با چنين روشي وقتي كه برنامه اجرا مي‌گردد، تا زماني كه كاراكترهاي متوالي خوانده شده از طريق دستگاه ورودي با يكي از كاراكترهاي موجود در درون كروشه‌ها يكسان باشد، عمل خواندن رشته‌ها ادامه مي‌يابد. فضاي خالي نيز در داخل رشته‌ها منظور می‌شود. به محض اينكه كاراكتري خوانده شود كه در داخل كروشه‌ها وجود نداشته باشد، عمل خواندن خاتمه مي‌پذيرد. درضمن يك كاراكتر null به طور خودکار به پايان رشته افزوده می‌شود.

مثال 3ـ10 برنامة زير كاربرد تابع scanf را براي خواندن رشته‌هايي كه شامل حروف بزرگ و فضاي خالي است‌ نشان مي‌دهد. طول اين رشته با درنظر گرفتن كاراكتر پايان رشته 80 كاراكتر خواهد بود.


کد:

#include
main ()
{
char line[80] ;
..........
scanf("%[ ABCDEFGHIJKLMNOPQRSTUVWXYZ ]", line) ;
..........
}


حال اگر از طريق ورودي، رشتة COMPUTER SCIENCE وارد شود، وقتي كه برنامه اجرا مي‌گردد، تمامي رشتة‌ مزبور به آراية lineنسبت داده مي‌شود. به هرحال اگر يكي از حروف رشتة مزبور به حرف كوچك تايپ شود، ورود رشته در همان كاراكتر خاتمه مي‌پذيرد. مثلاً اگر در مثال بالا p به‌صورت كوچك تايپ شود، فقط سه حرف com به آراية line نسبت داده مي‌شود و عمل خواندن در حرف چهارم (حرف p) خاتمه خواهد يافت.
راه ديگر آن است كه به جاي اينكه كاراكترهاي مجاز در رشتة مورد نظر را در داخل كروشه ذكر كنيم، فقط كاراكترهايي را كه مجاز نيستيم در رشته‌ها به كار ببريم مشخص می‌کنيم. براي اين كار كافي است كاراكترهاي مورد نظر را به دنبال نماد "^" كه circumflex ناميده مي‌شود، در داخل كروشه قرار دهيم. يعني در اينجا نقش كاراكترهاي كروشه‌اي عكس حالت قبلي است و وجود هركدام از آنها در داخل يك رشته موجب قطع ورود بقية كاراكترهاي رشته مي‌گردد و عمل خواندن رشته خاتمه مي‌پذيرد.
اگر كاراكتر داخل كروشه‌ها كه بعد از "^" مي‌آيد، فقط كاراكتر خط جديد "\n" باشد، رشته‌اي كه از طريق دستگاه ورودي استاندارد وارد مي‌شود هر كاراكتر اسكي به جز كاراكتر خط جديد را شامل می‌شود. بنابراين، كاربر مي‌تواند هرچه خواست به‌عنوان كاراكترهاي رشته وارد كند و در پايان كليد Enterرا فشار دهد. اين كليد كاراكتر خط جديد را صادر مي‌كند و درنتيجه پايان رشته را اعلام خواهد كرد.

مثال 3ـ11 فرض كنيد كه يك برنامة C شامل دستورهاي زير است.



کد:

#include
main ()
{
char line[80] ;
..........
..........
scanf("%[^\n]", line) ;
..........
..........
}


وقتي كه تابع scanfدر برنامة بالا اجرا مي‌گردد، رشته‌اي به طول نامشخص (ولي حداكثر 79كاراكتر) از طريق دستگاه ورودي استاندارد وارد مي‌گردد و به line نسبت داده مي‌شود. هيچ گونه محدوديتي در مورد كاراكترهاي تشكيل‌دهندة رشته وجود نخواهد داشت، فقط بايد در يك خط بگنجد. براي مثال رشتة زير از طريق صفحه‌‌كليد وارد و به line نسبت داده می‌شود.
WE LEARN MATHEMATICS.


تابع getchar()
براي خواندن يك كاراكتر از دستگاه ورودي، مي‌توان علاوه بر تابع scanf از تابع getcharنیز استفاده کرد. تابع مزبور كه جزء كتابخانة I/O زبان استاندارد C است، كاراكتری از دستگاه ورودي استاندارد که معمولاً صفحه‌‌كليد است مي‌خواند. اين تابع آرگومان ندارد و به طور متعارف در يك دستور انتساب يا جايگذاري به كار می‌رود و كاراكتر دريافتي از ورودي را به متغيري كه در سمت چپ دستور جايگذاري مورد نظر استاختصاص مي‌دهد. شکل كلي آن به صورت زير است.


character variable = getchar() ;



= getchar() ; متغير كاراكتري

كه در آن متغير كاراكتري نام متغيري از نوع كاراكتر است كه بايد از قبل توصيف شده باشد.
مثال 3ـ12 به دستورهاي زير توجه کنيد. کد:

char ch ;
ch = getchar() ;

در عبارت اول، متغير ch از نوع كاراكتر توصيف شده است. وقتي كه اجراي برنامه به دستور دوم برسد، برنامه منتظر فشار دادن كليدي از صفحه‌‌كليد مي‌شود. حال كاراكتر كليد فشار داده شده، به متغير ch اختصاص می‌یابد. چنانچه متغير ch از نوع int معرفي گردد، کد اسكي كاراكتر مربوط به كليد فشار داده شده، به آن متغير اختصاص مي‌يابد.
اگر هنگام خواندن كاراكتر با تابع getchar، شرايط پايان فايل پيش‌ آيد مقدار سمبوليكي EOF به طور خودكار برگشت داده می‌شود (اين مقدار در داخل فايل stdio.h اختصاص می‌یابد. به طور متعارف مقدار 1- به EOF اختصاص داده مي‌شود، اگرچه ممكن است اين مقدار از کامپایلری به کامپایلر ديگر فرق كند). ظاهر شدن EOF به‌اين طريق، راه ساده‌اي براي تشخيص پايان فايل در هنگام اجراي آن است ( در اين مورد، در مبحث فايلها بيشتر بحث خواهیم کرد. لذا به هيچ وجه نگران آن نباشيد). مي‌توان تابع getchar را نيز براي خواندن رشتة چند كاراكتري به صورت حلقة تكرار به كار برد كه در هر تكرار یک كاراكتر را بخواند.



تابع putchar()
اين تابع براي شمارش يك كاراكتر روي خروجي استاندارد كه معمولاً صفحه نمايش است به كار می‌رود و نقش آن مشابه تابع getchar اما در جهت عكس است. طبيعي است كاراكتري كه انتقال مي‌يابد به صورت ثابت كاراكتر يا متغيری از نوع كاراكتر که آرگومان تابع مزبور است به كار می‌رود. شکل كلي اين تابع به صورت زير است.
putchar (character variable) ;


; (متغير كاراكتري) putchar

البته مي‌توان ثابت كاراكتري را نيز به عنوان آرگومان تابع مزبور به كار برد. اين تابع با استفاده از آرايه يک رشته را در خروجي چاپ می‌کند.
مثال 3ـ13برنامة‌ زير به تدريج در هر بار يك كاراكتر مي‌خواند و سپس آن را در خروجي چاپ مي‌كند.



کد:

#include
main ()
{
char ch ;
while (1)
{
ch = getchar() ;
putchar(ch) ;
}
}


در اين برنامه ch كاراكتر اعلان شده است. هر بار كه يك كاراكتر از طريق دستگاه ورودي استاندارد خوانده مي‌شود، به همان طريق به خروجي انتقال مي‌يابد. اما به لحاظ اينكه عبارت مربوط به while، يعني مقدار داخل پرانتز بعد از while، برابر "1" و هميشه غيرصفر است، براساس قوانين زبان C، اين عبارت هميشه درست يا true است. بنابراين ساختار while(1) حلقه‌ای بي‌‌نهايت است و تنها راه متوقف ساختن برنامه وقفه‌ای است كه‌ با کليدهاي control-c عملي خواهد شد.
راه ديگر براي نوشتن برنامة بالا به صورت زير است.



کد:

#include
main ()
{
int ch ;
while ((ch=getchar()) != EOF)
putchar(ch) ;
}


این برنامه تركيب دو عمل در يك دستور را در حلقه نشان مي‌دهد. گفتیم EOF در برنامة بالا علامت سمبوليك پايان فايل است. آنچه در واقعيت نشانة پايان فايل را نشان می‌دهد تابع سيستم است. براي اين كار اغلب عدد 1- به كار می‌رود، ولي سيستمهاي مختلف ممکن است مقادير متفاوتي داشته باشند. با گنجانيدن فايل stdio.h و به كار بردن ثابت سمبوليكي EOF، برنامه را قابل حمل يا قابل اجرا ساخته‌ايم. يعني، فايل مبنا روي سيستمهاي مختلف بدون تغيير اجرا می‌شود.
ملاحظه مي‌كنيد كه در روش اخير، متغير ch به جاي char به صورت int معرفي شده است. هرچه براي نشان دادن پايان فايل به كار می‌رود، نمي‌تواند مقداري باشد كه يك كاراكتر را معرفي نمايد. حال چون C به‌صورت int معرفي شده است، مي‌تواند مقادير تمام كاراكترهاي ممكن و همين طور مقدار ويژة EOF را نگهداري کند.
همان طور كه گفتیم، هر دو تابع getchar و putchar در فايل stdio.h تعريف شده‌اند و ممكن است در بعضي سيستمها در فايلهاي ديگري نيز مانند فايل conio.h تعريف شده باشند.


مثال 3ـ14 برنامة زير يك خط متن را از ورودي با حروف كوچك دريافت و آن را به حروف بزرگ تبديل مي‌كند.
کد:


#include
main ()
{
char line[80] ;
int count , k ;
/* read in the line */
for (k=0 ; (line[k]=getchar())!=’\n’ ; + + k) ;
count = k ;
/* write out the line in upper-case */
for(k=0 ; k
putchar(toupper(line[k])) ;
}


در برنامة بالا از حلقة for و تابع کتابخانه‌اي toupper استفاده شده است. نقش اين تابع آن است كه حروف كوچك را به بزرگ تبديل مي‌كند. بنابراين اگر حروف ورودي هنگام تايپ حروف بزرگ يا ارقام و مشابه آن باشند، به شکل اولية خود نمايش داده خواهند شد. براي مثال اگر ورودي به صورت Advanced programming باشد، خروجي به صورت ADVANCED PROGRAMMING خواهد بود.


مثال 3ـ15 برنامة زير يك خط از متن را مي‌خواند و در آن هر كاراكتر را (به غير از كاراكتر فضاي خالي يا space) به كاراكتر بعدي تبديل مي‌كند و نمايش مي‌دهد (درواقع متن را به ‌شکلی به صورت رمز در مي‌آورد و نمايش مي‌دهد).


کد:

#include
#define space ’ ’
main ()
{
char ch ;
ch = getchar () ; /* read a character from i/o */
while(ch!=’\n’) /*while not end of line */
{
if (ch= =space) /* leave the space */
putchar(ch) ; /* character unchanged */
else
putchar(ch+1) ; /* change other characters */
ch = getchar() ; /* get next character */
}
}

برای مثال اگر computer science2 ورودي باشد، خروجي dpnqvufs tdjfodf3 خواهد بود.
با تركيب دو دستور خواندن و تست كردن پايان متن در يك عبارت، برنامة مزبور را مي‌توان به صورت ساده‌ و فشرده‌تر زير نوشت.



کد:

#include
#define space ’ ’
main ()
{
char ch ;
while ((ch=getchar()) != ’\n’)
{
if (ch = = space) /* leave the space */
putchar(ch) ; /* character unchanged */
else
putchar(ch+1) ; /* change other characters */
}
}

که در اين برنامه دستور while ((ch=getchar()) != ’\n’) تركيب دو عمل در يك دستور را نشان مي‌دهد كه روشی متداول در زبان C است. اين دو عمل آن است كه اول به كمك تابع getchar مقداري به ch نسبت داده مي‌شود و سپس مقدار ch با كاراكتر خط جديد مقايسه می‌شود. وجود پرانتز دور عبارت ch = getchar()آن را اپراند چپ اپراتور != مي‌سازد. اگر آن را حذف كنيم نتيجة مطلوب به دست نمي‌آيد زيرا اپراتور !=نسبت به اپراتور = تقدم بالاتري دارد. بنابراين اگر دستور مزبور را به صورت while (ch = getchar()!= ’\n’)بنويسيم، اول عبارت ’\n’ getchar()!=ارزيابي مي‌شود كه عبارتی رابطه‌اي است (بنابراين كاراكتر خط جديد برنمي‌گرداند، بلكه يك مقدار برمي‌گرداند) كه ارزش آن يك يا صفر (درست يا نادرست يعني trueيا false) خواهد بود. سپس اين مقدار به ch نسبت داده مي‌شود كه هدف مورد نظر ما را از دستور مزبور تأمين نمي‌كند.


مثال 3ـ16 برنامة‌ زير كاراكترها را از طريق ورودي صفحه‌‌كليد دريافت مي‌كند و آنها را به صفحة نمايش مي‌فرستد. اين برنامه با دريافت كاراكتر $ از ورودي خاتمه مي‌پذيرد.


کد:

#include
main ()
{
char ch ;
while ((ch=getchar()) != ’$’)
putchar(ch) ;
}

در اين برنامه نيز از ترکيب دو دستور در يک دستور در درون حلقة while استفاده شده است.

در زبان C علاوه بر تابع getchar دو تابع getchو getche نيز براي خواندن يك كاراكتر از ورودي به كار مي‌رودکه در ادامه بررسي می‌کنیم.
تابع getche()
اگر بخواهيم كاراكتري به كمك تابع scanf يا تابع getchar خوانده شود، بايد پس از تايپ كاراكتر مورد نظر، كليد Enter را نيز استفاده کنیم. يعني، درواقع دو تابع مزبور تا موقعي كه كليد برگشت (كه به آن carriage return يا به اختصار CR گویند) فشرده نشود ورودي را در بافر نگه مي‌دارند. پس از زدن كليد برگشت، دادة تايپ شده در اختيار برنامه قرار مي‌گيرد. حسن اين روش آن است كه اگر كليدي را اشتباه وارد كرده باشيم، مي‌توانيم آن را با backspace تصحيح كنيم. يعني، قبلي را پاك كنيم و دوباره كاراكتر صحيح مورد نظر را تايپ كنيم. عيب اين كار آن است كه ‌اين عمل در محيط محاوره‌اي امروز وقت‌گير و دردسرزاست. ازاين رو تابع getche به‌وجود آمد كه در آن ديگر نيازي به تحرير كليد برگشت يا CR نيست. اشكال اين تابع آن است كه اگر كاراكتر اشتباه تحرير شود امكان تصحيح وجود ندارد. همچنين كاراكتر تحرير شده، روي صفحة تصوير نمايش داده مي‌شود كه‌اين عمل echoing ناميده مي‌شود. در واقع حرف e در آخر نام تابع getche به مفهوم echo (عكس‌العمل) است.
تابع getch()
اين تابع همانند تابع getche است با اين تفاوت كه كاراكتر تحرير شده در صفحة تصوير ظاهر نمي‌گردد. در مورد هريك از اين سه تابع وقتي كه كنترل اجراي برنامه به ‌اين توابع مي‌رسد، برنامه منتظر فشردن كليدي در صفحه‌‌كليد مي‌شود. اگر متغير مورد نظر از نوع كاراكتري باشد، يعني در برنامه با فرمت %c توصيف شده باشد، مقدار كاراكتري كليد فشرده شده به‌اين متغير نسبت داده مي‌شود و درصورتي كه‌اين متغير از نوع عددي باشد کد اسكي‌ كاراكتر مربوط به كليد فشرده شده در اين متغير قرار مي‌گيرد.
توابع puts() و gets()
اين دو تابع اين امكان را فراهم مي‌سازند كه بتوان رشته‌هايي از كاراكترها را از طريق كنسول خواند يا در خروجي نوشت (دستگاههاي ورودي و خروجي استاندارد را كنسول نامند كه در مورد ريزكامپيوترها معمولاً صفحه‌‌‌كليد ورودي استاندارد و مانيتور خروجي استاندارد را تشكيل مي‌دهند).
تابع gets() يك رشته از كاراكترها را كه از طريق صفحه‌‌كليد وارد مي‌شود، مي‌خواند و آنها را در آدرسي قرار مي‌دهد كه با آرگومانهاي آن تعيين شده است و اشاره‌گری كاراكتری است. كاراكترهاي رشتة مورد نظر را تايپ مي‌كنيد و در پايان، كليد Enter را می‌زنید. با اين عمل به طور خودكار كاراكتر null يا ’\0’ نيز در پايان رشته قرار می‌گیرد. در اينجا اگر كاراكتری اشتباه تايپ شود، مي‌توان آن را قبل از فشردن كليد Enter با استفاده از كليد backspace تصحيح كرد. در واقع در اينجا نيز كاراكترهاي تايپ شده در بافر مي‌ماند و تا موقعي كه كليد برگشت فشرده نشده است در اختيار برنامه قرار نمي‌گيرد.
تابع puts() آرگومانهاي رشته‌اي خود را به صفحه نمايش مي‌فرستند و سپس قلم نوشتار به خط جديد انتقال مي‌يابد.
مثال 3ـ17 برنامة زير رشته‌اي را از طريق صفحه‌‌كليد مي‌خواند و در آراية line قرار مي‌دهد. سپس آن را روي خروجي نمايش مي‌دهد.





فراخواني تابع puts در مقايسه با فراخواني printfداراي overhead كمتري است و درنتيجه سريع‌تر از آن عمل مي‌كند زيرا تابع puts فقط يك رشته از كاراكتر را به خروجي می‌فرستد و نمي‌تواند مشابه printf تبديل فرمت انجام دهد. همچنين نمي‌تواند مقادير عددي را به عنوان خروجي داشته باشد. بنابراين چون puts فضاي كمتري مي‌گيرد و سريع‌تر از printf اجرا مي‌گردد، هنگامي كه در برنامه‌سازي حالت خيلي بهينه مورد نظر باشد، از اين تابع استفاده مي‌شود.



خودآزمایی 3
1. برنامه‌اي بنويسيد كه با استفاده از تابع printf و تابع puts رشتة زير را در دو خط جداگانه چاپ کند.
"Payam noor university"
2. برنامه‌اي بنويسيد كه كاراكتري از ورودي بخواند و کاراکتر بعدي آن را در خروجي چاپ ‌كند.
3. برنامه‌اي بنويسيد كه عدد صحيح m1 وعدد اعشاري m2، اطلاعات كاراكتري و آدرس متغير m3 را در خروجي چاپ ‌كند.
4. خروجي برنامة زير چيست ؟ کد:


# include < stdio. h>
main ()
{
double x ;
x = 2e + 004 ;
printf ("\n x1 = %e" , x) ;
printf ("\n x2 = %E" , x) ;
printf ("\n x3 = %g" , x) ;
}

5. خروجي برنامة زير چيست ؟



6. برنامه‌اي بنويسيد كه سه عدد صحيح را از ورودي بخواند و ميانگين آنها را چاپ کند.
7. برنامه‌اي بنويسيدكه دو متغير صحيح را از ورودي بخواند و محتويات آنها را بدون استفاده از متغير كمكي عوض کند و نتيجه را در خروجي نمايش دهد.
8. برنامه‌اي بنويسيد كه سن شما را برحسب روز از ورودي بخواند و مشخص ‌كند كه چند سال، چند ماه، چند هفته و چند روز دارید.

آبجی
25th May 2010, 12:17 AM
عملگرهاي رابطه‌اي (مقايسه‌اي)
عملگرهاي رابطه‌اي، همان طور كه از نامشان پيداست، رابطة بين دو مقدار را تعيين مي‌كنند. اين عملگرها در جدول 4ـ12 نشان داده شده‌اند.

جدول 4ـ12 عملگرهاي رابطه‌اي

نام عملگر
نشانه
شکل
نتيجه
بزرگ‌تر از
>
a > b
اگر a بزرگ‌تر از b باشد، نتيجه 1 وگرنه 0 است.
كوچك‌تر از
<
a < b
اگر a كوچك‌تر از b باشد، نتيجه 1 وگرنه 0 است.
مساوي يا بزرگ‌تر از
>=
a >= b
اگر a مساوي يا بزرگ‌تر از b باشد، نتيجه 1 وگرنه 0 است.
مساوي يا كوچك‌تر از
=<
a<=b
اگر a مساوي يا كوچك‌تر از b باشد، نتيجه 1 وگرنه 0 است.
مساوي
= =
a = =b
اگر a مساوي b باشد، نتيجه 1 وگرنه 0 است.
مخالف
!=
a!=b
اگر a مخالف b باشد، نتيجه 1 وگرنه 0 است.


ايده و مفهوم اصلي در مورد عملگرهاي رابطه‌اي وابسته به مفهوم مقدار true و false است. در زبان C، true هر مقدار غير از صفر و false مقدار صفر است. عباراتي كه عملگرهاي رابطه‌اي يا منطقي را به كار مي‌برند براي حالت نادرست يا false مقدار صفر و براي حالت درست يا true مقدار يك برمي‌گردانند.
تقدم عملگرهاي رابطه‌اي پايين‌تر از تقدم عملگرهاي محاسباتي است. بنابراين دو عبارت


کد:

15 > 14+7 15 > (14+7)

يكسان ارزيابي خواهند شد. همين طور عبارت a + b* c < d / h به صورت زير ارزيابي می‌شود.


کد:

(a +(b* c)) < (d / h)


ترتيب تقدم بين خود عملگرهاي رابطه‌اي به صورت جدول 4ـ13 است.

جدول 4ـ13 ترتيب تقدم عملگرهاي رابطه‌اي

> >= < <=
بالاترين تقدم
=! = =
پايين‌‌ترين تقدم


در اينجا نيز مشابه عملگرهاي محاسباتي در مورد عملگرهاي ‌هم‌تقدم، عمليات از چپ به راست انجام مي‌گيرد.
مثال 4ـ16 به قطعه برنامة زير توجه کنيد.



کد:

int a ; a = 10 ; printf (" %d " , a>5) ;





عبارات رابطه‌اي، نتيجه 0 يا 1 ايجاد مي‌كنند. بنابراين قطعه برنامة بالا درست است و مقدار 1 را روي صفحة نمايش نشان خواهد داد.





مثال 4ـ17 با توجه به اعلان داده شده چندين عبارت مقايسه‌اي همراه با مقدار آنها در زير نمايش داده شده است.


کد:

int I = 1 , J = 2 , K = 3 ;





مقدار
تفسير
عبارت مقايسه‌اي
1
true
I = = 1
0
false
J != 2
1
true
I < J
1
true
(I+J) >= k
0
false
(J+k) > (k+5)


استفاده از پرانتز در اينجا ضروري نيست. پرانتز فقط خوانايي برنامه را بيشتر مي‌‌کند.





مثال 4ـ18 با توجه به اعلان داده شده چندين عبارت مقايسه‌اي همراه با مقدار آنها در زير نمايش داده شده است.

کد:

int A = 7 ; float B = 5.5 ; char C = 'w' ;



مقدار
تفسير
عبارت
1
True
B > 5
0
False
(A + B) <= 10
1
True
C = =119
1
True
’p’ C !=
0
False
(C >= 10 * (A + B






مثال 4ـ19 با توجه به اعلان داده شده، در جدول 4ـ14 نمونه‌‌هايي از نحوة عملكرد مفسر با عبارات مقايسه‌اي پيچيده نشان داده شده است.


int j = 0 , m = 1 , n = -1 ;



float x = 2.5 , y = 0.0 ;


جدول 4ـ14

مقدار
عبارت معادل آن
عبارت مقايسه‌اي
0
j > m
j > m
1
((j= n)
j <= m >= n
1
((j
j <= x = = m
0
((-x)+j)= =((y>n)>=m)
-x+j = = y>n>m
3.5
x =(x+(y>=n))
x += (y>=n)
1
((++j) = = m) != (y*2)
++j = = m! =y*2
1
((j<=x) = = m
j <= x = = m
0
((-x)+y = =((y>n) > m
-x+y = = y>n>m
1.5
x = (x-(y>=n))
x -= (y>=n)
1
((++y) = = m != (y*2)
++y = = m != y*2






عملگرهاي منطقي
عملگرهاي منطقي به طور متعارف بر عملوندها يا عبارات منطقي‌ای عمل می‌کنند كه دو ارزش درست يا true و نادرست يا false دارند. جدول 4ـ15 عملگرهاي منطقي را نشان مي‌دهد.در بين عملگرهاي منطقي، عملگر"!" بالاترين تقدم و عملگرد "| |" پايين‌ترين تقدم را دارد.

جدول 4ـ15 عملگرهاي منطقي

نتيجه
شکل
علامت مفعول
عملگر
اگر a و b هر دو برابر يك يا غيرصفر (true) باشند، نتيجه برابر يك، در غيراين صورت برابر صفر خواهد بود.
a&&b
&&
و (AND) منطقي
اگر b يا a يا هر دو غيرصفر باشند، نتيجه برابر با يك، در غيراين صورت برابر صفر خواهد بود.
a | | b
| |
يا (OR) منطقي
اگر a برابر صفر (false) باشد، نتيجه برابر يك، در غير اين‌صورت صفر خواهد بود.
!a
!
نفي يا نقيض (NOT) منطقي






همان‌طور که در عملگرهاي رابطه‌اي بيان شد در زبان C ارزش نادرست يا false با مقدار صفر و ارزش درست يا true با مقادير غيرصفر مشخص مي‌گردد. عملگرهاي منطقي را در منطق رياضي به ترتيب با علايم "Ù"، "Ú" و "~" نمايش مي‌دهند و آنها را به ترتيب تركيب عطفي، تركيب فصلي، و نقيض يا نفي نامند. عملگرهاي منطقي، بيشتر به صورت تركيبي با عملگرهاي رابطه‌اي به كار می‌روند. در واقع عملگرهاي رابطه‌اي براي مقايسة ارزش دو عبارت هستند، درحالي كه عملگرهاي منطقي AND و OR براي اتصال دو عبارت ارزشي و در مورد NOT براي نفي آن به كار مي‌روند.
vمثال 4ـ20 با توجه به اعلان داده شدهجدول 4ـ16 مثالهايي از عبارات منطقي را همراه با معادل هر عبارت نشان مي‌دهد.


int j = 0 , m = 1 , n = -1 ;



float x = 2.5 , y = 0.0 ;

جدول 4ـ16

نتيجه
تفسير
عبارت معادل
عبارت منطقي
0
false
(j) && (m)
j && m
1
true
(j
j
1
true
(m+n) | | (!j)
m+n | | !j
1
true
((x*5)&&5) | | (m/n)
X*5 && 5 | | m/n
1
true
((j<=10)&&(x>=1))&&m
J<=10 && x>=1 &&m
0
false
((!x) | | (!n)) | | (m+n)
!x | | !n | | m+n
1
true
((x*y)<(j+m)) | | n
x *y
2
true + true
((x>y)+(!j)) | | (n+ +)
(x>y)+!j | | n++
2
true + true
(j | | m) + (x | | (+ +n))
(j | | m) + (x | | ++n)



v

معمولاً يك عبارت رابطه‌اي پيچيده، قسمت شرطي يك دستور حلقه‌ای يا if را تشکیل مي‌دهد (دستور if را در فصل دستورهای کنترلي بررسي می‌کنیم). براي مثال عبارت

کد:

if ((a state1 ;

از نظر عملكرد معادل دستورهاي زير است.

کد:

if (a if (b state1 ;





و اين سازوکار تا جايي كه else وجود نداشته باشد درست است. به هرحال مجموعه‌ دستورهاي

کد:

if ((a state1 ; else state2 ;

معادل دستورهاي زير نيست.

کد:

if (a if (b state1 ; else state2 ;





و براي اينكه ازنظر عملكرد همان نتايج به دست آيد، بايد آن را به صورت زير نوشت.
کد:


if (a if(b state1 ; else state2 ; else state2 ;

عملگر شرطي (:?)
عمليات شرطي ساده را عملگر شرطي انجام می‌دهد. اين عملگر سه عملوند دارد و شکل کلي آن در جدول 4ـ17 نشان داده شده است.
جدول 4ـ17

عملگر
علامت
شکل
نحوة عمل
شرطي
?:
a ? b: c
اگر a غيرصفر باشد، نتيجه b و گرنه نتيجه c است.


به عبارت ديگر شکل كلي عبارت شرطي به صورت زير است.


exp1 ? exp2: exp3

كه در آن ابتدا عبارت اول (exp1) ارزيابي مي‌شود، اگر نتيجة آن درست يا true (يعني مقدار آن غيرصفر) باشد، عبارت دوم (exp2) ارزيابي مي‌شود و مقدار عبارت شرطي برابر نتيجة ارزيابي عبارت دوم خواهد بود. ولي چنانچه عبارت اول نادرست يا false (يعني ارزش آن برابر صفر) باشد، عبارت سوم (exp3) ارزيابي مي‌شود و مقدار عبارت شرطي برابر نتيجة ارزيابي عبارت سوم خواهد بود.
در واقع عملگر شرطي، شکل كوتاه دستور کنترلي if...else است. براي مثال عبارت

کد:
if (x z = 2 ;


else



z = 3 ;







را مي‌توان به‌اين صورت نوشت.


کد:

z = ((x 3) ;


اولين عملوند، بررسی شرط است كه بايد از نوع اسكالر باشد. عملوندهاي دوم و سوم نتيجة نهاييعبارت را نشان مي‌دهندكه برحسبمقدار عملوند اول، فقطيكي از آندو انتخابمي‌گردد. عملوندهاي دوم و سوم ممکن است از هر نوع داده‌اي باشند تا جايي كه دو نوع، براساس قوانين طبيعي تبديل، سازگار باشند. براي مثال اگر عملوند دوم int و عملوند سوم double باشد، نتيجه بدون توجه به ‌اينكه كدام انتخاب خواهد شد double خواهد بود (يعني اگر int انتخاب شود، به double تبديل خواهد شد).
v مثال 4ـ21 در عبارت شرطي زير فرض كنيد كه متغير i از نوع int باشد.


(i<0) ? 0: 100

ابتدا عبارت (i<0) ارزيابي مي‌شود. اگر پاسخ true بود (يعني مقدار متغير i كوچك‌تر از صفر بود)، كل عبارت شرطي مقدار صفر را خواهد پذيرفت. در غير اين صورت (يعني اگر مقدار i كوچك‌تر از صفر نباشد)، كل عبارت شرطي مقدار 100 را خواهد پذيرفت.


عبارات شرطي، اغلب در طرف راست دستور انتساب ظاهر مي‌گردند، مانند مثال اول. در چنين مواردي، مقدار عبارت شرطي به متغير واقع در طرف چپ دستور انتساب اختصاص مي‌یابد.

مثال 4ـ22 به عبارت شرطي زير توجه کنيد.


کد:

min = (i<0) ? 0: 10 ;


در اينجا اگر متغير i منفي باشد، به متغير min مقدار صفر نسبت داده خواهد شد. وگرنه به متغير min مقدار 10 اختصاص خواهد يافت. عملگر شرطي تقدمي بالاتر از عملگرهاي انتساب دارد و شرکت‌‌پذيري آن از راست به چپ است.





مثال 4ـ23 به قطعه برنامة زير توجه کنيد.

کد:

int a =1 , b = 2 , c = 3 ; c += (a > 0 && a<= 10) ? ++a: a/b ;







در اينجا مقدار عبارت شرطي برابر 2 مي‌شود و با توجه به عملگر انتساب جمع داريم


کد:

c = 3 + 2 = 5


معمولاً اين عملگر خوانايي برنامه را كاهش مي‌دهد. لذا به جاي آن اغلب از دستور if else استفاده مي‌شود.





عملگر كاما
عملگر كاما "," اين امکان را مي‌دهد كه چندين عمل در يك دستور انجام شوند. نحوة عملكرد اين عملگر در جدول 4ـ18 نشان داده شده است.

جدول 4ـ18 شکل کلي عملگر كاما

عملگر
علامت
شکل
عمل
كاما
,
a , b ;
a ارزيابي مي‌شود، b ارزيابي مي‌شود، نتيجه b خواهد شد.


يك روش براي استفاده از عملگر كاما به صورت زير است.


کد:

; (عبارت2 , عبارت1) = متغير


در اينجا عملگر كاما موجب مي‌گردد كه ابتدا عبارت 1 و سپس عبارت 2 ارزيابي شود و نتيجة ارزيابي عبارت 2 به متغير مورد نظر نسبت داده شود. در اين گونه موارد معمولاً عبارت 1 و عبارت 2 با يكديگر مرتبط‌اند.
مثال 4ـ24 عبارت زیر را درنظر بگيريد.


a = (b=5 , b+15) ;

در عبارت مزبور، ابتدا b برابر 5قرار داده مي‌شود و سپس عبارت b+15 محاسبه مي‌گردد كه نتيجة آن برابر 20 خواهد بود. در پايان، اين مقدار به متغير a نسبت داده مي‌شود، يعني پس از اجراي دستور مزبور مقدار a برابر 20 خواهد شد.





كاربرد ديگري از عملگر كاما در دستور forاست كه ‌اين نوع كاربرد بيشتر متداول است و در فصل دستورهاي كنترلي بررسي می‌شود.
عملگرهاي حافظه
در زبان C چند عملگر وجود دارد كه اجازه مي‌دهند به خانه‌‌هاي حافظه و محتواي آنها دستيابي داشته باشيد. با بعضي از اين عملگرها، مانند عملگر آدرس (يعني &)، آشنایيد. اين گونه عملگرها در جدول 4ـ19 نشان داده شده‌اند.

جدول 4ـ19 عملگرهاي حافظه

نام عملگر
علامت عملگر
مثال
آدرس
&
&a
محتوا
*
*a
عضو آرايه
[ ]
a[2]
نقطه
.
a. b
پيكان راست
->
p-> a

خودآزمایی 4
<!--[if !supportLists]-->1. <!--[endif]-->برنامه‌اي بنويسيد كه عددي را بخواند و قدرمطلق آن را چاپ كند.
2. برنامه‌‌اي بنويسيد كه طبق فرمول زير درجه حرارت برحسب فارنهايت (F) را به درجه حرارت برحسب سیلسيوس (C) تبديل كند.


کد:

C = 5/9 * (F - 32)


3. اگر b = 5 و a = 2‌، حاصل عبارت y = a*b + ++a + 10 ; چيست ؟
4. برنامه‌اي بنويسيد كه سه عدد از ورودي بگیرد و مشخص کند آيا اين اعداد مي‌توانند اضلاع يك مثلث باشند يا خير.
5. دستورهای زير را به ترتيب اجرا کنید و در هر قسمت معادل بيتی و محتواي متغير x را مشخص سازيد.



x = 7 ;



x = x >> 1 ;



x = x >> 3 ;



x = x >> 2 ;



x = x << 1 ;



x = x << 2 ;



x = x ^ x ;



کد:

printf ("%d" , x & y) ;



int x = 7 , y = 8 ;
printf ("%d" , x && y) ; کد:



6. خروجي قطعه برنامة زير چيست ؟

آبجی
25th May 2010, 12:27 AM
کد:

if (condition) statement ;





درصورتي كه بيش از يک دستور مورد نظر باشد، شکل دستور if به صورت زير خواهد بود.



کد:

if (condition) { statements ; }







در هر دو شکل ifدستورها درصورتي اجرا مي‌گردد كه شرط مورد نظر، كه پس از كلمة كليدي if در داخل يك زوج پرانتز بيان شده است، برقرار باشد. در هر حال پس از پايان اجراي ساختار if، دستورهاي پس از ساختار if اجرا مي‌گردند. شرط مورد نظر ممكن است به صورت عبارت منطقي بيان گردد كه در اين صورت اگر نتيجة آن true (يا عدد غيرصفر) باشد، باز هم دستورهای داخل زوج آكولاد اجرا مي‌گردد و سپس كنترل به اولين دستور بعد از ساختار if انتقال مي‌يابد؛ و اگر نتيجة آن نادرست يعني false (يا عدد صفر) باشد، مشابه حالت شرطي كنترل مستقيماً به بعد از ساختار if انتقال مي‌يابد.
شکل کلي دستور if-elseبه صورت زير است.

کد:


if (condition) { statements1; } else{ statements2 ; } next statement ;
















در اين حالت condition عبارت شرطي يا عبارت منطقي است كه اگر شرط مورد نظر برقرار باشد يا نتيجة عبارت منطقي درست باشد، دستورهاي داخل زوج آكولاد اول اجرا مي‌گردد و كنترل به next statement انتقال مي‌يابد وگرنه دستورهاي داخل زوج آكولاد دوم اجرا مي‌شود و باز هم كنترل به next statement انتقال مي‌يابد.
نمودار هر دو ساختار در شکل 5ـ4 نشان داده شده است. اگر دستورهاي بعد از if يا else بيش از يك دستور نباشد، به استفاده از زوج آكولاد نیازی نخواهد بود. ساختار if را مي‌توان به صورت تودرتو نيز به كار برد كه در اين صورت هم if و هم else به صورت تودرتو تا هرچند سطح كه منطق برنامه نياز داشته باشد تكرار می‌شوند.
مثال 5ـ10 برنامه‌اي بنويسيد كه متني را بخواند و تعداد محلهاي خالي، ارقام، حروف، پايان خط و جمع ساير نشانه‌هاي موجود در آن متن را بشمارد و چاپ کند.
کد:

#include main() { int c , blank_cnt , digit_cnt , letter_cnt , n1_cnt , other_cnt ; blank_cnt=digit_cnt=letter_cnt=n1_cnt=other_cnt= 0; while ((c=gethar())!=EOF) if (c= =’ ’) ++ blank_cnt ; else if (’0’<=c&&c<=’9’) ++ digit_cnt ; else if (’a’<=c && c<=’z’ | | ’A’<=c && c<=’Z’) ++ letter_cnt ; else if (c= =’\n’) ++n1_cnt ; else ++ other_cnt ; printf ("\n%12s %12s %12s %12s %12s %12s","blanks","digits", "letters","lines","others","totals") ; printf("\n\n %12d %12d %12d %12d %12d %12d \n\n" , blank_cnt , digit_cnt , letter_cnt , n1_cnt , other_cnt , blank_cnt + digit_cnt + letter_cnt + n1_cnt + other_cnt) ; }
http://i34.tinypic.com/2it2cnq.jpg
http://i38.tinypic.com/313qhqc.jpgشکل 5ـ4 نمودار دو ساختار if و if – else

مثال 5ـ11 برنامه‌اي بنويسيد كه کد اسكي كاراكتری را بخواند و تشخيص دهد كه كدام يك از كاراكترهاي پايان فايل يا EOF، خط جديد يا new line، رقم يا digit، كنترل كاراكتر (كاراكترهايي كه کد اسكي آنها كوچك‌تر از 32 است و قابل چاپ نيستند و 32 كه کد اسكي كاراكتر فضاي خالي يا ’’ است، پس کد اسكي كنترل كاراكترها از کد اسكي ’’ كوچك‌تر است)، حروف بزرگ، حروف كوچك و يا ساير كاراكترهایند.
کد:


#include main () { int ch ; printf("please enter a character?") ; ch = getchar() ; if (ch= = EOF) printf("\n end of file found\n") ; else if (ch= =’\n’) printf("\n new line character\n") ; else if (ch<’ ’) printf("\n control character %d \n", ch) ; else if ((ch>=’0’) && (ch<=’9’)) printf("\n character %c is a digit\n", ch) ; else if ((ch>’A’) && (ch<=’Z’)) printf("\ncharacter %c is upper-case\n", ch)) ; else if ((ch>=’a’) && (ch<=’z’)) printf("\n character %c is lower-case\n", ch) ; else printf("\n other printable character %c \n", ch) ; }



دستور switch
اين ساختار يا دستور موجب مي‌گردد كه گروه مشخصي از دستورها بين چندين گروه از دستورها انتخاب گردد. اين انتخاب بستگي به مقدار فعلي يك عبارت خواهد داشت كه در switch منظور شده است. قبلاً گفتیم که در دستور if-else، بر اثر وجود يا عدم وجود شرط (يا شرايطي)، يكي از دو مجموعه دستورها انتخاب و اجرا مي‌گردد. به عبارت ديگر در اينجا حداكثر دو انشعاب يا دو شاخه وجود دارد كه بايد فقط بر اثر نتيجة بررسی شرط مورد نظر، يكي از آن دو شاخه يا مسير انتخاب گردد. دستور switch اين امكان را فراهم مي‌سازد كه از بين شاخه‌هاي متعدد (بيش از دو شاخه) فقط يكي انتخاب گردد كه قانون انتخاب را نتيجة ارزيابي عبارت ذكر شده در switch تعيين مي‌كند. بنابراين، اين دستور اجازة چندين انشعاب مي‌دهد.

شکل كلي ساختار switch به صورت زير است.
کد:





switch(expression) { case exp1: statements 1 break ; case exp2: statements 2 break ; .... .... case exp n: statements n break ; default: statements break ; }







در دستور switch نتيجة عبارت يا expression كه پس از كلمة كليدي switch در داخل يك زوج پرانتز قرار دارد يك عدد صحيح خواهد بود. در ضمن expression ممکن است كاراكتر نيز باشد زيرا هر كاراكتر نيز مقدار صحيح هم‌ارزي دارد كه کد اسكي‌ آن كاراكتر است. statement معمولاً دستوری مرکب است. break براي خروج از دستور است.
نمودار ساختار switch در شکل 5ـ5 نشان داده شده است.
نحوة عملکرد ساختار switch بدين شکل است كه وقتي اين دستور اجرا مي‌شود عبارت ذكر شده در switch محاسبه و ارزشيابي مي‌شود. سپس نتيجة آن از بالا به پايين به ترتيب با مقدار ذكر شده در case يعني exp 1 , exp 2 ,... , exp nمقايسه مي‌شود. اگر نتيـجة مقايسه با هركدام از مقادير ذكر شده در case هاي مزبور برابر باشد، دستورهاي ذكر شده در آن case اجرا مي‌گردد و كنترل اجراي برنامه به اولين دستور پس از ساختار switch انتقال مي‌يابد. چنانچه مقدار ذكر شده در switch با هيچ يك از مقادير ذكر شده در caseهاي متوالي يكسان نباشد، مجموعه دستورهاي مربوط به default به عنوان پيش‌فرض اجرا مي‌گردد.


http://i35.tinypic.com/20h2had.jpg

شکل 5ـ5 نمودار ساختار switch
در دستور switch استفاده از حالت default دلخواه است. بنابراين چنانچه حالت default به كار برده نشود و مقدار عبارت switch در مقابله با مقادير ذكر شده در caseهاي متوالي‌ مساوي (همسان) نباشد، دستور switch خاتمه مي‌يابد و كنترل برنامه به اولين دستور بعد از switch انتقال مي‌يابد.
يادآوري مهم. گفتیم، عبارت ذكر شده در switch فقط مقادير صحيح يا كاراكتر را می‌پذیرد. بنابراين برخلاف دستور if نمي‌توان در آن از عبارت رابطه‌اي و منطقي استفاده كرد؛ به عبارت ديگر switch فقط تساوي را تست مي‌كند، اما if عبارات رابطه‌اي و منطقي را نيز ارزيابي مي‌كند. نتيجه‌اي كه مي‌توان گرفت آن است كه در حالت كلي نمي‌توان دستور switch را حالت تعميم‌يافتة دستور if-else براي m انشعاب تصور كرد.
دستور switch براي پردازش فرامين صفحه كليد بسيار مناسب است و در واقع شکل تغييريافته‌اي از دستور if-else است.
مثال 5ـ12 برنامة زير با استفاده از دستور switch ارقام 0 تا 9 را از ورودي دريافت می‌کند و آنها را با حروف نمايش مي‌دهد.





#incl کد:

ude

کد:

main () { char digit ; digit = getchar() ; switch (digit) { case 0: printf ("zero") ; break ; case 1: printf ("one") ; break ; case 2: printf ("two") ; break ; case 3: printf ("three") ; break ; case 4: printf ("four") ; break ; case 5: printf ("five") ; break ; case 6: printf ("six") ; break ; case 7: printf ("seven") ; break ; case 8: printf ("eight") ; break ; case 9: printf ("nine") ; break ; default: printf("it is not digit"); } }






مثال 5ـ13 برنامة‌ زير با استفاده از دستور switch متغير كاراكتري color را كه معرف رنگ است از صفحه‌ كليد دريافت می‌کند و رنگي را که با آن حرف آغاز مي‌شود در خروجي چاپ مي‌کند.

کد:


#include main () { char color ; color = getchar() ; switch (color) { case ’Y’: printf ("Yellow") ; break ; case ’B’: printf ("Black") ; break ; case ’W’: printf ("White") ; break ; case ’R’: printf ("Red") ; break ; case ’G’: printf ("Green") ; break ; default: printf("error"); } }




در اين برنامه مي‌توان دستور switch را با دستور خواندن متغير از ورودي به شکل زير ترکيب کرد.

کد:

switch (color=getchar())

در مواردي براي چندين حالت مختلف يك نوع عمل انجام مي‌گيرد. در اين گونه موارد مي‌توانيم همان دستورها را با چندين ثابت case مشخص كنيم.
مثال 5ـ14 به قطعه برنامة زير توجه کنید.

کد:


switch (ch) { case 'a': case 'b': x = x + 1 ; break ; case 'c': case 'd': case 'e': x = x + 2 ; break ; default: x = x + 3 ; break ; }





دستور break
اين دو دستور مسير معمولي و ثابت كنترل را تغيير يا قطع مي‌کنند. دستور break براي خارج شدن از دستور switch و يا پايان دادن حلقه‌‌ها استفاده مي‌شود. در واقع كنترل را به پايان ساختاري كه break در داخل آن به كار برده شده است انتقال مي‌دهد. در صورتي که دستور مزبور در يکي از حلقه‌هاي for وwhile و do-while به كار رود، کنترل به محض رسيدن به break بلافاصله از حلقه خارج مي‌شود. بنابراين، اين روش براي پايان دادن به حلقه‌‌ها در صورت بروز خطا يا شرايط خاص مناسب است.
مثال 5ـ15 به قطعه برنامة زير توجه کنيد.

کد:


while(1) { ch = getchar() ; if (ch = = '@') break ; /* exit loop */ printf ("%c ", toupper(ch)) ; }






در صورتي که کاراکتر @ از ورودي خوانده شود، دستور break موجب خروج از حلقة بي‌‌نهايت while مي‌گردد. در غير اين صورت حلقه ادامه خواهد يافت.
همان طور که ملاحظه مي‌‌کنيد شکل كلي دستور break به صورت زير است.

break ;
نحوة عملکرد اين دستور در شکل 5ـ6 آمده است.

http://i37.tinypic.com/53kadc.jpg
شکل 5ـ6 نمودار دستور break

لازم به ذکر است که در حلقه‌هاي تو در تو، دستور break براي انتقال کنترل به خارج از حلقة داخلي به کار مي‌رود.
دستور continue
این دستور به منظور عبور جانبي از کنار ساير مراحل جاري حلقه به کار می‌رود. در واقع باقيماندة تکرار جاري حلقه ناديده گرفته می‌شود و بلافاصله تكرار بعدي حلقه آغاز مي‌گردد. حلقه زماني که به دستور continue مي‌‌رسد خاتمه نمي‌‌يابد و از اين جهت با دستور break تفاوت دارد. اين دستور ممکن است با ساختارهاي for , do-while , while به كار رود و شکل كلي آن به صورت سادة زير است.


continue ;

همچنين نحوة عملکرد اين دستور به صورت شکل 5ـ7 است.

http://i38.tinypic.com/f2f79.jpg شکل 5ـ7 نمودار دستور continue

مثال 5ـ16 برنامة‌ زير با استفاده از دستور continue، n عدد از ورودي می‌خواند و مجموع اعداد مثبت را محاسبه مي‌کند.


کد:

#include main () { int n , i , x , sum = 0 ; printf("how many numbers? ") ; scanf("%d", &n) ; for (i=1 ; i { scanf ("%d", &x) ; if (x<=0) continue ; sum += x ; } printf ("\n sum = %d \n", sum) ; }




دستور goto
اين دستور ترتيب طبيعي اجراي برنامه را تغيير می‌دهد و کنترل را به قسمت ديگري از برنامه منتقل مي‌کند. در واقع انتقال كنترل بدون شرط است و اصول برنامه‌سازي ساخت‌يافته در زبان C را لغو مي‌کند. از اين رو استفاده از آن توصيه نمي‌شود. در برخي زبانهاي برنامه‌‌نويسي قديمي مثل فورترن و بيسيک کاربرد گسترده‌اي دارد. شکل كلي اين دستور به صورت زير است.

goto label ;
كه در آن label شناسه‌اي است كه محل انتقال يا محل دستور بعدي‌ای را كه بايد اجرا شود نشان مي‌دهد. بنابراين، محل انتقال كنترل يا جملة هدف بايد label داشته باشد. پس از برچسب علامت دو نقطه به کار مي‌رود. شکل آن به صورت زير است.

کد:

label: statement

مثال 5ـ17 به قطعه برنامة زير توجه کنيد.




{

---------

---------

goto msg ;

---------

---------

}

msg: printf("\n please try again") ;
اما گاهي استفاده از دستور goto مفيد است و کار را ساده مي‌کند. به عنوان مثال در صورتي که نياز باشد كنترل برنامه ‌از درون دو حلقة تودرتو به خارج انتقال یابد معمولاً ساده‌‌ترين حالت استفاده از دستور goto خواهد بود.
مثال 5ـ18 برنامة زير عددي صحيح از ورودي می‌خواند. در صورتي که زوج باشد پيغام مناسب را نمايش مي‌دهد، در غير اين صورت از برنامه خارج مي‌شود.





کد:

#include

کد:

main ()
{
int n ;
scanf("%d", &n) ;
if (n % 2 = =0)
goto even ;
else
goto odd ;
even: printf("even number.\n") ;

exit(1) ; odd: exit (0); }







تابع exit
اين تابع اجراي برنامه را به طور كامل قطع ‌می‌کند و كل برنامه را خاتمه می‌بخشد. اين تابع كه در كتابخانة استاندارد وجود دارد معمولاً با آرگومان صفر فراخواني مي‌شود و بر خاتمه پذيرفتن طبيعي برنامه دلالت مي‌كند. اما آرگومانهاي ديگري نيز دارد.
كاربرد متداول exitزماني است كه شرط خاصی براي اجراي برنامه برقرار نباشد و اجراي برنامه قطع ‌شود.
مثال 5ـ19 به قطعه برنامة زير توجه کنيد.



کد:

{ .... if x<5 exit (0); .... }

خودآزمایی 5
1. برنامه‌اي بنويسيد كه جدول ضرب اعداد 1 تا 10 را محاسبه و چاپ كند.
2. برنامه‌اي بنويسيد كه يك سطر متن را بخواند و تعداد محلهاي خالي (blank) موجود در آن را تعيين و چاپ كند.
3. موجودي 500000 ريال با سود بانکي 16 درصد در سال داريم. برنامه‌اي بنويسيد كه براي پنج سال متوالي موجودي را در پايان هر سال محاسبه و چاپ كند.
4. برنامه‌اي بنويسيد كه كاراكتري را از طريق ورودي بخواند و تعيين كند كه آيا كاراكتر مزبور يكي از كاراكترهاي EOF (پايان فايل)، خط جديد، رقم، حروف كوچك، حروف بزرگ يا از كاراكترهاي ديگر است.
5. عدد ي که مساوي مجموع مقسوم‌عليه‌هاي خود باشد را عدد كامل نامند، مانند عدد 6؛ يعني 6 = 3 + 2 + 1. برنامه‌اي بنويسيد كه عددي صحيح و مثبت را بخواندو تعيين كند كه آيا اين عدد كامل است يا نه.
6. در رياضي، سري فيبوناچي به صورت زير تعريف شده است.

1 1 2 3 5 8 13 …
كه در آن دو جملة اول و دوم برابر 1 است. در مورد بقية جمله‌ها هر جمله برابر است با مجموع دو جملة قبلي آن. برنامه‌اي بنويسيد تا جمله‌های اول تا ده سري مزبور و مجموع آنها را محاسبه و چاپ كند.
7. برنامه‌ای بنويسيد که چهار عمل اصلي ماشين حساب (جمع، تفريق، ضرب و تقسيم) را انجام ‌دهد.
8. برنامه‌اي بنويسيد كه نمرات امتحاني n نفر دانشجو را بخواند و معدل كلاس، نمرة امتحاني شاگرد اول و شاگرد آخر كلاس را تعيين و چاپ كند.
9. برنامه‌اي بنويسيد که مجموع اعداد زوج و نيز مجموع اعداد فرد 1 تا n را محاسبه و چاپ کند.

آبجی
25th May 2010, 12:29 AM
توابع و کلاس حافظه هدف کلی
آشنایی با توابع، پارامترهای خط فرمان، آرگومانهای argc و argv و حافظه‌های C
هدفهای رفتاری
از دانشجو انتظار مي‌رود پس از مطالعة این فصل،
1. تابع و انواع آن را تعریف کند.
2. مزایای تعریف تابع فرعی را بیان کند.
3. عناصر تشکیل‌دهندة هر تابع را بشناسد.
4. کاربرد دستور return را بیان کند.
5. نحوة فراخوانی تابع را بشناسد.
6. روش انتقال آرایه به تابع را بیان کند.
7. روشهای تعریف پارامتری که اشاره‌گر آرایه دریافت مي‌کند بیان کند.
8. توابع بازگشتی یا خودگردی را بشناسد.
9. پارامترهای خط فرمان را بشناسد.
10. آرگومانهای argc و argv را بشناسد.
11. تفاوت فراخوانی توابع در C و پاسکال را بیان کند.
12. متغیرهای محلی یا خصوصی و متغیرهای عمومی را بشناسد.
13. کلاس حافظه و کاربرد هریک را شرح دهد.
مقدمه
در حالت كلي و بدون توجه به زبان برنامه‌نویسیخاص، برنامة مورد نظر براي پياده‌سازي هر پیمانه یا ماژول را زيربرنامه گويند. در زبان پاسكال به آنها تابع يا رويه گویند. پيمانه يا ماژول را در زبان C تابع نامند؛ يعني براي پياده‌سازي هر ماژول مي‌توان يك تابع نوشت. تابع قطعه برنامه‌اي کامل است که کار معيني انجام مي‌دهد و موجب جلوگيري از برنامه‌‌نويسي تکراري در بين برنامه‌‌ها مي‌شود.
گفتیم هر برنامه در زبان C، مجموعه‌اي از يك يا چندين تابع است كه يكي و فقط يكي از آنها تابع اصلي یا main است و بقيه تابع فرعي‌اند. توابع به دو گروه دسته‌بندي مي‌شوند. يك سري توابع از پيش تعريف شده‌اند و آنها را توابع كتابخانه‌اينامند. كتابخانة استاندارد C، مجموعه‌اي غني از اين گونه توابع دارد كه محاسبات رياضي، انجام عمليات روي نوشته‌ها و كاراكترها، انجام عمليات ورودي و خروجي، انجام عمليات در زمينه‌هاي گرافيكي و جز آن را به عهده دارند كه متداول‌ترين آنها را بررسي می‌کنیم. توربو C و همين طور گونه‌هاي ديگر C، از اين لحاظ كتابخانه‌هاي گسترده‌تري دارند كه آنها را نيز به اختصار بررسي می‌کنیم. وجود اين ‌گونه توابع از پيش‌ تعريف شده كار برنامه‌نويسان را ساده‌تر می‌کند و توانمندي آنها را براي نوشتن برنامه‌هاي كارآمد بالا مي‌برد.
گروه ديگر از توابع فرعي را برنامه‌نويس تعريف مي‌کند. C، مشابه ساير زبانهاي برنامه‌نویسي، اجازه مي‌دهد كه برنامه‌نويس، برحسب سليقة خود، زيربرنامه‌هايي را به عنوان تابع فرعي طراحي كند و آنها را برحسب نياز در برنامه يا تابع اصلي و يا ساير توابع فراخواند. اين شيوه، به برنامه‌نویس امكان مي‌دهد كه برنامه‌ای بزرگ را به صورت ماژول‌‌شده طراحي کند؛ يعني كار يا پروژة مورد نظر را به قسمتهاي كوچك‌تري تجزيه کند، براي هر قسمت يك تابع بنويسد و آنها را به كمك تابع اصلي به يكديگر پيوند دهد و برحسب لزوم آنها را فراخواند.
<!--[if !vml]-->file:///C:%5CDOCUME%7E1%5CMilad%5CLOCALS%7E1%5CTemp%5Cmsoh tml1%5C01%5Cclip_image001.gif<!--[endif]-->طراحي برنامه به صورت پيمانه‌اي يا ماژول‌‌شده، يعني به صورت مجموعه‌اي از توابع، مزايايي دارد كه مهم‌ترين آنها عبارت‌اند از:
ـ امکان استفادة مجدد از تابع
ـ ساده ‌شدن كنترل و خطايابي
ـ امکان انجام تغييرات در برنامه و اصلاح آن
ـ امكان همكاري برنامه‌نويسان متعدد در نوشتن يك برنامه.
در اين فصل ايجاد و کاربرد توابع را بررسي می‌کنیم.
نحوة تعريف تابع
چنانکه گفتیم هر برنامة C‌ از يك يا چندين تابع تشكيل مي‌گردد كه فقط يكي از آنها تابع اصلي است. به طور كلي هر تابع شامل عناصر زير است:
- عنوان تابع كه شامل نام تابع، نوع تابع و آرگومانهاي تابع است. تابع بايد از لحاظ نوعتوصيف شود که قبل از نام آورده مي‌شود و مشخص مي‌کند كه تابع چه نوع مقداري را برمي‌گرداند. در صورتي که تابع آرگومان داشته باشد به دنبال نام تابع و درون يك جفت پرانتز، آرگومانهاي تابع درج مي‌شود. همچنين نوع هر آرگومان نيز بايد اعلان شود.آرگومانها با ويرگول از هم جدا مي‌شوند. اگر تابع مقدار صحيح برمي‌گرداند، تعريف نوع را مي‌توان حذف کرد. در صورتي که تابع آرگومان نداشته باشد، يک جفت پرانتز خالي به دنبال نام آن مي‌‌آيد.
- بدنة تابعکه شامل موارد زير است:
الف) اعلان متغيرهاي محلي. هر متغيري را كه جزء آرگومانهاي تابع نباشد و به عبارت ديگر مخصوص خود تابع باشد متغير محلي نامند و بايد در آغاز تابع پس از عنوان تابع اعلان گردد.متغيرهاي محلي خارج از تابع شناخته نمي‌شوند.
ب) ساير دستورهاي تابع. متن تابع و دستورهاي اجرايي در اين قسمت واقع مي‌شود و شامل دستورهاي محاسباتي، دستورهاي کنترلي و حتي دستور فراخواني خود تابع است. شكل 6ـ1 عناصر يك تابع را نمايش مي‌دهد.
وقتي كه تابعي در داخل تابع اصلي فراخواني مي‌شود، اصطلاح آرگومان به كار می‌رود.

ولي در خود تابع فرعي، يعني در تعريف تابع فرعي، اصطلاح پارامتر به كار می‌رود.

آبجی
25th May 2010, 12:40 AM
هدف کلی
آشنایی با مهم‌ترین دستورهای کنترلی در زبان C و کاربرد آنها
هدفهای رفتاری
از دانشجو انتظار مي‌رود پس از خواند این فصل،
1. با کاربرد دستورهای کنترلی آشنا شود.
2. شکل کلی و کاربرد دستور while را بداند.
3. شکل کلی و کاربرد دستور while‌do- را بداند و تفاوت آن را با while بیان کند.
4. شکل کلی و کاربرد دستور for را بداند.
5. شکل کلی و کاربرد دستور عملگر کاما را بداند.
6. شکل کلی و کاربرد دستورهای ‌if و if-else را بداند.
7. شکل کلی و کاربرد دستور switch را بداند.
8. شکل کلی و کاربرد دستور break را بداند.
9. شکل کلی و کاربرد دستور continue را بداند.
10. شکل کلی و کاربرد دستور goto را بداند.
11. شکل کلی و کاربرد تابع exit را بداند.
مقدمه
يکي از امکانات زبانهاي برنامه‌نویسی جدید، استفاده از دستورها و ساختارهاي كنترلي است و در نتيجه ‌اين امكان را فراهم مي‌‌سازند كه قطعه‌ای از برنامه تا موقعي كه شرط ويژه‌اي برقرار است چندين بار اجرا شود.
زبان برنامه‌‌نويسي C داراي قلمرو گسترده‌اي از اين نوع ساختارهاست. در حالت عادي دستورهاي هر برنامه به طور متوالي اجرا مي‌شود. اما اگر نياز باشد كه دستور يا مجموعه‌اي از دستورها در صورت وجود يا عدم وجود شرط يا شرايط خاصي اجرا گردند بايد شيوة ديگري به کار برد. ساختارهاي كنترلي دستورهايي‌اند كه چنين زمينه‌اي را در برنامه‌نويسي فراهم مي‌كنند.
مهم‌ترين دستورهاي كنترلي عبارت‌اند از do _ while و while _ forکه ساختارهاي حلقه‌هاي تكرار را تشکیل می‌دهندو دستورهاي switch و if که دستورهاي شرطي يا ساختارهاي تصميم‌گيري‌اند و بالاخره دستورهايgoto , ،continue ،break ، و exit.
حال به دو مفهوم درست يا true و نادرست يا false توجه کنيد. اغلب دستورهاي كنترلي برنامه در زبان C بر نتيجة وجود شرط تكيه مي‌كند تا برحسب برقراري آن شرط عملي انجام گيرد يا انجام نگيرد. درواقع نتيجة آزمايش اين شرط مقدار درست يا نادرست است. اغلب زبانهاي كامپيوتري مقاديري را به عنوان ارزش درستي يا نادرستي مشخص مي‌كنند (مثلاً 1 براي درست و 1- براي نادرست)، اما در زبان C هر مقدار غيرصفر (مثبت يا منفي) درست يا true (يعني شرط مورد نظر برقرار است) و مقدار صفر نيز نادرست يا false تلقي مي‌گردد.
در اين فصل، مهم‌ترين دستورها و ساختارهاي كنترلي زبان C را بررسي مي‌کنیم.
دستور while
اين دستور يكي از دستورهاي كنترلي زبان C است كه براي انجام عمليات تکراري به کار مي‌رود. با استفاده از اين دستور، حلقه تا موقعي كه شرط معيني برقرار باشد اجرا مي‌گردد. شکل كلي اين دستور به صورت زير است.



کد:

while (condition) statement ;






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



کد:

while (condition) { statements ; }






نمودار كلي آن را نیز در شکل 5ـ1 می‌بینید.
http://i30.tinypic.com/kbrgno.jpg (http://pnu-club.com/redirector.php?url=http%3A%2F%2Ftinypic.com%2F)


سازوکار و نحوة عملكرد دستور در while به‌اين طريق است که تا موقعي كه شرط مورد نظر كه پس از كلمة كليدي whileدر داخل پرانتز نوشته می‌شود برقرار باشد، مجموعه دستورهاي داخل حلقة while به صورت تكراري اجرا خواهد شد. شرط مورد نظر با استفاده از عملگرهاي رابطه‌اي به صورت عبارات رابطه‌اي يا به صورت عبارت منطقي بیان می‌شود كه در اين صورت تا موقعي كه عبارت مزبور ارزش درست يا true داشته باشد حلقه اجرا خواهد شد.
مثال 5ـ1 برنامة زير به دو روش اعداد صحيح صفر تا 10 را در روي خطوط متوالي چاپ مي‌كند.
کد:



روش اول

روش دوم
#include main() { int number = 0 ; while (number<=10) printf ("%d\n", number ++); }
#include main() { int number = 0 ; while (number<=10) { printf("%d\n", number); ++ number; } }







مثال 5ـ3 برنامة زير يك خط متن با حروف كوچك را كاراكتر به كاراكتر از آراية text مي‌خواند. سپس با استفاده از تابع كتابخانه‌اي toupper متن مزبور را به حروف بزرگ تبديل و چاپ مي‌كند.



کد:

#include #define eol ’\n’ main () { char text[80] ; int tag , count = 0 ; /*read the text in lower case */ text [count] = getchar() ; while (text[count]!eol) { count = count + 1 ; text[count]=getchar() ; } tag = count ; count = 0 ; while (count { putchar (toupper(text[count])) ; + + count ; } }




در برنامة بالا دو عبارت while جداگانه به كار رفته كه يكي براي خواندن متن از حافظه و ديگري براي تبديل حرف كوچك به بزرگ و چاپ متن تبديل شده است. حال اگر mathematics and statistics وارد شود، عبارت MATHEMATICS AND STATISTICSدر خروجي نمايش داده می‌شود.
دستور do - while
در دستور while آزمايش شرط براي ادامة حلقه در آغاز هر تكرار حلقه انجام مي‌گيرد. گاهي مطلوب است كه ‌اين آزمايش در پايان حلقه انجام شود. اين كار با دستور كنترلي do-while امكان‌پذير است. شکل كلي دستور do-whileبه صورت زير است.





کد:

do { statements }while (condition) ;




در صورتي که حلقة تكرار فقط شامل يك دستور باشد، نيازي به قراردادن زوج آكولاد نخواهد بود. در اينجا اول statements اجرا مي‌گردد، سپس شرط داخل پرانتز، يعني condition بررسی می‌شود. بنابراين، در اين ساختار هميشه statements حداقل يك بار اجرا خواهد شد. در اين حالت نيز عبارت داخل پرانتز معمولاً يك عبارت رابطه‌اي يا منطقي است كه نتيجة آن مشابه while است.
در اغلب كاربردها، آزمايش شرط ادامه براي اجراي حلقه، به طور طبيعي در آغاز حلقه صورت مي‌گيرد. بدين لحاظ دستور do-while در مقايسه با دستور while كاربرد كمتري دارد. نحوة عملكرد اين دستور در شكل 5ـ2 نشان داده شده است.




http://i30.tinypic.com/2z57hnp.jpg (http://pnu-club.com/redirector.php?url=http%3A%2F%2Ftinypic.com%2F)


مثال 5ـ4 برنامه‌اي بنويسيد كه با استفاده از دستور do - while اعداد صحيح صفر تا 10 را در روي خطوط متوالي چاپ كند.
کد:



#include main () { int number = 0 ; do printf ("%d\n", number + +) ; while (number<=10) ; }












مثال 5ـ5 برنامه‌اي بنويسيد كه با استفاده از دستور do - while عدد صحيح n را بخواند و فاكتوريل آن را حساب و با خود عدد چاپ کند.
کد:

#include main () { int n , i =1 , fact =1 ; scanf ("%d",&n) ; do fact *= i ; while (+ +i<= n) ; printf ("factorial of %d is %d", n , fact) ; }












دستور for
دستور for متداول‌ترين دستور حلقه در زبان C و شبيه به دستور while است. اين دستور شامل يک عبارت است که مقدار نخستين يک شاخص را مشخص مي‌سازد. عبارت ديگر چگونگي ادامه يا پايان حلقه را تعيين مي‌کند و سومين عبارت شاخص را در پايان هر حلقه تغيير مي‌دهد. نمودار آن را در شکل 5ـ3 می‌بینید.
شکل كلي اين دستور نيز به صورت زير است.

کد:

for (expression1; expression2; expression3) statement ;

در اينجا expression1 براي مقداردهي اولية پارامتري كه حلقه را كنترل مي‌کند (و شاخص يا index ناميده مي‌شود) به كار می‌رود. expression2 يك شرط را معرفي مي‌کند كه بايد براي ادامة اجراي حلقه صادق باشد و expression3 نيز براي تغيير مقدار پارامتري كه در آغاز به expression1 اختصاص داده شده به كار می‌رود. معمولاً expression1 عبارت جايگذاري، expression2 عبارت منطقي يا رابطه‌اي و expression3 عبارت جایگذاری یا unary expression است.
وقتي كه دستور for اجرا مي‌گردد قبل از هر گذر در داخل حلقه، expression2 ارزيابي و آزمايش مي‌شود. اما expression3 در پايان هر گذر ارزيابي مي‌گردد. بنابراين دستورfor

معادل دستورهاي زير است.
http://i31.tinypic.com/316b6kk.jpg (http://pnu-club.com/redirector.php?url=http%3A%2F%2Ftinypic.com%2F)


کد:

expression1 ; while (expression2) { statements expression3 ; }






اجراي حلقه تا زماني که مقدار expression2 مساوي صفر نباشد، يعني تا هنگامي که شرط معرفي شده با expression2 برقرار و يا true باشد، ادامه خواهد داشت.
مثال 5ـ6 با استفاده از دستور for برنامه‌اي بنويسيد كه اعداد صحيح صفر تا 10 را روي خطوط متوالي چاپ كند.


کد:

#include main () { int number ; for (number=0 ; number<=10 ; + + number) printf ("%d\n", number) ; }





در اين برنامه اولين خط در دستور for شامل سه expression است كه در داخل پرانتز قرار گرفته‌اند. اولين expression مقدار صفر را به متغير number اختصاص مي‌دهد. دومين expression بيان مي‌كند كه تكرار حلقه تا هنگامي كه مقدار فعلي number از 10 تجاوز نكرده باشد ادامه خواهد يافت. سومين expression پس از هر بار گذر حلقه، مقدار number را يك واحد افزايش مي‌دهد.
از نظر دستوري نياز نيست هر سه expression مربوط به دستور for به كار برده شود، اگرچه به كار بردن سميكولون مربوط به هر expression الزامي است. نتيجة حذف هر expression بايد به طور كامل فهميده شود. اگر آغازين كردن و يا تغيير شاخص يا هر دو به طريق ديگري انجام گيرد، ممكن است expression هاي اول و سوم حذف گردند. درصورتي كه expression دوم حذف گردد، ارزش آن مقدار ثابت true درنظر گرفته خواهد شد و در نتيجه تكرار حلقه به صورت نامتناهي ادامه خواهد يافت مگر اينكه خروج از حلقه به طريق ديگري مثلاً با دستور break يا return پيش‌بيني گردد. در اغلب كاربردهاي دستور for هر سه expression استفاده مي‌شود.
مثال 5ـ7 با استفاده از دستور for برنامه‌اي بنويسيد كه عدد صحيح n را بخواند و فاكتوريل آن را حساب و با خود عدد چاپ کند.


کد:

#include main () { int n , fact =1 ; scanf ("%d", &n) ; for (i=2 ; i<=n ; ++i) fact = fact * i ; printf ("factorial of %d is %d", n , fact) ; }




مثال 5ـ8 برنامه‌اي بنويسيد كه نمره‌های امتحاني دانشجويان كلاسهاي مختلف را بخواند و معدل هر كلاس را حساب و چاپ کند. تعداد كلاسها و تعداد دانشجويان هر كلاس از طريق دستگاه ورودي خوانده شود.
کد:


#include main () { int n , count , loops , loopcount ; float x , average , sum ; scanf("%d",&loops) ; /*outer loop*/ for (loopcount=1 ; loopcount<=loops ; ++ loopcount) { sum = 0 ; printf("\n class number %d \n how many numbers?", loopcount) ; scanf ("%d",&n) ; for (count=1 ; count<=n ; + +count) /* inner loop */ { scanf ("%f",&x) ; sum += x ; } /*end of inner loop*/ average = sum / n ; printf("\n the average is %f\n", average) ; } /*end of outer loop*/ }







حلقه‌ها مي‌توانند در يکديگر قرار گيرند يعني به صورت تودرتو به كار روند كه در اين حالت حلقة داخلي بايد كاملاً توسط حلقة بيروني احاطه گردد. به عبارت ديگر دو حلقه نبايد يكديگر را قطع کنند. همچنين هر حلقه بايد با شاخص جداگانه‌اي كنترل شود.برنامة فوق از دو حلقه تشكيل شده است. در آغاز تعداد كلاسها (loops) خوانده می‌شود و بر اساس آن حلقة بيروني تكرار مي‌گردد يعني به ازاي هر كلاس يك بار اجرا مي‌شود. هر بار در داخل حلقة بيروني، متغير sum مساوي صفر قرار داده می‌شود، سپس تعداد دانشجويان يا تعداد نمره‌هاي امتحاني n خوانده مي‌شود. پس از آن حلقة دروني به تعداد دانشجويان كلاس مورد نظر n اجرا مي‌شود كه در هر تكرار نمرة امتحاني يك دانشجو خوانده و به sum افزوده مي‌شود. هر بار پس از كامل شدن حلقة دروني، جمع نمره‌هاي امتحاني كلاس به دست مي‌آيد كه سپس معدل كلاس با نام average حساب و چاپ مي‌شود.



عملگر كاما
در خصوص اين عملگر در فصل 4 مطالبي بيان شد. اين عملگرعملگری باينري است و به دو عبارت مختلف اجازة ظاهر شدن در موقعيتهايي را مي‌دهد که در آن بايد فقط يک عبارت به کار رود.همچنينعملگر كاما از چپ به راست عمل مي‌كند و در مجموعه عملگرهاي زبان C کمترين تقدم را دارد. عملوندهاي آن عبارت‌اند از

کد:

expression1, expression2

در اينجا ابتداexpression1و سپس expression2 محاسبه مي‌شود.
كاما ممکن است در دستور for به كار رود و اجازة پردازش چندين انديس را به شکل يکجا مي‌دهد. همچنين امکان مقداردهي اولية چند متغير را به شکل همزمان فراهم مي‌سازد.حالتهاي مختلف دستور for با توجه به عملگر کاما به شکل زير است.



کد:

for (expression1 ; expression2 ; expression3) for (expression1A , expression1B ; expression2 ; expression3) for (expression1 ; expression2 ; expression3A , expression3B)




مثال5ـ9 به برنامة زير توجه کنيد.






کد:

#include

کد:

main () { int i , n , sum ; scanf("%d", &n) ; for (sum = 0 , i = 1 ; i printf ("\n %d", sum) ; }




اين برنامه مجموع اعداد صحيح 1 تا nرا محاسبه و چاپ مي‌کند. همانطور که ملاحظه مي‌‌کنيد در اينجا دو بار از عملگر کاما در دستور for استفاده شده است. همچنين در انتهاي دستور for سميکولون به کار رفته است. يعني پس از پايان حلقه که مقدار sum محاسبه شد، کنترل برنامه به دستور printf منتقل مي‌شود.
لازم به توضيح است که براي تفکيک متغيرها، اعلان متغيرها و آرگومانهاي توابع از کاراکتر کاما استفاده مي‌شود که نبايد آن را با عملگر کاما اشتباه کرد.

استفاده از تمامی مطالب سایت تنها با ذکر منبع آن به نام سایت علمی نخبگان جوان و ذکر آدرس سایت مجاز است

استفاده از نام و برند نخبگان جوان به هر نحو توسط سایر سایت ها ممنوع بوده و پیگرد قانونی دارد