آموزش ++C، ساختار(Struct) – مثالها

بدون دیدگاه

در نوشته قبل و در آموزش ساختار به بیان مفاهیم و اصول استراکچر پرداخته شد. در این نوشته در قالب دو مساله کاربردی از این مفاهیم استفاده شده است . در هر دو مساله مثالهای مرتبط از ساده به سخت مرتب شده است.

مساله اول – دانشجویان

در این مساله به بیان چند مثال کاربردی مرتبط با دانشجویان پرداخته شده است. اولین نکته ای در مثال بعد خواهید آموخت طریقه استفاده از آرایه ای از استراکچر است:

مثال ۱- برنامه ای بنویسید که از ورودی اطلاعات ۱۰۰ دانشجو شامل نام دانشجو، شماره دانشجو و معدل دانشجو دریافت کند و بالاترین معدل را چاپ کند.

در آموزش ساختار در مورد دریافت اطلاعات یک دانشجو صحبت کردیم و در آنجا استراکچر student را معرفی کردیم. اما در این مثال نیاز است که ما اطلاعات ۱۰۰ دانشجو را از ورودی دریافت کنیم. بنابراین باید از آرایه ها استفاده کنیم. اگر به یاد داشته باشید برای تعریف یک آرایه ۱۰۰ تایی از نوع int از کد زیر استفاده میکردیم:

;int A[100]

دقیقا به همین صورت می‌توان آرایه ای از استراکچر student تعریف کرد:

;student s[100]

در تصویر زیر استراکچر student را می‌بینید که شامل سه عضو داده ای number، name و avg است. ما در این مثال به آرایه ای از جنس student نیاز داریم. آرایه S آرایه ای از جنس student است و همانطور که در تصویر می‌بینید هر درایه این آرایه شامل سه عضو داده ای است.که برای دسترسی به هر کدام از اعضا مانند قبل باید از دات ( . ) استفاده کنیم. مثلا چنانچه بخواهید به نام Ali دسترسی داشته باشید باید اینگونه بنویسید: s[0].name و یا برای دسترسی به شماره دانشجویی Sina باید به این شکل دسترسی پیدا کنید: S[3].number. با توجه به اینکه شما میخواهید بالاترین معدل را پیدا کنید در واقع به یک پیمایش شبیه به نوار قرمز رنگ در تصویر زیر نیاز دارید:

با این توضیحات به سراغ کد می‌رویم:

توضیح کد:
در خط ۱۸ تا ۳۰ اطلاعات دانشجویان در آرایه قرار میگیرد. آرایه s از جنس student است بنابراین هر خانه آرایه از جنس student است و شامل سه متغیر name، number و avg است. بنابراین دستور cin>>s[i] به تنهایی یک کد اشتباه است و باید مشخص کنیم که کدام عضو داده ای این اندیس قرار است دریافت شود. در خط ۲۱، ۲۴ و ۲۷ اعضای داده ای s[i] دریافت می‌شوند.
دز خط ۳۲ تا ۳۴ کل آرایه پیمایش می‌شود و فقط عضو داده ای avg اعضا ملاقات می‌شود. دوباره تاکید میکنیم که s[i] به تنهایی بی معنی است و باید دقیق مشخص شود که به چه عضو داده ای s[i] نیاز داریم. در خط ۳۳ با استفاده از s[i].avg به تک تک معدل دانشجویان دسترسی پیدا میکنیم و با مقایسه آن با max بزرگترین عدد را پیدا میکنیم.

تذکر: در خط ۱۳ مقدار n را برابر ۱۰۰ قرار داده ایم، شما اگر میخواهید این برنامه را تست کنید n=3 قرار دهید تا در تست برنامه نیاز به وارد کردن اطلاعات ۱۰۰ دانشجو نداشته باشید! اگر از نحوه استفاده const هم اطلاعی ندارید مثال ۴ آموزش آرایه را بخوانید.

در مثال بالا فقط معدل دانشجو را پیدا کردیم. در مثال بعدی همه اطلاعات دانشجویی که بیشترین معدل را دارد چاپ می‌شود.

مثال ۲ – برنامه ای بنویسید که اطلاعات ۱۰۰ دانشجو را از ورودی دریافت کند و نام دانشجویی که بیشترین معدل دارد را چاپ کند.

