چهارشنبه , ۲۴ مهر ۱۳۹۸
آخرین مطالب
LINK TABLES
خانه | برنامه‌نویسی | زبان C – ساختارها (جلسه ۷)

زبان C – ساختارها (جلسه ۷)

امروز خیلی روز خوبیه. من خیلی پر انرژی هستم. امیدوارم که شما هم شارژ باشید 😀  بحث ساختار رو قرار بود باهم کار کنیم. پس وقتو از دست ندیم که خیلی این جلسه کار داریم برای انجام دادن.

 

یادآوری

لطفا قبل از مطالعه این بحث مباحث زیر را مطالعه کنید:

انواع داده در زبان C               اشاره گرهای زبان C               آرایه ها در زبان C

رشته ها در زبان C                آرایه ها و اشاره گرها

ساختار ( structure )

اگر به پست های بخش یادآوری سری زده باشید متوجه شده اید که امروز آخرین بخش از داده ها تدریس می شود. داده ها ساده و سپس داده های مرکب بررسی شدند و امروز می توانید در ساختارها ( structure ) مجموع تمام جلسات قبل را یک جا داشته باشید.

همان‌طور که تا اینجا آموختیم، آرایه‌ها می‌توانند برای جمع‌آوری گروهی از داده های هم نوع استفاده شوند؛ اما نمی‌توان آرایه‌ای تعریف کرد که مثلا شامل پنج‌ خانه از نوع صحیح و پنج‌ خانه از نوع اعشاری باشد. از طرفی در کاربردهای مختلف برنامه‌نویسی نیاز به تعریف کردن عناصر مختلف در کنار هم و منسوب کردن یک نام به همه‌ی آن‌ها است تا بتوان مجموعه‌ی آن‌ها را به‌صورت یکجا مورد پردازش‌ (مانند بازنویسی آن‌ها به‌صورت یکجا، ارسال کل آن‌ها به یک تابع و یا آماده‌سازی و برگرداندن همه‌ی آن‌ها به‌عنوان نتیجه یک تابع) قرار داد.

فرض کنید داده‌های مربوط به یک دانشجو مثل شماره دانشجویی، نام خانوادگی، نام، جنسیت، تعداد واحد گذرانده شده و معدل کل را که دارای نوع‌های متفاوتی هستند را بخواهیم تحت یک نام تعریف کنیم.

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

پاسخ این است که می‌توان متغیرهایی با نوع‌های مختلف را با داده‌ای به نام ساختار ( structure ) گروه‌بندی کرد. بنابراین می‌توان گفت که ساختار در زبان C، نامی برای مجموعه‌ای از متغیرهاست که این متغیرها می‌توانند هم نوع نباشند، یعنی ساختار می‌تواند انواع مختلف داده‌ها ازجمله float, int, char, unsigned char و … را تحت عنوان یک نام در خود داشته باشد و کاربر در هر زمان به آن‌ها دسترسی داشته باشد.

قالب تعریف ساختار را در زیر مشاهده می‌کنیم:

نام ساختار یا (structure tag ) از قانون نام‌گذاری برای متغیرها تبعیت می‌کند. عضوهای ساختار یا (member)، متغیرهایی هستند که قسمتی از ساختار می‌باشند و همانند یک متغیر معمولی یا آرایه، باید اسم و نوع هرکدام مشخص باشد. لیست نام‌ها یا (structure variables) هم متغیرهایی هستند که قرار است ساختمان این ساختار را داشته باشند. برای استفاده از عناصر ساختار معرفی‌شده باید متغیرهایی از نوع ساختار پس‌ازآن معرفی شود. اگر کمی (فقط کمی 😀 ) گیج شدید، برای رفع گیجی ادامه بحث را دنبال کنید.

دو روش برای معرفی متغیرهایی از نوع ساختار وجود دارد.

در زیرقالب روش اول را مشاهده می‌کنید:

