بسماللهالرحمنالرحیم
اگر سری آموزشهای میکروبلیز را تا کنون دنبال کرده باشید به مطالبی چون تعریف اصولی متغیر و عملگرها در زبان برنامهنویسی C پرداختیم که برای دیدن این سری از آموزشها میتوانید اینجا کلیک کنید. در این قسمت میخواهیم به توضیح اصولی و دقیق کاراکترها، رشتهها و آرایهها به همراه مثال در هر بخش بپردازیم.
کاراکتر در زبان برنامهنویسی C چیست؟
کاراکتر (char) یک نوع متغیر (Variable) در زبان برنامه نویسی C است که برای ذخیره تنها یک کاراکتر به کار میرود. منظور از کاراکتر در واقع، حروف الفبا، اعداد و علامت هایی است که در متن ها به کار میبریم. نکته ای که در استفاده از کاراکترها بسیار حائز اهمیت است، اندازه آن میباشد. که در قسمت ” آموزش میکروبلیز قسمت سوم: آموزش زبان برنامهنویسی C ” به این موضوع پرداختیم.
طرز صحیح استفاده از کاراکتر در زبان برنامهنویسی C به صورت زیر است.
1 | char Character = 'B'; |
هشدار: در خط برنامه ای که نوشتیم فقط تنها کلمه ای که کلیدی است و باید باشد اسم char است و ما بقی همگی اسمهایی کاملا اختیاری هستند.
هشدار: یک کاراکتر در بین دو علامت ‘ ‘ تعریف میشود (نباید علامت ” ” را به کار ببرید).
هشدار: تلفظ صحیح کلمه Char به صورت کر است نه چر ( لطفا درست تلفط کنید خودتونو مسخره میکنند خیرتونو میخوام اینجوری میگم).
آرایه در زبان برنامهنویسی C چیست؟
آرایه (Array)، تعدادی عنصر از یک نوع خاص هستند که با یکدیگر تعریف میشوند و با استفاده از اندیس های (در ادامه توضیح میدهیم) متناظر آنها، میتوانیم به آنها اشاره نماییم.
طرز صحیح تعریف آرایه در زبان برنامهنویسی C
1 | نوع آرایه اسم آرایه [ اندازه آرایه]; |
1 | double balance[10]; |
طرز صحیح مقدار دهی اولیه به متغیر در زبان برنامهنویسی C
روش اول:
1 | double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0}; |
روش دوم:
1 | double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0}; |
توصیه: ترجیحا اگر تعداد اعضای آرایهای که تعریف میکنید زیاد بود نیازی نیست که حتما اندازه آن را بنوسید و دقیقا مانند روش دوم عمل کنید.
نحوه فراخوانی اعضای آرایه در زبان برنامهنویسی C
ابتدا نیاز است که با نحوه شماره گذاری (اندیس گذاری) آرایهها آشنا شویم. برای درک این موضوع به تصویری که در ادامه قرار میدهیم دقت کنید.
اگر به تصویر دقت کنید دقیقا همان متغیری است که قبلا تعریف کردهایم حال به شمارههایی (اندیسهایی) که در بالای هر خانه نوشته شده است دقت کنید میبینید که اولین خانه آرایه همیشه از صفر شروع میشود و بعد از آن شمارش به ترتیب انجام میگیرد.
نتبجه مهم: در آرایهها اولین عضو همیشه از عدد صفر شروع میشود.
خب حالا با توجه به اینکه با نحوه اندیس گذاری آرایهها آشنا شدیم نوبت به استفاده از اعضای آرایه رسیده است که برای این کار کافیاست به صورت دستور زیر عمل کنیم.
1 | balance[4] = 50.0; |
حال اگر به جدولی که در بالا قرار دادهایم دقت کنید میبینید که خانه چهارم متعلق به عدد 50 است.
دقت کنید که برای فراخوانی هر عضو از آرایه فقط کافی است که اندیس مربوطه آن را درون براکتی که آرایه را تعریف کردهایم قرار دهیم.
تعریف آرایه چند بعدی در زبان برنامهنویسی C
تقریبا میتوان گفت مثل آرایه تک بعدی است اما با این تفاوت که اعضای آن بسته به چند بعدی بودن آرایه متفاوت است.
به فرمول زیر دقت کنید.
1 | نوع اسم [اندازه آرایه شماره 1][اندازه آرایه شماره2]...[اندازه آرایه شماره n]; |
به طور مثال
1 | int threedim[5][10][4]; |
حال با تعریف بالا، میخواهیم آرایه دو بعدی را تعریف کنیم.
1 | نوع آرایه اسم آرایه[ x ][ y ]; |
در واقع اگر به فرمول بالا نگاه کنیم میبینیم که دقیقا یک ماتریس تشکیل داده است. برای درک بهتر لطفا به تصویری که در ادامه قرار میدهیم دقت کنید.
اگر به جدول دقت کنید دقیقا متوجه خواهید شد که یک ماتریس تشکیل شده است که اگر با تعریف آرایه دو بعدی آن را قیاس کنیم به اینگونه است که مقدار X در واقع همان ROW و مقدار Y همان Column است. برای درک بهتر به مثال زیر توجه کنید.
1 2 3 4 5 | int a[3][4] = { {0, 1, 2, 3} , /* initializers for row indexed by 0 */ {4, 5, 6, 7} , /* initializers for row indexed by 1 */ {8, 9, 10, 11} /* initializers for row indexed by 2 */ }; |
توصیه : نرمافزار متلب دارای ساختار ماتریسی است.(دیگه متوجه داستان باشید که چقدر این مبحث مهمه)
دسترسی به اعضای آرایه دو بعدی در زبان برنامهنویسی C
1 | int val = a[2][3]; |
تمرین: مقدار a چه عددی است؟
برای درک بهتر به مثال زیر توجه کنید.(تحلیلش با خودتون واقعا ساده است)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <stdio.h> int main () { /* an array with 5 rows and 2 columns*/ int a[5][2] = { {0,0}, {1,2}, {2,4}, {3,6},{4,8}}; int i, j; /* output each array element's value */ for ( i = 0; i < 5; i++ ) { for ( j = 0; j < 2; j++ ) { printf("a[%d][%d] = %d\n", i,j, a[i][j] ); } } return 0; } |
1 2 3 4 5 6 7 8 9 10 | a[0][0]: 0 a[0][1]: 0 a[1][0]: 1 a[1][1]: 2 a[2][0]: 2 a[2][1]: 4 a[3][0]: 3 a[3][1]: 6 a[4][0]: 4 a[4][1]: 8 |
اشارهگرها در آرایهها
یکی از مباحثی که بسیار زیاد در برنامهنویسی از اهمیت زیادی برخوردار است بحث اشارهگرها (Pointer) است که در بخش خودش به طور مفصل در این مورد صحبت خواهیم کرد ان شالله اما در این قسمت میخواهیم صرفا از اشارهگرها برای ارتباط با آرایهها صحبت کنیم.
طرز استفاده از اشارهگرها در آرایهها
خب اگر به نکتهای که در بالا اشاره کردیم دقت کنیم میتوانیم به صورت زیر عمل کنیم.
1 2 3 4 | double *p; double balance[10]; p = balance; |
اجازه دهید این قسمت را با یک دیگر تحلیل کنیم.
علامت * به معنی اشارهگر است که در اینجا اشارهگر P از نوع Double تعریف شده است.
تعریف یک آرایه 10 عضوی با نام Balance که نکته جالب اینجا است که از نوع اشارهگر تعریف نشده است ( معنیش اینکه خودش یک نوع اشارهگره وگرنه امکان نداشت بتونن اینجوری خوش و خرم کنار هم باشن)
دسترسی به اعضای آرایه از طریق اشارهگر
اگر خاطرتان باشد در مورد اندیسهای آرایهها صحبت کردیم و به این نکته هم اشاره کردیم که اولین عضو آرایه از صفر شروع میشود. با این توضیحات به مثال زیر دقت کنید.
1 2 | double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0}; double *p; |
تا این قسمت که چیز جدیدی را نگفتهایم و دقیقا یک آرایه 5 عضوی و یک اشارهگر P تعریف کردهایم. حالا برای دسترسی به هر عضو باید به صورت دستور زیر عمل کنیم.
1 2 3 4 5 | *(p + 0) : 1000.0 * (p + 1) : 2.0 * (p + 2) : 3.4 * (p + 3) : 17.0 * (p + 4) : 50.0 |
اگر دقت کنید اشارهگر بعلاوه اندیس موردنظر آرایه به همراه علامت * در خارج از پرانتز قادر هستیم که هر عضو آرایه را فراخوانی کنیم.
نوشتن توابع بر حسب آرایهها
این بخش خود شامل سه قسمت است که به صورت زیر تقسیم میشوند.(البته هنوز در مورد توابع صحبت نکردهایم که در ادامه مقالات به طور مفصل به این مبحث خواهیم پرداخت نگران نباشید)
- تابع اشارهگر با آرایهها
- تابع آرایه با اندازه محدود
- تابع آرایه با اندازه نامحدود
تابع اشارهگر با آرایهها
این تابع داری ورودی از نوع اشارهگر است که به صورت زیر تعریف میشود.
1 2 3 4 5 | void myFunction(int *param) { . . . } |
تابع آرایه با اندازه محدود
این تابع داری ورودی از نوع آرایه از نوع سایز محدود است که به صورت زیر تعریف میشود.
1 2 3 4 5 | void myFunction(int param[10]) { . . . } |
تابع آرایه با اندازه نامحدود
این تابع داری ورودی از نوع آرایه از نوع سایز نامحدود است که به صورت زیر تعریف میشود.
1 2 3 4 5 | void myFunction(int param[]) { . . . } |
خب حال میخواهیم با استفاده از دانشی که تا کنون نسبت به آرایهها پیدا کردیم یک مثال کاربردی را انجام دهیم.
مثال: تابعی بنوسید که اسم و سایز آرایه را به همراه تشخیص اعضای آرایه بدست آورد و در نهایت عمل میانگیری را انجام دهد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | double getAverage(int arr[], int size) { int i; double avg; double sum = 0; for (i = 0; i < size; ++i) { sum += arr[i]; } avg = sum / size; return avg; } |
خب اگر به تابع دقت کنید از دو ورودی اسم آرایه موردنظر و سایز تشکیل شده است که در ادامه هر عضو از آرایه را دریافت و سپس عمل میانگیری را انجام میدهد. اگر بخواهیم از این تابع در برنامه اصلی خود استفاده کنیم راهحل چیست؟ راه حل فراخوانی تابع نوشته شده در برنامه اصلی است که باید به صورت زیر عمل کنیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <stdio.h> /* function declaration */ double getAverage(int arr[], int size); int main () { /* an int array with 5 elements */ int balance[5] = {1000, 2, 3, 17, 50}; double avg; /* pass pointer to the array as an argument */ avg = getAverage( balance, 5 ) ; /* output the returned value */ printf( "Average value is: %f ", avg ); return 0; } |
همانطور که گفتیم اگر به کد دقت کنید ابتدا تابعی که نوشته بودیم را فراخوانی کردیم و در نهایت از آن در برنامه اصلی خود استفاده کردیم. در برنامه یک آرایه یک بعدی با نام Balance تعریف شده است که در نهایت توسط تابعی که فراخوانی کرده بودیم عمل میانگیری را انجام دادیم که در نهایت جواب به صورت زیر است.
1 | Average value is: 214.400000 |
مثال: تابعی نویسید که اعداد تصادفی تولید کند. (تحلیل این کد رورمیزارم با خودتون فقط راهنمایی که وجود داره به تابع اشارهگری که تعریف شده دقت کنید.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #include <stdio.h> /* function to generate and return random numbers */ int * getRandom( ) { static int r[10]; int i; /* set the seed */ srand( (unsigned)time( NULL ) ); for ( i = 0; i < 10; ++i) { r[i] = rand(); printf( "r[%d] = %d\n", i, r[i]); } return r; } /* main function to call above defined function */ int main () { /* a pointer to an int */ int *p; int i; p = getRandom(); for ( i = 0; i < 10; i++ ) { printf( "*(p + %d) : %d\n", i, *(p + i)); } return 0; } |
خروجی کد هم به صورت زیر میباشد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | r[0] = 313959809 r[1] = 1759055877 r[2] = 1113101911 r[3] = 2133832223 r[4] = 2073354073 r[5] = 167288147 r[6] = 1827471542 r[7] = 834791014 r[8] = 1901409888 r[9] = 1990469526 *( p + 0) : 313959809 *(p + 1) : 1759055877 *(p + 2) : 1113101911 *(p + 3) : 2133832223 *(p + 4) : 2073354073 *( p + 5) : 167288147 *(p + 6) : 1827471542 *( p + 7) : 834791014 *(p + 8) : 1901409888 *(p + 9) : 1990469526 |
رشته در زبان برنامهنویسی C چیست؟
رشته، آرایه ای از کاراکترها است. پس برای تعریف رشته باید مانند تعریف آرایه عمل کرد با این تفاوت که نوع رشته فقط می تواند char انتخاب شود.
اگر به تعریفی که کردیم با دقت نگاه کنید، گفتهایم که رشتهها، آرایهای از متغیرها هستند. خب اجازه دهید برای درک بهتر یک مثال از کاراکتر و سپس نحوه اصولی نوشتن رشته در زبان C بپردازیم.
1 | char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; |
اگر به برنامه بالا نگاه کنیم میبینیم که دقیقا آرایه ای از کاراکترها کنار یک دیگر قرار گرفتهاند که در نهایت، این حروف میخواهند به کلمه Hello تبدیل شوند اما سوال اینجا است که کاراکتر آخر چیست؟
تعریف اصولی رشته در زبان برنامهنویسی C
روش اول
1 | char greeting[6] = "Hello"; |
اما سوال اینجا است که همیشه باید این مقدار دهی را انجام دهیم اگر رشته خیلی بزرگ بود راهحل چیست؟ پاسخ این سوال در روش دوم گفته شده است.
روش دوم
در این روش دیگر نیازی نیست که حتما اندازه رشته را مشخص کنیم و یا به کاراکتر تهی دقت کنیم بلکه خود کامپایلر این کار را برای ما انجام میدهد البته به شرط اینکه به صورت ساختار زیر عمل کنیم.
1 | char greeting[] = "Hello"; |
خب برای اینکه درک بهتری از این نوع کد داشته باشیم نیاز است به تصویری که در ادامه قرار میدهیم دقت کنید.
اگر به تصویر دقت کنید میبینید که خود کامپایلر به صورت خودکار کاراکتر تهی را قرار داده است و در بخش آدرسهای حافظه نیز به صورت پشت سر هم قرار گرفتهاند.
تعریف آرایهای از رشتهها
اگر بخواهیم متغیری را تعریف کنیم که چندین رشته را در خود قرار دهد باید آرایه ای از رشته ها را تعریف کنیم. که باید به صورت زیر عمل کنیم.
تعریف اصولی آرایهای از رشتهها در زبان
روش اول
در این روش باید طول هر رشته و تعداد رشته را حتما مشخص کنیم.
در طول رشته کاراکتر تهی را فراموش نکنید.
1 | char names[3][7] = { "BLOOM", "Phonix", "Zeus", }; |
روش دوم
1 | char names[3][] = { "BLOOM", "Phonix", "Zeus", }; |
معرفی توابع کاربردی کتابخانه String.h
1 2 3 4 5 6 7 8 9 10 11 | strcpy(s1, s2); strcat(s1, s2); strlen(s1); strcmp(s1, s2); strchr(s1, ch); strstr(s1, s2); |
تابع strcpy
1 | strcpy(s1, s2); |
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include <stdio.h> #include <string.h> int main () { char str1[]="Sample string"; char str2[40]; char str3[40]; strcpy (str2,str1); strcpy (str3,"copy successful"); printf ("str1: %s\nstr2: %s\nstr3: %s\n",str1,str2,str3); return 0; } |
1 2 3 | str1: Sample string str2: Sample string str3: copy successful |
تابع strcat
1 | strcat(s1, s2); |
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include <stdio.h> #include <string.h> int main () { char str[80]; strcpy (str,"these "); strcat (str,"strings "); strcat (str,"are "); strcat (str,"concatenated."); puts (str); return 0; } |
1 | these strings are concatenated. |
تابع strlen
1 | strlen(s1); |
1 2 3 4 5 6 7 8 9 10 11 | #include <stdio.h> #include <string.h> int main () { char szInput[256]; printf ("Enter a sentence: "); gets (szInput); printf ("The sentence entered is %u characters long.\n",(unsigned)strlen(szInput)); return 0; } |
خروجی برنامه به صورت زیر است.
1 2 | Enter sentence: just testing The sentence entered is 12 characters long. |
تابع strcmp
1 | strcmp(s1, s2); |
حالت اول (0>)
زمانیکه مقدار S1 کوچکتر از مقدار S2 باشد که در این حالت خروجی نادرست است.
حالت دوم (0)
زمانیکه مقدار S1 و S2 برابر باشند که در این حالت مقدار خروجی درست است.
حالت سوم (0<)
زمانیکه مقدار S1 بزرگتر از مقدار S2 باشد که در این حالت هم خروجی نادرست است.
برای درک بهتر به مثال زیر دقت کنید.
در این مثال یک رشته که نام آن apple انتخاب شده است در اول برنامه تعریف شده است و در نهایت برنامه ای نوشته شده است که در صورتیکه رشته ای برابر با apple وارد شود در خورجی عبارتی مبنی بر صحیح بودن جواب میبینیم در غیر اینصورت پاسخی مبنی بر صحیح بودن جواب دریافت نخواهیم کرد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #include <stdio.h> #include <string.h> int main () { char key[] = "apple"; char buffer[80]; do { printf ("Guess my favorite fruit? "); fflush (stdout); scanf ("%79s",buffer); } while (strcmp (key,buffer) != 0); puts ("Correct answer!"); return 0; } |
خروجی برنامه به صورت زیر است.
1 2 3 | Guess my favourite fruit? orange Guess my favourite fruit? apple Correct answer! |
تابع strchr
1 | strchr(s1, ch); |
برنامه چون واضح نوشته شده فکر نمیکنیم که نیاز به توضیح داشته باشد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include <stdio.h> #include <string.h> int main () { char str[] = "This is a sample string"; char * pch; printf ("Looking for the 's' character in \"%s\"...\n",str); pch=strchr(str,'s'); while (pch!=NULL) { printf ("found at %d\n",pch-str+1); pch=strchr(pch+1,'s'); } return 0; } |
خروجی برنامه به صورت زیر است.
1 2 | Looking for the 's' character in "This is a sample string"... found at 4 |
تابع strstr
1 | strstr(s1, s2); |
1 2 3 4 5 6 7 8 9 10 11 12 | #include <stdio.h> #include <string.h> int main () { char str[] ="This is a simple string"; char * pch; pch = strstr (str,"simple"); strncpy (pch,"sample",6); puts (str); return 0; } |
1 | This is a sample string |
امیدوارم که این آموزش هم مورد توجه شما مخاطبین عزیز قرار گرفته باشد.
بسیار عالی مبحث رشته ها رو آموزش دادین در زبان سی که تو دوتا کتابی که من دارم اینطور جزئی این مبحث رو آموزش نداده بود ،خیلی ممنون دوست عزیز
ممنون از این مقاله کاربردی
سلام
شوخی هایی که در متن آموزش می کنین خوبه
ادامه بدین
ممنون از سیسوگ
سلام
دستان درد نکند از اینکه زحمت می کشید و مطالب آموزشی زبان سی را منتشر می کنید .
من زبان سی را با کامپیوتر 80286 و با کامپایلر توربو سی شروع کردم و از آن زمان تا حالا هم برای میکرو های مختلف از 8051 تا ARM از آن استفاده کرده و می کنم .
با وجود این مقاله های شما را از قسمت اول تا الان خواندم در من شوق دوباره خوانی اصول و روش های برنامه نویسی به زبان سی زنده کرد و مطالبی بود که یا فراموش کرده بودم یا فکر کرده بودم که زیاد لازم نباشد و از آن ها استفاده نمی کردم .
متوجه شدم که باید زودتر این کار را می کردم .
این را به شما مدیونم .
خیلی خیلی سپاسگزارم از اینکه قبول زحمت کردین و این مطالب را تهیه می کنید .
مطمئن باشید که سطر به سطر این مطالب را خواندم و خواهم خواند.
با تشکر مجدد
مجید
سلام مجید عزیز خیلی خوشحال شدم از اینکه باعث شده این اموزش برای شما مفید باشه و یک تلنگری باشه که مجددا این زبان رو برای خودتون یاداوری کنید چون باور کنید هر چی بگم مهمه کمه حالا جلوتر که رفتیم ان شالله بیشتر متوجه داستان خواهید شد. و من هم به نوبه خودم تمام تلاشمو میکنم مقالاتی که در این زمینه مینویسم بیشترین فایده رو برای شما و مخاطبین عزیز داشته باشه.
با ارزوی موفقیت برای شما مجید عزیز.
BLOOM