آشنایی با مفهوم آرایه یکبعدی و نحوه تعریف و مقداردهی اولیه آن در C++
دسترسی صحیح به عناصر آرایه و درک خطای Out of Bounds
پیادهسازی الگوریتمهای یافتن ماکزیمم و اندیس آن، شمارش تکرار و میانگین k عدد آخر
تشخیص اشکال VLA و جایگزینی آن با `const int` یا `std::vector`
آرایه یکبعدی چیست؟
آرایه یکبعدی مجموعهای از خانههای پشتسرهم در حافظه است که همگی نوع دادهی یکسان دارند و یک نام مشترک. به هر خانه با یک عدد به نام اندیس (Index) دسترسی پیدا میکنیم. اندیسها در C++ همیشه از ۰ شروع میشوند، یعنی اولین خانه اندیس ۰ و آخرین خانه اندیس size - 1 دارد.
مزایای آرایه:
ذخیرهی چند مقدار همنوع با یک نام
دسترسی سریع O(1) به هر عنصر با اندیس
امکان پیمایش با حلقه for
تعریف و مقداردهی اولیه آرایه
آرایه را میتوان به چند روش تعریف و مقداردهی کرد. اگر تعداد مقادیر داخل آکولاد کمتر از اندازهی آرایه باشد، خانههای باقیمانده خودکار صفر میشوند.
روشهای مختلف تعریف و مقداردهیcpp
$خروجی برنامه
15 0
0
در حال باز کردن ویرایشگر…
مقداردهی جزئی: بقیه صفر میشوند
وقتی بنویسید int a[100] = {1, 2};، کامپایلر a[0] را ۱ و a[1] را ۲ میکند و تمام خانههای باقیمانده (a[2] تا a[99]) را خودکار صفر میکند. این یک ویژگی مفید است که بهسادگی میتوانید یک آرایهی کاملاً صفر داشته باشید: int z[100] = {0};
مثال: محاسبهی میانگین عناصر آرایه
برای محاسبهی میانگین، ابتدا مجموع را با یک حلقه جمع میکنیم و سپس بر n تقسیم میکنیم. حتماً از static_cast<double> استفاده کنید تا تقسیم اعشاری انجام شود، در غیر این صورت تقسیم صحیح انجام میشود و قسمت اعشاری از دست میرود.
خواندن n عدد، محاسبهی میانگین اعشاریcpp
$خروجی برنامه
Enter n: 4
10 20 30 40
Average = 25
در حال باز کردن ویرایشگر…
خطای Out of Bounds — دسترسی غیرمجاز به اندیس
اگر آرایه را int a[100] تعریف کنید، اندیسهای مجاز از 0 تا 99 هستند. نوشتن a[100] یا a[200] به حافظهی غیرمجاز دسترسی پیدا میکند که به آن Out of Bounds یا Buffer Overflow میگویند. این خطا ممکن است در زمان اجرا باعث Crash، رفتار غیرقابل پیشبینی، یا حتی مشکل امنیتی شود و کامپایلر معمولاً هشداری نمیدهد!
main.cppcpp
اشتباه جزوه: آرایه با اندازه متغیر (VLA)
در جزوه اصلی بعد از cin >> n نوشته شده int a[n];. این قابلیت که به آن VLA (Variable Length Array) میگویند، در استاندارد C++ مجاز نیست و فقط در زبان C (از C99) یا بهعنوان افزونهی کامپایلرهای GCC/Clang کار میکند. در محیطهای استاندارد (مثل MSVC یا کامپایلرهای آموزشی قدیمی) خطای کامپایل میدهد. دو راهحل استاندارد داریم:
۱. اگر اندازهی حداکثر از قبل معلوم است: const int N = 100; int a[N];
۲. اگر اندازه در زمان اجرا معلوم میشود: vector<int> a(n);
نسخه اشتباه جزوه
کد دارای باگcpp
نسخه اصلاحشده و استاندارد
کد صحیحcpp
یافتن ماکزیمم و اندیس آن
الگوریتم: فرض میکنیم اولین عنصر (a[0]) ماکزیمم است. سپس از i = 1 شروع به پیمایش میکنیم و هر بار که عنصری بزرگتر از max فعلی پیدا شد، مقدار max و اندیس آن (k) را بهروز میکنیم.
الگوریتم جستجوی خطیcpp
$خروجی برنامه
Enter n: 5
12 70 1 5 9
a[1] = 70
در حال باز کردن ویرایشگر…
فلوچارت یافتن ماکزیمم
گامهای الگوریتم یافتن ماکزیمم و اندیس آن در آرایه:
flow.svg
شمارش تکرار هر عنصر (هیستوگرام اولیه)
ایده: برای هر عنصر a[i]، یک حلقه داخلی روی کل آرایه میزنیم و تعداد دفعاتی که a[i] == a[j] است را میشماریم. این روش دارای پیچیدگی O(n²) است. (در درس بعد با هیستوگرام ستارهای آشنا میشویم.)
برای هر عنصر، تعداد تکرار آن را در آرایه بشماردcpp
برای میانگین k عدد آخر، باید از اندیس n - k تا n - 1 را پیمایش کنیم. اگر k > n باشد، خطا رخ میدهد؛ پس حتماً چک کنید.
جمع k عنصر انتهایی و تقسیم بر kcpp
$خروجی برنامه
Enter n and k: 5 3
10 20 30 40 50
Average of last 3 = 40
در حال باز کردن ویرایشگر…
نکتهی کاربردی: استفاده از `static_cast<double>`
همیشه برای تقسیم اعشاری، یکی از دو طرف تقسیم را به double تبدیل کنید. روش قدیمی (float)sum / n یا float(sum) / n نیز کار میکند اما روش پیشنهادی C++ مدرن static_cast<double>(sum) / n است که امنتر و خواناتر است.
همیشه متغیرها را مقداردهی اولیه کنید
در C++ اگر یک متغیر محلی را تعریف کنید و به آن مقدار ندهید، مقدار زباله (Garbage Value) در حافظهی آن قرار میگیرد. مثلاً اگر int sum; بنویسید و بعد sum += a[i] کنید، نتیجهی غیرقابل پیشبینی خواهد بود. همیشه بنویسید int sum = 0; یا int max = a[0];.
استفاده از `size_t` یا `int` برای اندیس؟
تابع a.size() در vector نوع size_t (بدون علامت) برمیگرداند. اگر آن را با یک int مقایسه کنید ممکن است هشدار کامپایلر بگیرید. برای حل این مشکل، یا متغیر حلقه را size_t i = 0 بگیرید یا به int تبدیل کنید: (int)a.size(). در این درس، چون از آرایههای C-style با اندازه ثابت استفاده میکنیم، نیازی به این نکته نیست.
برنامهای بنویسید که n عدد را در یک آرایه بخواند و کوچکترین (مینیمم) عنصر و اندیس آن را چاپ کند.
نمایش راهنما
الگوریتم مانند ماکزیمم است ولی شرط `a[i] < min` استفاده میشود.
02
تمرین•حل کامل دارد
برنامهای بنویسید که n عدد بگیرد و تعداد عناصری که از میانگین کل آرایه بزرگتر هستند را چاپ کند.
نمایش راهنما
ابتدا میانگین را حساب کنید، سپس در یک حلقهی دوم شرط `a[i] > avg` را بشمارید.
03
تمرین•حل کامل دارد
برنامهای بنویسید که n عدد بگیرد و تعداد دفعات تکرار بیشترین مقدار (ماکزیمم) را چاپ کند. مثال: آرایه {3, 5, 5, 2, 5} → ماکزیمم ۵ است که ۳ بار تکرار شده است.
نمایش راهنما
ابتدا در یک حلقه، max را پیدا کنید. سپس در حلقه دوم، تعداد برابری با max را بشمارید.
04
تمرین•حل کامل دارد
برنامهای بنویسید که n عدد بگیرد و k عدد آخر را با هم جمع کرده و میانگین آنها را چاپ کند (با استفاده از `vector`).
نمایش راهنما
از `vector<int> a(n);` استفاده کنید و از اندیس `n-k` تا `n-1` را جمع کنید.
// نکات-کلیدی۶
01آرایه یکبعدی مجموعهای از خانههای همنوع با یک نام و اندیس از ۰ تا `size-1` است.
02اگر در مقداردهی اولیه، مقادیر کمتر از اندازهی آرایه باشد، بقیه خودکار صفر میشوند.
03دسترسی به اندیس خارج از محدوده (مثلاً `a[100]` برای آرایهی ۱۰۰تایی) خطای Out of Bounds است.
04آرایه با اندازهی متغیر (VLA) در C++ استاندارد مجاز نیست؛ از `const int` یا `vector` استفاده کنید.
05برای یافتن ماکزیمم: `max = a[0]` فرض کنید و از `i = 1` به بعد با `a[i] > max` بهروزرسانی کنید.
06برای میانگین اعشاری همیشه از `static_cast<double>` استفاده کنید تا تقسیم صحیح انجام نشود.
گام بعدی پیشنهادی
هیستوگرام و آرایههای کاراکتری
رسم نمودار ستونی با ستاره، شمارش اعداد بزرگتر از قبلی و معرفی آرایه کاراکتری
1#include<iostream>2usingnamespace std;34intmain(){5constint MAX =100;6int n;7 cout <<"Enter n: ";8 cin >> n;910int a[MAX];11longlong sum =0;12for(int i =0; i < n; i++){13 cin >> a[i];14 sum += a[i];15}1617double avg =static_cast<double>(sum)/ n;18 cout <<"Average = "<< avg << endl;19return0;20}
int x[10];x[10]=9;// ✗ خطای Out of Bounds (اندیس مجاز 0 تا 9 است)cout << a[200];// ✗ برای آرایهی ۱۰۰ تایی خطاست
1#include<iostream>2usingnamespace std;3intmain(){4int n;5 cin >> n;6int a[n];// ✗ VLA غیراستاندارد7for(int i =0; i < n; i++) cin >> a[i];8// ...9return0;10}
1#include<iostream>2#include<vector>3usingnamespace std;4intmain(){5int n;6 cin >> n;7 vector<int>a(n);// ✓ استاندارد و قابل حمل8for(int i =0; i < n; i++) cin >> a[i];9// ...10return0;11}
1#include<iostream>2usingnamespace std;34intmain(){5int n;6 cout <<"Enter n: ";7 cin >> n;89int a[100];10for(int i =0; i < n; i++) cin >> a[i];1112int max = a[0];13int k =0;// اندیس ماکزیمم14for(int i =1; i < n; i++){15if(a[i]> max){16 max = a[i];17 k = i;18}19}2021 cout <<"a["<< k <<"] = "<< max << endl;22return0;23}
flow.svg100%
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.
شروع/پایانپردازشتصمیمورودی/خروجی
1#include<iostream>2usingnamespace std;34intmain(){5int n, k;6 cout <<"Enter n and k: ";7 cin >> n >> k;89if(k <=0|| k > n){10 cout <<"Invalid k!"<< endl;11return1;12}1314int a[100];15for(int i =0; i < n; i++) cin >> a[i];1617longlong sum =0;18for(int i = n - k; i < n; i++)// k عنصر آخر19 sum += a[i];2021double avg =static_cast<double>(sum)/ k;22 cout <<"Average of last "<< k <<" = "<< avg << endl;23return0;24}