پرش به محتوا

زبان برنامه نویسی سی/آغاز

ویکی‎کتاب، کتابخانهٔ آزاد

استانداردی که در سال 2011 توسط ISO بازتعریف شد شامل چند افزایش و تغییر در فایل‌های سرآیند و تابع‌های کتابخانه‌ای و ماکروها بود و از طرفی ، مقرر کرد تا از کاراکتر سِت یا به اختصار کارسِت Unicode یونیکد UTF-8 و UTF-16 استفاده شود که باید بدانید در حال حاضر ، فقط کامپایلرهای بزرگ عمومی نظیر GCC و کِلنگ و ++Visual Studio C از استاندارد C11 و در ادامه C18 پشتیبانی می‌نمایند و بقیه همچنان مطابق با استانداردهای C98 و C99 یا استانداردهای اختصاصی خود هستند

اولین چیزی که باید بدانید این است که Encoding ( رمزنویسی ) در برنامه‌نویسی و برنامه‌های کامپیوتری به الگوریتم ذخیره سازی اطلاعات گرافیکی ، صوتی ، متنی و ... در فایل به صورت باینری می‌باشد و Decoding ( رمزگشایی ) به معنای ترجمه یک یا چند بایت Byte به اطلاعات خروجی ( که می‌تواند متنی ، گرافیکی ، صوتی و ... باشد ) گفته می‌شود . اما در زبان های متنی این انکدینگ‌ها و دکودینگ‌ها بر اساس کاراکترست‌ها که به صورت مخفف کارسِت‌ها نیز خوانده می‌شوند می‌باشندکه بایت‌هایی هستند ( یک یا چند بایت ) که توسط استاندارد خود ، تعریف می‌شوند تا معین کنند چه کاراکتری را با کمک فونت‌های متناظر خود ( که دارای تعریف کارست مورد استفاده در متن باشند ) نمایش دهند ( دکدینگ ) و یا کاراکتر وارد شده در برنامه را به بایت یا بایت‌های کارست استاندارد تعیین شده ترجمه کنند ( انکدینگ ) . سپس پردازنده‌های متنی ( ویرایشگرهای متن ) این امکان را به کاربر می‌دهند تا با استفاده از کیبورد خود یا کیبورد مجازی و مجموعه‌های کاراکتری ( کاراکترست ) که در برنامه ، موجود هستند و تعریف شده‌اند ، کاراکتری را وارد نماید . کاراکتر به هر نشانه‌ای گفته می شود که مورد پردازش متنی قرار می‌گیرد . مثلاً « آ » ، « ۲ » ، « 5 » ، « i » و « @ » ، همگی کاراکتر هستند . برخی کاراکترها حرفی ( مثل حروف فارسی یا انگلیسی ) برخی کاراکترها عددی ( مثل اعدادی که به زبان فارسی یا انگلیسی نوشته می‌شوند ) و برخی کاراکترها گرافیکی هستند ، مثل @ ، # ، * و البته بسیاری از کاراکترهای دیگر که در تعریف‌های کارست‌های Unicode ( یونیکد ) نظیر UTF-8 و مخصوصاً UTF-16 تعریف شده‌اند مثل ایموجی‌ها وجود دارند و می‌توان از آنها استفاده نمود ( در کارست یا کاراکترست‌های یونیکد ما مجاز به استفاده از کاراکترهای بی‌شماری هستیم ) ، در حالی که در تعریف کارست سازمان استاندارد سازی ملی آمریکا ANSI که این کارست ، همان اسکی یا ازکی ( ASCII ) می‌باشد ، تنها حروف و اعداد انگلیسی و علائم و کاراکتر های گرافیکی محدود به همراه کاراکتر های سفید ( مثل فضای خالی یا همان اسپیس Space یا سطر جدولی Tab ) می‌توانند ذخیره شوند و به نمایش در بیایند

پس اول بررسی کنید که کامپایلر شما مبتنی بر کدام استاندارد است ، چرا که هر برنامه‌ای که می‌نویسید را باید در همان کاراکترست متناظر با کامپایلر خود در یک فایل متنی با پسوند c ذخیره نمائید . پس فراموش نکنید : متون معمولی در فایل های txt ذخیره می‌شوند و شما مجاز به استفاده از آن برای نوشتن برنامه‌های C نیستید و باید حتماً پسوند فایل خود را برای ذخیره c بگذارید تا کامپایلر آن را از شما بپذیرد

مثل :


test.c
Hello.c

و نه :

test.txt
Hello.txt

دستور زبان سی

[ویرایش]