به مثال زیر توجه کنید:
  • در خط یک ساختاری با نام الگوی student record تعریف شده است.
  • توجه شود که نام الگو متغیر نیست بلکه اسمی برای ساختار است. مثلا برای دانشجو می توان الگویی با نام پروفایل دانشجو تعریف کرد. حال هر دانشجو به صورت جدا گانه از این ساختار جهت ذخیره اطلاعاتش استفاده می کند. پس باید برای هر دانشجو یک متغیر جدا از نوع ساختار تعریف شود.
  • در خطوط  ۲ تا ۷ انواع متغیرهای لازم برای ذخیره اطلاعات پروفایل دانشجو تعریف شده اند.
  • در خط ۸ یک متغیر از نوع ساختار student record تعریف شده است. پس در حافظه فقط به اندازه همین یک متغیر حافظه اشغال می شود.
  • student1 نام متغیری است با ساختمان این ساختار که دارای شش عضو است. درصورتی‌که بعد از خاتمه‌ی تعریف ساختار (بعد از { ) نامی نوشته نشود، فقط یک الگو تعریف‌شده است و چون متغیری با ساختمان این ساختار تعریف‌نشده، حافظه‌ای اشغال نخواهد شد. در این حالت می‌توان در ادامه‌ی برنامه از کلمه‌ی struct و نام ساختار (در اینجا student_record) برای تعریف ساختارهای موردنیاز استفاده کرد.

در زیرقالب روش دوم را می‌بینید که پس از معرفی ساختار صورت می‌گیرد:

  • متغیرهایی بانام p1,p2 از نوع ساختار s_type معرفی‌شده‌اند. هرکدام از این‌ها حاوی کل ساختار معرفی‌شده، می‌باشند. 

دسترسی به عناصر ساختار

قالب دسترسی به عناصر ساختار را در زیر مشاهده می‌کنید.  

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

مثال: ساختاری را تعریف کنید که اطلاعات یک دانشجو را در خود ذخیره نماید.

  • متغیری بنام s از نوع ساختار student تعریف شده است.
  • اکنون متغیر s شامل کلیه عناصر تعریف‌شده در ساختار موردنظر است و کامپایلر C به‌صورت خودکار حافظه لازم را به ساختار اختصاص می‌دهد.

مثال: مقداردهی اولیه به عناصر متغیر ساختاری s

  •  همان طور که چند خط بالاتر توضیح داده شد، ابتدا نام متغیر ساختاری و سپس نقطه نوشته می شود. بعد از آن نام عنصر دلخواه ساختار نوشته شده و مقداردهی انجام می شود.

نکات مهم ساختارها

  • مقداردهی اولیه به ساختار (مشابه مقداردهی آرایه‌ها) مجاز است. در این جا یک شیوه دیگر برای مقدار دهی به ساختار را مشاهده می کنید که روش بهتری نسبت به روش مقدار دهی با نقطه است. 
  • می‌توان هنگام تعریف ساختار همزمان چند متغیر از آن نوع ساختار را تعیین کرد.

 اکنون دو متغیر با اگوی ساختار rectangle با نام های r1 و r2 تعریف شده اند.

تخصیص ساختارها

در مقداردهی اولیه می‌توان مجموعه‌ای از مقادیر را به یک ساختار نسبت داد، ولی انجام چنین کاری در متن برنامه به‌صورت دستور اجرایی امکان‌پذیر نیست. تنها عمل تخصیص که در مورد رکوردها در زبان C تعریف‌شده است، تخصیص یک ساختار به ساختار دیگری با ساختمان دقیقا یکسان (هر دو ساختار از طریق یک struct تعریف‌شده باشند) است که در این صورت محتویات هر عنصر از ساختار مبدأ به عنصر متناظر از ساختار مقصد منتقل می‌شود. ساختار مبدأ می‌تواند متغیری در برنامه یا خروجی یک تابع باشد.

 

آرایه‌ای از ساختارها

در C، نام آرایه را می‌توان در مقابل نام ساختار قرار داد تا آرایه‌ای از ساختارها اعلام شود. یکی از بیشترین موارد کاربرد ساختارها، استفاده از آن‌ها به‌عنوان عناصری از آرایه است. برای تعریف آرایه‌ای از ساختارها، ابتدا نوع ساختار را تعریف کرده سپس همانند متغیرهای معمولی، آرایه‌ای از آن نوع ساختار را تعریف می‌کنیم. برای نمونه، با فرض داشتن ساختاری به نام x, داریم:

آرایه‌ای به نام array _of_structure از ساختار x اعلام شده است. این آرایه ۸ عنصر دارد، در هر خانه از آرایه یک نمونه از ساختار x وجود دارد. برای فهم بیشتر مثال زیر را در نظر بگیرید:

در این دستورات، آرایه ۱۰۰ عنصری st طوری تعریف شده که هر یک از عناصر آن، از نوع ساختار student است.

اشاره‌گرها و ساختارها

در زبان C تعریف اشاره‌گری از نوع ساختار، همانند تعریف سایر انواع اشاره‌گرها امکان‌پذیر است. همان‌طور که در فراخوانی تابع می‌توان اشاره‌گری را که به آرایه اشاره می‌کند ارسال کرد، می‌توان اشاره‌گری را که به ساختار اشاره می‌کند نیز ارسال کنید. فراخوانی به معنای ارسال آرگومان به تابع و تحویل گرفتن خروجی است. فراخوانی به دوشکل تعریف می‌گردد. فراخوانی تابع با مقدار(call by value) و فراخوانی تابع با ارجاع(call by reference).

اگر با بحث تابع در زبان C آشنایی کافی ندارید پست تابع را مطالعه کنید.

به‌هرحال برخلاف ارسال ساختار به تابع که نسخه‌ی کاملی از ساختار را به تابع می‌فرستد، ارسال اشاره‌گر به ساختار فقط آدرس ساختار را به تابع می‌فرستد. سپس تابع می‌تواند جهت دستیابی مستقیم به اعضای ساختار از آدرس استفاده کند. بنابراین این روش نسبت به ارسال خود ساختار را به تابع کارآمدتر است.

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

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

مثال زیر را در نظر بگیرید: 

در این دستورات person یک متغیر ساختار و p یک اشاره‌گر ساختار است.

اکنون دستور زیر را در نظر بگیرید

با این دستور، آدرس متغیر ساختار person در اشاره‌گر p قرار می‌گیرد. برای دسترسی به محتویات عناصر ساختار از طریق اشاره‌گر، باید اشاره‌گر را در داخل پرانتز محصور کرد. به‌عنوان‌ مثال دستور زیر موجب دسترسی به عنصر balance از ساختار person می‌شود. علت قرار دادن متغیر اشاره‌گر در پرانتز، این است که تقدم عملگر (.) از * بالاتر است. 

به‌طورکلی برای دسترسی به عناصر ساختاری که یک اشاره‌گر به آن اشاره می‌کند به دو روش می‌توان عمل کرد:

  • ذکر نام اشاره‌گر در داخل پرانتز و سپس نام عناصر موردنظر که با نقطه از هم جدا می‌شوند. (مثل دسترسی به عنصر balance از ساختار person توسط اشاره‌گر p)
  • استفاده از عملگر <- که روش مناسب‌تری است. اگر بخواهیم با استفاده از عملگر < – به عنصر balance از ساختار person دسترسی داشته باشیم باید به طریق زیر عمل کنیم (علامت <- متشکل از علامت منها و علامت بزرگ‌تر است.)

در این‌جا بیان این نکته ضروری است که آرایه‌ها، اشاره‌گرها و ساختارها دارای ارتباط نزدیکی باهم هستند. در ضمن عمگرهای مربوط به آن‌ها شامل زیر نویس یا []، عضو ساختار یا نقطه و دستیابی غیرمستقیم به عضو ساختار یا <- همگی دارای بالاترین تقدم هستند.

عملگرهای دستیابی غیرمستقیم یا * و استخراج آدرس یا & هم دارای تقدم دوم می‌باشند. حال اگر این عبارت‌ها همراه همدیگر در عبارتی ظاهر شوند باید کمی با دقت کد مورد نظر نوشته شود.

برای درک بحث گیج کننده ی تقدم ها ( 😀 ) و فهم بیشتر انواع ساختارها به مثال زیر دقت کنید:

  • چون در مثال های بالا نکات ریز ساختار کاملا توضیح داده شده است، در این جا قسمت های مهم را توضیح می دهیم.
  • در خطوط ۱ تا ۴ ساختاری با نام point تعریف شده ولی هیچ متغیری برایش تعریف نشده است.
  • در خطوط ۶ تا ۱۰ ساختاری با نام Line تعریف شده و متغیری با نام a برای آن تعریف و مقدار دهی اولیه شده است.
  • دو عنصر اول ساختار line، ساختار pint است. پس عناصر یک ساختار می توانند ساختار هم باشند.
  • در خطوط ۱۲ تا ۱۵ دو اشاره گر ساختار برای ساختار line با نام های pa و pm تعریف شده و یک متغیر ساختار دیگر هم برای line تعریف و مقدار دهی شده است. در این جا هم متغیر m آرایه ای از ساختار است.
  • در خط ۱۶ آدرس متغیر a در اشاره گر pa قرار داده شده است.
  • در خط ۱۷ آدرس خانه دوم آرایه m در اشاره گر pm قرار داده شده است.

با توجه به تعاریف بیان شده و اینکه ترتیب اجرای دو عملگر عضو ساختار و دستیابی غیرمستقیم از چپ به راست است، عبارت‌های زیر معادل هستند:

  • خط یک: a متغیری از نوع ساختار line است که به وسیله نقطه به عضو first دسترسی پیدا کردیم. first هم یک متغیر ساختاری از نوع point است که به وسیله نقطه به عضو x آن دسترسی پیدا کردیم.
  • خط دو: pa اشاره گر به متغیر ساختاری a است. پس با عملکر <- می توانیم به اعضای آن دسترسی پیدا کنیم.
  • با توجه به توضیحات داده شده سایر خط ها را برای خودتان تفسیر کنید. اگر سوالی داشتید حتما در بخش نظرات بپرسید.

دو عبارت زیر نیز یک معنی می‌دهند:

در خط یک: دستیابی از طریق اندیس خانه‌ی یکم آرایه‌ی m که یک ساختار است به عضو last و سپس به عضو y انجام شده است.

در خط دو: دستیابی به عضو last از طریق آدرس خانه‌ی یکم آرایه‌ی m که در متغیر pm قرار دارد انجام شده است.

ساختارها که خیلی سخت نبود؟ آفرین همین انتظارم ازتون داشتم. کمی که تمرین کنید تمام مفاهیمش خوب توی ذهنتون شکل می‌گیره. یادتون نره فقط که باید برنامه نویسیو پای لپ تاپ یا سیستمتون تمرین کنید. فقط خوندن قوانینش نمیتونه کمک کننده باشه. برای جلسه بعد می‌خوایم روی انواع عملگرها در زبان C (این جا کلیک کن) کار کنیم و دیگه بریم سمت کد نویسی واقعی. پس تا جلسه بعد  😉

درباره ی احسان عبداللهی

احسان عبداللهی هستم | کارشناسی الکترونیک خوندم و کارشناسی ارشد مخابرات |در سال 94 وب سایت میکرولرن را راه اندازی کردم | سعی کردم هر چیزی را به صورت کاربردی دنبال کنم، برای همین از کارشناسی کار با میکروکنترلرهای AVR و ARM، برنامه نویسی C و طراحی PCB را به صورت تخصصی کار کردم و از کارشناسی ارشد برنامه نویسی پایتون ، Computer vision و deep learning را به صورت تخصصی و کاربردی شروع کردم | الان هم سعی میکنم همیشه خودم را به روز نگه دارم و لذت کار کردن با دنیای برنامه نویسی و امبدد سیستم ها را به دیگران انتقال بدم

۱۳ دیدگاه

  1. سلام چطوری دوتا استراکچر رو باهم مقایسه کنیم

  2. با سلام و خسته نباشید خدمت شما.
    مطالب و اموزش هاتون واقعا خوب و مفید ولی مثالها کمه.میشه لطف کنید تعدادی سوال و تمرین بذارید برای حل کردن که یه مقدار عملی هم کار کنیم و فقط تیوری نباشه.
    ولی در کل خیله سایتتون خوبه و مرسی بابت اموزش ها.

    • سلام دوست عزیز
      توجه کنید که مطالبی که برای شما تهیه شده به صورت رایگان هست. تمرین های بیشتر در قالب رایگان قابل ارائه نیست. میتونید برای تمرین های و دوره های عملی و پیشرفته در دروره های آموزشی vip ما شرکت کنید.

  3. نسبت به اشاره گر و تابع که عالی آموزش دادین، این خیلی عالی نبود.

    منظور از آرایه‌ای از ساختارها
    یعنی الان میتونیم آرایه ای داشته باشیم که همه نوعی رو داره ؟
    که قبلا گفتین آرایه فقط یک نوع رو میتونه داشته باشه.

  4. سلام ، ممنون مهندس ، واقعا فکرم از مطالب تون بازتر شد و بهتر تونستم درک کنم ، فقط مونده کمی تمرین کنم تا برام جا بیفته —>>>ضمنا این مطالب شما رو درسایتی دیدم ک بدون اینکه نامی از سایت شما بیاره ب عنوان منبع مطالبش ،، واو ب واو مطالبتون رو کپی کرده بود —>>> اینم آدرس سایتش http://naqale.ir/2017/11/14/ساختارstructure/
    براشون متاسفم .

  5. سلام
    آیا هر structcher variable باید حاوی تمام اعضای استراگچر باشه؟ مثلا” ۱۰ متغیر برای یک استراکچر تعریف کردیم و مثلا” ۳ تا structcher variable . در این حالت هر کدوم از این structcher variable ها باید دیتای هر ۱۰ متغیر رو در خودشون ذخیره کنند؟ یا میشه مثلا” ۵ تا بگیرن و خطا بوجود نیاد

  6. اگر بشه اموزش هاتون رو بصورت pdf در بیارید عالیه . خیلی اوقات اینترنت درست حسابی نداریم به سایتتون سر بزنیم . ممنون از اموزش خوبتون

  7. سلام وقت بخیر
    عالییییییییییییییییییییییییییییییییییییییی بود….ولی ساختار خیلی گیج کنندس

  8. سلام – مطلب خوبی نوشتی داش – ممنون.

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *