Java,我不明白为什么会发生这种变化

时间:2021-11-15 22:07:39
    public void askForDate(Scanner in) {
    System.out.println("Please enter the date that the vehicle entered the car park in this format dd/mm/yyyy :");
    String enteredDate = in.nextLine();

    //This array will hold the 3 elements of which the date is made up of, day, month and year, and this method returns it.
    String[] dateEnteredSplit = enteredDate.split("/");

    //I am using the split method to seperate each number, which returns an array, so I am assigning that array to the dateEnteredSplit array.
    //dateEnteredSplit = enteredDate.split("/");
    //So now the first element holds the day, second the month, and the third element holds the year.

    //System.out.println(Arrays.toString(dateEnteredSplit));

    //Assigning each element and converting them to integers.
    int day = Integer.parseInt(dateEnteredSplit[0]);
    int month = Integer.parseInt(dateEnteredSplit[1]);
    int year = Integer.parseInt(dateEnteredSplit[2]);

    **System.out.println("day: " + day + "  month: " + month + "  year: " + year);**

    //The loop will be entered if any of the values are wrong. which will use recursion to call this method again for a chance to enter the date again.
    while (!(day >= 1 && day <= 31) || !(month >= 1 && month <= 12) || !(year > 1000 && year < 5000)) {
        **System.out.println("day: " + day + "  month: " + month + "  year: " + year);**
        //Im calling these methods to inform which one specifially was wrong so they know what they need to change.
        this.setDay(day);
        this.setMonth(month);
        this.setYear(year);

        dateEnteredSplit[0] = "0";
        askForDate(in);
    }

    //I then assign any correct value into the object attribute because the while loop is either finished or not entered at all. 
    //No need to use setDay etc. here because the checks have been done above in the while loop.
    this.day = day;
    this.month = month;
    this.year = year;  
}

Ok that is a method in a class. It asks for input in the format dd/mm/yyyy

好的,这是一个类中的方法。它要求输入格式为dd / mm / yyyy

If the first time I input 12/1/1996 it works, but if I enter a wrong date for example like this first, 123/123/123 and the enter a correct date for example 12/1/1996, it still enters the loop.

如果我第一次输入12/1/1996它可以工作,但如果我输入一个错误的日期,例如第一个123/123/123,并输入一个正确的日期,例如12/1/1996,它仍然进入循环。

After debugging, the first line that is bold, the values are different from the second line that is bold, its like the values are changing by their own.

调试后,第一行是粗体,值与粗体的第二行不同,它的值就像它们自己的值一样。

What is the problem here? I have been trying to find out in the past 1 hour.

这里有什么问题?我一直试图找出过去1小时。

Thanks in advance!

提前致谢!

2 个解决方案

#1


0  

The problem very likely is in the way you are trying to combine recursive and iterative approach to update values (there is a while loop, that call the function recursively, which may also trigger while loop in next level of call and the previous one will continue calling itself recursively and you will end up with just mess)

问题很可能在于你试图将递归和迭代方法结合到更新值的方式(有一个while循环,它递归地调用函数,这也可能在下一级调用中触发while循环而前一个循环将继续递归地调用自己,你最终只会乱七八糟)

There is no real reason to do that recursively, I would do iterative only approach, something like this:

没有真正的理由以递归的方式做到这一点,我会做迭代式的方法,如下所示:

public void askForDate(Scanner in) {
    System.out.println("Please enter the date that the vehicle entered the car park in this format dd/mm/yyyy :");

    int day, month, year;
    do { // We use do-while to get the first read without condition, although setting date to invalid value (like day = 0) and then running standard while loop will work just as fine
        String[] dateEnteredSplit = in.nextLine().split("/");

        //Assigning each element and converting them to integers.
        day = Integer.parseInt(dateEnteredSplit[0]);
        month = Integer.parseInt(dateEnteredSplit[1]);
        year = Integer.parseInt(dateEnteredSplit[2]);
    } while (!(day >= 1 && day <= 31) || !(month >= 1 && month <= 12) || !(year > 1000 && year < 5000));

    // Now day month and year variables are set correctly and we can do stuff with it
}

If you insist or recursive approach, the correct way would be to call the function just once:

如果你坚持或递归方法,正确的方法是只调用一次函数:

public void askForDate(Scanner in) {
    System.out.println("Please enter the date that the vehicle entered the car park in this format dd/mm/yyyy :");

    int day, month, year;
    String[] dateEnteredSplit = in.nextLine().split("/");

    //Assigning each element and converting them to integers.
    day = Integer.parseInt(dateEnteredSplit[0]);
    month = Integer.parseInt(dateEnteredSplit[1]);
    year = Integer.parseInt(dateEnteredSplit[2]);

    if (!(day >= 1 && day <= 31) || !(month >= 1 && month <= 12) || !(year > 1000 && year < 5000)) askForDate(in);

    // You need to save day/month/year variables to other than local scope (like this.day = day)
    // Otherwise it would just somewhere in recursion stack and you wouldn't be able to use it
}

