我对Java还很陌生。我做了一些C++,所以我理解了很多概念。我一直在编写这段代码,它允许我在小费计算器上请求输入。我知道有些代码不一致,但这是因为我一直在尝试各种方法来显示它。
一旦请求用户输入,我就可以浏览该程序。然而,当我再次循环它时,它只显示我之前输入的相同输入。我试图让它显示出来,然后循环,接受新的输入并显示出来。我一直在自学,所以这对我来说是一次学习经历,但我被难住了,不知道该何去何从。感谢您的帮助。
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.InputMismatchException;
import java.util.Scanner;
public class TipApp {
public static void main(String[] args) {
calculateTips();
}
public static void calculateTips () {
Scanner input = new Scanner(System.in);
Scanner scan = new Scanner(System.in);
String pattern = "$##,###,###.00;"; // Pattern string for the decimal format
DecimalFormat moneyFormat = new DecimalFormat(pattern); // Decimal Money format
NumberFormat defaultFormat = NumberFormat.getPercentInstance();
defaultFormat.setMinimumFractionDigits(1);
String choice;
double theBill;
int theTip;
int thePartySize;
boolean isBillValid = true;
boolean isTipValid = true;
boolean isPartySizeValid = true;
TipCalculator tipCalculator1 = new TipCalculator();
System.out.println("*** Tip Calculator ***");
do {
System.out.print("nEnter the bill amount: ");
while (isBillValid) {
try {
if (input.hasNextDouble()) {
theBill = input.nextDouble();
isBillValid = false;
tipCalculator1.setBillAmount(theBill);
}
} catch (InputMismatchException e) {
System.out.println(input.next() + " is not a valid number");
}
input.nextLine();
}
System.out.print("Enter your desired tip percentage (20 equals 20%): ");
while (isTipValid) {
if (input.hasNextInt()) {
theTip = input.nextInt();
isTipValid = false;
tipCalculator1.setTipPercentage(theTip);
} else {
System.out.println("Please enter a valid tip percentage.");
isTipValid = true;
}
input.nextLine();
}
System.out.print("Enter the size of your party: ");
while (isPartySizeValid) {
if (input.hasNextInt()) {
thePartySize = input.nextInt();
isPartySizeValid = false;
tipCalculator1.setPartyAmount(thePartySize);
} else {
System.out.println("Please enter a valid party size.");
isPartySizeValid = true;
}
input.nextLine();
}
System.out.println("*** Your Bill ***");
System.out.print("nBill Amount: ");
System.out.println(moneyFormat.format(tipCalculator1.getBillAmount()));
System.out.print("Tip Percentage: ");
System.out.println(defaultFormat.format(tipCalculator1.getTipPercentage()));
System.out.print("Party Size: ");
System.out.println(tipCalculator1.getPartyAmount());
System.out.print("nTotal Bill (with Tip): ");
System.out.print(moneyFormat.format(tipCalculator1.getTotalAmount()));
System.out.print("nShare for Each Individual: ");
System.out.print(moneyFormat.format(tipCalculator1.getIndividualShare()));
System.out.print("nAnother Bill? (y/n): ");
choice = scan.nextLine();
} while (choice.equalsIgnoreCase("y")) ;
System.out.println("nGoodbye!");
}
}
public class TipCalculator {
private double billAmount;
private int tipPercentage;
private int partyAmount;
// Constructor that holds 3 arguments
public TipCalculator() {
setBillAmount(billAmount);
setTipPercentage(tipPercentage);
setPartyAmount(partyAmount);
}
public double getBillAmount() {
return billAmount;
}
public void setBillAmount(double billAmount) {
this.billAmount = billAmount;
}
public double getTipPercentage() {
return tipPercentage / 100f;
}
public void setTipPercentage(int tipPercentage) {
this.tipPercentage = tipPercentage;
}
public int getPartyAmount() {
return partyAmount;
}
public void setPartyAmount(int partyAmount) {
this.partyAmount = partyAmount;
}
public double getIndividualShare() {
return (getTotalAmount() / partyAmount);
}
public double getTotalAmount() {
return (billAmount * getTipPercentage()) + billAmount;
}
}
[1]: https://i.stack.imgur.com/5tHIs.png
首先,只使用一个Scanner对象,您不需要更多。名称可能是userInput。
你遇到的问题是因为你没有为下一个要计算的账单重置一些关键变量,特别是那些用于循环条件的变量。
取以下变量:
boolean isBillValid = true;
boolean isTipValid = true;
boolean isPartySizeValid = true;
double theBill;
int theTip;
int thePartySize;
和将移动到do循环(主外循环)的顶部,并初始化字符串变量选项以保持空字符串("),例如:
do {
choice = "";
boolean isBillValid = false;
boolean isTipValid = false;
boolean isPartySizeValid = false;
double theBill = 0.0d;
int theTip = 0;
int thePartySize = 0;
System.out.print("nEnter the bill amount: ");
while (isBillValid) {
try {
//..... The rest of your code ....
这样,如果用户输入"y"来处理另一个账单,则循环的条件将不会从上一个账单设置。
在我看来,每个需要某种用户输入的提示都应该确保有效输入,这将包括Another Bill? (y/n):
提示,例如:
while (choice.isEmpty()) {
System.out.print("nAnother Bill? (y/n): ");
choice = userInput.nextLine();
// Is only a 'y' or a 'n' supplied (regardless of letter case)
if (!choice.matches("(?i)[yn]")) {
// No...inform User and have him her try again.
System.out.println("Invalid input - 'y' or 'n' only! Try again...");
choice = ""; // Reset the 'choice' variable to null string.
}
}
上面代码中的if语句条件使用String#matches()方法和一个小型正则表达式(RegEx)。在正则表达式字符串中,(?i)
表示"忽略字母大小写",[yn]
表示:仅匹配"y"或"n"字符。因此,如果提供的选项与y
、Y
、n
或N
不匹配,则条件为true。
这种验证应该适用于您对用户的所有提示,以确保用户无故障体验,毕竟,打字错误确实会发生。以小费百分比条目为例,如果用户输入-10
会发生什么?。如果你申请的是折扣优惠券或其他什么的,这是可以的,但不需要太多小费。我认为用户最好输入一个特定范围内的值,如0到100(或任何你喜欢的):
while (!isTipValid) {
System.out.print("Enter your desired tip percentage (0 to 100): --> ");
try {
theTip = userInput.nextInt();
// Is the tip percentage inclusively between 0 and 100?
if (theTip < 0 || theTip > 100) {
// No...
throw new java.util.InputMismatchException();
}
isTipValid = true;
tipCalculator1.setTipPercentage(theTip);
}
catch (java.util.InputMismatchException ex) {
System.out.println("Invalid tip percentage supplied (" + theTip + ")! Try again...");
}
userInput.nextLine();
}
在上面的循环代码示例中,您很可能会注意到这里做了一些不同的事情。
首先,while循环的条件更好地表示布尔变量isTipValid
的名称。变量名称在某种意义上更像是一个问题:提示有效吗。默认情况下,您将该变量初始化为true,这基本上就像说"Yes, the Tip is Valid!"
,而实际上它还没有建立。为了更清楚起见,我认为这个变量(以及其他类似的变量)应该初始化为booleanfalse,然后只有在确定提供的值确实有效后才更改为booleantrue。
您可能已经注意到的另一个变化是,控制台窗口中显示的提示字符串被放置在while循环中,而不是它的上方。这确保了如果出现无效情况,并且提示需要进一步输入,那么用户肯定会知道请求了什么。所有提示机制都包含在与其相关的while循环中,这是一个好主意。提示字符串也经过了修改,可以向用户指示期望的值在0到100之间。
您可能已经注意到的另一个变化是if (input.hasNextInt()) {
行已被Try/Catch机制替换。这实际上提供了一种更明确的方法来确保正确的数据输入,因为Scanner#hasNextInt()方法(和其他hasNext…()方法)更适合标记化输入,而一系列定界的整数可以在该输入中或在该输入内组合。它当然可以在这个用例中使用,但需要额外的处理来适应所有可能的无效情况。
您还将看到一个额外的if语句,该语句用于检查所提供的值是否在所描述的0到100的范围内。如果不是,则抛出InputMismatchException,强制代码流立即落入catch子句,该子句最终向用户指示问题并重新提示输入另一个值。
与其他提示类似地执行上述操作将产生更好的结果,并且您将知道所提供的值将是有效的,但Bil Amount提示除外:
while (!isBillValid) {
System.out.print("Enter the bill amount: --> ");
try {
theBill = userInput.nextDouble();
if (theBill < 0) {
throw new java.util.InputMismatchException();
}
isBillValid = true;
tipCalculator1.setBillAmount(theBill);
} catch (java.util.InputMismatchException e) {
System.out.println("Invalid Bill amount supplied (" + theBill + ")! Try again...");
}
userInput.nextLine();
}
除了这个简单的打字错误:3e4
示例之外,这将适用于几乎所有无效的可能性。Scanner#nextDouble()方法认为这是一个有效的双精度值。所提供的值中的e
或E
在科学E符号中被视为一个值,并且在其抽出状态下与30000.0的双倍值相同。因此,3e4
最终成为30000.00美元的真正健康的纸币,而不是预期的34美元纸币。为了解决这种情况,需要使用稍微不同的方法。在下面的代码中,您不仅可以看到如何使用这种不同的方法来完成账单金额提示代码,还可以看到所有其他提示:
public void calculateTips() {
Scanner userInput = new Scanner(System.in);
String pattern = "$##,###,###.00;"; // Pattern string for the decimal format
java.text.DecimalFormat moneyFormat = new java.text.DecimalFormat(pattern); // Decimal Money format
java.text.NumberFormat defaultFormat = java.text.NumberFormat.getPercentInstance();
defaultFormat.setMinimumFractionDigits(1);
String choice;
TipCalculator tipCalculator1 = new TipCalculator();
System.out.println("*** Tip Calculator ***");
do {
choice = "";
boolean isBillValid = false;
boolean isTipValid = false;
boolean isPartySizeValid = false;
double theBill = 0.0d;
int theTip = 0;
int thePartySize = 0;
boolean breakAll = false;
while (!isBillValid) {
System.out.print("Enter the bill amount: --> ");
String theBillStrg = userInput.nextLine().trim();
// Is 'c' or 'C' for CANCEL entered?
if (theBillStrg.equalsIgnoreCase("c")) {
// Set breakAll to true break out of this loop.
breakAll = true;
break;
}
// If the value starts with a decimal point then
// prefix it with a 0.
if (theBillStrg.startsWith(".")) {
theBillStrg = "0" + theBillStrg;
}
// If the value ends with a decimal point then
// postfix it with a 0.
else if (theBillStrg.endsWith(".")) {
theBillStrg += "0";
}
// Is the supplied value a string representation of a
// Integer or double type value?
if (theBillStrg.matches("\d+(\.\d+)?")) {
// Yes it is...
// Parse the string value to a double type
theBill = Double.parseDouble(theBillStrg);
isBillValid = true;
tipCalculator1.setBillAmount(theBill);
}
else {
System.out.println("Invalid Bill amount supplied (" + theBillStrg + ")! Try again...");
}
}
while (!isTipValid && !breakAll) {
System.out.print("Enter your desired tip percentage (0 to 100): --> ");
String theTipStrg = userInput.nextLine();
// Is 'c' or 'C' for CANCEL entered?
if (theTipStrg.equalsIgnoreCase("c")) {
// Set breakAll to true break out of this loop.
breakAll = true;
break;
}
// Is a string representation of a Integer value supplied?
if (theTipStrg.matches("\d+")) {
// Yes...Convert the string value to Integer
theTip = Integer.parseInt(theTipStrg);
// Is the tip percentage inclusively between 0 and 100?
if (theTip < 0 || theTip > 100) {
// No...
System.out.println("Out of Range tip percentage supplied (" + theTip + ")! Try again...");
continue;
}
isTipValid = true;
tipCalculator1.setTipPercentage(theTip);
}
else {
System.out.println("Invalid tip percentage supplied (" + theTipStrg + ")! Try again...");
}
}
while (!isPartySizeValid && !breakAll) {
System.out.print("Enter the size of your party: ");
String partySizeStrg = userInput.nextLine();
// Is 'c' or 'C' for CANCEL entered?
if (partySizeStrg.equalsIgnoreCase("c")) {
// Set breakAll to true break out of this loop.
breakAll = true;
break;
}
else if (partySizeStrg.matches("\d+")) {
thePartySize = Integer.parseInt(partySizeStrg);
isPartySizeValid = true;
tipCalculator1.setPartyAmount(thePartySize);
}
else {
System.out.println("Invalid party size supplied (" + partySizeStrg + ")! Try again...");
}
}
if (!breakAll) {
System.out.println();
System.out.println("======================================");
System.out.println("*** Your Bill ***");
System.out.println();
System.out.print("Bill Amount: ");
System.out.println(moneyFormat.format(tipCalculator1.getBillAmount()));
System.out.print("Tip Percentage: ");
System.out.println(defaultFormat.format(tipCalculator1.getTipPercentage()));
System.out.print("Party Size: ");
System.out.println(tipCalculator1.getPartyAmount());
System.out.print("nTotal Bill (with Tip): ");
System.out.println(moneyFormat.format(tipCalculator1.getTotalAmount()));
System.out.print("nShare for Each Individual: ");
System.out.println(moneyFormat.format(tipCalculator1.getIndividualShare()));
System.out.println("======================================");
}
while (choice.isEmpty()) {
System.out.print("nAnother Bill? (y/n): ");
choice = userInput.nextLine();
if (!choice.matches("(?i)[yn]")) {
System.out.println("Invalid input - 'y' or 'n' only! Try again...");
choice = "";
}
}
System.out.println();
} while (choice.equalsIgnoreCase("y"));
System.out.println("nGoodbye!");
}