Java 电费程序无法打印完整 billing details
结论
费用能够正常输出,说明输入和部分计算逻辑已经执行。name、account num 和 actual reading 没有显示,问题通常不在计算公式,而在于对应的输出语句没有执行。常见原因包括:
- 输出语句写在了未命中的
if或else if分支中。 - 程序在打印完整账单前执行了
return、System.exit(...),或者抛出了异常。 - 程序只调用了费用计算方法,没有调用打印账单的方法。
- 大括号位置有误,导致输出语句被归入其他条件分支。
Bactual只在 Business 方法或某个局部代码块中定义,却在错误的位置使用。
比较稳妥的处理方式是先完成所有计算,再到条件语句外统一打印账单,不要在每个费率分支中重复输出。
先检查控制流程
可以在关键位置加入临时标记,确认程序执行到了哪一步:
System.out.println("Before calculation");
int actualReading = currentReading - previousReading;
System.out.println("After calculation");
System.out.println("Before billing details");
// 打印完整账单
如果某条标记没有出现,检查它前面是否存在以下代码:
return;
System.exit(0);
throw new RuntimeException(...);
也要检查大括号的位置。在下面的写法中,只有条件成立时才会打印账单详情:
if (actualReading > 500) {
System.out.println("The cost is " + cost);
System.out.println("Name: " + name);
System.out.println("Account No.: " + accountNo);
}
条件不成立时,整个代码块都会被跳过。通用输出应该放在条件语句之后:
if (actualReading <= 500) {
cost = actualReading * RATE_1;
} else {
cost = actualReading * RATE_2;
}
System.out.println("Name: " + name);
System.out.println("Account No.: " + accountNo);
System.out.println("The actual reading is " + actualReading);
System.out.println("The cost is " + cost);
注意条件表达式的写法
问题中展示的代码片段:
if(Dactual 501 && Dactual 601 && Bactual
不是合法的 Java 条件表达式。粘贴代码时可能漏掉了比较运算符或后续内容。Java 要求每次比较都写完整,例如:
if (actualReading >= 501 && actualReading <= 600) {
// ...
}
不能照搬数学中的连续比较写法:
// 错误
if (501 <= actualReading <= 600) {
}
各个费率区间还需要保持连续,不能重叠。例如:
if (actualReading <= 500) {
// 0 到 500
} else if (actualReading <= 600) {
// 501 到 600
} else {
// 601 以上
}
程序进入第二个分支时,已经能够确定 actualReading > 500,所以不用再判断下限。
推荐的程序结构
下面的示例把输入、计算和输出分开,最后只打印一次完整账单。示例中的费率需要替换为题目规定的数值。
import java.util.Scanner;
public class MajanBilling {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Welcome to Majan Electricity Billing");
System.out.println("1. Domestic Customer");
System.out.println("2. Business Customer");
System.out.print("Select your choice: ");
int choice = scanner.nextInt();
scanner.nextLine(); // 清除输入缓冲区中的换行符
switch (choice) {
case 1:
processDomesticCustomer(scanner);
break;
case 2:
processBusinessCustomer(scanner);
break;
default:
System.out.println("Invalid choice.");
}
scanner.close();
}
private static void processDomesticCustomer(Scanner scanner) {
System.out.print("Enter your name: ");
String name = scanner.nextLine();
System.out.print("Enter your Account No.: ");
String accountNo = scanner.nextLine();
System.out.print("Enter your current month reading: ");
int currentReading = scanner.nextInt();
System.out.print("Enter your previous month reading: ");
int previousReading = scanner.nextInt();
int actualReading = calculateActualReading(
currentReading,
previousReading
);
double cost = calculateDomesticCost(actualReading);
printBillingDetails(
"Domestic",
name,
accountNo,
currentReading,
previousReading,
actualReading,
cost
);
}
private static void processBusinessCustomer(Scanner scanner) {
System.out.print("Enter your name: ");
String name = scanner.nextLine();
System.out.print("Enter your Account No.: ");
String accountNo = scanner.nextLine();
System.out.print("Enter your current month reading: ");
int currentReading = scanner.nextInt();
System.out.print("Enter your previous month reading: ");
int previousReading = scanner.nextInt();
int actualReading = calculateActualReading(
currentReading,
previousReading
);
double cost = calculateBusinessCost(actualReading);
printBillingDetails(
"Business",
name,
accountNo,
currentReading,
previousReading,
actualReading,
cost
);
}
private static int calculateActualReading(
int currentReading,
int previousReading
) {
if (currentReading < previousReading) {
throw new IllegalArgumentException(
"Current reading cannot be less than previous reading."
);
}
return currentReading - previousReading;
}
private static double calculateDomesticCost(int units) {
// 示例费率,必须按题目给出的实际费率修改
if (units <= 500) {
return units * 0.15;
} else if (units <= 600) {
return 500 * 0.15
+ (units - 500) * 0.20;
} else {
return 500 * 0.15
+ 100 * 0.20
+ (units - 600) * 0.25;
}
}
private static double calculateBusinessCost(int units) {
// 示例费率,必须按题目给出的实际费率修改
if (units <= 500) {
return units * 0.20;
} else if (units <= 600) {
return 500 * 0.20
+ (units - 500) * 0.25;
} else {
return 500 * 0.20
+ 100 * 0.25
+ (units - 600) * 0.30;
}
}
private static void printBillingDetails(
String customerType,
String name,
String accountNo,
int currentReading,
int previousReading,
int actualReading,
double cost
) {
System.out.println();
System.out.println("Billing Details");
System.out.println("-------------------------");
System.out.println("Customer type: " + customerType);
System.out.println("Name: " + name);
System.out.println("Account No.: " + accountNo);
System.out.println("Current reading: " + currentReading);
System.out.println("Previous reading: " + previousReading);
System.out.println("The actual reading is " + actualReading);
System.out.printf("The cost is %.2f%n", cost);
}
}
关于 Bactual 没有输出
如果代码是这样写的:
if (Bactual > 500) {
System.out.println("The actual reading is " + Bactual);
}
当 Bactual 等于 200 时,条件不成立,这条输出语句不会执行。应该把它移到费率判断之外:
int Bactual = current - last;
if (Bactual <= 500) {
cost = ...;
} else if (Bactual <= 600) {
cost = ...;
} else {
cost = ...;
}
System.out.println("The actual reading is " + Bactual);
还要确认变量没有混用。Domestic 客户应使用类似 Dactual 的计算结果,Business 客户则使用 Bactual。更简单的做法是让两个流程采用同一个变量名:
int actualReading = current - last;
这样复制代码时不容易误把 Dactual 写成 Bactual。
输入时容易忽略的问题
调用 nextInt() 后紧接着调用 nextLine(),可能会读取输入缓冲区中残留的换行符,最终得到空字符串:
int choice = scanner.nextInt();
scanner.nextLine(); // 必须消费换行符
String name = scanner.nextLine();
账号也适合使用 String,而不是 int:
String accountNo = scanner.nextLine();
账号可能带有前导零或字母。它是标识符,不是参与计算的数值。
另外,The cost is 30** 中的 ** 只是普通字符串内容。如果不想显示星号,检查代码中是否写了:
System.out.println("The cost is " + cost + "**");
将其改成:
System.out.println("The cost is " + cost);
修正时只需让各个费率分支负责给 cost 赋值,然后在所有分支结束后统一调用账单打印逻辑。只要计算方法正常返回,客户信息和实际用电量就会一起输出。
备注:内容仅供参考。
