بازگشت
یک متد بهنام down بنویسید که یک int بهنام n بگیرد. اگر n برابر 0 یا کمتر است، با return; لخت بایستید. وگرنه n را بنویسید، بعد از داخل همان متد down(n - 1) را صدا بزنید. از Main صدا بزنید down(3);. صفحه باید سه خط نشان دهد: 3، بعد 2، بعد 1. متد با عدد کوچکتر خودش را صدا میزند تا توقف زنجیره را تمام کند. همین خودفراخوانی با توقف چیزی است که این صفحه آموزش میدهد. نام کلاس عمومی را Pine نگه دارید.
متدی که خودش را صدا میزند
در صفحهٔ محدوده، mark یکبار اجرا شد و تمام شد. اینجا down اجرا میشود، بعد پیش از تمام شدن کامل فراخوانی اول، یک down دیگر با آرگومان تازه شروع میکند. هر فراخوانی n خودش را دارد. زنجیره فقط وقتی تمام میشود که یک فراخوانی به توقف برسد.
فایل Pine را باز کنید. نام کلاس Pine میماند. این صفحه نوع را عوض نام نمیکند. اگر هنوز دموی mark باقی مانده و همهٔ چیزی است که در Main دارید، پاکش کنید. هر باقیماندهٔ paint را پاک کنید. هر خط ReadLine را هم پاک کنید. فایلی که نگه میدارید منتظر تایپ نیست.
بیرون از Main، هنوز داخل آکولادهای کلاس، بنویسید static void down(int n). در این صفحه void را نگه دارید: هر گام مینویسد و چیزی لازم نیست از راه return تایپدار برگردد. توقف از return; بدون مقدار استفاده میکند — فقط همین فراخوانی را تمام میکند. پیش از اجرا فایل را ذخیره کنید. برنامهٔ کامل اول در جعبهٔ بعدی است.
فایلی که نگه میدارید
این نسخهای است که اول اجرا میکنید. Main یک فراخوانی نگه میدارد. down توقف، خط نوشتن، و خودفراخوانی را نگه میدارد.
using System;
public class Pine
{
public static void Main()
{
down(3);
}
static void down(int n)
{
if (n <= 0)
{
return;
}
Console.WriteLine(n);
down(n - 1);
}
}
از بالا بخوانید. using System; نامهای کوتاه را آماده میکند. public class Pine نوع را نام میگذارد. public static void Main() جایی است که زمان اجرا شروع میکند. فراخوانی down(3) با n برابر 3 وارد میشود. آن بزرگتر از 0 است، پس متد 3 مینویسد، بعد down(2) صدا میزند. فراخوانی دوم 2 مینویسد، بعد down(1) صدا میزند. فراخوانی سوم 1 مینویسد، بعد down(0) صدا میزند. فراخوانی با 0 به n <= 0 میخورد و بدون نوشتن برمیگردد. زنجیره تمام میشود. روی صفحه سه خط: 3، بعد 2، بعد 1.
با dotnet run اجرا کنید. برنامه سه خط مینویسد و تمام میشود. منتظر نمیماند که شما چیزی تایپ کنید. اگر dotnet run منتظر ماند، هنوز ReadLine داخل فایل است. آن خط را پاک کنید و down(3); بههمراه متد down بالا را نگه دارید. صفحه 3، بعد 2، بعد 1 را نشان میدهد. اگر صفحه فقط 4 نشان دهد، هنوز فراخوانی باقیماندهٔ mark(4) اجرا میشود. اگر صفحه حرفهای down را نشان دهد، خط نوشتن گیومه دارد: Console.WriteLine("down");. برای صفحهای که خط اشتباه نشان میدهد SDK داتنت را دوباره نصب نکنید.
یک اجرای کامل را به ترتیب راه بروید. C# از Main شروع میکند. فراخوانی down(3) با n برابر 3 وارد میشود. آن بزرگتر از 0 است، پس متد 3 مینویسد، بعد down(2) صدا میزند. فراخوانی دوم 2 مینویسد، بعد down(1) صدا میزند. فراخوانی سوم 1 مینویسد، بعد down(0) صدا میزند. فراخوانی با 0 به n <= 0 میخورد و بدون نوشتن برمیگردد. زنجیره تمام میشود. صفحه سه خط نوشتهشده را نگه میدارد.
هر کدام از آن فراخوانیها یک گذر جدا از همان متن متد است. گذر اول هنوز بعد از شروع down(2) کاری منتظر دارد — یعنی تمام شدن بعد از برگشت فراخوانی درونی. چهار نام متد متفاوت نمینویسید. یک متد مینویسید و میگذارید آرگومان کوچکتر پیشرفت بهسوی توقف را حمل کند.
اگر شروع را به down(2); عوض کنید، صفحه باید 2 بعد 1 نشان دهد. بدنهٔ متد همان میماند؛ فقط آرگومان اول عوض میشود، پس زنجیره کوتاهتر است. شروع با down(4); باید چهار خط نشان دهد: 4، 3، 2، 1. دوباره بدنه عوض نشده؛ فقط Main مقدار اول را برمیگزیند.
توقف را اول بگذارید
توقف باید پیش از خط نوشتن و پیش از خودفراخوانی چک شود. اگر اول بنویسید و هرگز n را نیازمایید، یا همیشه با همان مقدار down(n) صدا بزنید، برنامه تمام نمیشود. در این شکل مبتدی بلوک if (n <= 0) را بالای متد نگه دارید.
using System;
public class Pine
{
public static void Main()
{
down(2);
}
static void down(int n)
{
if (n <= 0)
{
return;
}
Console.WriteLine(n);
down(n - 1);
}
}
این فایل دوم است. همان بدنه را با شروع کوتاهتر آموزش میدهد. با dotnet run اجرا کنید. صفحه 2 بعد 1 نشان میدهد. توقف هنوز وقتی n به 0 برسد زنجیره را تمام میکند. نوشتن down(n) بهجای down(n - 1) همان عدد را دوباره و دوباره میفرستد. آنوقت برنامه ممکن است تا وقتی سیستم بایستاندش اجرا شود. آرگومان کوچکتر بخشی از ایده است: هر فراخوانی باید بهسوی توقف حرکت کند.
توقف را مثل درِ خروجی بدانید. خط نوشتن کاری است که در این گام میکنید. خودفراخوانی گام بعدی است. اگر در نباشد، هر گام گام دیگری باز میکند بیپایان. اگر گام بعدی همان n را به کار ببرد، هرگز بهسوی در راه نمیروید. هر دو اشتباه در سورس متفاوت بهنظر میرسند، ولی هر دو در این شکل مبتدی تمیز تمام نمیشوند. بعد از دیدن 2 بعد 1، اگر شکل ذخیرهای که میخواهید down(3) است، فایل نگهداشتنی را برگردانید.
زنجیرهٔ فراخوانی کنار صفحه
یک فراخوانی شروع را کنار خطهایی که میسازد بخوانید. هر ردیف یک دیدار به down است که هنوز مینویسد.
📊 down call chain for down(3)
| Call | Value of n | Screen line |
|---|---|---|
first down(3) |
3 |
3 |
then down(2) |
2 |
2 |
then down(1) |
1 |
1 |
then down(0) |
0 |
(no line — stop) |
اشتباه رایج حذف توقف است. آنوقت هر فراخوانی مینویسد و دوباره برای همیشه صدا میزند. اشتباه دیگر نوشتن بعد از فراخوانی بازگشتی بهجای پیش از آن است. در این صفحه خط نوشتن اول میآید، پس صفحه معکوس میشمارد. اگر Console.WriteLine را زیر down(n - 1) ببرید، ترتیب خطها عوض میشود — برای شمارش معکوس نشاندادهشده اینجا خط نوشتن را بالای خودفراخوانی نگه دارید.
محدودهٔ صفحهٔ قبلی هنوز بهصورت کوچک مهم است: n هر فراخوانی پارامتر همان فراخوانی است. n فراخوانی بیرونی وقتی فراخوانی درونی اجرا میشود خودش را بازنویسی نمیکند. فراخوانی درونی n جدا دارد. وقتی فراخوانی درونی برمیگردد، فراخوانی بیرونی از خط بعد از خودفراخوانی ادامه میدهد — و در این صفحه آن فقط پایان متد است.
دموی باقیماندهٔ mark میتواند در همان فایل بنشیند و صفحه را گیج کند اگر Main هنوز mark صدا بزند. Main را تا down(3); یا down(2); پاک کنید وقتی این صفحه را یاد میگیرید. down را داخل آکولادهای Main تودرتو نکنید. متدها داخل کلاس، کنار Main مینشینند.
نوشتن Console.WriteLine("down"); در Main واژهٔ down را مینویسد. زنجیره را شروع نمیکند. وقتی میخواهید سه خط شمارش معکوس، down(3); را نگه دارید.
یک شکل دیگر: توقف چیزی نمینویسد
از قبل دیدید که فراخوانی با 0 آرام برمیگردد. میتوانید شروع با مقدار 1 را هم تمرین کنید. صفحه باید یک خط نشان دهد: 1. سپس فراخوانی بعدی down(0) است که میایستد.
using System;
public class Pine
{
public static void Main()
{
down(1);
}
static void down(int n)
{
if (n <= 0)
{
return;
}
Console.WriteLine(n);
down(n - 1);
}
}
این فایل سوم است. با dotnet run اجرا کنید. صفحه یک خط نشان میدهد: 1. همان بدنهٔ متد down(3)، down(2)، و down(1) را پوشش میدهد. فقط آرگومان اول در Main عوض میشود. برای این صفحهٔ مبتدی کافی است. ایدههای عمیقتر مثل برگرداندن جمع از بازگشت برای دورههای بعد میمانند؛ اینجا هدف خودفراخوانی، آرگومان کوچکتر، و توقف است.
اگر صفحه اصلاً چیزی نشان ندهد، چک کنید آیا Main هنوز چیز دیگری صدا میزند، یا آزمون توقف اشتباه است — مثلاً if (n >= 0) وقتی با n مثبت شروع کنید پیش از هر نوشتن میایستد. n <= 0 را بهعنوان خروج آرام نگه دارید، و در Main شروع مثبت نگه دارید تا حداقل یک خط ظاهر شود.
حالا میتوانید down(int n) بنویسید، وقتی n برابر 0 یا کمتر است بایستید، n را بنویسید، بعد down(n - 1) صدا بزنید. از Main، یک فراخوانی کل زنجیره را شروع میکند. صفحه خطهای شمارش معکوس را نشان میدهد. متدی که هرگز بهسوی توقف حرکت نکند تمام نمیشود. صفحهٔ بعدی classes است؛ آنجا ساختن نوعها با فیلدها را فراتر از این صفحات متد static شروع میکنید.
صفحه شمارش معکوس را نگه میدارد
فایلی که نگه میدارید وقتی Main صدا میزند down(3);، اول 3 بعد 2 بعد 1 مینویسد. خودفراخوانی داخل down است، و حرفهای down روی صفحه بهعنوان برچسب چاپشده نیستند مگر گیومه دورشان گذاشته باشید. تودرتو کردن down داخل Main شکل این درس نیست.
🧠 دانش خود را بیازمایید
دانش خود را بیازمایید
خود را با این آزمون تعاملی به چالش بکشید و ببینید موضوع را چقدر خوب درک کردهاید
📝 دستورالعملها
- هر سوال را با دقت بخوانید
- بهترین پاسخ را برای هر سوال انتخاب کنید
- میتوانید آزمون را هر چند بار که میخواهید تکرار کنید
- پیشرفت شما در بالا نمایش داده میشود