شما در زبان سی ، همانند هر زبان دیگری در یک محدوده مجاز ، قادر به برنامه‌نویسی خواهید بود . در زبان سی شما یا از پیش‌پردازنده ها Preprocessors استفاده می‌نمائید یا حکم ـی Statements را می‌نویسید که با سمی‌کالن « ; » نقطه ویرگول در انگلیسی پایان می‌یابند که معمولاً داخل تابع هستند یا اینکه طی نوشتن برنامه ، داخل یا خارج از بلوک داده‌ها Data هایی را ایجاد می کنید که به مجموعه آنها عبارت Expressions گفته می شود که با کمک عملگرها ( Operators ) ی متناظر ، مورد مقایسه یا پردازشی قرار می‌دهید ( اغلب هم باید با دستورها ، امکان پردازش فراهم می شود ) و از آنها استفاده می‌کنید . شما داده‌ها را یا ایجاد می کنید یا از سیستم دریافت می نمائید ؛ مورد پردازش قرار می دهید و سپس با تابع‌های کتابخانه‌ای آنها را صادر می نمائید . قسمت دیگری که اختیاری است و توسط کامپایلر نادیده گرفته می‌شود یادداشت‌های شما Comments هستند

همچنین قبل از آغاز توضیحات بیشتر ، بهتر است یک مطلب را روشن نمائیم . در کتاب‌های آموزش زبان سی ( چه فارسی و چه انگلیسی ) مدام از دو گروه از عناصر زبان ، به نام ثابت استفاده می‌کنند که ما این دو گروه را از هم جدا می‌نمائیم . یک گروه ، ثابت‌های پایه‌ای هستند که بدین معنی خواهند بود که جزء پایه‌ها و ارکان زبان حساب می شوند و به صورت ثابت در زبان تعریف شده‌اند و داخل متن منبع ( Source Code ) برنامه ( Program ) نوشته می‌شوند . ثابت‌های عددی مثل « 2 » یا « 564 » یا ثابت های حرفی مثل « 'c' » و ثابت‌های رشته‌ای مثل « " This is A String " » همگی ثابت‌های پایه‌ای می‌باشند . اما دسته دیگری از ثابت‌ها وجود دارند که به آنها ثابت مقداری خواهیم گفت که داده‌هایی هستند که به دستور شما ایجاد می‌شوند تا طی کامپایل و اجرای خروجی شما ، مقدار و موجودی داخل آن داده‌ها هرگز تغییر نیابند ( که در مبحث مربوط به خود ، مفصلاً به آن خواهیم پرداخت )

ما همواره در برنامه‌نویسی ، داده‌هایی را ایجاد می‌نمائیم و یا داده‌ها و سیگنال‌هایی را از ورودی‌های سیستم دریافت می‌کنیم و داده‌ها را به کمک دستورهای شرطی ، حلقه‌ها و عملگرهای منطقی و محاسباتی ، داخل تابع‌ها مورد پردازش قرار می‌دهیم و سپس با توجه به نیاز خود به کمک دستورات و احکام آن زبان ( تابع‌های از پیش تعریف شده در زبان C ) آن را به یک خروجی خواهیم فرستاد . در زبان C ، کنترل تمام برنامه بر عهده تابع اصلی برنامه که در برنامه‌های سطح بالا تابع main می‌باشد ( با همین نام یعنی تابع main ) ؛ اما در زبان C تابع‌ها خود نیز دارای نوع داده هستند و خود نیز داده محسوب می‌شوند ؛ بنابراین همواره در برنامه‌نویسی ، طی نوشتن برنامه‌های متداول کاربردی ، جانبی ، خدماتی ، ابزارها و ... داده یا داده‌هایی را ایجاد نمائیم که داده‌های پایه همگی متغیر نامیده می‌شوند ؛ چرا که هر زمان در برنامه می‌توانیم مقدار آن را تغییر دهیم یا به سیستم عامل یا سخت‌افزار اجازه تغییر آن را بدهیم ( یا اینکه آن را ثابت کنیم و از قابلیت تغییر یک متغیر جلوگیری نمائیم ) پس هر داده‌ای در زبان سی ، متغیر حساب می شود . هر متغیر دارای یک نام یا به اصطلاح برنامه‌نویسی ، شناسه Identifier خواهد بود به علاوه مقدار Value و موجودی‌ای که به آن اختصاص می‌دهیم و هر متغیر باید نام اختصاصی خود را داشته باشد ( یعنی دو یا چند متغیر نمی توانند شناسه یکسانی داشته باشند ) . در متغیرهای عددی ، عدد متناظر با نوع داده را می‌نویسیم ( که باید در طیف قابل ذخیره در نوع داده باشد ) اما هر گاه بخواهیم یک کاراکتر یا مجموعه‌ای از کاراکترها ( رشته String ) را وارد نمائیم باید به ترتیت : از دو علامت کوت ' و یا دابل کوت " استفاده نمائیم . مثلاً « 'L' » یک کاراکتر را ایجاد می‌نماید و « " This is a String " » یک رشته را

