הקריאה הרקורסיבית יכולה להימצא בכל מיני מקומות בקוד. לרגע בוא נתעלם מקוד מורכב בתוך הפונקציה, ונחשוב על שני מקרים פשוטים - אתה עושה משהו עם הנתונים שלך, ואז מבצע את הקריאה הרקורסיבית, או שאתה מבצע את הקריאה הרקורסיבית, ואז עושה את מה שבא לך לעשות.
זה נשמע קצת אנטי-אינטואטיבי, אבל לפעמים צריך לחשוב על הדרך השנייה, כדי למצוא את הפיתרון. ב-merge sort לדוגמה, משתמשים בצורה השנייה. הדרך שבה רקורסיה כזו עובדת היא שאתה נכנס לעומק מחסנית הקריאות, ואז ביציאה, עושה את מה שאתה רוצה לעשות.
שוב, אני אדגיש, הפעולה העיקרית של הפונקציה שלך נעשית ביציאה ממחסנית הקריאות.
הבעיה שלך היא המגבלה המלאכותית שהוסיפו בתרגיל - שאתה לא יודע את אורך המחרוזות. אסור לך להשתמש ב-strlen. לכן, אתה לא יכול להשתמש בפיתרון כמו זה ש-rlsf הציע - כי אתה לא יודע איפה נמצא התו האחרון (הוא נמצא ב-str1[len-1], אבל אתה לא יודע מהו len).
אסור לך ללכת עד ה-NULL כדי לגלות את אורך המחרוזת, זה שקול לקריאה ל-strlen.
אז מה אתה יכול לעשות?
יש קטגוריה של פיתרונות רקורסיביים שבהם מבצעים פעולה על חלק ממערך (לדוגמה, ההתחלה), ואז קוראים לעצמך רקורסיבית על שאר המערך. לדוגמה, אתה רוצה להכפיל כל מספר בערך פי 2 - אתה מכפיל את המספר הראשון במערך פי 2, וקורא לעצמך על המערך ללא התו הראשון:
קוד:
void doubleArray(int*arr, size_t size) {
if (size == 0) return;
arr[0] = arr[0] * 2;
doubleArray(arr+1, size-1);
};
אתה הולך לעשות משהו דומה, לעבור תו-תו כשכל תו נעשה בקריאה אחרת. ההבדל הוא שאתה רוצה להתחיל מסוף המחרוזת, ובשביל זה תצטרך לדעת מה הגודל שלה. היופי הוא שכשתגיע לעומק מחסנית הקריאות, אתה גם תדע מה אורך המחרוזת. תיכנס רקורסיבית עד שתגיע לסוף המחרוזת (זה מותר), ועכשיו ביציאה אתה יודע מה אורך המחרוזת, ומסוגל לבצע את ההחלפה.