برای روشن کردن ترمینال، کلیک کن یا هر کلیدی را بزن

پرش به محتوای اصلی
>_
درس ۲۹پیشرفته

struct و ساختار‌ها

گروه‌بندی داده‌ها، آرایه ساختار‌ها و توابع عضو

معمولی
توابع و اشاره‌گر‌ها•صفحات ۴۸-۴۹•۵۰ دقیقه•۱٬۶۸۱ کلمهزمان مطالعه: ۰ دقیقه
فهرست این درس
// اهداف۵
  • درک مفهوم struct و چرا برای گروه‌بندی داده‌های مرتبط لازم است
  • تعریف struct، دسترسی به فیلد‌ها با عملگر نقطه
  • ساخت آرایه‌ای از structها (مانند student x[100])
  • آشنایی با توابع عضو درون struct (روش ابتدایی OOP در ⁦C++⁩)
  • پیاده‌سازی مرتب‌سازی حبابی روی آرایه‌ی struct

ساختار (struct) چیست؟

فرض کنید می‌خواهید اطلاعات یک دانشجو را ذخیره کنید: نام، تاریخ تولد، نام خانوادگی و معدل. اگر برای هر کدام یک متغیر جداگانه بسازید، مدیریت ده‌ها دانشجو به‌شکل ​name1, name2, ... غیرممکن می‌شود.

struct به ما اجازه می‌دهد چند متغیر مرتبط را در یک نوع داده‌ی جدید گروه‌بندی کنیم. سپس می‌توانیم به‌سادگی متغیرهایی از این نوع تعریف کنیم:

main.cppcpp

حالا student x; یک متغیر کامل است که شامل همه‌ی این فیلدهاست.

تعریف و استفاده از struct student

هر فیلد با عملگر نقطه . در دسترس است: x.name, x.avg و غیره. به نقطه‌ویرگول }; در انتهای struct دقت کنید؛ فراموش کردن آن خطای کامپایل است.

تعریف struct، تعریف متغیر، دسترسی به فیلد‌هاcpp
خروجی برنامه
nam: Ali
tarikh tavalod: 1380
nam khanevadegi: Rezaei
moadel: 18.5

--- etelaat daneshjoo ---
Ali Rezaei  tarikh: 1380  moadel: 18.5

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

وقتی بخواهیم اطلاعات چندین شیء را نگه داریم (مثلاً ۱۰۰ دانشجو)، از آرایه‌ی struct استفاده می‌کنیم:

main.cppcpp

هر عنصر x[i] یک student کامل با همه‌ی فیلدهاست. دسترسی به فیلد iامین دانشجو به این شکل است: x[i].name, x[i].avg.

آرایه‌ای از ساختار‌های دانشجو

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

خواندن اطلاعات چند دانشجو و چاپ معدل بالای ۱۲cpp
خروجی برنامه
tedad daneshjoo: 3
name va moadel 1: Ali 18.5
name va moadel 2: Sara 9.5
name va moadel 3: Reza 15.0

--- moadel > 12 ---
Ali 18.5
Reza 15

توابع عضو (Member Functions)

در ⁦C++⁩ می‌توانیم توابعی را داخل خود struct تعریف کنیم که به فیلد‌های آن دسترسی مستقیم دارند. این یک قدم اولیه به سمت برنامه‌نویسی شیءگرا (OOP) است.

main.cppcpp

فراخوانی: x.calc_sal();. این تابع مقدار salary را بر اساس hours و per_h محاسبه می‌کند.

محاسبه حقوق کارکنان با struct

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

struct employee با تابع عضو calc_salcpp
خروجی برنامه
saat kar: 40
nerkh saat: 50
hoghoogh = 2000

خطاهای رایج در تعریف struct

در جزوه اصلی دو خطای متداول وجود داشت:

  1. استفاده از علامت - در نام فیلد مثل per-h. در ⁦C++⁩ نام شناسه‌ها فقط می‌تواند شامل حروف، اعداد و _ باشد. باید per_h یا perH نوشته شود.

  2. عدم تطابق بزرگی/کوچکی حرف در تعریف توابع عضو: در جزوه از Point (با P بزرگ) در تعریف تابع و از point (با p کوچک) در تعریف struct استفاده شده بود. ⁦C++⁩ به بزرگی و کوچکی حروف حساس است.

نسخه اشتباه جزوه
کد دارای باگcpp
نسخه اصلاح‌شده و استاندارد
کد صحیحcpp

struct point برای کار‌های هندسی

یکی از کاربرد‌های رایج struct، تعریف نقطه در صفحه است. با تعریف point که شامل x و y است، می‌توانیم راحت‌تر با اشکال هندسی کار کنیم.