آغاز

[ویرایش]

پیش از آغاز مبحث برنامه‌نویسی باید بگوئیم زمانی که برنامه خود را می‌نویسید و می‌خواهید آن را با انکدینگ اسکی یا ازکی در یک فایل c ذخیره نمائید ( اگرچه بعدها که مسلط شدید می توانید فایل های سرآیند را که با پسوند h. ذخیره می‌شوند را هم بنویسید ) یا اگر کامپایلر شما جدید است و می خواهید آن را با انکدینگ UTF-8 ذخیره نمائید باید بدانید که تنها مجاز به استفاده از حروف a تا z و از A تا Z و ارقام و اعدادی که از 0 تا 9 ایجاد شده‌اند به همراه :

'! , '' , " , # , % , & , ( , ) , * , + , - , = , . , , , ; , < , > , [ , ] , / , \ , ^ , _ , { , } , |

و البته فضاهای سفید شامل فاصله «  » Space ، شکست خط :

«

»

و tab های افقی و عمودی خواهید بود ( سطر یا ستون‌های جدولی ) به علاوه کاراکترهای UTF-8 در نوع داده کاراکتر و متون داده‌هایی که تعریف می کنید . ضمن اینکه تنها می‌توانید روی داده‌هایی که ایجاد و تعریف کرده‌اید پردازشی انجام دهید ( در غیر این صورت برای کامپایلر وجود ندارد و نامفهوم است ) و هر داده باید دارای یک نام و یک مقدار باشد ، دستورها و حکم‌ها فقط می‌توانند با آرایش خاصی نوشته شوند و نمی‌توانید آنها را پس و پیش کنید یا چیزی را از آنها کم کنید . در واقع شما فقط مجاز هستید تا در ایجاد نام داده‌ها که متغیرها هستند و ممکن است این متغیر نام تابعی که میخواهید تعریف کنید باشد و مقدار و موجودی متغیرها را تغییر دهید و با ترکیب منظم بخش‌های مختلف برنامه ، آن طور که میخواهید ، برنامه خود را بنویسید . در غیر این صورت کامپایلر برنامه شما را کامپایل نخواهد کرد و خطا خواهد گرفت و به شما خواهد گفت که خطای برنامه نوشته شده شما از کجاست

حال می پردازیم به خود برنامه‌نویسی . شما در داده کاراکتری فقط می‌توانید یک کاراکتر را ذخیره کرده و مورد پردازش قرار دهید . اما در ایجاد یک رشته شما هر آنچه را در داخل دو دابل کوت « " » قرار داده باشید ذخیره خواهد گردید . ضمن اینکه شما با نوشتن کدهایی داخل رشته که متغیرهای استاندارد C هستند می‌توانید کاراکترهایی که امکان تایپ را در استاندارد C ندارند ( نظیر سطر جدولی Tab ) بنویسید تا در برنامه کامپایل شده خروجی به کاراکتر مورد نظر شما تبدیل شوند . خارج از دو علامت کوت یعنی « ' » که برای ذخیره کاراکتر می‌باشد و یا دو علامت دابل کوت ، یعنی « " » که برای ذخیره رشته می‌باشد ؛ هر گاه از علامت شارپ « # » استفاده نمائید ، مجاز و مجبور به نوشتن یک پیش‌پردازنده هستید . پیش‌پردازنده‌ها از منظر کامپایلر بر هر عمل و اقدام دیگری اولویت دارند . از پیش‌پردازنده‌ها برای شرط کردن اجرای بخشی از برنامه و تکرار آن یا جا به جایی کدهای برنامه ، ایجاد داده‌هایی برای تعیین زمان ، نسخه سیستم عامل و ... و یا پیوست فایل های سرآیند که در آنها تابع‌های کتابخانه‌ای و ماکروها وجود دارند ، استفاده می‌نمائیم . هر گاه یک فایل سرآیند را ضمیمه نمودید ، با نوشتن تابع‌های کتابخانه‌ای و یا ماکروهای آن فایل سرآیند ، مجاز و مجبورید که از آن استفاده نمائید و نمی‌توانید داده دیگری را ( حتی یک تابع را ) با هم همان نام ایجاد کنید . همین مسئله در مورد کلید واژه‌های زبان سی نیز صادق می‌باشد . واژه های زیر همگی کلیدواژه های زبان سی محسوب می شوند :