Just to be complete, keep in mind that date string could be wrong in other way that just number out of range. What if user types 1. 2. 3456 or a/b/c or not even something very different like Hello At your snippet of code would crash (either throw NumberFormatException when trying to parse non-integer or ArrayIndexOutOfBoundsException when accessing dateEnteredSplit array at element that doesnt exists (there are no '/' in 'Hello'))

为了完整,请记住,日期字符串可能是错误的,只是编号超出范围。如果用户类型1. 2. 3456或A / B / C,甚至没有像你好非常不同的。在你的代码片段会崩溃(无论是抛出NumberFormatException的努力在元素访问dateEnteredSplit阵列时,解析非整数或者ArrayIndexOutOfBoundsException异常时不存在('Hello'中没有'/')

#2


0  

Here is what happens. Wrong values on a first while loop iteration make a call to askForDate possible. You receive a second prompt and provide correct input. The second call of askForDate ends as expected. The execution returns again to a while loop, where you still have the first wrongly set values and the process starts again.

这是发生了什么。第一次while循环迭代的错误值可以调用askForDate。您收到第二个提示并提供正确的输入。 askForDate的第二次调用按预期结束。执行再次返回到while循环,您仍然有第一个错误设置的值,并且该过程再次启动。

If you really do want to use recursion here, you should return a value from your function (dates or boolean flag) and check it in a while loop condition.

如果你真的想在这里使用递归,你应该从函数中返回一个值(日期或布尔标志)并在while循环条件下检查它。

#1


0  

The problem very likely is in the way you are trying to combine recursive and iterative approach to update values (there is a while loop, that call the function recursively, which may also trigger while loop in next level of call and the previous one will continue calling itself recursively and you will end up with just mess)

问题很可能在于你试图将递归和迭代方法结合到更新值的方式(有一个while循环,它递归地调用函数,这也可能在下一级调用中触发while循环而前一个循环将继续递归地调用自己,你最终只会乱七八糟)

There is no real reason to do that recursively, I would do iterative only approach, something like this:

没有真正的理由以递归的方式做到这一点,我会做迭代式的方法,如下所示:

public void askForDate(Scanner in) {
    System.out.println("Please enter the date that the vehicle entered the car park in this format dd/mm/yyyy :");

    int day, month, year;
    do { // We use do-while to get the first read without condition, although setting date to invalid value (like day = 0) and then running standard while loop will work just as fine
        String[] dateEnteredSplit = in.nextLine().split("/");

        //Assigning each element and converting them to integers.
        day = Integer.parseInt(dateEnteredSplit[0]);
        month = Integer.parseInt(dateEnteredSplit[1]);
        year = Integer.parseInt(dateEnteredSplit[2]);
    } while (!(day >= 1 && day <= 31) || !(month >= 1 && month <= 12) || !(year > 1000 && year < 5000));

    // Now day month and year variables are set correctly and we can do stuff with it
}

If you insist or recursive approach, the correct way would be to call the function just once:

如果你坚持或递归方法,正确的方法是只调用一次函数:

public void askForDate(Scanner in) {
    System.out.println("Please enter the date that the vehicle entered the car park in this format dd/mm/yyyy :");

    int day, month, year;
    String[] dateEnteredSplit = in.nextLine().split("/");

    //Assigning each element and converting them to integers.
    day = Integer.parseInt(dateEnteredSplit[0]);
    month = Integer.parseInt(dateEnteredSplit[1]);
    year = Integer.parseInt(dateEnteredSplit[2]);

    if (!(day >= 1 && day <= 31) || !(month >= 1 && month <= 12) || !(year > 1000 && year < 5000)) askForDate(in);

    // You need to save day/month/year variables to other than local scope (like this.day = day)
    // Otherwise it would just somewhere in recursion stack and you wouldn't be able to use it
}

Just to be complete, keep in mind that date string could be wrong in other way that just number out of range. What if user types 1. 2. 3456 or a/b/c or not even something very different like Hello At your snippet of code would crash (either throw NumberFormatException when trying to parse non-integer or ArrayIndexOutOfBoundsException when accessing dateEnteredSplit array at element that doesnt exists (there are no '/' in 'Hello'))

为了完整,请记住,日期字符串可能是错误的,只是编号超出范围。如果用户类型1. 2. 3456或A / B / C,甚至没有像你好非常不同的。在你的代码片段会崩溃(无论是抛出NumberFormatException的努力在元素访问dateEnteredSplit阵列时,解析非整数或者ArrayIndexOutOfBoundsException异常时不存在('Hello'中没有'/')

#2


0  

Here is what happens. Wrong values on a first while loop iteration make a call to askForDate possible. You receive a second prompt and provide correct input. The second call of askForDate ends as expected. The execution returns again to a while loop, where you still have the first wrongly set values and the process starts again.

这是发生了什么。第一次while循环迭代的错误值可以调用askForDate。您收到第二个提示并提供正确的输入。 askForDate的第二次调用按预期结束。执行再次返回到while循环,您仍然有第一个错误设置的值,并且该过程再次启动。

If you really do want to use recursion here, you should return a value from your function (dates or boolean flag) and check it in a while loop condition.

如果你真的想在这里使用递归,你应该从函数中返回一个值(日期或布尔标志)并在while循环条件下检查它。