كارت dvb , كارت دي وي بي , دی وی بی , رسيور , رسیور
| |
اين يك بخش از موضوع آشنائی با زبان #c است كه در انجمن برنامه نویسی مطرح گرديده و اين انجمن نيز زير مجموعهي برنامه نویسی و طراحی وب ، سيستمهاي مديريت سایت است: مايكروسافت در مصاف با جاوا، بدنبال ارائه يك زبان كامل بود كه سايه جاوا را در ميادين برنامه نويسی كم رنگ تر نمايد. شايد بهمين دليل باشد كه #C را ايجاد كرد. شباهت های بين دو زبان بسيار چشمگير است. مايكروسافت در رابطه با ميزان استفاده و گسترش زبان فوق ...
| ثبت نام | پست جدید | All Albums | Blogs | راهنما | فهرست کاربران | تقویم | جستجو | ارسالهاي امروز | نشانه گذاري انجمن ها به عنوان خوانده شده |
| | ||||||||
| برنامه نویسی بحث ، آموزش ، رفع اشکال و تبادل نظر در مورد برنامه نویسی برای محیط ویندوز. ويژوال بيسيک - دلفی و ... |
| اطلاعيههاي سايت |
|
| LinkBack | ابزارهای موضوع |
| | #1 | |||||||||||
| سرپرست انجمن ![]() ![]() ![]() ![]() ![]() ![]() ![]() تاریخ عضویت: January 24th, 2007
نوشته ها: 47,791
سطح دانش: 103 [ ![]() ![]() ![]() ![]() ]سابقه در سایت: 3842 / 3842 Thanks: 69
Thanked 1,394 Times in 1,055 Posts
قدرت اعتبار: 50 | مايكروسافت در مصاف با جاوا، بدنبال ارائه يك زبان كامل بود كه سايه جاوا را در ميادين برنامه نويسی كم رنگ تر نمايد. شايد بهمين دليل باشد كه #C را ايجاد كرد. شباهت های بين دو زبان بسيار چشمگير است. مايكروسافت در رابطه با ميزان استفاده و گسترش زبان فوق بسيار خوشبين بوده و اميدوار است بسرعت زبان فوق گستردگی و مقبوليتی به مراتب بيشتر از جاوا را نزد پياده كنندگان نرم افزار پيدا كند. با توجه به نقش محوری اين زبان، از آن بعنوان مادر زبانهای برنامه نويسی در دات نت نام برده می شود. مورد فوق به تنهائی، می تواند دليل قانع كننده ای برای يادگيری اين زبان باشد، ولی دلايل متعدد ديگری نيز وجود دارد كه در ادامه به برخی از آنها اشاره می گردد. مطرح شدن بعنوان يك استاندارد صنعتی انجمن توليدكنندگان كامپيوتر اروپا (ECMA) زبان #C را در سوم اكتبر سال 2001 بعنوان يك استاندارد پذيرفته (ECMA-334) و بدنبال آن تلاش های وسيعی برای كسب گواهی ISO نيز انجام شده است. زبان فوق در ابتدا توسط شركت مايكروسافت و بعنوان بخشی از دات نت پياده سازی و بلافاصله پس از آن توسط شركت های اينتل، هيوليت پاكارد و مايكروسافت مشتركا، جهت استاندارسازی پيشنهاد گرديد. زبان #C بگونه ای طراحی شده است كه نه تنها وابستگی به يك Platform خاص را ندارد، بلكه در اغلب موارد وابستگی RunTime نيز ندارد. كامپايلر #C می تواند بر روی هر نوع معماری سخت افزاری طراحی و اجرا گردد. در برخی از نسخه های اوليه كامپايلر زبان فوق كه توسط برخی از شركت های جانبی ارائه شده است، كدهای #C را به بايت كدهای جاوا كمپايل می كنند. يكی از چنين كامپايلرهائی را می توان در سايت Halcyonsoft.com مشاهده نمود. بنابراين كدهای #C براحتی قابليت حمل بر روی محيط های متفاوت را دارا خواهند بود. مشخصات تعريف شده زبان #C با ساير استاندارهای تعريف شده ECMA نظير (ECMA-335) CLI (Common Language Infrastructure) بخوبی مطابقت می نمايند. CLI قلب و روح دات نت و CLR(Common Language Runtime) است. اولين نسخه از كامپايلر زبان #C كه از CLI استفاده می كند، NET Framwork. مايكروسافت است. با توجه به موارد گفته شده، مشخص می گردد كه اين زبان بسرعت بسمت استاندارد شدن حركت و با تاييد استانداردهای مربوطه از طرف انجمن های معتبر بين المللی و حمايت فراگير شركت های معتبر كامپيوتری در دنيا مسير خود را بسمت جهانی شدن بخوبی طی می نمايد. #C چيست ؟ طراحان زبان #C با تاكيد و الگوبرداری مناسب از مزايای زبانهائی نظير ++C، C و جاوا و ناديده گرفتن برخی از امكانات تامل برانگيز و كم استفاده شده در هر يك از زبانهای فوق، يك زبان برنامه نويسی مدرن شی گراء را طراحی كرده اند. در مواردی، برخی از ويژگی های استفاده نشده و درست درك نشده در هر يك از زبانهای گفته شده، حذف و يا با اعمال كنترل های لازم بر روی آنها، زمينه ايجاد يك زبان آسان و ايمن برای اغلب پياده كنندگان نرم افزار بوجود آمده است. مثلا C و ++C می توانند مستقيما با استفاده از اشاره گرها عمليات دلخواه خود را در حافظه انجام دهند. وجود توانائی فوق برای نوشتن برنامه های كامپيوتری با كارائی بالا ضرورت اساسی دارد. اما در صورتيكه عملياتی اينچنين بدرستی كنترل و هدايت نگردند، خود می تواند باعث بروز مسائل (Bugs) بيشماری گردد. طراحان زبان #C، با درك اهميت موضوع فوق، اين ويژگی را كماكان در آن گنجانده ولی بمنظور ممانعت از استفاده نادرست و ايجاد اطمينان های لازم مسئله حفاظت نيز مورد توجه قرار گرفته است. جهت استفاده از ويژگی فوق، برنامه نويسان می بايست با صراحت و به روشنی خواسته خود را از طريق استفاده از Keyword های مربوطه اعلان نمايند( فراخوانی يك توانائی و استفاده از آن). #C بعنوان يك زبان شی گراء عالی است. اين زبان First-Class را برای مفهوم Property (Data Member) بهمراه ساير خصائص عمومی برنامه نويسی شی گراء حمايت می كند. در C و ++C و جاوا يك متد get/set اغلب برای دستيابی به ويژگی های هر Property استفاده می گردد. CLI همچنان تعريف Property را به متدهای get/ser ترجمه كرده تا بدين طريق بتواند دارای حداكثر ارتباط متقابل با ساير زبانهای برنامه نويسی باشد. #C بصورت فطری Events ، Declared Value، Reference Type ، Operator Overloading را نيز حمايت می كند. كد مديريت يافته با استفاده از نسخه پياده سازی شده #C توسط مايكروسافت، می توان همواره كد مديريت يافته ای را توليد كرد. يك برنامه #C پس از كامپايل، بصورت برنامه ای در خواهد آمد كه شامل دستورالعمل های تلفيق شده ( CIL (Common Intermediate Language است (درست بر خلاف دستورالعمل های مختص يك ماشين خاص). CIL (گاها با نام MSIL(Microsoft Intermediate Language) با به اختصار IL نيز ناميده می شود ) ، در مفهوم مشابه بايت كدهای جاوا بوده و شامل مجموعه ای از دستورالعمل های سطح پايين قابل فهم توسط تكنولوژی مبتنی بر CLI نظير CLR مايكروسافت خواهد بود. اين برنامه ها بدين دليل كد مديريت يافته، ناميده می شوند كه CLR مسئوليت تبديل اين دستورالعمل ها به كدهای قابل اجرا برروی ماشين و ارائه اغلب سرويس های اساسی برای كدينگ نظير : Garbage Collection، مديريت Heap و عمر مفيد يك Object و يا Type Verification را فراهم می كند. روش يادگيری #C يادگيری اين زبان برای افراديكه دارای سابقه آشنائی با يكی از زبانهای برنامه نويسی ++C، C و يا جاوا باشند كار مشكلی نخواهد بود، حتی افراديكه دارای آشنائی اوليه با جاوااسكريپت و يا ديگر زبانهای برنامه نويسی نظير ويژوال بيسك می باشند، امكان پذير و راحت خواهد بود. برخی از برنامه نويسان حرفه ای بر اين باور هستند كه #C نسبت به VB.NET با اقبال بيشتر و سريعتری مواجه خواهد شد، چراكه #C نسبت به ويژوال بيسك خلاصه تر است. حتی برنامه های بزرگ و پيچيده ای كه توسط #C نوشته می گردند خواناتر، كوتاه و زيبا خواهند بود. برخی از ويژگی های ارائه شده در #C نظير Unsigned Integer، Operator OverLoading و امنيت بيشتر Type ها، در VB.NET وجود نداشته و اين امر می تواند دليلی بر فراگيرتر شدن #C نسبت به VB.NET نزد برنامه نويسان با تجربه باشد. برای يادگيری هر يك از زبانهای حمايت شده در دات نت، می بايست از BCL (Basic Class Library) مربوط به NET Framework. شروع كرد. #C خود صرفا دارای ۷۷ کلمه کليدی يا Keyword بوده كه برای اكثر برنامه نويسان غريب نخواهند بود. در مقابل BCL، دارای ۴۵۰۰ كلاس و تعداد بيشماری متد و Property است كه برنامه نويسان #C، می توانند از آنها برای انجام عمليات دلخواه خود استفاده نمايند. شايد يكی از مسائل قابل توجه جهت يادگيری اين زبان برای برخی از برنامه نويسان حرفه ای عدم وجود برخی از ويژگی ها و امكاناتی باشد كه در گذشته و از طريق ساير زبانهای استفاده شده، بخدمت گرفته می شدند. مثلا عدم وجود امكاناتی جهت توارث چندگانه (MI) سلسله مراتبی يك شئ. خلاصه بدون شك فراگيری و تسلط بر زبان #C بمنزله كسب يك پتانسيل با ارزش بوده كه ثمرات آن برای برنامه نويسان در حال و آينده ای نه چندان دور بيشتر هويدا خواهد شد. استاندارد بودن و وجود كتابخانه ای مملو از كلاس اين اطمينان را بوجود خواهد آورد كه با فراگيری زبان فوق و كسب، مهارت های لازم، به يك توانائی فرا محيطی جديد دست پيدا خواهيم كرد كه امكان استفاده از آن بر روی محيط های متفاوت وجود خواهد داشت. ويژگی ها و قابليت های بيشمار اين زبان از جمله دلايل قانع كننده ديگری است كه فراگيری آن را توجيه پذير و منطقی می كند. ارسال آرایه های چندبعدی به توابع در برنامه نویسی سی در این قسمت، ابتدا به نحوه ارسال آرایه های دو بعدی به توابع می پردازیم و سپس آرایه های با ابعاد بالاتر می پردازیم. شاید تصور کنید که برای تعریف یک آرایه دوبعدی بعنوان پارامتری از یک تابع، تنها قرار دادن دو علامت [] کافی است و نیازی به ذکر ابعاد آن نیست. اما متاسفانه اینگونه نیست، بلکه برنامه نویس باید تعداد ستونهای آرایه دوبعدی را صریحا مشخص نماید، اما نیازی به تعیین تعداد ردیفهای آن نیست. بعنوان مثال فرض کنید تابعی مانند test داریم که بعنوان ورودی یک آرایه دو بعدی و تعدادی پارامتر دیگر دریافت می کند. تعریف تابع بصورت زیر اشتباه است: void test(int A[][], …) { تعریف درست، تعریفی مانند زیر است: void test(int A[][10] , …) { همانطور که می بینید تعداد ردیفها مشخص نشده است، اما تعداد ستونها برابر 10 تعیین شده است. در هنگام فراخوانی تابع test، می توان هر آرایه دوبعدی 10 ستونی را به آن ارسال کرد. آرایه ارسالی به تابع می تواند 5×10 و یا 20×10 باشد، اما نمی تواند مثلا 5×20 باشد. اکنون به 2 برنامه نمونه دقت کنید. مثال) تابعي بنويسيد كه ميزان فروش تعدادي شركت در 12 ماه سال را بعنوان ورودي دريافت، و ميانگين فروش شركتي را كه بيشترين ميانگين فروش را داشته است، بازگرداند. حل) با توجه به صورت مسئله مسلم است كه اين تابع بايد يك آرايه دو بعدي را بعنوان ورودي دريافت نمايد. رديفهاي اين آرايه به تعداد شركتهاي مورد نظر و ستونهاي آن برابر 12 (يك ستون براي هر ماه از سال) مي باشد. بنابراين كافيست تابع را بگونه اي تعريف نماييم كه يك آرايه 12 ستوني را بعنوان ورودي دريافت نمايد. حل دقيق بصورت زير است: float maxSales(const long int sales[][12], int companyNo) { int i,j; float average , max; max = 0.0; for (i=0 ;i< companyNo; i++) { average = 0; for (j= 0;j<12; j++) average += sales[i][j] ; if (average > max) max = average ; } return(max); } مثال ) برنامه ای بنویسید که حاصلضرب دو ماتریس را با استفاده از یک تابع محاسبه نماید. حل) برای حل این مسئله ابتدا باید تابعی بنویسیم که دو ماتریس را بعنوان ورودی دریافت و حاصلضرب آنها را بازگرداند. مسلما بهترین روش برای ذخیره هر ماتریس، استفاده از یک آرایه دوبعدی است. اما مشکل اینجا است که طبق تعاریف گفته شده، تعداد ستونهای آرایه های ورودی باید مشخص گردد و این باعث می شود که تابع نوشته شده محدود به ضرب ماتریسهای با تعداد ستونهای مشخصی گردد. درچنین مواردی برنامه نویسان یک حد بالا برای تعداد ستونهای آرایه دوبعدی تعیین می کنند و در تعریف پارامترهای تابع از آن حد بالا استفاده می نمایند. گرچه در هنگام فراخوانی تابع، آرایه دوبعدی حتما باید دارای تعداد ستونهای مشخص شده باشد، اما لزومی ندارد همه آنها دارای داده های معتبر باشند. ممکن است فقط تعدادی از این ستونها حاوی داده های واقعی باشند. معمولا تعداد ستونهای واقعی آرایه دوبعدی بعنوان یک پارامتر مجزا به تابع ارسال می شود. به برنامه زیر دقت کنید: const int maxCol = 10; void multiply(const int A[][maxCol], const int B[][maxCol], int m,int p, int n, int C[][maxCol] ) { for (i=0; i< m; i++) for (j=0; j< n; j++) { sum = 0; for (k= 0;k < p; k++) sum += A[i][k] * B[k][j] ; C[i][j] = sum; } } void printMatrix(int matrix[][maxCol], int row,int col) { int i,j; for (i=0; i< row; i++) { for (j=0; j< col ;j++) printf(“%d ”,matrix[i][j]); printf(“\n”); } } void main() { int matrix1[2][maxCol] = { {7 ,3 , 2} , {-2, 6, 1} }; int matrix2[3][maxCol] = { {2 , 7 , -4, -1} , { 3 ,-3, 5, -8} , {6, -7, 2, 3} }; int result[2][maxCol] ; multiply(matrix1, matrix2, 2, 3, 4, result); printf(“matrix1 is :\n”); printMatrix(matrix1,2,3) ; printf(“\nmatrix2 is :\n”); printMatrix(matrix2,3,4) ; printf(“\nmultiply of matrix1 and matrix2 is :\n”); printMatrix(result,2,4) ; } matrix1 is : 7 3 2 -2 6 1 matrix2 is : 2 7 -4 -1 3 -3 5 -8 6 -7 2 3 multiply of matrix1 and matrix 2 is : 35 26 -9 -25 20 -39 40 -43 اگر به تابع multiply دقت كنيد، ابتدا دو ماتريس را بصورت ثابت دريافت مي كند (چرا كه مقادير ماتريسهاي اوليه نبايد عوض شود). سپس اندازه واقعي ماتريسها را در قالب سه پارامتر m، p و n دريافت مي نمايد، بدينصورت كه ماتريس اول m × p و ماتريس دوم p × n فرض شده است. مسلما ستونهاي ماتريس اول يعني p و ستونهاي ماتريس دوم يعني n، بايد كوچكتر از حداكثر تعداد ستونها يعني maxCol باشند. آخرين پارامتر نيز ماتريس حاصلضرب است كه خروجي تابع است (و بهمين دليل بصورت ثابت تعريف نشده است). مسلم است كه اندازه ماتريس خروجي m × n خواهدبود و نيازي به بازگردندان ابعاد آن نيست. نحوه انجام عمليات ضرب نيز قبلا و در مبحث الگوريتمها تشريح شده است. و اما در تابع اصلي، ابتدا دو ماتريس matrix1 و matrix2 تعريف شده و مقدار اوليه گرفته اند. توجه كنيد كه گرچه ابعاد اصلي matrix1 برابر 2×3 است، اما از آنجا كه تابع multiply فقط ماتريسهايي را مي پذيرد كه تعداد ستونهاي آنها برابر maxCol يعني 10 باشد، مجبور شده ايم آن را بصورت 2×10 تعريف كنيم ولي از 7 ستون آخر استفاده نكنيم. بهمين دليل matrix2 نيز كه در حقيقت 3×4 بوده است، بصورت 3×10 تعريف شده است و ماتريس حاصلضرب يعني result نيز كه بايد 2×4 باشد، بصورت 2×10 تعريف شده است. با اين تعاريف، مي توان بدون هيچ مشكلي تابع multiply را فراخواني كرد. در پايان نيز با استفاده از تابع printMatrix، ماتريسهاي اوليه و حاصلضرب آنها چاپ شده است. دقت كنيد كه تابع printMatrix نيز يك ماتريس با maxCol ستون را به همراه تعداد واقعي سطر و ستونهاي آن دريافت و آن را چاپ مي نمايد. و اما ارسال آرايه هاي با ابعاد بالاتر به توابع نيز مشابه آرايه هاي دوبعدي است. به اين صورت كه در هنگام تعريف يك پارامتر از تابع بعنوان يك آرايه چندبعدي، مشخص كردن بعد اول لزومي ندارد، اما اندازه كليه ابعاد بعدي بايد حتما مشخص گردد. بعنوان مثال تابع زير: void test(int A[][5][10], … ) { يعنوان ورودي يك آرايه سه بعدي دريافت مي نمايد كه حتما بايد بعد دوم آن 5 و بعد سوم آن 10 باشند، اما اندازه بعد اول هر مقداري مي تواند باشد. | |||||||||||
| |
| | #2 | |||||||||||
| سرپرست انجمن ![]() ![]() ![]() ![]() ![]() ![]() ![]() تاریخ عضویت: January 24th, 2007
نوشته ها: 47,791
سطح دانش: 103 [ ![]() ![]() ![]() ![]() ]سابقه در سایت: 3842 / 3842 Thanks: 69
Thanked 1,394 Times in 1,055 Posts
قدرت اعتبار: 50 | ارسال آرایه های یک بعدی به توابع در برنامه نویسی C آرایه ها را نیز همچون سایر نوع داده ها می توان به یک تابع ارسال کرد. برای اینکار ابتدا باید تابع را بگونه ای تعریف کنیم که یک پارامتر از نوع آرایه را دریافت کند. فرض کنید تابعی بنام sumArray داریم که یک آرایه یک بعدی از اعداد صحیح را بعنوان ورودی دریافت می نماید و مجموع عناصر آن را باز می گرداند. تعریف این تابع بصورت زیر است: int sumArray(int A[], int size) { int i , sum = 0; for (i=0; i< size; i++) sum += A[i]; return(sum) ; } در تابع فوق، پارامتر A بعنوان یک آرایه از اعداد صحیح معرفی شده است. همانطور که می بینید، اندازه آرایه مشخص نشده است و این یک نکته مثبت است؛ چرا که تابع sumArray می تواند هر آرایه صحیحی را با هر اندازه ای دریافت نماید. درواقع حتی اگر اندازه آرایه را نیز مشخص نمایید، کامپایلر از آن صرفنظر خواهد کرد. دومین پارامتر، اندازه واقعی آرایه A را مشخص می نماید. معمولا توابع بگونه ای نوشته می شوند که هنگام ارسال یک آرایه به یک تابع، اندازه آن نیز بعنوان یک پارامتر ارسال گردد. درغیراینصورت مجبوریم در تابع اندازه مشخصی را برای آرایه در نظر بگیریم که باعث ایجاد محدودیت در ارسال آرایه های با اندازه دلخواه می گردد. در هنگام فراخوانی تابع sumArray، برای ارسال آرایه موردنظر کافی است که تنها نام آرایه را بدون کروشه استفاده نماییم. البته اندازه واقعی آرایه نیز باید بعنوان دومین آرگومان به تابع ارسال شود. void main() { int data1[3] = {5, 10, 15}; int data2[5] = {1, 6, 4, 12, 5} ; int sum1, sum2; sum1 = sumArray(data1, 3); sum2 = sumArray(data2, 5); printf(“sum1 = %d\n”,sum1); printf(“sum2 = %d\n”,sum2); } sum1 = 30 sum2 = 28 همانطور که در مثال فوق دیده می شود، تابع sumArray دوبار فراخوانی شده است. در بار اول یک آرایه با اندازه 3، و در دفعه دوم یک آرایه با اندازه 5 به آن ارسال شده است و تابع در هر دو مورد بدون هیچ مشکلی مجموع عناصر آرایه را باز گردندانده است. نکته بسیار مهم، نحوه ارسال آرایه ها به توابع است. زبانC آرایه ها را توسط ارجاع به تابع ارسال می نماید (برخلاف انواع دیگر داده ها که درحالت عادی توسط مقدار به توابع ارسال می شدند). بدین معنا که در هنگام ارسال یک آرایه به تابع، بجای یک کپی از آرایه، خود آرایه ارسال می شود. در حقیقت در فصلهای بعدی خواهید دید که برای ارسال یک آرایه، آدرس اولین عنصر آن ارسال می گردد. لذا تابع می تواند از طریق این آدرس، به کلیه داده های آرایه اصلی دسترسی پیدا کند. اما چرا C در مورد آرایه ها به روش متفاوتی عمل می نماید؟ دلیل این مسئله آن است که معمولا یک آرایه حافظه بسیار زیادی را اشغال می کند، لذا تهیه یک کپی کردن از آن، نه تنها باعث اشغال حافظه می شود بلکه زمان زیادی را نیز صرف خواهد کرد. با ارسال آرایه ها توسط ارجاع در زمان و حافظه صرفه جویی زیادی صورت می گیرد. اما آیا می توان یک آرایه را توسط مقدار به یک تابع ارسال کرد؟ متاسفانه خیر. اما اگر نگران تغییر سهوی آرایه ارسالی به یک تابع هستید می توانید آن را بگونه ای به تابع ارسال نمایید که تغییر آن در تابع ممکن نباشد. زبان C یک نحوه دیگر ارسال داده ها به توابع بنام ارسال توسط ارجاع ثابت می باشد. چنانچه در هنگام تعریف یک پارامتر از یک تابع، از کلمه کلیدی const استفاده شود، کامپایلر اجازه تغییر مقادیر آن پارامتر را در حین اجرای تابع نخواهد داد. با این ارسال آرایه ها بصورت ارجاع ثابت، می توانیم مانع از انجام تغییرات ناخواسته در آرایه شویم. مثال زیر نحوه انجام این کار را نشان می دهد. برنامه ) برنامه ای بنویسید که با استفاده از یک تابع، اشتراک دو مجموعه را محاسبه و چاپ نماید. void intersection(const int A[], int na, const int B[], int nb, int C[], int &nc) { k = 0; for (i=0; i< na; i++) { sw = 1; for (j=0; j< nb && sw; j++) if (A[i] == B[j]) { C[k] = A[i] ; k ++; sw = 0; } } nc = k; } void printSet(int set[], int size) { int i; printf(“{ “) ; for (i=0; i< size; i++) printf(”%d ”,set[i]) ; printf(“}\n”); } void main() { int set1[5] = {5, 8, 3, 12, 20}; int set2[3] = {12, 16, 8} ; int result[3] , resultSize ; intersection(set1, 5, set2, 3, result, resultSize); printf(“set 1 = “); printSet(set1) ; printf(“set 2 = “); printSet(set2) ; printf(“intersection = “); printSet(result) ; } set1 = { 5 8 3 12 20 } set2 = { 12 16 8 } intersection = { 8 12 } همانگونه که در مثال بالا دیده می شود، تابع intersection، دو مجموعه را بعنوان ورودی دریافت و اشتراک آنها را بعنوان خروجی باز می گرداند. آرایه های A و B بعنوان پارامترهای ورودی هستند که نماینده دو مجموعه اولیه هستند. از آنجا که لزومی ندارد مقادیر این دو آرایه در تابع تغییر نماید، بعنوان پارامتر ثابت (const) به تابع ارسال شده اند. اندازه این دو آرایه نیز به ترتیب در قالب پارامترهای na و nb ارسال شده است. اما آرایه C پارامتر خروجی است که اشتراک دو مجموعه را باز می گرداند، به همین دلیل بصورت ثابت تعریف نشده است. تابع intersection، اشتراک دو مجموعه را محاسبه و مجموعه حاصل را در پارامتر C و اندازه آن را در پارامتر nc قرار می دهد. از آنجا که هم پارامتر C (بدلیل اینکه یک آرایه است) و هم پارامتر nc (بدلیل استفاده از عملگر &) توسط ارجاع به تابع ارسال شده اند، تغییرات انجام شده در آنها (یعنی حاصل نهایی) به تابع فراخواننده منتقل خواهد شد. در تابع اصلی ابتدا دو مجموعه بنامهای set1 و set2 تعریف شده و مقدار اولیه گرفته اند. سپس با استفاده از تابع intersection، اشتراک آنها محاسبه و حاصل در آرایه result و اندازه آن نیز در متغیر resultSize قرار گرفته است. سرانجام دو مجموعه اولیه و اشتراک آنها با فراخوانی تابع printSet چاپ شده اند. نکته مهم دیگر آنکه خروجی یک تابع نمی تواند یک آرایه باشد. برای بازگرداندن یک آرایه از تابع، باید آن را بصورت یک پارامتر خروجی به تابع ارسال نمود. | |||||||||||
| |
| | #3 | |||||||||||
| سرپرست انجمن ![]() ![]() ![]() ![]() ![]() ![]() ![]() تاریخ عضویت: January 24th, 2007
نوشته ها: 47,791
سطح دانش: 103 [ ![]() ![]() ![]() ![]() ]سابقه در سایت: 3842 / 3842 Thanks: 69
Thanked 1,394 Times in 1,055 Posts
قدرت اعتبار: 50 | آرایه های چند بعدی در برنامه نویسی C آرايه ها مي توانند داراي ابعاد بيشتري نيز باشند. در زبان C نيز مي توان يك آرايه چند بعدي را بصورت زير اعلان كرد: <type> <var-name> [<size 1>][<size 2>] … [<size n>] ; بعنوان مثال، اعلان زير يك آرايه دوبعدي را معرفي مي نمايد: int A[5][8] ; براي دسترسي به هر عنصر از اين آرايه بايد از دو علامت [] استفاده كرد. توجه كنيد كه انديس سطرها و ستونها هر دو از 0 آغاز مي گردند. بعنوان مثال: int A[5][8] ; A[3][1] = 24; البته در مورد آرايه هاي با ابعاد بالاتر نيز به شكل مشابهي عمل مي گردد. بعنوان مثال به نحوه استفاده از يك آرايه سه بعدي در مثال زير دقت كنيد: int B[5][8][6] ; B[2][4][0] = 12; برنامه 3) برنامه اي بنويسيد كه نمرات تعدادي دانشجو را براي 5 درس دريافت و آنها را بهمراه معدل دانشجو ذخيره نمايد، سپس براي هر دانشجو معدل وي را چاپ نمايد. void main() { const int maxStudent = 100; float grades[maxStudent][5] ; float average[maxStudent]; int i, j, n; printf("enter student number:"); scanf("%d",&n); for (i=0 ; i< n ; i++) { printf("student no %d:\n",i+1); sum = 0; for (j= 0 ;j<5 ; j++) { printf("enter grade : "); scanf("%f", &grades[i][j]); sum += grades[i][j] ; } average[i] = sum / 5 ; } for (i=0 ; i< n ; i++) printf("average of student %d is %f \n",i+1, average[i]); } و نكته آخر اينكه مقداردهي اوليه به آرايه هاي چندبعدي امكان پذير است و بصورت زير انجام مي پذيرد: int A[3][4] = { {12, 5, 3, 8} , {-3, 7, -9, 2}, {4, 22, 18, 6} }; يعني يك علامت {} براي كل مقداردهي قرار مي گيرد، سپس هر رديف از آرايه در داخل يك {} مجزا قرار مي گيرد. براي ابعاد بالاتر نيز به روش مشابهي عمل مي گردد. بعنوان مثال براي آرايه هاي سه بعدي داريم: int A[2][3][4] = { { {12, 5, 3, 8} , {-3, 7, -9, 2}, {4, 22, 18, 6} } , { {8, 1, -3, 4} , {-2, 8, 11, 21} , {7, 3, -15, -8} } }; با آرزوی موفقیت برای شما | |||||||||||
| |
| | #4 | |||||||||||
| سرپرست انجمن ![]() ![]() ![]() ![]() ![]() ![]() ![]() تاریخ عضویت: January 24th, 2007
نوشته ها: 47,791
سطح دانش: 103 [ ![]() ![]() ![]() ![]() ]سابقه در سایت: 3842 / 3842 Thanks: 69
Thanked 1,394 Times in 1,055 Posts
قدرت اعتبار: 50 | آرایه ها در برنامه نویسی c ( بخش اول ) آرايه در C عبارتست از مجموعه اي از داده هاي همنوع كه تحت يك نام مشترك و در خانه هاي متوالي حافظه ذخيره مي گردند. براي دسترسي به عناصر آرايه، بايد از نام آرايه بعلاوه انديس استفاده كرد. در قسمتهاي بعدي، نحوه تعريف و استفاده از آرايه ها را تشريح خواهيم كرد. آرايه هاي يك بعدي پيش از آنكه بتوان از يك آرايه يك بعدي استفاده كرد، بايد آن را اعلان كرد. اعلان آرايه ها بصورت زير انجام مي گردد: <type> <var-name>[<size>] ; بعنوان مثال: int A[10]; خط بالا يك آرايه 10 تايي از اعداد صحيح بنام A ايجاد مي نمايد. هر كدام از عناصر اين آرايه مي توانند بعنوان يك متغير مستقل مورد استفاده قرار گيرد. براي دسترسي به عناصر اين آرايه بايد از انديس استفاده نمود. در زبان C انديسها در داخل كروشه [] قرار مي گيرند. نكته بسيار مهمي كه بايد بدان توجه كرد آنستكه در C انديس يك عدد صحيح است كه از 0 آغاز مي گردد. به مثال زير توجه نماييد: int A[10] ; A[2] = 8; و يا چنانچه بخواهيم مقدار خانه سوم را بر 2 تقسيم و در متغير x بريزيم، داريم: x = A[3] / 2; اكنون به يك مثال دقت كنيد. برنامه 1) برنامه اي بنويسيد كه شماره دانشجويي و معدل تعدادي دانشجو را دريافت، و سپس چنانچه معدل دانشجو از ميانگين كلاس : - بيش از يك نمره بيشتر باشد، چاپ كند : عالي - حداكثر يك نمره بيشتر يا كمتر باشد، چاپ كند : خوب - بيش از يك نمره كمتر باشد، چاپ كند : ضعيف #include <stdio.h> void main() { float average[100] ; long int id[100] ; int i, n ; float totalAverage; printf("enter number of students : "); scanf("%d", &n); for (i = 0; i < n ; i ++) { printf("enter id and average : "); scanf("%ld %f", &id[i], &average[i]); totalAverage += average[i]; } totalAverage /= n; for (i = 0; i < n ; i ++) { if (average[i] > = totalAverage + 1) printf("%ld : excellent !\n", id[i]); else if (average[i] > = totalAverage – 1) printf("%ld : good !\n", id[i]); else printf("%ld : weak !\n", id[i]); } } چند نكته مهم راجع به آرايه در C وجود دارد كه حتما بايد به آنها دقت كنيد: 1- اندازه آرايه ها در C ثابت بوده و حتما بايد توسط يك مقدار ثابت صحيح تعيين گردد. بعنوان مثال اعلان زير خطاي نحوي محسوب مي گردد: int n ; n=100 ; int A[n]; اما مي توان با استفاده از متغير هاي ثابت (ثابتهاي داراي نام)، اندازه آرايه را تعيين كرد، كه در قسمتهاي بعدي به آن اشاره خواهد شد. 2- انديس آرايه ها در C عدد صحيح بوده و هميشه از 0 شروع مي شود. لذا به تفاوت "عنصر چهار آرايه" يعني A[4] و "چهارمين عنصر آرايه" يعني A[3] دقت كنيد. اين مسئله معمولا باعث بروز خطاهاي منطقي مي گردد. 3- در C مرز آرايه ها بررسي نمي گردد. بدين معنا كه چنانچه انديسي خارج از محدوده مجاز يك آرايه استفاده شود، باعث ايجاد خطا توسط كامپايلر نمي گردد، اما مسلما برنامه را دچار يك خطاي منطقي خواهد كرد. بعنوان مثال: int A[10] ; A[12] = 20 ; //this is not a syntax error but a logical error لذا بررسي مرزهاي آرايه بعهده خود برنامه نويس است و بايد از درستي برنامه خود و خارج نشدن از محدوده مجاز مطمئن گردد. 4- مقداردهي اوليه به آرايه هاي يك بعدي بصورت زير انجام مي پذيرد: int A[3] = {5, 2, 8}; كه در اينجا A[0] برابر 5 ، A[1] برابر 2 و A[2] برابر 8 خواهد شد. علاوه براين مي توان فقط به تعدادي از عناصر آرايه مقدار داد، دراينصورت مقدار عناصر باقيمانده آرايه اتوماتيك 0 خواهد شد. int B[10] = {5, 8} ; در اينجا عناصر B[2] به بعد مقدار 0 خواهند گرفت. بنابراين مي توان براي 0 كردن كليه عناصر يك آرايه به شكل زير عمل كرد : int C[10] = {0}; چنانچه به آرايه مقدار دهي اوليه كرده باشيم، مي توان تعداد عناصر آرايه را نيز ذكر نكرد، دراينصورت اندازه آرايه بطور اتوماتيك برابر تعداد مقادير مشخص شده خواهد شد. int C[] = {10, 15, 20}; در مثال فوق آرايه C با 3 عضو درنظر گرفته مي شود. | |||||||||||
| |
| | #5 | |||||||||||
| سرپرست انجمن ![]() ![]() ![]() ![]() ![]() ![]() ![]() تاریخ عضویت: January 24th, 2007
نوشته ها: 47,791
سطح دانش: 103 [ ![]() ![]() ![]() ![]() ]سابقه در سایت: 3842 / 3842 Thanks: 69
Thanked 1,394 Times in 1,055 Posts
قدرت اعتبار: 50 | ساختارهای کنترلی در زبان c در فصل ششم اشاره کردیم که در برنامه نویسی ساختیافته، هر برنامه از 3 ساختار کنترلی بنام: ساختار ترتیب، ساختار انتخاب و ساختار تکرار تشکیل می گردد. از آنجا كه اين 3 ساختار، نحوه و ترتيب اجراي برنامه را كنترل مي كنند، به آنها ساختارهاي كنترلي گفته مي شود. تا کنون فقط با برنامه هایی سروکار داشته ایم که از ساختار ترتیب استفاده می کرده اند، چرا که دستورهای زبان C در حالت عادی به همان ترتیبی که نوشته شده اند، یکی پس از دیگری اجرا می شوند. اما زبان C دارای 3 نوع ساختار انتخاب می باشد که عبا رتند از : ساختار if یا ساختار تک انتخابی، ساختار if / else یا ساختار دو انتخابی و ساختار switch یا ساختار چند انتخابی. علاوه براین، این زبان دارای 3 نوع ساختار تکرار بنامهای while، for و do / while نیز می باشد که هریک را بطور کامل شرح خواهیم داد. قرارداد: توجه کنید که در هنگام تشریح یک دستور، خود دستور با رنگ آبی و عملگرهای آن مانند () با رنگ قرمز نشان داده می شوند. قسمتهایی که در داخل <> قرار می گیرند، عبارت یا دستوری هستند که باید در هنگام استفاده جایگزین گردند. ساختار انتخاب if این دستور به شکل زیر استفاده می شود: if (<expresion>) <statement>; نحوه کار بدینصورت است که ابتدا عبارت موجود در قسمت <expression> ارزیابی می شود. در صورتیکه درست ارزیابی گردد، دستور قسمت <statement> اجرا خواهد شد و در صورتیکه نادرست باشد، بدون اینکه دستور قسمت <statement> را اجرا کند به دستور بعدی خواهد رفت. این دستور می تواند بصورت زیر نیز استفاده گردد: if (<expresion>) <statement 1>; else <statement 2>; در اینصورت ابتدا عبارت موجود در قسمت <expression> ارزیابی می شود. در صورتیکه درست ارزیابی گردد، دستور قسمت <statement 1> اجرا خواهد شد، و در صورتیکه نادرست باشد، دستور قسمت <statement 2> اجرا خواهد شد. در هر حال فقط یکی از این دو قسمت اجرا خواهد گردید. دقت کنید که پرانتز استفاده شده پس از دستور if برخلاف برخی زبانهای دیگر، اجباری است. علاوه براین، در این دستور نیازی به استفاده از then نمی باشد. بعنوان مثال چنانچه متغیر grade حاوی نمره دانشجو باشد و بخواهیم بر مبنای نمره وی، پیغام مناسبی چاپ کنیم، می توانیم از دستور زیر استفاده کنیم: if (grade> = 10) printf(“Passed !”); else printf(“Failed!”); در حالت عادی دستور if منتظر یک دستور در بدنه خود می باشد، اما چنانچه می خواهید چندین دستور را در بدنه یک دستور if دهید، باید آنها را در داخل آکولاد باز وبسته { } قرار دهید. این مجموع دستورات را یک دستور مرکب می گویند. بطور کلی در زبان C هرجا که می توان یک دستور قرار داد، می توان از یک دستور مرکب نیز استفاده کرد.به یک دستور مرکب، بلوک نیز گفته می شود. بنابراین صورت کلی دستور if به شکل زیر است: if (<expression>) { <statement 1> ; <statement 2> ; …. <statement n> ; } else { <statement 1> ; <statement 2> ; ……. <statement m> ; } توجه کنید که وجود قسمت else اختیاری است و در ضمن ممکن است یکی از دو قسمت دارای دستور ساده و دیگری دارای دستور مرکب باشد. بعنوان یک مثال کاملتر به برنامه زیر توجه کنید: برنامه 1) برنامه ای بنویسید که ضرایب یک معادله درجه 2 را دریافت و ریشه های آن را محاسبه و چاپ نماید. #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <math.h> void main() { int a, b, c; float x1, x2, delta; clrscr(); printf(“Please enter a, b and c : “); scanf(“%d %d %d”, &a, &b, &c); if (a==0) { printf(“wrong equation!”); exit(1) ; } delta = b*b – 4*a*c; if (delta <0) printf(“No answer !”); else if (delta == 0) { x1 = -b / (2*a); printf(“There is one answer, x = %f”,x1); } else { delta = sqrt(delta); x1 = (-b+delta) / (2*a); x2 = (-b-delta) / (2*a); printf(“There are two answers, x1= %4.2f and x2= %4.2f”, x1, x2); } } Please enter a, b and c : 3 -7 2 There is two answers, x1 = 2.00 and x2 = 0.33 چندين نكته درمورد برنامه بالا قابل ذكر است. 1- در اين برنامه از 2 تابع جديد استفاده شده است.اولي تابع sqrt كه يك عدد را به عنوان ورودي دريافت و جذر آن را باز مي گرداند. اين تابع در فايل math.h تعريف شده است. و ديگري تابع exit كه باعث مي شود اجراي برنامه خاتمه يابد. اين تابع نيز در فايل stdlib.h تعريف شده است. 2- به نحوه دندانه گذاري در برنامه دقت كنيد، هرجا كه بلوك جديدي ايجاد شده است، دستورات آن حدود 3 كاراكتر جلوتر نوشته شده اند. اينكار باعث مي شود كه خوانايي برنامه افزايش يابد. 3- توجه كنيد كه همانطور كه قبلا نيز گفته شد، خروجي يك عبارت مقايسه اي، يك عدد است كه 0 نشانه نادرست و هر عدد ديگر نشانه درست است. بنابراين در قسمت شرط يك دستور if مي توان بجاي يك عبارت مقايسه اي، هر عبارت ديگري كه يك مقدار عددي بازگرداند نيز قرار داد! بعنوان مثال مي توان بجاي دستور if (a==0) … از دستور زير استفاده كرد: if (!a) … دراينصورت چنانچه a برابر صفر باشد، نادرست تلقي خواهد شد و در نتيجه نقيض آن يعني ! ، درست محسوب مي گردد. يك روش متداول استفاده از دستور if، استفاده از if هاي تودرتو مي باشد كه در مثال بالا نيز ديده مي شود. دراينحالت مجموعه اي از عبارات if-else-if بصورت متداخل قرار داده مي شوند. بعنوان نمونه به مثال زير توجه كنيد: if (grade> = 18) printf("good!"); else if (grade> = 15) printf("medium!"); else if (grade> = 12) printf("rather weak!"); else if (grade> = 10) printf("weak"); else printf("failed!"); در چنين دستوري، كليه شرطها بترتيب از بالا به پايين بررسي شده و به محض اينكه يكي از آنها درست باشد، دستور مربوط به آن اجرا شده و از بقيه دستورات صرفنظر مي گردد. درصورتيكه هيچ يك از شرطها درست نباشد، دستور مربوط به آخرين else اجرا مي گردد. درچنين حالتي توصيه مي گردد كه شرطهاي نادر را كه امكان وقوع آنها كم است، در انتهاي كار بررسي نماييد، تا تعداد مقايسه كمتري صورت پذيرد. مشكلي كه در مورد if هاي تودرتو پيش مي آيد، مسئله تعيين if مربوط به هر else است. بعنوان مثال در مورد دستور زير، else به كدام if تعلق دارد؟ if (a <b) if (c <d) <statement1>; else <statement2>; همانطور كه از دندانه گذاري نيز مشخص است، else مربوط به دومين if مي باشد. يعني <statement 2> درصورتي اجرا خواهد شد كه a<b درست باشد، اما c<d درست نباشد. بطور كلي طبق قوانين گرامري، هر else مربوط به نزديكترين if قبل از خود مي باشد. اما سوال اين است كه اگر بخواهيم else به if اول بازگردد از چه روشي استفاده نماييم. دراينصورت مي توان از يكي از دو روش زير استفاده كرد: if (a < b) if (a <b) { if (c <d) <statement 1> ; if (c <d) <statement1>; else ; } else <statement2>; else <statement2>; بعنوان يك مثال ديگر، به نمونه زير دقت كنيد: if (<c1>) { if (<c2>) if (<c3>) <statement2>; else <statement 3>; // this refer to if (<c3>) } else <statement 4>;//this refer to if <c1> برنامه 2) برنامه اي بنويسيد كه 3 عدد را دريافت و حداكثر آنها را چاپ كند. #include <stdio.h> void main() { int a, b, c, max; printf("Please enter 3 numbers :"); scanf("%d %d %d",&a, &b, &c); if (a> b) if (a> c) max = a; else max= c; else if (b> c) max = b; else max = c; printf("Maximum is %d",max); } ساختار تكرار while همانطور كه در بخش الگوريتمها نيز گفته شد، يك ساختار تكرار باعث مي شود تا زمانيكه شرط خاصي برقرار است، عمليات مشخصي تكرار گردد. دستور while نيز باعث ايجاد يك حلقه تكرار به شكل زير مي گردد: while (<expression>) <statement>; اين دستور باعث مي شود تا زمانيكه شرط موجود در قسمت <expression> درست است، دستور قسمت <statement> تكرار شود، و به محض اينكه شرط نادرست گردد، كنترل اجرا به دستور بعد از حلقه مي رود. بازهم دستور موجود در قسمت <statement> مي تواند يك دستور مركب باشد، دراينصورت دستور بصورت زير درخواهد آمد: while (<expression>) { <statement1>; <statement2>; ……. <statementn>; } برنامه 3) برنامه اي بنويسيد كه يك عدد را دريافت و فاكتوريال آن را محاسبه و چاپ نمايد. #include <stdio.h> void main() { int i,number; long int factorial; printf("Please enter number :"); scanf("%d",&number); factorial = 1; i = 1; while (i <= number) { factorial *= i; i ++; } printf("Factorial of %d is %ld"number,factorial); } برنامه 4) برنامه اي بنويسيد كه يك متن را از كاربر دريافت و آن را با حروف بزرگ چاپ كند. #include <stdio.h> void main() { char ch; ch = getch() ; while (ch != 13) { if (ch>= 'a' && ch <= 'z') ch -= 32; putch(ch); ch = getch(); } } ساختار تكرار for همانگونه كه در مثال مربوط به حل مسئله فاكتوريال ديده مي شود، گاهي نياز به حلقه تكراري داريم كه به تعداد دفعات مشخصي تكرار گردد. در چنين مواقعي با استفاده از يك متغير شمارنده، تعداد تكرارها را تا رسيدن به مقدار مورد نظر می شماریم و سپس به حلقه پایان می دهیم. به چنین حلقه هایی، تکرار تحت کنترل شمارنده یا تکرار معین می گوییم، چرا که تعداد تکرار ها از قبل مشخص است. چنین حلقه ای دارای 3 جزء اصلی می باشد: 1- مقداردهی اولیه به متغیر شمارنده حلقه 2- شرط پایان حلقه (پایان شمارش) 3- نحوه افزایش متغیر شمارنده از آنجا که در تمام حلقه هایی که تکرار معین دارند، همین ساختار استفاده می شود؛ در اکثر زبانهای برنامه سازی یک ساختار تکرار ویژه، بنام حلقه for، برای اینکار در نظر گرفته شده است. اما در این بین، حلقه تکرار for در زبان C دارای ویژگیهای خاصی است که آنرا از سایر زبانها متمایز کرده و به آن قدرت بسیار بالایی داده است. شکل کلی این دستور بصورت زیر است: for (<exp1> ; <exp2> ; <exp3> ) <statement>; وظایف عبارات فوق بشرح زیر است : 1- <exp1>، مقداردهی اولیه به متغیر حلقه 2- <exp2>، شرط اجرای حلقه 3- <exp3>،نحوه افزایش متغیر حلقه البته همانندموارد قبل بازهم قسمت <statement> می تواند یک دستور مرکب باشد. نحوه کار حلقه بدینصورت است که در ابتدای شروع حلقه <exp1> فقط برای یکبار اجرا می شود. سپس عبارت <exp2> بررسی می گردد و در صورتیکه درست ارزیابی شود (≠ 0)، آنگاه دستور <statement> اجرا شده و سپس به ابتدای حلقه باز می گردد. از اجرای دوم به بعد، ابتدا عبارت <exp3> اجرا می گردد (یعنی متغیر حلقه افزایش می یابد) و سپس عبارت <exp2> بررسی می گردد و مجددا درصورت درست بودن، حلقه تکرار می شود. اینکار تا زمانیکه مقدار عبارت <exp2> نادرست ( = 0) ارزیابی شود، تکرار می گردد. به محض اینکه این اتفاق بیفتد، کنترل اجرا به دستور پس از حلقه انتقال می یابد. درحقیقت هر حلقه for معادل با حلقه while زیر است: <exp1> ; while (<exp2>) { <statement>; <exp3>; } بعنوان یک مثال ساده، تکه برنامه زیر اعداد بین 0 تا 100 را چاپ می نماید: int count; for (count = 0; count <= 100; count ++) printf(“%d “,count); اگر بخواهيم تنها مضارب 5 چاپ شوند، حلقه را به شكل زير تغيير مي دهيم: for (count = 0; count <= 100; count += 5) حتي مي توان مضارب 5 را از آخر به اول چاپ كرد: for (count = 100; count> = 0; count -= 5) قسمت شرط مي تواند يك شرط مركب نيز باشد، بعنوان مثال: for (count = 0; count <100 && sw==1; count ++) كه در اينصورت در هربار اجراي حلقه، علاوه بر مقدار شمارنده، مقدار متغير sw نيز بررسي مي گردد. نكته آخر اينكه قسمت مقدار دهي اوليه و افزايش متغير نيز مي توانند شامل چند عبارت باشند كه در اينصورت با كاما از يكديگر جدا مي شوند. بعنوان مثال: for (a = 0, b = 100; b – a> 50; a++, b--) در ادامه یک مثال کاملتر برای تشریح این حلقه آمده است: برنامه 5) برنامه ای بنویسید که تعدادی عدد را از کاربر دریافت و 2 عدد بزرگتر و مجموع آنها را محاسبه و چاپ نماید. #include <stdio.h> void main() { int i, n, number; int sum, max1, max2; printf(“please enter n : “); scanf(“%d”,&n); sum = 0; max1 = max2 = -1; for (i=1 ; i<n ; i++) { printf(“enter number : “); scanf(“%d”,&number); sum += number; if (number> max1) { max2 = max1; max1 = number; } else if (number> max2) max2 = number; } //end for printf(“Sum = %d, Maximum 1=%d, Maximum 2= d”, sum, max1, max2); } نكته جالب در مورد حلقه for آنستكه مي توان هريك از 3 عبارت فوق را حذف كرد. به مثالهاي زير توجه كنيد: for (;i<100; i++) مقداردهي اوليه حذف شده است. اين در صورتي است كه بنحوي قبل از شروع حلقه، مقدار متغير i تعيين شده باشد. for (i= 0;i<100 نحوه افزايش متغير حلقه حذف شده است. اين مورد زماني بكار مي رود كه نحوه افزايش متغير حلقه پيچيده بوده و توسط برنامه نويس در داخل حلقه انجام شود. for (;i<100 هر دو مورد فوق حذف شده است. for (i=0; ;i++) شرط ادامه حلقه حذف شده است. اين مورد زياد متداول نيست و ممكن است باعث شود حلقه براي هميشه اجرا شود. در چنين مواردي حتما بايد در داخل حلقه با استفاده از دستور break (كه در قسمتهاي بعدي توضيح داده خواهد شد)، راهي براي خروج از حلقه قرار داده شود. حلقه do / while همانگونه كه در قسمت الگوريتمها توضيح داده شد، در بعضي مواقع لازم است كه شرط ، در انتهاي حلقه بررسي گردد. دستور do / while از نوع حلقه هايي است كه ابتدا دستورات را اجرا كرده و سپس شرط ادامه حلقه را بررسي مي نمايد. شكل كلي اين دستور بصورت زير است: do <statement> ; while (<expression>) ; نحوه كار اين حلقه به اين صورت است كه ابتدا دستور <statement> اجرا مي گردد، سپس شرط حلقه بررسي شده و درصورتيكه درست بود، به ابتداي حلقه باز گشته و آن را مجددا اجرا مي كند. البته دستور <statement> مي تواند يك دستور مركب باشد. بعنوان يك مثال كوچك، ممكن است شما از كاربر خواسته ايد كه اعلام كند آيا مايل به ادامه هست يا خير؟ وي بايد پاسخ y يا n بدهد، اما ممكن است يك حرف اشتباه (مانند m) وارد كند. قصد داريم تكه برنامه اي بنويسيم كه عمل دريافت پاسخ را تا زمانيكه يك حرف درست وارد شود، تكرار كند. مسلم است كه بايد ابتدا يك پاسخ وارد شود و سپس درستي آن بررسي گردد. char answer; do { printf("Do you want to continue (y/n) ?"); answer = getch(); } while (answer != 'y' && answer != 'n') ; بعنوان يك نمونه كاملتر به مثال زير توجه كنيد. برنامه 6) فرض كنيد نمرات يك گروه از دانشجويان بصورت درجه بندي (A, B, C and D) آماده شده است. برنامه اي بنويسيد كه نمرات دانشجويان را دريافت و در پايان درصد هريك از نمرات را محاسبه و چاپ نمايد. در ضمن از آنجا كه تعداد دانشجويان از قبل مشخص نيست، كاربر در انتهاي نمرات، حرف Q (مخفف Quit) را وارد مي نمايد. #include <stdio.h> void main() { int aCount, bCount, cCount, dCount, n; char grade; aCount = bCount = cCount = dCount = n = 0; do { printf("Enter grade (Q for Quit) : "); grade = getch() ; n ++; if (grade == 'A') aCount ++; else if (grade == 'B') bCount ++; else if (grade == 'C') cCount ++; else if (grade == 'D') dCount ++; else if (grade == 'Q') n --; else { printf("Wrong grade, try again.\n"); n --; } } while (grade != 'Q' ) ; printf("Statistics :\n"); printf("Grade A : %f percent\n", float(aCount)/float(n)); printf("Grade B : %f percent\n", float(bCount)/float(n)); printf("Grade C : %f percent\n", float(cCount)/float(n)); printf("Grade D : %f percent\n", float(dCount)/float(n)); } // end main ساختار switch / case اگر مجددا به برنامه 6 دقت كنيد، خواهيد ديد كه در بعضي موارد قصد داريم برحسب مقادير مختلف يك عبارت (در اينجا مقدار متغير grade)، عمليات متفاوتي را انجام دهيم. گرچه اينكار با استفاده از دستورات if / else متداخل قابل انجام است، اما ساختار مناسبتري نيز براي اينكار وجود دارد، كه به آن ساختار چندانتخابي مي گوييم. شكل كلي ان ساختار بصورت زير است: switch (<expression>) { case <exp1> : <statement 1> ; <statement 2> ; … <statementn>; case <exp2> : <statement 1> ; <statement 2> ; … <statementn>; … default : <statement 1> ; <statement 2> ; … <statementn>; } برنامه 7) برنامه 6 را با استفاده از دستور switch / case بازنويسي نماييد. برنامه را بگونه اي بنويسيد كه حروف بزرگ و كوچك هردو مورد قبول واقع شود. #include <stdio.h> void main() { int aCount, bCount, cCount, dCount, n; char grade; aCount = bCount = cCount = dCount = n = 0; do { printf("Enter grade (Q for Quit) : "); grade = getch() ; n ++; switch (grade) { case 'A' : case 'a' : aCount ++; break ; case 'B' : case 'b' : bCount ++; break ; case 'C' : case 'c' : cCount ++; break ; case 'D' : case 'd' : dCount ++; break ; case 'Q' : case 'q' : n--; break ; default : printf("Wrong grade, try again.\n"); n --; } //end switch } while (grade != 'Q' ) ; printf("Statistics :\n"); printf("Grade A : %f percent\n", float(aCount)/float(n)); printf("Grade B : %f percent\n", float(bCount)/float(n)); printf("Grade C : %f percent\n", float(cCount)/float(n)); printf("Grade D : %f percent\n", float(dCount)/float(n)); } // end main برنامه 8) برنامه اي بنويسيد كه يك عدد، يك عملگر و يك عدد ديگر را از كاربر دريافت و پس از اعمال عملگر برروي دو عدد، حاصل را چاپ نمايد. #include <stdio.h> void main() { int number2, number2, result; char op ; printf("Please enter number1 operator number2 : "); scanf("%d %c %d",&number1, &number2, &op, &number3); result = 0; switch (op) { case '+' : result = number1 + number2 ; break; case '-' : result = number1 - number2 ; break; case '*' : result = number1 * number2 ; break; case '/' : if (number2 != 0) result = number1 / number2 ; else printf("There is no answer!\n"); break; case '%' : if (number2 != 0) result = number1 % number2 ; else printf("There is no answer!\n"); break; default : printf("invalid operator!\n"); } printf("Result = %d",&result); } دستورات break و continue اين دستورات قادرند مسير اجراي برنامه را در يك حلقه تكرار تغيير دهند. البته اين تغيير مسير بصورت كنترل شده بوده و همانند دستور goto نمي توان به هرجاي دلخواه پرش كرد. چنانچه دستور break در يك ساختار while، for، do/while ويا switch بكار رود، باعث مي شود كه بلافاصله كنترل اجراي برنامه از ساختار خارج شده و به اولين دستور پس از ساختار برود. قبلا كاربرد اين دستور را در switch ديده ايد. در اينجا به مثال زير دقت كنيد: برنامه 9) برنامه 5 را بگونه اي تغيير دهيد كه فقط اعداد مثبت را بپذيرد، و درصورتيكه عدد منفي وارد شد، بلافاصله به عمليات خاتمه داده و نتايج تا همين نقطه را چاپ نمايد. #include <stdio.h> void main() { int i, n, number; int sum, max1, max2; printf(“please enter n : “); scanf(“%d”,&n); sum = 0; max1 = max2 = -1; for (i=1 ; i<n ; i++) { printf(“enter number : “); scanf(“%d”,&number); if (number <0) break; // this is the difference sum += number; if (number> max1) { max2 = max1; max1 = number; } else if (number> max2) max2 = number; } //end for printf(“Sum = %d, Maximum 1=%d, Maximum 2= d”, sum, max1, max2); } اما دستور continue فقط در حلقه هاي while، for و do/while بكار مي رود. نحوه عمل آن بدين صورت است كه به محض آنكه كنترل اجرا به اين دستور برسد، بلافاصله از باقيمانده حلقه صرفنظر كرده و مجددا به ابتداي حلقه باز مي گردد و اجراي آن را از سر مي گيرد. در مورد حلقه for، پس از بازگشت به ابتداي حلقه، عمل افزايش مقدار متغير حلقه نيز صورت مي پذيرد. بعنوان مثال، چنانچه بخواهيم برنامه 9 را بگونه اي تغيير دهيم كه از اعداد منفي صرفنظر كند و آنها را در محاسبات لحاظ نكند، كافيست دستور if (number <0) break; را به دستور زير تبديل كنيم: if (number <0) continue; دراينصورت، چنانچه عدد منفي باشد، بدون اينكه محاسبات بعدي انجام شوند، كنترل به ابتداي حلقه بازگشته و عدد بعدي را دريافت مي كند. | |||||||||||
| |
| | #6 | |||||||||||
| سرپرست انجمن ![]() ![]() ![]() ![]() ![]() ![]() ![]() تاریخ عضویت: January 24th, 2007
نوشته ها: 47,791
سطح دانش: 103 [ ![]() ![]() ![]() ![]() ]سابقه در سایت: 3842 / 3842 Thanks: 69
Thanked 1,394 Times in 1,055 Posts
قدرت اعتبار: 50 | مفاهیم اولیه زبان C در این فصل به مقدمات اولیه برنامه نویسی به زبان C می پردازیم و اصول اولیه آن را بررسی می نماییم شناسه ها در C شناسه (identifier) نامی است که به یک قسمت از برنامه مانند متغیر، تابع، ثابت و یا ... داده می شود. در زبان C برای انتخاب شناسه ها فقط می توان از علائم زیر استفاده کرد: - حروف انگلیسی کوچک و بزرگ (A…Z a…z) - ارقام (0…9) - علامت خط پایین یا _ البته یک شناسه تمی تواند با یک رقم شروع شود. مثلا شناسه های sum ، average ، name2 و یا student_average مجاز هستند، اما شناسه های 2name و یا student average مجاز نیستند. البته در برنامه نویسی امروزی پیشنهاد می شود بجای شناسه هایی همانند student_average از studentAverage استفاده گردد. یعنی بجای اینکه در شناسه ها از _ برای جداکننده استفاده کنیم، اولین حرف هر قسمت را بصورت بزرگ بنویسیم. نکته مهم دیگری که باید به آن اشاره کرد آنستکه زبان C برخلاف بسیاری از زبانهای دیگر به کوچک و بزرگی حروف حساس است (case sensitive). در نتیجه شناسه های زیر با یکدیگر متفاوتند : Sum ≠ sum ≠ SUM این مسئله معمولا درهنگام برنامه نویسی باعث ایجاد بعضی خطاها می شود. آخرین نکته اینستکه در هنگام انتخاب شناسه نمی توانید از کلمات کلیدی که برای منظورهای خاص در زبان C رزرو شده اند استفاده کنید. زبان C دارای 32 کلمه کلیدی است که عبارتند از : 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 البته در نسخه های جدید C کلمات کلیدی دیگری نیز به لیست فوق اضافه شده است. دقت کنید که کلیه این کلمات با حروف کوچک نوشته شده اند. انواع داده ها در C همانطور که قبلا نیز گفتیم هر متغیر پیش از آنکه استفاده گردد ابتدا باید اعلان گردد. اعلان یک متغیر تعیین نوع آن را نیز دربر می گیرد. سوال اصلی آنستکه چه نوع داده هایی در زبان C و جود دارد. انواع داده های متداول عبارتند از : نوع داده توضیح اندازه (بیت) محدوده char کاراکتر 8 -128 to +127 int عدد صحیح 16 -32768 to + 32767 float عدد اعشاری 32 3.4e-38 to 3.4e+38 double عدد اعشاری با دقت مضاعف 64 1.7e-308 to 1.7e+308 البته چند نکته مهم درمورد جدول فوق قابل ذکر است : - اندازه int در محیطهای 16 بیتی مانند DOS برابر 16 بیت است. اما در محیطهای 32 بیتی همانند Windows اندازه آن 32 بیت می باشد که در اینصورت محدوده ای برابر -2,147,483,647 تا +2,147,483,647 را پوشش می دهد. - در بعضی از کامپایلرهای C، نوع داده bool نیز وجود دارد که می تواند یکی از مقادیر true(درست) یا false (غلط) را نشان دهد . اما در نسخه های اولیه C از همان نوع داده صحیح یا int برای اینکار استفاده می شد. بدین صورت که 0 نشاندهنده false و هر عدد غیر صفر (معمولا 1) نشاندهنده true است. - از آنجا که برای ذخیره سازی کاراکترها کد اسکی آنها ذخیره می گردد، از یک متغیر کاراکتری یا char می توان بعنوان یک عدد صحیح کوچک نیز استفاده کرد و اعمال ریاضی برروی آنها نیز مجاز است. علاوه براین چندین اصلاح کننده نیز وجود دارد که به ما اجازه می دهد نوع داده مورد نظر را با دقت بیشتری برای نیازهای مختلف استفاده نماییم. این اصلاح کننده ها عبارتند از : short, long, signed, unsigned تمام اصلاح کننده های فوق می توانند به نوع داده int اعمال شوند و اثر آنها بستگی به محیط دارد. مثلا در یک محیط 16 بیتی، short int بازهم برابر 16 بیت است ولی long int برابر 32 بیت خواهد بود. علاوه براین unsigned int باعث می شود که یک عدد 16 بیتی بدون علامت داشته باشیم که بازه بین 0 تا 65535 را پوشش می دهد. signed int نیز همانند int معمولی بوده و تفاوتی ندارد. البته ترکیب این اصلاح کننده ها نیز ممکن است. مثلا unsigned long int یک عدد 32 بیتی بدون علامت است که بازه 0 تا 4,294,967,295 را پوشش می دهد. اما برروی نوع داده char فقط اصلاح کننده های signed و unsigned را می توان اعمال کرد. معمولا از اصلاح کننده unsigned وقتی استفاده می شود که قصد داشته باشیم از char بعنوان یک عدد صحیح مثبت بین 0 تا 255 استفاده کنیم. برروی نوع داده double تنها اصلاح کننده long قابل اعمال است و دراینصورت عدد اعشاری با 80 بیت را خواهیم داشت که قادر است هر عددی در بازه 3.4e-4932 تا 1.1e+4932 را در خود نگاه دارد. تعریف متغیرها برای تعریف متغیرها به شکل زیر عمل می کنیم: <type> <variable-list>; که type یکی از نوع داده های گفته شده و variable-list لیستی از متغیرها است که با کاما از یکدیگر جدا شده اند. بعنوان مثال : int sum; float average; long int a, b, c ; unsigned long int i, j, k ; علاوه براین می توان در هنگام تعریف متغیر به آن مقدار اولیه نیز داد. مثال : int d = 0 ; نكته مهم آنكه زبان C به متغيرها مقدار اوليه نمي دهد (حتي 0) و برنامه نويس خود بايد اينكار را صريحا انجام دهد، درغير اينصورت مقدار اوليه متغير، نامعين خواهد بود. تعریف متغیرها طبق اصول زبان C میتواند درهرجایی از برنامه صورت پذیرد، و متغیرهای تعریف شده از همان خط به بعد قابل استفاده خواهد بود. اما معمولا توصیه می گردد كه تعریف متغیرها در همان خط ابتدایی تابع و بلافاصله پس از { صورت پذیرد. ثوابت ثابتها مقادیر ثابتی هستند كه مقدار آنها در حین اجرای برنامه تغییر نمی یابد. ثابتها می توانند از هریك از نوع داده های اصلی باشند. برای نمایش هر ثابت بسته به نوع آن عمل می كنیم كه شرح هریك در زیر آمده است : 4 ثوابت عددی صحیح : برای نمایش این دسته از ثوابت، از دنباله ای از ارقام بعلاوه علامت + یا - استفاده می كنیم. بعنوان مثال 45- و یا 3489 ثوابت صحیح هستند. در حالت عادی C هر عدد را در كوچكترین نوع داده ای كه می تواند قرار می دهد. مثلا عدد 85 در یك int قرار می گیرد، اما عدد 145398 در یك long int قرار خواهد گرفت. اما اگر قصد دارید یك عدد كوچك بعنوان long محسوب گردد، می توانید از پسوند L در انتهای آن استفاده می كنیم. مثلا 245L یك عدد long محسوب می شود. long int a = 20L; ضمن اینكه پسوند U در انتهای عدد نیز نشانه بدون علامت بودن آن است. نكته دیگر آنكه C به شما اجازه می دهد درصورت لزوم ثوابت صحیح خود را در مبنای 8 یا 16 نیز كه از مبناهای متداول در برنامه نویسی هستند، بنویسید. برای نوشتن عدد در مبنای 8 باید آن را با 0 آغاز كنید، مثلا 0342 یك عدد در منای 8 محسوب می گردد. اما برای نوشتن یك عدد در مبنای 16 باید آن را با 0x آغاز نمایید، مانند 0x27A4. 8 ثوابت عددی اعشاری : برای نمایش اعداد اعشاری، باید از نقطه اعشار استفاده كنیم، مانند 237.45 ، اما نكته جالب آنستكه می توانید از نماد علمی نیز برای نمایش اعداد اعشاری استفاده كنید. برای اینكار كافی است از حرف e برای نمایش قسمت توان استفاده نمایید. بعنوان مثال : -23.47 × 10 5 = -23.47e5 42.389 × 10 -3 = 42.389e-3 دقت كنید كه قسمت توان، حتما یك عدد صحیح است. نكته جالب اینجاست كه برخلاف مورد قبل، كامپایلر بطور پیش فرض داده های اعشاری را از نوع double فرض می كند.چنانچه دوست دارید ثابت شما ازنوع float درنظر گرفته شود، در انتهای آن F قرار دهید. ضمنا پسوند L نیز داده اعشاری را از نوع long double درنظر می گیرد. 10 ثوابت كاراكتری : برای نشان دادن ثوابت كاراكتری، آنها را در داخل ' قرار می دهیم. بعنوان مثال 'A' یك ثابت كاراكتری است. char ch = 'S' ; دقت كنید كه همانطور كه قبلا گفته شد، كد اسكی كاراكترها در متغیر ذخیره می گردد، بنابراین می توان از آن بعنوان یك عدد صحیح نیز استفاده كرد. نكته مهم دیگر آنستكه به تفاوت عدد 5 و كاراكتر '5' دقت داشته باشید. در حقیقت '5' برابر است با عدد 53 كه همان كد اسكی آن است. از آنجا كه بعضی كاراكترها، مانند enter قابل نمایش نیستند، بهمین دلیل آنها را با استفاده از \ نمایش می دهیم. علاوه براین بعضی كاراكترها مانند خود " نیز چون دارای معنای خاص هستند، باید با استفاده از \ نمایش داده شوند. موارد مهم عبارتند از : \n خط جدید \t tab كاراكتر \a بوق كامپیوتر \" " \' ' \\ \ 14 ثوابت رشته ای : C علاوه بر ثوابت فوق، از یك ثابت دیگر بنام رشته نیز حمایت می كند. رشته، دنباله ای از كاراكترها است كه در داخل " قرار می گیرند. بعنوان مثال "this is a test" یك رشته است. دقت كنید كه 'a' یك كاراكتر است، اما "a" یك رشته است كه فقط شامل یك كاراكتر می باشد. عملگرها عملگر، نمادی است كه به كامپایلر می گوید تا عملیات محاسباتی یا منطقی خاصی را برروی یك یا چند عملوند، انجام دهد. به عملگرهایی كه فقط یك عملوند دارند، عملگر یكانی می گوییم و همواره عملگر در سمت چپ عملوند قرار می گیرد(مانند عدد -125). اما عملگرهایی كه برروی دو عملوند اثر می كنند را عملگر دودویی نامیده و عملگر را بین دو عملوند قرار می دهیم (مانند 23+86). هر ترکیب درستی از عملگرها و عملوندها را یک عبارت می نامیم. C از نقطه نظر عملگرها یك زبان بسیار قوی است. این عملگرها به چند دسته اصلی تقسیم می گردند كه آنها را به ترتیب بررسی می كنیم.. عملگرهای محاسباتی این عملگرها، همان اعمال متداول ریاضی هستند كه در زبان C مورد استفاده قرار می گیرند. این اعمال عبارتند از : عمل; نوع عملگر منفی كردن عملوند سمت راست یكانی - جمع دو عملوند دودویی + تفریق دو عملوند دودویی - ضرب دو عملوند دودویی * تقسیم دو عملوند دودویی / محاسبه باقیمانده تقسیم دو عملوند دودویی % | |||||||||||
| |
| | #7 | |||||||||||
| سرپرست انجمن ![]() ![]() ![]() ![]() ![]() ![]() ![]() تاریخ عضویت: January 24th, 2007
نوشته ها: 47,791
سطح دانش: 103 [ ![]() ![]() ![]() ![]() ]سابقه در سایت: 3842 / 3842 Thanks: 69
Thanked 1,394 Times in 1,055 Posts
قدرت اعتبار: 50 | مقدمه ای بر زبان C پس از نوشتن یک الگوریتم باید آن را با استفاده از یک زبان برنامه نویسی تبدیل به یک برنامه قابل اجرا برای کامپیوتر نماییم. این زبانها به سه دسته کلی تقسیم میگردند : 1- زبان ماشین (سطح پایین) : این زبان مستقیما با صفر و یک نوشته می شود و بدون هیچ واسطه ای برروی کامپیوتر قابل اجرا است. طراحان سخت افزار هر کامپیوتر، زبان ماشین خاص خود را برای آن ماشین طراحی می نمایند. به همین دلیل هر برنامه ای که به زبان ماشین نوشته شود، فقط برروی همان ماشین خاص کار می کند، بهمین دلیل برنامه های نوشته شده به زبان ماشین را غیر قابل حمل می نامند. از طرف دیگر یادگیری این زبان بسیار مشکل بوده و برنامه نویسی با آن نیز بسیار سخت است و همچنین احتمال بروز خطا نیز در آن زیاد است. 2- زبان اسمبلی : این زبان شکل ساده تر زبان ماشین است، بدین صورت که برای هر دستورالعمل زبان ماشین، یک اسم نمادین انتخاب شده است (مانند دستور ADD بجای کد دودویی دستورالعمل جمع) که بخاطر سپردن و برنامه نویسی با آنها برای انسانها ساده تر است. اما این برنامه ها برای ماشین قابل فهم نیست و باید قبل از اجرا شدن توسط برنامه مترجمی بنام اسمبلر به زبان ماشین تبدیل شود. توجه کنید که از آنجا که هر دستور زبان اسمبلی معادل یک دستور زبان ماشین است، این زبان نیز وابسته به ماشین می باشد و برنامه های نوشته شده به این زبان فقط برروی همان کامپیوتری که برای آن نوشته شده اند قابل اجرا است. علاوه براین کار با این زبانها هنوز هم نسبتا مشکل بود و فقط متخصصین کامپیوتر قادر به استفاده از آنها بودند. 3- زبانهای سطح بالا : دستورالعملهای این زبانها بسیار نزدیک به زبان انسانها (بطور مشخص زبان انگلیسی) می باشد و بهمین دلیل برنامه نویسی به آنها بسیار ساده تر بوده و می توان الگوریتمها را به راحتی به این زبانها تبدیل کرد. از آنجا که این زبانها به هیچ ماشین خاصی وابسته نیستند، برنامه های نوشته شده با این زبانها (تا حد زیادی) قابل حمل می باشند. مثالهایی از این زبانها عبارتند از : - بیسیک (Basic): برای کاربردهای آموزشی - فرترن (Fortran) : برای کاربردهای علمی و مهندسی - پاسکال (Pascal) : برای کاربردهای آموزشی و علمی و بالاخره زبان برنامه نویسی C که درمورد آن بیشتر صحبت خواهیم کرد. البته برنامه های نوشته شده به این زبانها ابتدا باید به زبان ماشین ترجمه شوند تا برروی کامپیوتر قابل اجرا باشند. برای ترجمه این زبانها از کامپایلرها و یا مفسرها (به فصل 1 مراجعه کنید) استفاده می شود. تاریخچه C برای بررسی تاریخچه زبان C باید به سال 1967 بازگردیم که مارتین ریچاردز زبان BCPL را برای نوشتن نرم افزارهای سیستم عامل و کامپایلر در دانشگاه کمبریج ابداع کرد. سپس در سال 1970 کن تامپسون زبان B را بر مبنای ویژگیهای زبان BCPL نوشت و از آن برای ایجاد اولین نسخه های سیستم عامل Unix در آزمایشگاههای بل استفاده کرد. زبان C در سال 1972 توسط دنیس ریچی از روی زبان B و BCPL در آزمایشگاه بل ساخته شد و ویژگیهای جدیدی همچون نظارت بر نوع داده ها نیز به آن اضافه شد. ریچی از این زبان برای ایجاد سیستم عامل Unix استفاده کرد اما بعدها اکثر سیستم عاملهای دیگر نیز با همین زبان نوشته شدند. این زبان با سرعت بسیاری گسترش یافت و چاپ کتاب "The C Programming Language" در سال 1978 توسط کرنیگان و ریچی باعث رشد روزافزون این زبان در جهان شد. متاسفانه استفاده گسترده این زبان در انواع کامپیوترها و سخت افزارهای مختلف باعث شد که نسخه های مختلفی از این زبان بوجود آید که با یکدیگر ناسازگار بودند. در سال 1983 انستیتوی ملی استاندارد آمریکا (ANSI) کمیته ای موسوم به X3J11 را را مامور کرد تا یک تعریف فاقد ابهام و مستقل از ماشین را از این زبان تدوین نماید.در سال 1989 این استاندارد تحت عنوان ANSI C به تصویب رسید و سپس در سال 1990، سازمان استانداردهای بین المللی (ISO) نیز این استاندارد را پذیرفت و مستندات مشترک آنها تحت عنوان ANSI/ISO C منتشر گردید. در سالهای بعد و با ظهور روشهای برنامه نویسی شی گرا نسخه جدیدی از زبان C بنام C++ توسط بیارنه استراوستروپ در اوایل 1980 در آزمایشگاه بل توسعه یافت. در C++ علاوه بر امکانات جدیدی که به زبان C اضافه شده است، خاصیت شی گرایی را نیز به آن اضافه کرده است. با گسترش شبکه و اینترنت، نیاز به زبانی احساس شد که برنامه های آن بتوانند برروی هر ماشین و هر سیستم عامل دلخواهی اجرا گردد. شرکت سان مایکروسیستمز در سال 1995 میلادی زبان Java را برمبنای C و C++ ایجاد کرد که هم اکنون از آن در سطح وسیعی استفاده می شود و برنامه های نوشته شده به آن برروی هر کامپیوتری که از Java پشتیبانی کند(تقریبا تمام سیستمهای شناخته شده) قابل اجرا می باشد. شرکت مایکروسافت در رقابت با شرکت سان، در سال 2002 زبان جدیدی بنام C# (سی شارپ) را ارائه داد که رقیبی برای Java بشمار می رود. برنامه نویسی ساخت یافته در دهه 1960 میلادی توسعه نرم افزار دچار مشکلات عدیده ای شد. در آن زمان سبک خاصی برای برنامه نویسی وجود نداشت و برنامه ها بدون هیچگونه ساختار خاصی نوشته می شدند. وجود دستور پرش (goto) نیز مشکلات بسیاری را برای فهم و درک برنامه توسط افراد دیگر ایجاد می کرد، چرا که جریان اجرای برنامه مرتبا دچار تغییر جهت شده و دنبال کردن آن دشوار می گردید. لذا نوشتن برنامه ها عملی بسیار زمان بر و پرهزینه شده بود و معمولا اشکال زدایی, اعمال تغییرات و گسترش برنامه ها بسیار مشکل بود. فعالیتهای پژوهشی در این دهه باعث بوجود آمدن سبک جدیدی از برنامه نویسی بنام روش ساختیافته گردید؛ روش منظمی که باعث ایجاد برنامه هایی کاملا واضح و خوانا گردید که اشکال زدایی و خطایابی آنها نیز بسیار ساده تر بود. اصلی ترین نکته در این روش عدم استفاده از دستور پرش (goto) است. تحقیقات بوهم و ژاکوپینی نشان داد که می توان هر برنامه ای را بدون دستور پرش و فقط با استفاده از 3 ساختار کنترلی ترتیب، انتخاب و تکرار نوشت. ساختار ترتیب، همان اجرای دستورات بصورت متوالی (یکی پس از دیگری) است که کلیه زبانهای برنامه نویسی در حالت عادی بهمان صورت عمل می کنند. ساختار انتخاب به برنامه نویس اجازه می دهد که براساس درستی یا نادرستی یک شرط، تصمیم بگیرد کدام مجموعه از دستورات اجرا شود. ساختار تکرار نیز به برنامه نویسان اجازه می دهد مجموعه خاصی از دستورات را تا زمانیکه شرط خاصی برقرار باشد، تکرار نماید. (برای شرح بیشتر موارد فوق به فصل 3 مراجعه نمایید). هر برنامه ساختیافته از تعدادی بلوک تشکیل می شود که این بلوکها به ترتیب اجرا می شوند تا برنامه خاتمه یابد(ساختار ترتیب). هر بلوک می تواند یک دستورساده مانند خواندن، نوشتن یا تخصیص مقدار به یک متغیر باشد و یا اینکه شامل دستوراتی باشد که یکی از 3 ساختار فوق را پیاده سازی کنند. نکته مهم اینجاست که درمورد دستورات داخل هر بلوک نیز همین قوانین برقرار است و این دستورات می توانند از تعدادی بلوک به شرح فوق ایجاد شوند و تشکیل ساختارهایی مانند حلقه های تودرتو را دهند. نکته مهم اینجاست که طبق قوانین فوق یک حلقه تکرار یا بطور کامل داخل حلقه تکرار دیگر است و یا بطور کامل خارج آن قرار می گیرد و هیچگاه حلقه های روی هم افتاده نخواهیم داشت. از جمله اولین تلاشها در زمینه ساخت زبانهای برنامه نویسی ساختیافته، زبان پاسکال بود که توسط پروفسور نیکلاس ویرث در سال 1971 برای آموزش برنامه نویسی ساختیافته در محیطهای آموزشی ساخته شد و بسرعت در دانشگاهها رواج یافت. اما بدلیل نداشتن بسیاری از ویژگیهای مورد نیاز مراکز صنعتی و تجاری در بیرون دانشگاهها موفقیتی نیافت کمی بعد زبان C ارائه گردید که علاوه بر دارا بودن ویژگیهای برنامه نویسی ساختیافته بدلیل سرعت و کارایی بالا مقبولیتی همه گیر یافت و هم اکنون سالهاست که بعنوان بزرگترین زبان برنامه نویسی دنیا شناخته شده است. مراحل اجرای یک برنامه C برای اجرای یک برنامه C ابتدا باید آن را نوشت. برای اینکار می توان از هر ویرایشگر متنی موجود استفاده کرد و سپس فایل حاصل را با پسوند .C ذخیره نمود (فایلهای C++ با پسوند .CPP ذخیره می گردند). به این فایل، کد مبدا (source code) گفته می شود. مرحله بعدی تبدیل کد مبدا به زبان ماشین است که به آن کد مقصد (object code) گفته می شود. همانطورکه قبلا نیز گفته شد برای اینکار از یک برنامه مترجم بنام کامپایلر استفاده می شود. کامپایلرهای متعددی برای زبان C توسط شرکتهای مختلف و برای سیستم عاملهای مختلف نوشته شده است که می توانید برحسب نیاز از هریک از آنها استفاده نمایید. اما هنوز برنامه برای اجرا آماده نیست. معمولا برنامه نویسان از در برنامه های خود از یک سری از کدهای از پیش آماده شده برای انجام عملیات متداول (مانند محاسبه جذر و یا سینوس) استفاده می کنند که برنامه آنها قبلا نوشته و ترجمه شده است. این برنامه ها یا در قالب کتابخانه های استاندارد توسط شرکتهای ارائه کننده نرم افزار عرضه شده است و یا توسط دیگر همکاران برنامه نویس اصلی نوشته و در اختیار وی قرار داده شده است. در این مرحله باید کد مقصد برنامه اصلی با کدهای مربوط به این برنامه های کمکی پیوند زده شود. برای اینکار نیاز به یک پیوند زننده (Linker) داریم و نتیجه این عمل یک فایل قابل اجرا خواهد بود (در ویندوز این فایل پسوند .EXE خواهد داشت). مرحله بعدی اجرای برنامه و دادن ورودیهای لازم به آن و اخذ خروجیها می باشد. در شکل زیر این مراحل نشان داده شده اند. مسلما طی مراحل بالا برای اجرای هر برنامه زمانبر می باشد، بهمین دلیل اکثر تولید کنندگان کامپایلرها، محیطهایی را برای برنامه نویسی ارائه کرده اند که کلیه مراحل بالا را بطور اتوماتیک انجام می دهند. به این محیطها IDE (Integrated Development Environment) یا محیط مجتمع توسعه نرم افزار گفته می شود. این محیطها دارای یک ویرایشگر متن می باشند که معمولا دارای خواص جالبی همچون استفاده از رنگهای مختلف برای نشان دادن اجزای مختلف برنامه مانند کلمات کلیدی، و یا قابلیت تکمیل اتوماتیک قسمتهای مختلف برنامه می باشد. پس از نوشتن برنامه و با انتخاب گزینه ای مانند Run کلیه عملیات فوق بطور اتوماتیک انجام شده و برنامه اجرا می گردد. علاوه براين، اين محيطها معمولا داراي امكانات اشكالزدايي برنامه (Debug) نيز مي باشند كه شامل مواردي همچون اجراي خط به خط برنامه و يا ديدن محتويات متغيرها در زمان اجرا است. چند محيط معروف برنامه نويسي عبارتند از : Borland C++ 3.1 براي محيط DOS Borland C++ از نسخه 4 به بالا براي Windows Microsoft Visual C++ براي محيط Windows Borland C++ Builder برای محیط Windows براي شروع ما از محيط Borland C++ 3.1 تحت Dos كه نحوه كار ساده تري نسبت به سايرين دارد استفاده مي كنيم. پس از نصب اين نرم افزار، برنامه BC.exe را اجرا كنيد تا وارد محيط borland c شويد همانطور كه مي بينيد، اين محيط از 3 قسمت اصلي تشكيل شده است : - بخش ويرايش برنامه : بخش آبي رنگ وسط مي باشد كه در حقيقت يك ويرايشگر است كه برنامه در آن تايپ مي شود. همانطور كه مي بينيد در اين ويرايشگر از رنگهاي مختلف براي نشان دادن قسمتهاي مختلف برنامه استفاده مي شود. مثلا براي كلمات كليدي از رنگ سفيد استفاده شده است. - بخش منوهاي كاري : اين بخش كه در قسمت بالا واقع شده است،- حاوي تعدادي منو (گزينه) براي انجام وظايف مختلف است. خلاصه اين عمليات عبارتند از : o منوي File : عملياتي مانند باز كردن و يا ذخيره يك برنامه o منوي Edit : عمليات ويرايش مانند حذف،o كپي و يا چسباندن يك قسمت از برنامه o منوي Search : جستجوي و يا تعويض يك متن در برنامه o منوي Run : اجراي برنامه بصورت كامل يا دستور به دستور o منوي Compile : عمليات مربوط به كامپايل و پيوند برنامه o منوي Debug : عمليات مربوط به اشكالزدايي مانند ديدن مقادير متغيرها در زمان اجرا o منوي Project : عمليات مربوط به مديريت برنامه هايي كه شامل چندين فايل مستقل هستند (پروژه) o منوي Options : عمليات مربوط به تنظيمات سيستم مانند نحوه كامپايل و يا رنگ پيش فرض محيط o منوي Windows : عمليات مربوط به پنجره هاي باز فعلي (مربوط به چندين برنامه يا نمايش متغيرها و ... ) خطاهای برنامه نویسی بنظر می رسد خطاها جزء جداناپذیر برنامه ها هستند. بندرت می توان برنامه ای نوشت که در همان بار اول بدرستی و بدون هیچگونه خطایی اجرا شود. اما خطاها از لحاظ تاثیری که بر اجرای برنامه ها می گذارند، متفاوتند. گروهی ممکن است باعث شوند که از همان ابتدا برنامه اصلا کامپایل نشود و گروه دیگر ممکن است پس از گذشت مدتها و در اثر دادن یک ورودی خاص به برنامه، باعث یک خروجی نامناسب و یا یک رفتار دور از انتظار (مانند قفل شدن برنامه) شوند. بطور کلی خطاها به دو دسته تقسیم می شوند خطاهای نحوی (خطاهای زمان کامپایل): این خطاها در اثر رعایت نکردن قواعد دستورات زبان C و یا تایپ اشتباه یک دستور بوجود می آیند و در همان ابتدا توسط کامپایلر به برنامه نویس اعلام می گردد. برنامه نویس باید این خطا را رفع کرده و سپس برنامه را مجددا کامپایل نماید. لذا معمولا این قبیل خطاها خطر کمتری را در بردارند. خطاهای منطقی (خطاهای زمان اجرا): این دسته خطاها در اثر اشتباه برنامه نویس در طراحی الگوریتم درست برای برنامه و یا گاهی در اثر درنظر نگرفتن بعضی شرایط خاص در برنامه ایجاد می شوند. متاسفانه این دسته خطاها در زمان کامپایل اعلام نمی شوند و در زمان اجرای برنامه خود را نشان می دهند. بنابراین، این خود برنامه نویس است که پس از نوشتن برنامه باید آن را تست کرده و خطاهای منطقی آن را پیدا کرده و رفع نماید. متاسفانه ممکن است یک برنامه نویس خطای منطقی برنامه خود را تشخیص ندهد و این خطا پس از مدتها و تحت یک شرایط خاص توسط کاربر برنامه کشف شود. بهمین دلیل این دسته از خطاها خطرناکتر هستند. خود این خطاها به دو دسته تقسیم می گردند: a. خطاهای مهلک: در این دسته خطاها کامپیوتر بلافاصله اجرای برنامه را متوقف کرده و خطا را به کاربر گزارش می کند. مثال معروف این خطاها،b. خطای تقسیم بر صفر می باشد. c. خطاهای غیرمهلک: در این دسته خطا،d. اجرای برنامه ادامه می یابد ولی برنامه نتایج اشتباه تولید می نماید. بعنوان مثال ممکن است دراثر وجود یک خطای منطقی در یک برنامه حقوق و دستمزد،e. حقوق کارمندان اشتباه محاسبه شود و تا مدتها نیز کسی متوجه این خطا نشود! با توجه به آنچه گفته شد، در می یابیم که رفع اشکال برنامه ها بخصوص خطاهای منطقی از مهمترین و مشکلترین وظایف یک برنامه نویس بوده و گاهی حتی سخت تر از خود برنامه نویسی است! بهمین دلیل است که بسیاری از شرکتها(همانند مایکروسافت) ابتدا نسخه اولیه نرم افزار خود را در اختیار کاربران قرار می دهند تا اشکالات آن گزارش شده و رفع گردد. بسیار مهم است که در ابتدا سعی کنید برنامه ای بنویسید که حداقل خطاها را داشته باشد، در گام دوم با آزمایش دقیق برنامه خود هرگونه خطای احتمالی را پیدا کنید و در گام سوم بتوانید دلیل بروز خطا را پیدا کرده و آنرا رفع نمایید. هر سه عمل فوق کار سختی بوده و نیاز به تجربه و مهارت دارد. آخرین نکته اینکه در اصطلاح برنامه نویسی به هر گونه خطا، bug و به رفع خطا debug گفته می شود. يك برنامه نمونه در اين قسمت براي آشنايي اوليه با زبان C يك برنامه نمونه آورده شده است كه بدون هيچ تغييري در محيط BorlandCPP قابل اجرا است. // This Program Computes the Area of a Circle #include <stdio.h> void main() { int radius ; float area; printf("please enter radius : "); scanf("%d",&radius); area = 2 * 3.14 * radius; printf("Area is %f",area); { please enter radius : 10 Area is 62.8 درمورد برنامه فوق به نکات زیر توجه کنید : - خط اول یک توضیح درمورد برنامه است. در زبان C برای توضیحات یک خطی از علامت // استفاده می گردد. اما چنانچه توضیحات بیش از یک خط بود،- آن را با علامت /* شروع کرده و با */ پایان دهید. کامپایلر از این توضیحات صرفنظر خواهد کرد. این توضیحات باعث می شوند که برنامه شما خواناتر شده و دیگران بهتر آن را درک کنند. - هر دستوری که با علامت # شروع شود،- یک دستور C نیست،- بلکه جزو دستورات پیش پردازنده محسوب می گردد. دستورات پیش پردازنده،- دستوراتی هستند که توسط کامپایلر قبل از شروع به کامپایل انجام می شوند. بعنوان مثال دستور #include باعث می شود که تعاریف اولیه مربوط به توابعی (زیربرنامه هایی) که قصد استفاده از آنها را داریم به برنامه اضافه شود. در مثال بالا برای استفاده از توابع printf و scanf که در کتابخانه استاندارد C تعریف شده اند،- فایل سرآمد stdio.h را که این توابع در آن تعریف شده اند را استفاده کرده ایم. - هر برنامه C باید دارای تابعی به نام main باشد که اجرای برنامه از آن شروع می شود و در حقیقت همان برنامه اصلی است. البته می توان هر تعداد دیگری تابع (زیربرنامه) نیز تعریف کرد،- اما وجود تابع main الزامی است. دقت کنید که گرچه این تابع پارامتر ورودی ندارد،- اما از پرانتز باز و بسته تنها استفاده شده است. - در زبان C هر بلوک برنامه با علامت { آغاز شده و با } پایان می یابد. این دو معادل دستورات begin و end در زبانهای دیگر ازجمله پاسکال می باشند که برای سادگی زبان انتخاب شده اند. - دو خط بعدی به تعریف متغیرهای radius و area می پردازد. در زبان C قبل از استفاده از هر متغیری باید آن را اعلان نمایید. اعلان متغیر شامل نام و نوع متغیر است. در مثال فوق،- متغیر radius از نوع عدد صحیح(integer) و متغیر area از نوع عدد اعشاری (float) تعریف شده اند. - توابع printf و scanf جزو کتابخانه استاندارد C محسوب می گردند و به ترتیب برای چاپ اطلاعات در خروجی استاندارد (نمایشگر) و دریافت اطلاعات از ورودی استاندارد (صفحه کلید) استفاده می شوند. برای چاپ رشته مورد نظر باید آنها را در داخل علامت " قرار داد. درمورد این توابع بعداد توضیح خواهیم داد. - دقت کنید که در پایان هر دستورالعمل از علامت ; استفاده شده است. در مجموع C یک زبان قالب آزاد است و شما می توانید دستورات را به هر نحوی که دوست دارید قرار دهید (مثلا چند دستور در یک خط از برنامه). تنها چیزی که نشاندهنده پایان یک دستور است،- علامت ; است(و نه انتهای خط). - از آنجا که C یک زبان قالب آزاد است،- می توان با استفاده از مکان نوشتن دستورات شکل بهتری به برنامه داد. بعنوان مثال دقت کنید که پس از شروع تابع main،- دستورات حدود 3 کاراکتر جلوتر نوشته شده اند. به این نحوه نوشتن دستورات دندانه گذاری می گویند. بطور کلی هربار که بلوک جدیدی آغاز می شود،- باید آن را کمی جلوتر برد. این مسئله باعث جدا شدن بلوکها از یکدیگر و خوانایی بهتر برنامه می شود. - در پایان برنامه و در داخل مستطیل خاکستری،- یک نمونه از اجرای برنامه که شامل یک ورودی و خروجی نمونه است،- آورده شده است. | |||||||||||
| |
| برچسب ها |
| آشنائی , با , زبان |
| ابزارهای موضوع | |
| |
تمامي قوانين اين سايت از جمهوري اسلامي ايران پيروي مي کند و هرگونه مطالب مخالف قوانين ايران و بنر يا لينک مستهجن در اين سايت جايي ندارد