main.cppcpp

سپس با تعریف point P1, P2; دو نقطه داریم و می‌توانیم توابعی بنویسیم که روی نقاط کار می‌کنند: دریافت مختصات، رسم خط، محاسبه نقطه‌ی وسط، و غیره.

توابع عضو برای struct point

سه تابع عضو برای point تعریف می‌کنیم: get_point مختصات را از ورودی می‌گیرد (با ارجاع)، P_line خطی بین دو نقطه را شبیه‌سازی می‌کند (در محیط واقعی از line() استفاده می‌شود، اما اینجا چاپ متنی)، و mid نقطه‌ی وسط دو نقطه را چاپ می‌کند.

get_point, P_line, midcpp
خروجی برنامه
mokhtasate P1: 1 2
mokhtasate P2: 5 8
khat az (1,2) ta (5,8)
noghteye vaset = (3, 5)

حسابگر اشاره‌گر روی آرایه‌ی struct

می‌توانیم با اشاره‌گر روی آرایه‌ی struct هم حرکت کنیم. اگر q یک اشاره‌گر به point باشد، با q++ به عنصر بعدی آرایه می‌رود (همان b+1).

main.cppcpp

نکته: برای دسترسی به فیلد از طریق اشاره‌گر از عملگر -> (پیکان) استفاده می‌شود. یعنی q->x معادل (*q).x است.

حرکت اشاره‌گر روی آرایه‌ی struct

این مثال نشان می‌دهد چگونه با اشاره‌گر روی عناصر آرایه‌ی struct حرکت می‌کنیم و با -> به فیلد‌ها دسترسی پیدا می‌کنیم.

q = b + 1 و q--cpp
خروجی برنامه
q->x = 3
q->x = 1

مرتب‌سازی حبابی روی آرایه‌ی struct

می‌توانیم با همان الگوریتم Bubble Sort که قبلاً یاد گرفتیم، یک آرایه‌ی struct را بر اساس یکی از فیلد‌ها مرتب کنیم. مثلاً مرتب کردن دانشجویان بر اساس avg نزولی.

کلیدی‌ترین بخش: شرط مقایسه روی فیلد مورد نظر انجام می‌شود: x[j].avg < x[j+1].avg.

مرتب‌سازی حبابی آرایه‌ی struct دانشجو

این برنامه ن Student می‌گیرد، آن‌ها را بر اساس معدل از بیشترین به کمترین مرتب می‌کند و سپس چاپ می‌کند. برای جابجایی دو student از std::swap استفاده می‌کنیم که کل struct را عوض می‌کند.

مرتب‌سازی بر اساس معدل (نزولی)cpp
خروجی برنامه
tedad daneshjoo: 3
Ali 14
Sara 19.5
Reza 17.5

--- morattab shode ---
Sara 19.5
Reza 17.5
Ali 14

ارسال struct به تابع

یک struct را می‌توان به سه روش به تابع ارسال کرد:

  1. با مقدار (by value): void f(student s) — کل struct کپی می‌شود. اگر struct بزرگ باشد، پرهزینه است.
  2. با ارجاع (by reference): void f(student &s) — بدون کپی، می‌تواند ساختار اصلی را تغییر دهد.
  3. با اشاره‌گر (by pointer): void f(student *s) — همان ارجاع اما با syntax اشاره‌گر (s->name).

برای توابعی که فقط می‌خواهند ساختار را بخوانند (نه تغییر دهند)، بهترین روش const student &s است: هم کپی نمی‌شود، هم از تغییر تصادفی جلوگیری می‌کند.

ارسال struct با ارجاع به تابع

این تابع بدون کپی کردن، اطلاعات دانشجو را چاپ می‌کند. کلمه‌ی const به کامپایلر قول می‌دهد که s را تغییر نمی‌دهیم.

تابع printStudent با const referencecpp
خروجی برنامه
Ali  15.5
Ali  17.5

خطاهای رایج در کار با struct

  • فراموش کردن }; در انتهای تعریف struct — یکی از رایج‌ترین خطاها.
  • استفاده از کاراکتر‌های غیرمجاز در نام فیلد‌ها (مثل - یا شروع با عدد).
  • عدم تطابق بزرگی/کوچکی حروف (مثل تعریف point و استفاده از Point).
  • دسترسی نادرست به فیلد با اشاره‌گر: اگر p اشاره‌گر به student باشد، باید p->name بنویسید، نه p.name.
  • کپی کردن بی‌مورد structهای بزرگ در توابع — بهتر است از const & استفاده کنید.
  • مقداردهی‌نکردن فیلد‌ها قبل از استفاده می‌تواند به مقادیر آشغال منجر شود.

