0

While learning Java by doing online courses, I'm experimenting with some code written with the tutorial. There is a method, that should concatenate "courses" and in the end just print them out. I wanted to use recursion instead of loop.

private String courses = "";
private int tuitionBalance = 0;

public void enroll() {
    System.out.println("Enter course to enroll or \"Q\" to quit.");
    Scanner in = new Scanner(System.in);
    String course = in.nextLine();
    if (!course.equalsIgnoreCase("q")) {
        courses = courses + "\n" + course;
        tuitionBalance = tuitionBalance + costOfCourse;
        enroll();
    }

    System.out.println("Enrolled in: " + courses);
    System.out.println("Tuition balance: " + tuitionBalance);
    return; // even with "return", this method executes multiple times after leaving if statement.
}

When this method runs, it keeps prompting for input untill 'Q' is pressed. Concatenation works fine. Then it leaves "if statement" and (what is strange for me) it runs last two lines of println code as many times, as the input was provided.

For example when I enter three types of "course" and then press 'Q', the output is:

Enter course to enroll or "Q" to quit.
History  // My entry
Enter course to enroll or "Q" to quit.
Math  // My entry
Enter course to enroll or "Q" to quit.
Biology  // My entry
Enter course to enroll or "Q" to quit.
q  // My entry
Enrolled in: 
History
Math
Biology
Tuition balance: 1800
Enrolled in: 
History
Math
Biology
Tuition balance: 1800
Enrolled in: 
History
Math
Biology
Tuition balance: 1800
Enrolled in: 
History
Math
Biology
Tuition balance: 1800

Process finished with exit code 0

Could You please tell me what is happening?

EDIT: I've read Understanding recursion [closed] and I haven't found any information about how recursion affects the call stack. There is much excellent information on how to use recursion, but still I haven't found the answer to my question there.

  • 8
    Each time you recurse, it pushes the return address of the method call onto the stack. The multiple entries you are seeing are this stack of calls unwinding as you `return` from each method call. If you just want the list printed once, put the code that prints it outside of your recursive method. – Robert Harvey Aug 25 '18 at 17:32
  • 3
    This is a great opportunity to use your debugger to step through the code, line by line as it executes, and observe what it's doing. Think about it this way... One of the things your `enroll()` method does is print output. You call `enroll()` 4 times. Why specifically do you not expect `enroll()` to run 4 times? – David Aug 25 '18 at 17:35
  • Possible duplicate of [Understanding recursion](https://stackoverflow.com/questions/717725/understanding-recursion) – Timothy Truckle Aug 25 '18 at 17:39
  • @David I've used debugger, looking line by line what is happening. After providing 'Q', program bypasses the if statement and just goes through println lines few times. It was not obvious to me what makes the program to behave like that. –  Aug 25 '18 at 17:49

1 Answers1

0

The thing is you don't want recursions to print for cases where users have entered a course a simple else will solve the problem

private String courses = "";
private int tuitionBalance = 0;

public void enroll() {
    System.out.println("Enter course to enroll or \"Q\" to quit.");
    Scanner in = new Scanner(System.in);
    String course = in.nextLine();
    if (!course.equalsIgnoreCase("q")) {
        courses = courses + "\n" + course;
        tuitionBalance = tuitionBalance + costOfCourse;
        enroll(); 
    }
    else{//now it would come here only once after user has entered q after which it returns
    System.out.println("Enrolled in: " + courses);
    System.out.println("Tuition balance: " + tuitionBalance);
     }
    return;
}
Vaibhav Gupta
  • 638
  • 4
  • 12
  • Yes it works with "else", but still it is hard for me to understand why it was printing out few times. Using debugger, line by line, it did not touch the println functions, while those lines were put onto the stack... –  Aug 25 '18 at 18:30
  • It is the case that it did not touch the lines initially but as soon as you press q in your posted program it would start because the functions have been added to call stack and without the else, it would continue sequentially from each previous caller function return. To see it more clearly see how the code and call stack behaves after you press q in your initial program and how it behaves in my program – Vaibhav Gupta Aug 25 '18 at 18:49
  • I have checked it with debugger and when 'Q' is provided , program skips "if statement" , goes to "else" , prints, and then it goes back to `enroll()` and to the closing `}` (both ways , as many times as any previous input was provided) not evoking the method –  Aug 25 '18 at 19:00
  • This is threads report from Your solution (after providing 4 entries, the last was "Q") : `java.lang.Thread.State: RUNNABLE at studentdatabaseapp.Student.enroll(Student.java:57) at studentdatabaseapp.Student.enroll(Student.java:54) at studentdatabaseapp.Student.enroll(Student.java:54) at studentdatabaseapp.Student.enroll(Student.java:54) at studentdatabaseapp.StudentDatabaseApp.main(StudentDatabaseApp.java:9)` –  Aug 25 '18 at 19:19
  • I would recommend first you try to get some theoretical knowledge about recursion in general. https://medium.freecodecamp.org/how-recursion-works-explained-with-flowcharts-and-a-video-de61f40cb7f9 – Vaibhav Gupta Aug 25 '18 at 19:23
  • I will, thank You for Your input. I understand , that in this particular example recursion is just not the preferable solution. –  Aug 25 '18 at 19:40