I have a project where my method gets two dates and it keeps adding a day to the method until both dates are equal and then you can see how far apart the date were by seeing how many times a day was added. My problem is that my while loop is exiting out when the the day condition is met even though the day, month, and year must all be the same for it to stop working
while (pastDate.getDay() != futureDate.getDay() &&
pastDate.getMonth() != futureDate.getMonth() &&
pastDate.getYear() != futureDate.getYear()){
You need to OR together the conditions in your while loop:
while (pastDate.getDay() != futureDate.getDay() ||
pastDate.getMonth() != futureDate.getMonth() ||
pastDate.getYear() != futureDate.getYear()) {
// do something
}
In pseudo-code, the logic for the loop when the two dates are equal would be:
while (day1 == day2 && month1 == month2 && year1 == year2) {
// ...
}
By the DeMorgan's Laws, the opposite of P AND Q is ~P OR ~Q, which would lead the following while loop (again in pseudo-code) for when the dates are not equal:
while (day1 != day2 || month1 != month2 || year1 != year2) {
// ...
}
Use .equals():
while (!pastDate.equals(futureDate)) {
//
}
Not only is it more readable, it leaves exactly how dates are considered equal to the implementation, which is where OOP best practices says it should be.
Related
This is a program that allows the user to build a high school schedule.
I would like to validate an integer as a high school class number in my String method. Here's the name of my method with the parameters.
public static String addClass(String name, String day, String momentOfDay, int group){
The user has to put an integer as the value of a school class number. The number has to start with a specific number according to the day of class. Here's a table that explains the validation wanted
Day of Class | Valid Group
Monday | The first number of the group must start with 1 ( example 10, 14...)
Tuesday | The first number of the group must start with 2 ( example 20, 22...) ______________________________________________________________________________
Wednesday | The first number of the group must start with 3 ( example 30, 31...) ______________________________________________________________________________
Thursday | The first number of the group must start with 4 ( example 40, 31...) ______________________________________________________________________________
Friday | The first number of the group must start with 5 ( example 50, 56...)
Here's what the output should look like ( the terms in bold are the entered values by the user ) :
**********************
ADD CLASS TO SCHEDULE
**********************
Name of class : **INF1120**
Day of class : **Monday**
Moment of the day of the class : **PM**
Group of class : **12**
I'm using the scanner to allow the user to enter the wanted integer.
I completed the name of class, day and moment of the day part.
However, I'm having a hard time to validate the first number of the group integer according to the days in the table. Here's my code :
import java.util.Scanner;
public class schedule {
public static String addClass(String name, String day, String momentOfDay, int group) {
Scanner keyboard = new Scanner(System.in);
System.out.print("day of class: ");
day = keyboard.nextLine();
if( day != "monday" || day != "tuesday" || day != "wednesday"
|| day != "thursday" || day != "friday" ) {
System.out.print("Error, the day has to be either : monday, tuesday, wednesday, thursday, or friday...");
}
else if(day = "monday" || day = "tuesday" || day = "wednesday"
|| day = "thursday" || day = "friday" ) {
return day;
}
System.out.print("Moment of day: ");
momentOfDay = keyboard.nextLine();
if(momentOfDay != "am" || momentOfDay != "pm" || momentOfDay != "night") {
System.out.print("Error, the moment of the day has to be : am, pm, or evening...");
}
else if(momentOfDay == "am" || momentOfDay == "pm" || momentOfDay == "evening") {
return momentOfDay;
}
System.out.print("Class group");
group = keyboard.nextInt();
while(day == "monday" || day == "tuesday" || day == "wednesday"
|| day == "thursday" || day == "friday"){
if (String.valueOf(Math.abs(int(group)).charAt(0) == 1){
return group;
}
else {
System.out.print("Error, group number is invalid");
}
}
}
}
However, it is not compiling because the return value cannot be an int which is required. Here's the error.
Type mismatch: cannot convert from int to String
It is asking me to either change the return type to int or change the type of group to String.
Should I change the type of group in the parameter ? What did I do wrong ?
I tried to research the methods in this link but can't seem to figure it out.
When I copied the code of class schedule that you posted, I got a compilation error for this line:
if (String.valueOf(Math.abs(int(group)).charAt(0) == 1){
The int should be removed. group is a parameter of method addClass() and it is an int. So the line of code should be:
if (String.valueOf(Math.abs(group)).charAt(0) == 1){
After correcting that line, the line following it causes a compilation error. That line is:
return group;
Method addClass() is declared to return a String but group is an int. So that line should be changed to:
return String.valueOf(group);
After correcting that line of code, I got yet another compilation error, namely that the method does not return a value. This is the while loop in method addClass():
while (day == "monday" || day == "tuesday" || day == "wednesday" || day == "thursday"
|| day == "friday") {
If day is "sunday", the loop is terminated. There needs to be a return statement after that while loop.
But even after fixing all the compilation errors, your code will not work due to logic errors. I just showed you one of those errors in the while loop. Similarly this if statement will not do what you want.
if (day != "monday" || day != "tuesday" || day != "wednesday" || day != "thursday"
|| day != "friday")
Besides that fact that you need to use method equals() to check if two strings are equal, if day is "tuesday", then the first condition, namely day != "monday" is true. If you want to ensure that the user enters a valid day, then you need the following:
if ("monday".equals(day) ||
"tuesday".equals(day) ||
"wednesday".equals(day) ||
"thursday".equals(day) ||
"friday".equals(day)) {
return day;
}
else {
System.out.print(
"Error, the day has to be either : monday, tuesday, wednesday, thursday, or friday...");
}
If day and momentOfDay and group are all parameters of method addClass(), why do you ask the user to enter these values inside method addClass() ? Also the other method parameter, name, is never used in the method.
I think you need to create three, separate methods. One to get the day from the user, another to get the momentOfDay and yet another to get the group.
I suggest you read the book Java by Comparison by Simon Harrer, Jörg Lenhard, Linus Dietz
I was working on a game called the L game. In the function to check for a win, I had an if statement like this:
if (buttons[i][0].getText().equals(colour) || buttons[i][0].getText().equals("0") && buttons[i][1].getText().equals(colour) || buttons[i][1].getText().equals("0") && buttons[i][2].getText().equals(colour) || buttons[i][2].getText().equals("0") && buttons[i+1][2].getText().equals(colour) || buttons[i+1][2].getText().equals("0") && !(buttons[i][0].getText().equals(colour) && buttons[i][1].getText().equals(colour) && buttons[i][2].getText().equals(colour) && buttons[i+1][2].getText().equals(colour))) {
return false;
}
And this code didn't work. Not that I was getting an error, just it was not doing what it was supposed to do when a player won. However changed it to a few if statements in each other like this:
if (buttons[i][0].getText().equals(colour) || buttons[i][0].getText().equals("0")) {
if (buttons[i][1].getText().equals(colour) || buttons[i][1].getText().equals("0")) {
if (buttons[i][2].getText().equals(colour) || buttons[i][2].getText().equals("0")) {
if (buttons[i+1][2].getText().equals(colour) || buttons[i+1][2].getText().equals("0")) {
if (!(buttons[i][0].getText().equals(colour) && buttons[i][1].getText().equals(colour) && buttons[i][2].getText().equals(colour) && buttons[i+1][2].getText().equals(
return false;
}
}
}
}
}
And this does work.
Your two code snippets behave differently not because you have exceeded some "maximum characters in an if statement" limit, but because && has a higher precedence than ||.
When you say:
A || B && C || D
You meant
(A || B) && (C || D)
But without any parentheses, Java thought you meant:
A || (B && C) || D
This is because && has a higher precedence than ||. It's kind of like how you do multiplication first, than addition.
That aside, there is theoretically no limit on how long an if condition can be. It is not specified in the Java Language Specification. As long as you have enough RAM for the compiler, disk space to store the source file, and time for the compilation process, your code should compile eventually, if we assume the compiler implements the spec perfectly.
This doesn't mean that you should be writing super long if statements, though. Code is not only read by computers. Arguably, it is more often read by people than computers. So please keep that in mind when writing code.
A first step to refactoring your code would be to write a method like this:
private bool isButton0(int x, int y) {
return buttons[x][y].getText().equals("0");
}
so that you don't have to repeatedly say buttons[i][1].getText().equals("0").
I have the following problem. I need to validate date and time, so it returns false if the day of the week is Tuesday orThursday and the time is between 2:00 and 3:00 PM.
I have two options:
if (appointmentRequest.getDateTime().getDayOfWeek() == DayOfWeek.TUESDAY
|| appointmentRequest.getDateTime().getDayOfWeek() == DayOfWeek.THURSDAY) {
if (appointmentRequest.getDateTime().getHour() == 2) {
return false;
}
}
Option 2:
if ((appointmentRequest.getDateTime().getDayOfWeek() == DayOfWeek.TUESDAY
|| appointmentRequest.getDateTime().getDayOfWeek() == DayOfWeek.THURSDAY)
&& (appointmentRequest.getDateTime().getHour() == 2)) {
return false;
}
What is the best practice in cases like this?
Logically they are equivalent, and computationally there will be negligible difference in the run times.
Always strive for clarity and the one that is going to be more extensible, and simpler to maintain. As a rule of thumb, bear in mind that although you typically write a line of code once, you'll debug it hundreds of times.
My instinct is that the first option fits that. It's easy to set a line break on the second if if you make that choice.
I find your question a bit of a false dichotomy; clarity can be won in other ways, for example by a combination of extracting the common subexpression into a variable and relying on EnumSet:
LocalDateTime dt = appointmentRequest.getDateTime();
if (EnumSet.of(TUESDAY, THURSDAY).contains(dt.getDayOfWeek()) && dt.getHour() == 2) {
return false;
}
String userGuessParameters = "a,b";
while (!Character.isDigit(userGuessParameters.charAt(0)) ||
!Character.isDigit(userGuessParameters.charAt(2)) ||
userGuessParameters.length() != 3 ||
(int)(userGuessParameters.charAt(0)) >= parameters[0] ||
(int)(userGuessParameters.charAt(2)) >= parameters[1]) {
System.out.print("Mida kaevame (rida, veerg): ");
userGuessParameters = userInput.nextLine();
userGuessParameters = userGuessParameters.replaceAll(" ", "");
}
I'm trying to check if all the required conditions are fulfilled in the while loop. parameters is what user entered in array form. Let's assume parameters = [4, 4] (Parameters is used to create a 4x4 map).
I need userGuessParameters to be:
Numbers
Length equal to 3 (the input looks like this: 2,2 when the spaces are removed)
Smaller than the biggest coordinate (which is 3,3)
But for some reason, the loop never exits. I'm almost certain it is because of the last two conditions in the while loop, but I can't find the mistake.
You are using the logical OR operator when you should be using AND (you want all the conditions to be met, not just at least one of them).
Use the java notation for AND which is &&:
(!Character.isDigit(userGuessParameters.charAt(0)) &&
!Character.isDigit(userGuessParameters.charAt(2)) &&
userGuessParameters.length() != 3 &&
(int)(userGuessParameters.charAt(0)) >= parameters[0] &&
(int)(userGuessParameters.charAt(2)) >= parameters[1])
Try to use && instead of || like this:
while (!Character.isDigit(userGuessParameters.charAt(0)) && !Character.isDigit(userGuessParameters.charAt(2))
&& userGuessParameters.length() != 3 && (int)(userGuessParameters.charAt(0)) >= parameters[0]
&& (int)(userGuessParameters.charAt(2)) >= parameters[1]) {
This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 9 years ago.
I made a timer which checks if my twitch.tv stream is offline or not. the method get executed all 30 seconds.
If my stream is online the bot will automatically connect to my Stream.
If my Stream if offline there's an INT which will go +1 all 30 seconds and if it reaches 10 which are 5 minutes the bot should just part the IRC channel.
but somehow, the bot continues on counting. Did i made any faults with my if/else statements?
As soon my Stream is offline, bot starts counting all 30 seconds +1 as it should. but when it reaches 10 it just goes higher... its now at 30 already for example but i'm not sure why it doesn't part the channel.
Here is my function;
public void livemodetimer() {
if(livemode == "off" && TwitchStatus.isstreamlive){
livemode = "on";
}else
if(livemode == "on" && TwitchStatus.isstreamlive == false){
zaehler = zaehler+1;
System.out.println("Stream Offline Counter. Disconnect bei (10). Aktuell:"+zaehler);
}else
if(livemode == "on" && TwitchStatus.isstreamlive == true){
zaehler = 0;
if(zaehler >= 10){
livemode = "off";
zaehler = 0;
}
if (TwitchStatus.isstreamlive && livemode == "on" && multistartprepare == false){
joinChannel("#"+YBot.MyBot.ownerchannel+"");
multistartprepare = true;
startup();
}
if(TwitchStatus.isstreamlive == false && livemode == "off" && multistartprepare == true){
sendMessage("#"+YBot.MyBot.ownerchannel+"","Da der Stream Offline ist verzieh ich mich mal =) Bye!!");
partChannel("#"+YBot.MyBot.ownerchannel+"");
multistartprepare = false;
zaehler = 0;
TTmsg.cancel();
TTmsg.purge();
}
}
Does anyone have an idea why it doesn't call the partchannel stuff when it reaches 10.
Edited Version Below:
public void livemodetimer() {
if(livemode == false && TwitchStatus.isstreamlive){
livemode = true;
}else
if(livemode && TwitchStatus.isstreamlive == false){
zaehler = zaehler+1;
System.out.println("Stream Offline Counter. Disconnect bei (10). Aktuell:"+zaehler);
}else
if(livemode && TwitchStatus.isstreamlive == true){
zaehler = 0;
}
if(zaehler >= 10){
livemode = false;
zaehler = 0;
}
if (TwitchStatus.isstreamlive && livemode && multistartprepare == false){
joinChannel("#"+YBot.MyBot.ownerchannel+"");
multistartprepare = true;
startup();
}
if(TwitchStatus.isstreamlive == false && livemode == false && multistartprepare){
sendMessage("#"+YBot.MyBot.ownerchannel+"","Da der Stream Offline ist verzieh ich mich mal =) Bye!!");
partChannel("#"+YBot.MyBot.ownerchannel+"");
multistartprepare = false;
zaehler = 0;
TTmsg.cancel();
TTmsg.purge();
}
}
You have several problems.
You don't have an ending brace for your statement
if(livemode == "on" && TwitchStatus.isstreamlive == true){
zaehler = 0;
It's hard to tell where you want the block closed, partly because your code uses tabs to indent, which doesn't get displayed very well here (also, don't mix tabs and spaces, your code editor should have a way to convert one to the other). Using consistent indentation helps me to keep from getting confused about nesting of braces.
Because the indentation is unclear I'm not sure what you want the else clauses to do, it would be better to use braces to explicitly show the blocks that you mean to be executed. Using a consistent formatting scheme like One True Brace style would be a big help here.
Basically pick a consistent way to format your code that is very explicit and stick to it, and you will have an easier time.
Using == for string comparison is bad (because it compares references, you could have 2 separate references both holding "on", and == would return false). You should use the equals method instead because it will compare the values.
Also using == true for boolean comparisons is redundant. It doesn't hurt anything, it's just awkward-looking.
You are comparing strings with == when they need to be compared with equals
if(livemode == "on")
does not test if the value in livemode is equal to "on". Rather, it tests if these two objects are at the same physical memory location, which is most definitely what you do not want, since it is obviously possible for two strings in two different objects to contain the same value.
Change it to
if(livemode.equals("on")
Your if-statement String comparison should use .equals()
String is an Object type in Java meaning it needs to call an .equals() function in order to properly compare it to other Strings. The == operator, if I'm not mistaken (I often am), will compare the memory locations of the Object and report false when the comparison fails.
if ( livemode.equals("on") && ...
should fix your issues.