auto
break
case
char
const
continue
default
do
double
else
enum
extern
float
for
goto
if
int
long
register
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while


و شما نمی‌توانید برای نام متغیرها و داده‌های خود ( شناسه‌ها ) از آنها استفاده کنید ضمن اینکه با نوشتن هر کدام از این کلیدواژه‌ها شما موظف به استفاده از آن هستید که باید در جای معین و مجاز خود باشد و هر کلیدواژه علمکرد خاص خود را دارد که باید به همان گونه از آن استفاده نمائید .ضمناً برخی کامپایلرها تعدادی کلید واژه دیگر همچون _asm_ را به زبان سی اضافه نموده اند که جهت یادگیری آنها باید به راهنمای آن کامپایلر و مراجع دیگر ( برای آن زبان برنامه‌نویسی یا کد زدن ) ، رجوع کنید . ما در این کتاب تنها اشاره کوچکی به آنها می‌نمائیم ، چرا که مثلاً همین کلید واژه asm برای نوشتن کدهای اسمبلی در داخل متن سی می باشد ( که به صورت asm__ یا _asm_ و یک آکولاد باز و بسته نوشته می‌شود که کدهای اسمبلی را داخل جفت آکولاد باز و بسته می‌نویسیم ) و اگر بخواهیم مبحث این کلید واژه‌ها را باز نمائیم ، باید داخل همین کتاب ، علاوه بر زبان سی ، زبان های اسمبلی ، فورترن ، پاسکال و ... را نیز بنویسیم ( که اینها هر کدام زبان مجزایی هستند ولی کامپایلرهای سی جهت عرضه سهولت و قدرت بیشتر ، امکان تلفیق کدهای سی را با زبان‌های دیگر مخصوصاً اسمبلی می‌دهند ) ضمناً اگر در یک سیستم عامل شبه‌یونیکس ، برنامه‌نویسی می کنید بهتر است برای نام و شناسه متغیرهای خود از زیرخط « _ » برای اولین کاراکتر آن استفاده نکنید . تابع‌ها و ماکروهای بی شماری در کامپایلرهای این سیستم عامل‌ها از قبل با _ تعریف شده‌اند که ممکن است به اشتباه نامی را انتخاب کنید که تابع یا ماکروی یک سیستم عامل یونیکس باشد

پس دانستیم که اگر به طور مثال بنویسیم long ، که یک متغیر عددی را ایجاد می‌کند ، باید درست پس از آن حتماً یک نام را بنویسیم ( و نه دستور یا حکم و هر چیز دیگری ) که خارج از نام کلیدواژه‌ها و یا هر شناسه از پیش تعریف‌شده دیگری در متن برنامه ، باشد ( مثلاً در صورت ضمیمه کردن فایل‌های سرآیند ؛ خارج از نام و شناسه توابع فایل یا فایل‌های سرآیند ضمیمه شده ) باشد . ترتیب نوشتن نیز جزء دستورات زبان سی می باشد . مثلاً از if که از معنای انگلیسی آن هم پیداست ( به معنی « اگر » ) برای شرط کردن اجرای یک قطعه کد استفاده می کنیم . اما گاهی گزینه‌های ما در شرط کردن زیاد هستند ، آنگاه می‌نویسیم else if ، یعنی « و اگر نه » یا « در غیر این صورت اگر » . پس نمی‌توانیم بنویسیم : if else ! همچنین دقت کنید که زبان سی مانند بسیاری از زبان های دیگر به کوچک یا بزرگ بودن حروف حساس است که به این گونه زبان‌ها Case Sensitive می‌گویند یعنی IF همان if نمی باشد . از طرفی وجود فضاهای سفید ، ضروری هستند . شما باید فاصله بین کلمات و حروف و علائم را رعایت نمائید . اضاضه نوشتن فضاهای سفید ، توصیه نمی شود اما اگر زیاده روی کنید ، بهتر از این است که فاصله یا خطوط شکسته را نادیده بگیرید و کدها را پشت سر هم بنویسید ! مثلاً elseif غیر استاندارد و برای اکثر کامپایلرها ناخوانا می‌باشد

همچنین ، هر گاه خارج از رشته از دو علامت بک‌اسلش Backslash ( ممیز برعکس ) یعنی « // » استفاده نمائید ، هر متنی که در داخل همان خط ، پس از آن قرار بگیرد به عنوان یادداشت برنامه‌نویس محسوب شده و نادیده گرفته می‌شود ؛ به همین شکل هر متنی که خارج از دو دابل کوت ( " ) بین « */ » و « /* » قرار بگیرد به عنوان یادداشت چند خطی محسوب شده و هر آنچه نوشته شده باشد نایده گرفته خواهد شد . یادداشت گذاری شیوه مناسبی برای خودتان و یا کاربر دیگر است که میخواهد کد شما را بخواند ( و به طور مثال شریک و همکار برنامه‌نویس شماست ) که طی آن شما پس از // می‌توانید هر آنچه که میخواهید در یک خط بنویسید که به ان یادداشت تک خطی می‌گویند . یعنی شما مجاز نیستید خط را بشکنید و در خط بعدی یادداشت بگذارید یا بقیه یادداشتتان را بنویسید ، چون یادداشت شما که معمولاً و به صورت معقول ، خارج از زبان سی می باشد ، وارد متن برنامه سی می شود و شما چیزهایی نوشته‌اید که برای کامپایلر نامفهوم هستند . اگر مایل بودید در چند خط کامنت بگذارید علامت */ را بگذارید و تا جایی که شما علامت /* را وارد نکرده باشید ، کامپایلر کل نوشته های شما را نادیده می گیرد

مثال :

Comment یادداشت
Code 1 // This is a single line comment
Code 2 /* This


is another
comment , which is multiline */ Code 3

در مثال اول نوشته This is a single line comment یک یادداشت است در یک خط نوشته می‌شود و از نوع تک‌خطی می‌باشد و ما مجاز نیستیم تا یادداشت خود را در خط یا خطوط بعدی بنویسیم . اما یادداشت بعدی در چند خط نوشته شده است که پس از یک کد ( Code 2 ) ، با توجه به علامت های متناسب خود ، مجاز به نوشتن یادداشت خود در چند خط بودیم که بلافاصله بعد از اتمام یادداشت نیز ، کد دیگری را ( Code 3 ) نوشته‌ایم که اگر این کد را داخل کامنت یا یادداشت می‌نوشتیم ، کامپایلر ، آن را نادیده می‌گرفت ؛ چرا که مطابق با مطلبی که بیان نمودیم ، یادداشت‌ها ، هر چه که باشند توسط کامپایلر نادیده گرفته می‌شوند ؛ البته بهتر است همیشه برنامه خود را خوش‌فرم بنویسید ؛ یعنی کد ۲ را در خط بالاتر و نه درست قبل از یادداشت و کد ۳ را در خط پائین‌تر و بعد از یادداشت بنویسید ؛ به مرور ، در این کتاب ، شیوه نگارش خوش‌فرم که به خود شما و خواننده کد و برنامه شما کمک می‌کند را فرا خواهید گرفت

مطلب بعدی نیز اینکه ، هر گاه حکمی را نوشتید باید حتماً در انتهای آن از علامت و عملگر ( Operator ) سِمی‌کالُن « ; » استفاده نمائید که به آن عملگر Terminator یا پایان‌دهنده می‌گویند و در زبان‌های خانواده سی و مشابه با سی به عنوان پایان یک حکم به کار می‌رود . این عملگر به کامپایلر می‌فهماند که باید به سراغ دستور بعدی برود و این قسمت از کد که تا قبل از سمی‌کالن ( Semicolon ) « ; » نوشته شده ، مجزا از خط و کد بعدی بوده و کامپایلر با خواندن کاراکتر سمی‌کالن « ; » در برنامه که عملگر پایان‌دهنده می‌باشد ، کد یا کدهای نوشته شده پیش از آن را به اجرا در می‌آورد . ایجاد داده‌ها ، اجرای عملیات های مختلف مثل ریاضی بر روی داده‌ها و همین طور توابع کتابخانه‌ای و فراخوانی تابع‌هایی که خودتان تعریف کرده‌اید همگی مستلزم استفاده از علامت و عملگر پایان‌دهنده می‌باشند که گاهی مورد فراموشی قرار می‌گیرد و باعث گرفتن خطا توسط کامپایلر می‌گردد . استفاده بیجا از آن نیز باعث خطا گرفتن کامپایلر از شما می‌شود ؛ چون حکم استانداردی را که نیاز به پایان‌دهنده داشته باشد ، در متن منبع برنامه نمی‌بیند ( چون وجود ندارد ) پس از شما خطا می‌گیرد . در ابتدا شاید این مسئله را مرتباً فراموش کنید ولی با تمرین‌های مکرر به خوبی عادت می‌کنید تا هرگاه حکمی را نوشتید ، در پایان آن یک سمی‌کالن را قرار دهید