اگر به یاد داشته باشید در بحث آرایه ها به دو روش جستجوی یک عدد را انجام دادیم. یکی پیدا کردن عدد (به این معنی که آیا عدد در آرایه وجود دارد یا خیر) و دیگری پیدا کردن مکان آن عدد (به این معنی که اگر عدد در آرایه وجود دارد در چه خانه ای ذخیره شده است. (مثال ۵ آموزش آرایه را ببینید) در این مثال از ایده روش دوم استفاده می‌کنیم، یعنی اگر در پیمایش آرایه متوجه شدیم که معدل از max بزرگتر است اندیس خانه آرایه را در idx ذخیره میکنیم. مثلا در تصویر زیر ما به دنبال یافتن خانه ۲ آرایه هستیم. زیرا اگر شما این خانه را پیدا کنید ( که در آن بزرگترین معدل آرایه وجود دارد) به راحتی میتوانید به نام و معدل دانشجو دسترسی داشته باشید.

با این توضیحات به سراغ کد می‌رویم:

توضیح کد:
همانظور که بالاتر توضیح داده شد، در خط ۳۳ تا ۳۷ با استفاده از اندیس i، تک تک خانه های آرایه پیمایش می‌شود و چنانچه معدل دانشجو از max بیشتر باشد علاوه بر اینکه متغیر max آپدیت می‌شود اندیس آرایه یا همان i در idx ذخیره می‌شود.
اگر مثال ۵ از بحث آرایه را خوانده باشید متوجه خواهید شد که این کد را بدون استفاده از متغیر max نیز می‌توان پیاده کرد:

در مثال آخر از مساله دانشجویان چند

مثال سوم: برنامه ای بنویسید که از ورودی اطلاعات ۱۰۰ دانشجو شامل نام، شماره دانشجویی، معدل و تاریخ تولد آنها را دریافت کند. سپس:
الف) میانگین معدل کلاس را چاپ کند.
ب) نام دانشجویانی که معدل آنها از میانگین معدل دانشجویان بیشتر است را چاپ کند.
ج) تعداد دانشجویانی که معدل زیر ۱۴ دارند را چاپ کند.
د) نام جوانترین دانشجوی کلاس را چاپ کند.

با توجه به توضیحات کاملی که در مثال ۱ و ۲ دادیم انتظار داریم که موارد الف، ب و ج را بتوانید به راحتی کد نویسی کنید. بهتر است ابتدا خودتان این ۴ مورد را کدنویسی کنید و سپس کد زیر را نگاه کنید.

توضیح کد:
موارد الف، ب و ج نیاز به توضیح اضافه ندارند و کدها گویا هستند. اما در مورد قسمت د باید این نکته را اضافه کنیم که برای کار با تاریخ بهتر است تابعی به نام timestamp تعریف کنیم. در مواقع این تابع تاریخ دریافتی را به تعداد روزها تبدیل میکند. بنابراین اگر ما به دنبال جوانترین دانشجو هستیم و بخواهیم از این تابع استفاده کنیم در واقع باید به دنبال بزرگترین روز باشیم. زیرا فردی که جوان تر است عدد برگشتی آن از این تابع بزرگتر می‌شود. بنابراین در خط ۷۴ آرایه dates را تعریف کردیم که در این آرایه عدد برگشتیِ تاریخ تولد هر دانشجو از تابع timestamp در آن ذخیره می‌شود. یعنی به ازای هر دانشجو تاریخ تولدش را به تابع timestamp میدهیم و مقدار بازگشتی از این تابع را در اندیس متناظر آن در dates قرار میدهیم. (مثلا تایم استمپ دانشجوی اول در خانه اول dates ذخیره میشود، تایم استمپ دانشجوی دوم در خانه دوم dates و …) در خط ۷۸ تا ۸۱ با روش مثال دوم، اندیس بزرگترین خانه آرایه پیدا می‌شود و در انتها نام آن دانشجو چاپ می‌شود. توجه داشته باشید که آرایه های s و dates در راستای هم هستند. یعنی اطلاعات خانه صفر آرایه s و اطلاعات خانه صفر آرایه dates متعلق به یک دانشجو هستند و بنابراین می‌توانسیتیم این اطلاعات را در یک استراکچر جمع کنیم. به این معنی که مثلا عضو داده ای timestamp را به کلاس student اضافه کنیم:

