بخش اول زبان c یک زبان سطح میانی است .
کلمات کلیدی شاخص در این زبان عبارتند از auto do goto signed void break double if sizeof while case else int static char enum long switch const extem register typedef continue float returm union default for short unsigned انواع داده در c : زبان c شامل شش نوع اصلی می باشد که عبارتند از void ,enum double , float , int , char.
در زبان c برخی از انواع داده ها می توانند با عباراتی نظیر long short , unsigned , signed ترکیب شده ونوع داده أی دیگری را بوجود آورند.
هیچکدام از این عبارات نمی توانند با نوع داده أی void ترکیب شوند.
نوع داده أی void یک نوع داده تهی است یا به عبارت دیگر هیچ نوعی ندارد .
جدول زیر انواع داده ها و حالات مختلف ترکیب این عبارات ذکر شده با انواع داده ها را نشان می دهد .
نوع داده أی long با long int یکی است.
قوانین تعریف متغیرها نام متغیر شامل حروف a تا z بزرگ یا کوچک ، a تا z ،ارقام 0 تا 9 و خط ربط () است .
کاراکتر شروع نام متغیر نباید یک عدد باشد .
حداکثر تعداد کاراکتر های نام متغیر 32 کاراکتر است.
int var 1 , var2; char ch; unsigned int i; مقدار دهی به متغیرها به هنگام تعریف متغیر int b,c,d=4,e; char ch=’a’; 2-پس از تعریف b=0; c=d=2; در c مقدار دهی اولیه به متغیرها توسط کامپایلر انجام نمی گیرد .
با استفاده از کلمه کلیدی const می توانیم ثابتهایی تعریف کنیم که مقدار آنها در طول اجرای برنامه ثابت است .
نحوه تعریف این متغیر ها بصورت زیر است : لیست متغیرها نوع const const int a=10, b=20; اگر const ها را مقداردهی اولیه نکنیم از سوی کامپایلر پیغام خطا صادر می شود .
عملگر ها نمادهای هستند که برای انجام اعمال خاصی مورد استفاده قرار می گیرند .
عملگرها به چهار دسته محاسباتی ، رابطه أی ، منطقی و بیتی تقسیم می شوند .
عملگر های محاسباتی عملگر نام مثال + جمع و مثبت یکانی x+y , +x - تفریق و منهای یکانی x-y, -x * ضرب x*y / تقسیم x/y % باقیمانده تقسیم x%y -- کاهش یک واحد x--,--x ++ افزایش یک واحد x++,++x دستور ++x یا x++ معادل دستور x=x+1 است دستور x-- یا –x معادل دستور x=x-1 است اگر در یک عبارت از عملگر های افزایش و کاهش یک واحد استفاده کنیم به کاربردن این عملگر ها در قبل و بعد از عملوند مربوطه با یکدیگر متفاوت است .
اگر عمگرهای ++ و -- نظیر بعد از عملوند قرار گیرند مقدار فعلی عملوند مورد استفاده قرار گرفته و سپس عملگرها بر روی آن عمل می کنند a=4; b=a++; ابتدا مقدار 4 به متغیر b نسبت داده میشود و سپس مقدار a یک واحد افزایش یافته و 5 می شود .
اگر عملگرهای ++و -- قبل از عملوند مربوطه قرار گیرند پس از افزایش یا کاهش یک واحد به آنها مقدار جدید در عبارات مورد استفاده قرار می گیرند.
a=5; b=++a; ابتدا مقدارa یک واحد افزایش یافته و سپس بهb نسبت داده می شود.
ابتدا مقدارa یک واحد افزایش یافته و سپس بهb نسبت داده می شود.
تقدم عملگرهای محاسباتی عملگرهای محاسباتی – انتسابی عملگر های رابطه أی عملگر های منطقی بر روی عملوند های منطقی عمل می کنند .
در زبان c ارزش نادرستی (false) با مقدار صفر و ارزش درستی (true) با مقدار غیر صفر مشخص می شود .
عملگرهای بیتی این عملگر ها فقط بر روی متغیر های نوع int , char عمل می کنند و روی متغیرهایی از سایر نوعها مانند double , float و .
.
قابل اجرا نیستند .
نحوه کاربرد عملگر های شیفت به صورت زیر است : هر انتقال معادل راست به تقسیم کردن مقدار متغیر به 2 و هر انتقال به چپ معادل ضرب کردن در 2 است .
در صورت از دست دادن اطلاعات واقعی در شیفت به چپ یا راست مساله ضرب در 2 شدن با تقسیم بر 2 شدن صدق نمی کند.
عملگر ~ در متغیر کلیه بیتها را نقیض می کند یعنی بیت صفر را تبدیل به یک کرده و بیت یک را تبدیل به صفر می نماید .
عملگر ?: نحوه کاربرد: ابتدا exp 1 ارزیابی می شود اگر دارای ارزش true باشد مقدار exp2 پس از ارزیابی در متغیر قرار می گیرد و گرنه مقدار exp3 ارزیابی می شود و نتیجه به متغیر منتقل می شود .
x=(a>b)?5:10; در مثال فوق چنانچه a از b بزرگتر باش مقدار 5 و در غیر اینصورت مقدار 10 به x نسبت داده می شود .
عملگر های *,& عملگر & یک عملگر یکانی است که آدرس عملوند خود را مشخص می کند نحوه کاربرد به صورت زیر است .
نام عملوند & عملگر * یک عملگر یکانی است که محتویات یک آدرس حافظه را مشخص می کند عملگر sizeof جهت محاسبه طول یک نوع و یا یک متغیر به کار می رود .
نحوه کاربرد .
);متغیر یا نوع ) sizeof ;متغیر sizeof تقدم عملگر ها در حالت کلی تبدیل انواع داده أی به یکدیگر معمولاً در دو حالت انجام می شود 1- در عبارات 2- در حکم انتساب وقتیکه متغیرها با نوع های مختلف در یک عبارت با یکدیگر ترکیب می شوند با تبدیل نوع صورت می گیرد نوعهای با طول کوچکتر به نوعهای با طول بزرگتر تبدیل می شود در حکم انتساب نیز ممکن است تبدیل نوع داده ای است صورت گیرد .
در صورت تبدیل نوع ، ممکن است اطلاعاتی از بین برود که باید در نتیجه حاصل احکام انتساب دقت کافی به خرج داد .
در c چنانچه انواع گوناگون (به غیر از اشاره گرها) را به یکدیگر نسبت دهیم پیغام خطایی صادر نمی شود.
وقتی نوع بزرگتری به نوع کوچکتر انتساب داده می شود قسمتی از اطلاعات از بین می رود .
ساختار برنامه های c هر برنامه در زبان c دارای یک تابع به نام main() است .
در زبان c توابع را به دو صورت می توان تعریف نمود .
حالت اول : توابع قبل از تابع main() تعریف شوند .
func() { .
} .
main(){ .
} حالت دوم : عنوان (header) توابع را قبل از تابع main() تعریف کنیم و خود توابع را بعد از تابع main () قرار دهیم func(); .
} func(){ .
} تعریف یک تابع در داخل تابع دیگر امکان پذیر نیست ولی هر تابع می تواند یک یا چند تابع دیگر را فراخوانی کند.
در زبان c در هر جای برنامه می توان متغیر ها را تعریف کرد هر بلاک برنامه با علامت }شروع و با علامت { پایان می یابد.
جدا کننده دستورات ; است .
می توان چند دستور را در یک سطر نوشت.
می توان یک دستور را در چند سطر ادامه داد .
چنانچه نوع خروجی یک تابع تعیین نشود به طور پیش فرض از نوع int در نظر گرفته می شود.
چند تابع ورودی و خروجی تابع printf شکل کلی : “, رشته های ثابت ، کاراکترهای کنترلی و فرمت های خروجیprintf(“ ;(اطلاعات خروجی اطلاعات خروجی با فرمت مشخص شده در قسمت فرمت به خروجی منتقل می شوند.
کاراکترهای که برای تعیین فرمت خروجی مورد استفاده قرار می گیرند با کاراکتر % شروع می شوند وکاراکترهای کنترلی با کاراکتر 1 شروع می شوند .
خروجی تابع printf تعداد کاراکترهایی است که توانسته است بر روی خروجی ارسال کند.
برخی از کاراکترهای فرمت برخی از کاراکترهای کنترلی تعیین طول میدان در تابع printf() طول میدان به صورت n.d است که بعد از علامت % و قبل از کاراکتر فرمت ذکر می شود.
در اعداد اعشاری ممیز شناور ، طول میدان (حداکثر تعداد ارقام با در نظر گرفته نقطه اعشار)و d تعداد ارقام اعشاری را مشخص می کند.
printf(“\n%8.1f%16.4f,”,3.0,123.1234567); bbbbb3.0bbbbbbbb123.1235 چنانچه n ( حداکثر طول رقم ) از مجموع عدد تعیین شده برای d ، تعداد ارقام صحیح خود عدد و یک کاراکتر نقطه اعشار کمتر باشد در نظر گرفته نمی شود .
به مثال زیر توجه کنید .
printf(“%4.4f” , 123.957); 123.9570 اگر برای اعداد اعشاری قسمت d حذف گردد و یا اینکه کلاً طول میدان را مشخص نکنیم عدد مورد نظر با شش رقم اعشار چاپ می شود printf (“%5f”,123.957) ; یا printf (“%f”, 123.957); 123.957000 گرد کردن عدد اگر تعداد ارقام قسمت اعشار بیشتر از عدد مشخص شده در قسمت d باشد قسمت اعشار گرد می شود و تبعاً ممکن است بر روی قسمت صحیح نیز تاثیر گذار باشد .
به مثال های زیر توجه کنید : printf (“%5.2f”,12.957); 12.96 printf(“%5.0f” , 12.54); 13 اگر طول میدان عددی مثبت باشد مکان عددی که باید چاپ شود از سمت راست تنظیم میشود و اگر طول میدان عددی منفی باشد مکان عدد از سمت چپ تنظیم خواهد شد .
مثالهای زیر این نکته را نشان می دهند .
printf(“%7.2f”,12.5); bb12.50 printf(“%-7.2f”,12.5); 12.50bb در چاپ اعداد صحیح چنانچه در قسمت d نیز عددی قرار دهیم از بین d,n هر کدام که بزرگتر باشند برای طول میدان درنظر گرفته میشوند .
به مثال زیر توجه کنید : printf(“%6.3d”,1451); b1451 اگر d از n بزرگتر باشد به جای فضای خالی کاراکتر صفر چاپ می شود.
printf(“%3.6d”,1451); 001451 در مورد رشته ها n حداقل طول میدان و d حداکثر کاراکتر های قابل چاپ می باشد .
printf(“%7.3s”,”hello”); bbbbhel چنانچه n از d کوچکتر باشد هیچکدام در نظر گرفته نمی شوند و تمام رشته چاپ می شود .
printf(“%1.3s”,”hello”); hello در تنظیم مکان مقداری که قرار است چاپ شود منفی یا مثبت بودن طول میدان همانطور که گفته شد تاثیر گذار است تابع scanf() جهت خواندن اطلاعات از ورودی استاندارد مورد استفاده قرار می گیرد .
شکل کلی : scanf(“کاراکتر های فرمت “ , آدرس متغیرها); کاراکترهای فرمت نوع اطلاعاتی را که باید خوانده شوند را مشخص می کند .
آدرس متغیر ها مشخص کنند های محل هایی از حافظه هستند که اطلاعات ورودی باید در آن محلها باید قرار گیرند آدرس متغیر ها را با عملگر & مشخص می کنیم کاراکتر های فرمت در تابع scanf همانند تابع printf می باشد .
در ورود اطلاعات می توانیم آنها را با فاصله (blank) ، کلید enter یا tab جدا کنیم خروجی این تابع تعداد مقادیری است که از ورودی خوانده است .
int year; scanf(“%d” , & year); فرمان cout از cout می توانیم جهت چاپ در خروجی استفاده می کنیم.
شکل کلی : متغیر یا “رشته های ثابت ، کاراکترهای کنترلی” cout int i=3; cout فرمان cin از cin نیز جهت دریافت مقدار از ورودی استفاده می شود..
شکل کلی : cin از کاراکترهای کنترلی و کاراکترهای فرمت نمی توان در این فرمان استفاده کرد .
int i; float f; cin جهت استفاده از فرامین cin , cout باید فایل h.iostream در ابتدای برنامه include شود.
خواندن یک کاراکتر از ورودی تابع getch() شکل کلی : =getch(); متغیر پس از آن که کنترل اجرای برنامه به تابع getch() رسید برنامه منتظر فشار دادن کلیدی از صفحه کلید می شود .
تابع getche() مانند تابع getch() می باشد با این تفاوت که در این تابع پس از اخذ ورودی آن را روی صفحه نمایش چاپ می کند شکل کلی : ()=getche متغیر تابع getchar() عمل این تابع مانند دو تابع قبل است با این تفاوت که در این تابع پس از وارد نمودن کلید مورد نظر باید enter زده شود .
نوشتن یک کاراکتر در خروجی علاوه بر printf() دو تابع دیگر نیز بکار می رود که عبارتند از putchar() putch() شکل کلی putch(متغیر); putchar(متغیر); بخش دوم ساختارهای کنترلی و حلقه های تکرار اگر بخواهیم بعضی از دستورات تحت شرایط خاصی اجرا شوند و یا تعدادی از دستورات چندین مرتبه اجرا شوند و یا در شرایط خاصی تکرار شوند ، از ساختارهای تکرار و تصمیم استفاده می کنیم ساختار های تکرار تحت شرایط خاصی امکان اجرای مکرر دستور یا مجموعه أی از دستورات را فراهم می کنند ساختار for در مواردی مفید است که تعداد دفعات تکرار دستورات معلوم باشد دارای یک شمارنده است که تعداد دفعات اجرای دستورات داخل حلقه را شمارش می کند شمارنده حلقه می تواند دارای مقادیر مثبت ، منفی ، صحیح و یا اعشاری باشد .
شکل کلی : for (مقدار اولیه = شمارنده ; شرط حلقه ; گام حرکت شمارنده )دستور; مقدار اولیه مشخص می کند که شمارنده ، از چه مقداری شروع می شود .
شرط حلقه مشخص می کند که مجموع دستورات داخل حلقه تکرار ، تحت چه شرایطی اجرا شوند.
گام حرکت شمارنده حلقه مشخص می کند که در هر بار اجرای دستورات داخل حلقه، چه مقداری به شمارنده حلقه اضافه شود.
گام حرکت می تواند مثبت ، منفی ، صحیح یا اعشاری باشد.
دربین هر یک از پارامترها در حلقه for ، علامت ; قرار می گیرد هر کدام از پارامترها می توانند وجود نداشته باشند و می توان حلقه های تکرار بینهایت تولید نمود for(i = 0; i printf(“\n the value of i is : %d: , i); j=11; for (;j;) { j%=2; j--; } ساختار while در مواقعی که تکرار انجام دستورات به شرط خاصی وابسته است کاربرد دارد .
while (شرط ) دستور ; دستور می تواند مرکب باشد یعنی بین }و{ قرار بگیرد وقتی کنترل به ساختار while رسید شرط تست می شود .
اگر این شرط دارای ارزش منطقی درست باشد دستور یا دستورات اجرا می گردد و در غیر اینصورت کنترل اجرا به اولین خط بعد از بدنه حلقه می شود چنانچه شرط حلقه در داخل حلقه نقض نشود دستورات حلقه بینهایت بار اجرا می شوند.
ساختار do..while برای تکرار اجرای مجموعه دستورات در شرایط خاص کاربرد دارد .
شکل کلی : do { مجموعه دستورات }while (شرط ); شرط حلقه در انتها تست می شود وقتی کنترل اجرا به ساختار do while رسید دستورات داخل حلقه اجرا می شوند و سپس شرط ذکر شده تست می گردد ،چنانچه این شرط برقرار باشد مجموعه دستورات داخل حلقه مجددا اجرامی شوند و گرنه کنترل اجرا از حلقه خارج می شود در ساختار حلقه do..while مجموعه دستورات حداقل یکبار اجرامی گردند .
چنانچه بدنه do..while تنها شامل یک دستور باشد میتوانیم }و{ را حذف کنیم ولی در بقیه شرایط وجود آنها ضرورت دارد .
حلقه های تکرار بینهایت با هر یک از ساختارهای تکرار do..while , while , for میتوان حلقه های بینهایت ایجاد کرد .
در ساختارهای do..while , while می توان بجای شرط حلقه از 1 به معنی ارزش درستی ، استفاده کنیم و یا از شرطی استفاده کنیم که در تمام شرایط ارزش آن درست باشد(به عنوان مثال 2 جهت خروج از حلقه بینهایت در حین اجرا باید از کلید ctrl+ break استفاده کنیم دستور break در ساختارهای تکرار این دستور کنترل اجرای برنامه را به اولین دستور پس از حلقه تکرار منتقل می کند دستور continue در حلقه های تکرار موجب انتقال کنترل به ابتدای حلقه تکرار می شود.
پس از اجرای این دستور کنترل به ابتدای حلقه برگشته و شرط حلقه تست می گردد که در صورت بر قرار بودن شرط ، مجموعه دستورات داخل حلقه مجددا تکرار می شوند و گرنه کنترل از حلقه تکرار خارج خواهد شد ساختار های تصمیم اگر بخواهیم تحت شرایط خاصی در برنامه تصمیمی را اتخاذ کنیم بطوری که تحت شرایطی ، مجموعه دستوراتی اجرا شوند و مجموعه أی دیگر اجرا نشوند ، از ساختار های تصمیم استفاده می کنیم ساختار if/ else (ساختار شرطی انتقال کنترل ) موجب می گردد تا تحت شرایطی ، مجموعه أی از دستورات اجرا شده و یا از اجرای این مجموعه دستورات صرفنظر شود .
شکل کلی : if (شرط) دستور ; if (شرط ) دستور 1 ; else دستور 2; دستورات می توانند مرکب باشند .
وجود else در ساختار if اختیاری است .
وقتی کنترل اجرا به ساختار if رسید شرط تست می شود و در صورت برقرار بودن ، دستور بعد از آن اجرا می شود و در غیر اینصورت در صورت وجود بخش else دستورات این بخش اجرا می شود استفاده از ساختار if بصورت لانه أی (تو در تو ) نیز امکان پذیر است که در این صورت اولین else به آخرین if مربوط می شود.
ساختار else if اگر بخش else مربوط به ساختار if خود یک ساختار if باشد می توان جهت کوتاهتر کردن برنامه و خوانایی بهتر آن را ساختار else if استفاده کرد.
ساختار goto ( انتقال غیر شرطی کنترل ) سبب انتقال کنترل برنامه ، از نقطه أی به نقطه دیگر می گردد .
شکل کلی : goto برچسب; برچسب همانند یک متغیر نامگذاری میشود و به : ختم می گردد استفاده از goto خوانایی و ساخت یافتگی برنامه را کاهش میدهد labl : ch = getch(); putch(ch); goto labl; ساختار switch زمانی که بر اساس مقادیر مختلفی برای یک عبارت می خواهیم مجموعه دستورات خاصی انجام گردد از این ساختار استفاده می کنیم .
نحوه کاربرد : switch (عبارت ) { case :مقدار1 مجموعه دستورات 1; break; case : مقدار 2 مجموعه دستورات 2 ; break; … … … default: مجموعه دستورات ; } نحوه عمل بدین صورت است که عبارت ذکر شده ارزیابی می شود ، سپس نتیجه از بالا به پائین با مقادیر ذکر شده مقایسه می شود و در صورتی که با یکی از مقادیر ذکر شده برابر بود مجموعه دستورات متناظر با آن case اجرا می شود و سپس با رسیدن به break کنترل از این ساختار خارج می شود.
اگر مقدار عبارت با هیچکدام از مقادیر ذکر شده برابر نبود ، مجموعه دستورات پس از default اجرا می شود .
وجود default اختیاری است .
مقادیر و حاصل عبارت در ساختار switch باید نوع صحیح باشند مقادیر تکراری در ساختار switch نمی توان استفاده کرد .یعنی مقدار 1 و مقدار 2 و .
نمی توانند برابر باشند.
هر case در ساختار switch باید حداقل دارای یک دستور باشد.
اگر ثابتهای کاراکتری در ساختار switch بکار گرفته شوند ، به مقادیر صحیح تبدیل می شوند.
اگر در یک case از دستور break استفاده نشود پس از اجرای مجموعه دستورات مر بوط به این case مجموعه دستورات مربوط به case بعدی نیز اجرا می شوند .
دو یا چند شرط را می توان درساختار switch با هم or نمود که برای اینکار کافی است چند case را با مقادیری که می خواهیم با هم or شوند پشت سر هم قرار دهیم.
switch (i) { case 0 : case 1 : i++; break; case 2 : i++; } تفاوت ساختار if و switch در ساختار switch فقط مساله مساوی بودن مطرح است اما در ساختار if می توان یک عبارت منطقی و یا رابطه أی را بررسی کرد .
استفاده از switch درصورت امکان باعث خوانا تر شدن و بالا رفتن سرعت برنامه می شود.
توابع درزبان c فقط زیر برنامه نوع تابع وجود دارد.
نحوه تعریف تابع : (اسامی پارامترها و نوع آنها ) نام تابع نوع تابع { بدنه تابع } منظور از نوع تابع یکی از انواع داده أی در زبان c یا ساختارها وانواع داده ها تعریف شده توسط کاربر است.
تعیین نوع تابع اختیاری است و اگر نوعی تعیین نگردد کامپایلر زبان c فرض می کند که نوع تابع int است.
نام تابع از قانون نامگذاری برای متغیرها تبعیت می کند.
اسامی پارامترها شامل متغیرهایی است که باید به تابع منتقل شوند نوع پارامترها می تواند در همان لیست پارامترها یا قبل از { ذکر شود.
int func(int i , char c){ .
} int func(i,c) int i; char c; { .
} پارامتر ها با کاما جدا می شوند .
فراخوانی تابع بوسیله نام آن به همراه آرگومانهای واقعی انجام می شود.
اگر تابعی حتی هیچ پارامتر نداشته باشد بعد از نام آن () قرار می گیرد .
تعریف یک تابع در داخل تابع دیگر امکان پذیر نیست ولی فراخوانی سطوح مختلف توابع ممکن است .
در موقع فراخوانی توابع باید تعداد و نوع آرگومانها با تعداد و نوع پارامترها یکسان باشند.
توابع ازنظر تعداد مقادیری که برنامه فراخواننده بر می گردانند: توابعی که هیچ مقداری را بر نمی گردانند : به این توابع توابع نوع void گفته می شود توابعی که فقط یک مقدار را بر می گردانند .
توابعی که چند مقدار را بر می گردانند .
انواع فراخوانی فراخوانی توسط ارزش (call by value) در این روش مقدار آرگومان تابع،در پارامتر متناظر با آن کپی میشود لذا هرگونه تغییری در پارامترها هیچگونه تاثیری در مقدار آرگومانها نخواهد داشت.
بنابراین در این روش هیچ مقداری توسط پارامترها و آرگومانها به تابع فراخواننده ، برگرداننده نمی شودو فقط می توان یک مقدار را با استفاده از دستور return به برنامه فراخواننده بر گرداند.
int add (int &i) { i++; } .
add(i); فراخوانی توسط ارجاع (call by reference) در این روش ، آدرس آرگومان بجای مقدار آرگومان در پارامتر کپی می شود و این بدان معنی است که در فراخوانی توسط ارجاع ، پارامتر حاوی آدرسهای آرگومانها هستند .
لذا تغییرات در محتویات این آدرسها به تابع فراخواننده بر می گردد.
int add (int *i) { i++; } .
add (&i); بخش سوم آرایه ها به ساختمان داده ای خطی که عناصر آن در حافظه به دنبال یکدیگر قرار گرفته و دارای اسم واحدی باشند آرایه گفته می شود.
دسترسی به هر یک از عناصر توسط نام آرایه و محل قرار گرفتن این عنصر در آرایه انجام می شود .
نامگذاری آرایه ها از قانون نامگذاری متغیرها تبعیت می کند..
اندیس آرایه ها در c از صفر شروع می شود.
int temp [5]; آرایه های یک بعدی طول آرایه،عددی صحیح است که تعدادعناصر آنرا مشخص میکند.
محاسبه حافظه مورد نیاز آرایه : مقدار حافظه = sizeof(نوع آرایه ) *تعداد عناصر آرایه در زبان c کنترل محدوده (bounds checking) نداریم و بعنوان مثال می توان بدون هیچ خطایی از طرف کامپایلر به موقعیتهایی بالاتر از طول آرایه دسترسی داشت ولی بدیهی است که نتیجه مطلوبی حاصل نخواهد شد و ممکن است با مقدار دهی عناصر خارج از بازه طول آرایه ، متغیرهای دیگر برنامه را مقدار دهی کنیم.
نام آرایه در c بعنوان اشاره گری به ابتدای آرایه می باشد که آدرس می باشد که آدرس شروع آرایه را دارد .
لذا در دستور scanf() چنانچه بخواهیم مقداری برای عنصر خانه صفر بخوانیم نیازی به علامت & نیست.
scanf(“%d” , list); آرایه های چند بعدی نحوه تعریف : نام آرایه نوع آرایه [طول بعد 1] [طول بعد 2] .
.[nطول بعد]; عناصر آرایه در محلهای متوالی حافظه و بصورت سطری ذخیره می گردند .
ارزش دهی اولیه به آرایه ها نحوه تعریف : نام آرایه نوع آرایه [طول بعد 1][طول بعد 2]…[nطول بعد]={مقادیر}; مقادیری که در داخل {} قرار می گیرند به ترتیب به عناصر آرایه نسبت داده می شوند.
int array[2][3]={1,2,3,4,5,6}; int table[2][3]={3,4}; int array2[2][3]={{1,2,3},{4,5,6}}; int three_d[3][2][3]= {{{1,2,3},{5,6,7}},{{7,9,3},{4,6,8}},{{7,2,6},{0,1,9}}}; اگر در هنگام مقدار دهی اولیه آرایه مقادیری بیشتر از ابعاد آرایه به عناصر آن نسبت دهیم با خطا مواجه می شویم.
چنانچه به حداقل یکی از عناصر آرایه های عددی مقدار صفر(یا هر مقدار دیگری) را اختصاص دهیم مقادیر بقیه عناصر به طور خودکار صفر می شود و اگر به حداقل یکی از عناصر آرایه های کاراکتری,کاراکتر و یا ‘\0’ را نسبت دهیم مقادیر دیگر عناصر نیز ‘\0’ خواهد شد.
این مطلب در صورتی صادق است که تمام عناصر آرایه رامقدار دهی نکنیم.
int i[5][10] = {0}; آرایه ها بعنوان آرگومان تابع اگر آرگومان تابع یک آرایه باشد در حین انتقال با تابع فقط باید اسم آن را بدون اندیس ذکر کرد.
اگر بخواهیم آرایه را به عنوان پارامتر تابع تعریف کنیم به سه طریق می توان اینکار را انجام داد: بوسیله اشاره گر بوسیله آرایه ای با طول مشخص بوسیله آرایه ای با طول نا مشخص func1(int * list) {بدنه تابع 1} func2(int list[10]) {بدنه تابع 2} func3(int list[ ]) {بدنه تابع 3} main () { int arr[10]; func1(arr); func2(arr); func3(arr); } اگر آرایه ای که بعنوان آرگومان تابع ذکر می شود دو بعدی باشد در موارد 1و2 مشکلی نخواهد بود , اما در مورد سوم که پارامتر آرایه بدون طول می باشد باید تعداد ستونهای آرایه حتماً مشخص گردد.
بطور کلی درآرایه های n بعدی باید طول ابعاد دوم به بعد مشخص گردد.
func4(int templist[ ][4]) {بدنه تابع} main () { int myarr[8][4]; func4(myarr); } رشته ها در c رشته ها بصورت آرایه ای از کاراکتر ها (نوع char) هستند که به null ختم می شوند .
برای نمایش null از ‘\0’ استفاده می شود .
معمولا به دلیل اینکه رشته باید به ‘\0’ ختم شود طول رشته ها را یکی بیشتر طول مورد نیاز می گیریم .
در صورت استفاده از توابع c کامپایلر کاراکتر null را به انتهای رشته ها اضافه می کند و نیازی نیست که برنامه نویس آنرا قرار دهد.
char name [6]; strcpy (name , “abc”); مقدار دهی اولیه به رشته ها برای اینکار دو روش وجود دارد: روش اول مشابه با مقدار دهی اولیه به آرایه ها است .
چون رشته آرایه ای از کاراکتر ها می باشد در این روش بصورت کاراکتر مقدار دهی می کنیم و در انتها نیز باید کاراکتر ‘\’\0’را قرار دهیم..
char string[] = {‘c’, ‘a’ , ‘r’ , ‘\0’}; در این روش متن در بین دو علامت کوتیشن “ “” قرار می گیرد و نیاز به گذاشتن کاراکتر ‘\0’ در انتهای رشته نیست چون کامپایلر این عمل را انجام می دهد .
char string[] = ”car”; یا char string[] = {“car”}; در مقدار دهی اولیه به رشته ها اگر طول رشته مشخص نگردد, به تعداد کاراکتر هایی که به آن نسبت داده می شود به اضافه کاراکتر null عنصر منظور خواهد شد.(در دو مثال بالا طول رشته 4 در نظر گرفته می شود) آرایه ای از رشته ها هر گاه خواسته باشیم تعدادی رشته را در آرایه ای نگهداری کنیم , چون رشته ها خود از نوع آرایه هستند باید آرایه ای از آرایه ها را تعریف کنیم char list [4][21]= {“ali“ , “taha” , “ parsa” , “siavash”}; توابع رشته ای gets() برای خواندن رشته ها از صفحه کلید بکار می رود .
شکل کلی : gets(متغیر رشته ای ); تفاوت gets() و scanf() در ورودی رشته ها این است که scanf() رشته ها را پیوسته در نظر می گیرد یعنی اگر دربین رشته از فاصله استفاده شود و یا tab استفاده شود از این کاراکتر به بعد بعنوان رشته دیگری در نظر گرفته می شود ولی در gets() اینطور نیست و تا زمانی که کلید enter فشرده نشود رشته پایان نمی یابد .
puts() این تابع برای انتقال یک رشته به خروجی بکار می رود .
شکل کلی : puts(عبارت رشته ای ); تفاوت pust() و printf() در خروجی رشته در این است که puts() در هر زمان فقط می تواند یک رشته رابه خروجی ببرد و همچنین استفاده از puts ساده از printf() می باشد .
توابع دستکاری رشته ها strcpy() برای قرار دادن رشته ای در رشته دیگر کاربرد دارد .
شکل کلی : strcpy(رشته ثابت یا متغیر رشته ای , متغیر رشته ای ) ; char name [11]; strcpy(name , “ali”); نکته قابل توجه این است که عملیات انتساب مقدار به رشته از طریق این تابع انجام می گیرد و استفاده از = امکانپذیر نیست .
strncpy() n کاراکتر اول از رشته مبدأ را در رشته مقصد کپی می کند .
strcat() برای الحاق دو رشته بکار می رود .
strlen() برای تعیین طول یک رشته بکار می رود.
strcmp() برای مقایسه دو رشته بکار می رود و نحوه کاربرد و نتیجه بصورت زیر است : strchr() جهت جستجوی یک کاراکتر در یک رشته بکار می رود و محل اولین وقوع آن را بر می گرداند .
اگر کاراکتر مورد نظر وجود نداشته باشد , مقدار صفر (یا null) را بر می گرداند .
خروجی این تابع اشاره گری به اولین محل وقوع کاراکتر در رشته است.
strstr() برای جستجوی زیر رشته ای در یک رشته بکار می رود .
اگر زیر رشته مذکور پیدا شود محل اولین وقوع آنرا بر می گرداند و در غیر اینصورت مقدار صفر (یا همان مقدار null) را برمی گرداند.
اشاره گر ها اشاره گر (pointer) متغیری است که یک آدرس حافظه را در خود نگهداری می کند.
مزایای اشاره گر ها عمل تخصیص حافظه پویا را امکان پذیر می سازد..
کار با رشته ها و آرایه ها را آسانتر می کند .
فراخوانی با ارجاع در توابع .
با اشاره گر انجام می گیرد .
نحوه تعریف : نوع * نام متغیر اشاره گر ; نوع مشخص می کند که این اشاره گر به چه نوعی اشاره می کند .
اشاره گر از هر نوعی باید به متغیری از همان نوع اشاره کند.
در غیر اینصورت از طرف کامپایلر خطا صادر می شود , به عنوان مثال اختصاص دهی مقدار بصورت زیر اشتباه است : int *I; char *j; I = j; عملگر یکانی & آدرس عملوند خود را بر می گرداند.
عملگر یکانی * محتویات یک آدرس حافظه را مشخص می کند .
یک اشاره گر معمولاً به ناحیه ای در فضای heap اشاره می کند وخود شامل آدرس آن ناحیه است .
در c چنانچه اشاره گری بصورت near تعریف شود 2 بایت برای نگهداری آدرس محلی که به آن اشاره می کند , در نظر گرفته می شود .
پیش فرض تعریف اشاره گرها near می باشد .
اگر در c اشاره گری بصورت far تعریف شود 40 بایت برای نگهداری آدرس محلی که به آن اشاره می کند , اختصاص داده می شود .
int near *i; sizeof(i) = 2 char far *j sizeof j=4 اعمال روی اشاره گر ها می توان مقداری را به یک اشاره گر نسبت داد .
می توان دو اشاره گر ممنوع را به یکدیگر نسبت داد که در این صورت هر دو به یک مکان اشاره خواهند کرد.
int x; int *p1 , *p2; p1=&x; p2=p1; عمل جمع و تفریق آدرس به اشاره گر ها می توان مقادیری را افزود یا از آنها کم کرد که این عمل با توجه به نوع اشاره گر انجام می شود و به اندازه حاصلضرب مقدار مورد نظر در طول نوع اشاره گر به آدرس موجود در اشاره گر اضافه یا کم می شود .
int *p,x=3; p=&x; p++; در این مثال اگر مثلاً p به آدرس 2000 حافظه اشاره می کرد حالا با این افزایش به مکان 2002 حافظه اشاره می کند .
اعمال ضرب و تقسیم بر روی اشاره گر ها تعریف نشده است .
عمل مقایسه اشاره گر ها با استفاده از عملگر های رابطه ای میتوان اشاره گر ها را با یکدیگر مقایسه کرد.
که در اینحالت آدرس ها با یکدیگر مقایسه می شوند .
int x=3,y=5; int *p1, *p2; p1=&y; p2=&x; if (p1 اشاره گر و آرایه اسم آرایه در c در واقع اشاره گری به ابتدای آرایه در حافظه است .
بعبارت دیگر اسم آرایه آدرس اولین محلی را که عناصر آرایه از آنجا به بعد در حافظه قرار دارند و در خود نگهداری می کند .