struct در برابر class — تفاوت چیست؟

در ⁦C++⁩ تفاوت اصلی struct و class در پیش‌فرض دسترسی است:

  • در struct همه‌ی فیلد‌ها و توابع عضو به‌صورت پیش‌فرض public (قابل دسترس از بیرون) هستند.
  • در class همه‌ی فیلد‌ها به‌صورت پیش‌فرض private (فقط از داخل خود class) هستند.

برای داده‌های ساده‌ی بدون منطق (مثل point, student) معمولاً از struct استفاده می‌شود. برای کلاس‌های پیچیده‌تر با منطق و کپسوله‌سازی، class مناسب‌تر است.

مرور سریع مطالب

۱۷ بخش در این درس

تمرین‌ها

01
تمرین•حل کامل دارد

یک struct به نام `Book` با فیلد‌های `title` (رشته)، `author` (رشته) و `price` (عدد اعشاری) تعریف کنید. در `main` یک کتاب بسازید، مقادیر را از ورودی بگیرید و چاپ کنید.

نمایش راهنما
فراموش نکنید هدر `<string>` را اضافه کنید. برای دسترسی به فیلد از عملگر `.` استفاده کنید.
02
تمرین•حل کامل دارد

struct به نام `Point` با فیلد‌های `x` و `y` بسازید. تابع `double distance(Point a, Point b)` بنویسید که فاصله‌ی اقلیدسی دو نقطه را برگرداند. در `main` آن را تست کنید.

نمایش راهنما
فرمول فاصله: sqrt((a.x-b.x)² + (a.y-b.y)²). از `<cmath>` استفاده کنید.
03
تمرین•حل کامل دارد

struct `Student` با `name` و `avg` بسازید. در `main` آرایه‌ای از ۵ دانشجو بسازید (با مقادیر اولیه‌ی دلخواه) و دانش‌آموزی که بیشترین معدل را دارد پیدا و چاپ کنید.

نمایش راهنما
یک حلقه بزنید و در متغیر `int best = 0;` اندیس بهترین را نگه دارید. هر بار `x[i].avg > x[best].avg`، `best` را به‌روز کنید.
04
تمرین•حل کامل دارد

struct `Circle` با فیلد‌های `x` و `y` (مرکز دایره) و `r` (شعاع) تعریف کنید. تابع عضو `area()` بنویسید که مساحت دایره را برگرداند (πr²). در `main` یک دایره بسازید و مساحت آن را چاپ کنید.

نمایش راهنما
برای π از `M_PI` (در `<cmath>`) یا عدد `3.14159` استفاده کنید.
05
تمرین•حل کامل دارد

struct `Student` با `name` و `avg` بسازید. تابع `void sortByAvg(Student x[], int n)` بنویسید که آرایه را **صعودی** بر اساس معدل مرتب کند. در `main` آرایه‌ای از ۴ دانشجو بسازید، مرتب کنید و چاپ کنید.

نمایش راهنما
از الگوریتم Bubble Sort استفاده کنید، اما شرط را روی `x[j].avg > x[j+1].avg` بگذارید.
// نکات-کلیدی۶
  • 01struct چند متغیر مرتبط را در یک نوع داده‌ی جدید گروه‌بندی می‌کند و مدیریت داده‌های پیچیده را آسان می‌کند.
  • 02دسترسی به فیلد‌های struct با عملگر `.` برای متغیر معمولی و با `->` برای اشاره‌گر انجام می‌شود.
  • 03می‌توان آرایه‌ای از structها ساخت (مثل `student x[100];`) و توابعی نوشت که روی این آرایه کار می‌کنند.
  • 04⁦C++⁩ اجازه می‌دهد توابع عضو داخل struct تعریف شوند (مثل `calc_sal`) که اولین قدم به سمت برنامه‌نویسی شیءگرا است.
  • 05برای ارسال struct به تابع از `const &` استفاده کنید تا از کپی اضافی جلوگیری شود و از تغییر تصادفی محافظت گردد.
  • 06الگوریتم‌های مرتب‌سازی مثل Bubble Sort را می‌توان روی آرایه‌ی struct با مقایسه‌ی یکی از فیلد‌ها به کار برد.
گام بعدی پیشنهادی

توابع بازگشتی (Recursion)

از فاکتوریل تا فیبوناچی، توان و مجموع — با تحلیل پشته

۶۰ دقیقهپیشرفته۱۷ بخش

شروع درس

جستجوی سریع در درس‌ها

نام درس، موضوع یا کلمه کلیدی را بنویسید و با Enter به آن بروید