به عنوان تمرین می‌توانید قسمت د را با استراکچر جدید پیاده کنید. (توجه کنید که دیگر نیازی به آرایه dates نداریم)

مساله دوم – مختصات دو بعدی

در این مساله می‌خواهیم در مورد مختصات دوبعدی مثال حل کنیم. قبل از این که به مثالها برسیم کمی در مورد کاربرد جذاب این مساله صحبت کنیم. مطالبی که در ادامه مطرح می‌شود صرفا جهت بالا بردن انگیزه شما در یادگیری این مثالهاست و چنانچه این مطالب را کامل متوجه نشدید جای نگرانی نیست و میتوانید مستقیما به سراغ مثالها بروید.

OCR

OCR که مخفف عبارت Optical Character Reader است، تکنولوژی است که صفحات حاوی متنی که اسکن کرده‌اید را از فرمت عکس به متن تبدیل می‌کند. از یک مثال ساده استفاده می‌کنیم. حتما نرم افزارهایی را دیده‌اید که کارت بانکی شما را اسکن می‌کنند و شماره کارت موجود در عکس را بیرون می‌کشند. این نرم‌افزارها نمونه ساده ای از OCR ها هستند.

تصویر ۱

اما این نرم افزار ها چگونه عمل می‌کنند؟ در واقع این نرم افزارها داده هایی تحت عنوان داده های آموزشی دارند که از این داده ها برای تشخیص اعداد روی کارت استفاده می‌کنند. فرض کنید که این داده ها در نرم افزار برچسب گذاری شده اند و به ازای هر تصویر میدانیم که این تصویر چه عددی است:

تصویر ۲

حال کافیست الگوریتمی نوشته شود که ابتدا ارقام موجود در کارت به ۱۶ تصویر (که هر کدام شامل یک رقم است) تبدیل شود و هر عکس را با عکسهای موجود در داده های آموزشی (تصویر ۲) مطابقت دهد و نزدیکترین (شبیه ترین) عکس را پیدا کند. از آنجایی که داده های آموزشی برچسب گذاری شده است و میدانیم هر عکس چه عددی است به این شکل می‌توان اعداد روی کارت را شناسایی کنیم. سوالی که ممکن است در ذهن شما نقش ببندد این است که چطور میتوان نزدیکترن عکس را پیدا کرد؟ شاید اگر به این مساله بخواهید فکر کنید هیچ روشی که بتوان الگوریتم آن را نوشت و پیاده سازی کرد به ذهنتان نرسد. زیرا که داده های ورودی شما عکس است و تا به حال با این جنس مساله روبرو نشده اید. برای این کار ما نیاز به مدل بندی مساله داریم. برای این کار باید عکس را به گونه ای به آرایه تبدیل کنیم که آرایه نماد آن عکس باشد. به این معنی که بتوانیم از آن آرایه هم عکس را تولید کنیم. اینکه چه طور می‌شود عکس را به آرایه تبدیل کرد در حوصله این بحث نیست ولی همین که متوجه شدید برای کار کردن با عکس، باید عکس را به آرایه یا ماتریس مدل بندی کرد قدم بزرگی در درک برنامه ها و نرم افزارهای اطراف شماست. الان شما میدانید که اگر میخواهید دو عکس شبیه به هم را پیدا کنید در واقع باید به دو آرایه شبیه به هم را پیدا کنید. البته اگر بخواهیم دقیق تر صحبت کنیم منظور ما از آرایه مثلا ۵ تایی، یک نقطه در مختصات ۵ بعدی است. ساده تر بخواهیم در نظر بگیریم آرایه دوتا میشود همان نقطه ای که در صفحات دو بعدی روی کاغذ با آن کار میکنیم. در مثالهای پیش رو ما با مختصات دو بعدی کار میکنیم ولی شما می‌توانید همچنان مساله OCR را در ذهن خودتان در این مثالها دنبال کنید.

مثال ۱- برنامه ای بنویسید که از ورودی دو نقطه (در مختصات دو بعدی) از ورودی دریافت کند و فاصله این دو نقطه را محاسبه کند.

در این مثال داده ورودی ما نقطه است. هر نقطه یک x دارد و یک y. بنابراین بهتر است از یک استراکچر به نام point استفاده کنیم که شامل دو عضو داده ای x و y است. پس وقتی میخواهیم دو نقطه از ورودی دریافت کنیم در واقع میخواهیم دو متغیر از جنس point از ورودی دریافت کنیم. کد زیر را ببینید:

توضیح کد:
در خط ۶ تا ۸ استراکچر point تعریف شده است، در خط ۱۳ تا ۲۷ دو نقطه از ورودی دریافت شده است و در خط ۳۰ فاصله دو نقطه چاپ شده است. همانطور که در آموزشهای قبل هم گفته شده است تابع sqr(x) جذر x و تابع pow(a,b) مقدار a به توان b را محاسبه میکند که پارامترهای ورودی این دو تابع حتما باید double باشند ( به همین دلیل است که در استراکچر point متغیرهای x و y را از double تعریف کردیم.
تذکر: همانطور که میدانید فاصله دو نقطه از فرمول زیر محاسبه می‌شود:

مثال ۲- برنامه ای بنویسید که از ورودی ۱۰۰ نقطه دریافت کند و مرکز این نقاط را پیدا کند.

در تصویر زیر تعدادی نقاط سبز رنگ میبینید که دایره مشکی رنگ میانگی همه نقاط است. میانگین نقاط، نقطه ای است که مقدار x آن میانگین همه xها و y آن میانگین همه yهاست.

نوشتن این کد چندان سخت نیست:

مثال ۳- برنامه ای بنویسید که از ورودی ۱۰۰ نقطه دریافت کند. سپس نقطه ۱۰۱ ام را دریافت کند و نزدیکترین نقطه (از بین ۱۰۰ نقطه) به نقطه جدید را پیدا کند

این مثال شبیه به صورت مساله ای است که در OCR مطرح کردیم. یعنی ۱۰۰ داده آموزشی داریم و میخواهیم با استفاده از این ۱۰۰ داده ، تکلیف داده ۱۰۱ام را مشخص کنید!

در این مثال به یک آرایه ۱۰۰ تایی از جنس point نیاز داریم که بتوانیم ۱۰۰ نقطه را از ورودی بگیریم. با استفاده از فرمولی که در مثال ۱ استفاده کردیم فاصله نقطه جدید از تک تک نقاط را پیدا میکنیم و کوتاهترین فاصله را ذخیره میکنیم.

توضیح کد:
در خط ۱۹ تا ۳۶ اعداد ورودی دریافت شده است. آرایه points شامل ۱۰۰ نقطه و متغیر new_point شامل آخرین نقطه است. برای محاسبه فاصله بین دو نقطه از تابع distance_points استفاده شده است که دو نقطه از جنس point دریافت می‌کند و فاصله دو نقطه را برمیگرداند.
در خط ۳۸ تا ۴۷ نزدیکترین نقطه به new_point محاسبه شده است. به این صورت که ابتدا فاصله نقطه صفر و new_point در خط ۳۸ در min ذخیره شده است. سپس در حلقه for فاصله تک تک نقاط با new_point محاسبه می‌شود، چنانجه این فاصله از min کم باشد هم min آپدیت می‌شود و هم اندیس نقطه در idx ذخیره می‌شود.

در این نوشته با چند مثال کاربردی که با ساختار قابل پیاده شدن است، آشنا شدید. در قسمت بعد وارد مبحث اشاره گرها و می‌شویم و به صورت کوتاه و مختصر به اشاره گرها می‌پردازیم.

اگر در توضیح مثالهای این آموزش مشکل دارید، حتما در قسمت نظرات سوال خود را مطرح کنید.

  • نویسنده
    حمید جهانگیری
  • تعداد بازدید
    203
۰دیدگاه فرستاده شده است.
شما هم دیدگاه خود را بنویسید
نوشته‌های ویژه
اخبار ویژه

با عضویت در خبرنامه، تازه‌ترین نوشته‌های وبلاگ را در ایمیل‌تان دریافت کنید.
برای عضویت نشانی ایمیل خود را وارد کرده و بر روی دکمه عضویت کلیک نمایید.