英文:
Why is this java code not producing the result I am expecting?
问题
程序需要根据顾客的年龄
和性别
来发出正确的票价。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Person p1 = new Person();
System.out.println("输入乘客姓名:");
String name = sc.next();
p1.setName(name);
System.out.println("输入性别:");
char gen = sc.next().charAt(0);
p1.setGender(gen);
System.out.println("输入年龄:");
int age = sc.nextInt();
p1.setAge(age);
BusTicket b1 = getTicketDetails();
b1.setPerson(p1);
b1.calculateTotal();
System.out.println("票号:" + b1.getTicketno());
System.out.println("乘客姓名:" + p1.getName());
System.out.println("票价:" + b1.getTicketprice());
System.out.println("总金额:" + b1.getTotalamt());
}
public static BusTicket getTicketDetails() {
Scanner sc=new Scanner(System.in);
System.out.println("输入票号:");
int no=sc.nextInt();
BusTicket t1=new BusTicket();
t1.setTicketno(no);
System.out.println("输入票价:");
float cost=sc.nextFloat();
t1.setTicketprice(cost);
return t1;
}
}
public class Person {
private String name;
private char gender;
private int age;
public void setName(String name){
this.name=name;
}
public String getName() {
return this.name;
}
public void setGender(char gender){
this.gender = gender;
}
public char getGender() {
return this.gender;
}
public void setAge(int age){
this.age = age;
}
public int getAge() {
return this.age;
}
}
public class BusTicket {
private int ticketNo;
private float ticketPrice;
private float totalAmount;
private Person person;
public void setTicketno(int no) {
ticketNo = no;
}
public int getTicketno() {
return this.ticketNo;
}
public void setTicketprice(float price){
ticketPrice = price;
}
public float getTicketprice(){
return this.ticketPrice;
}
public void setTotalamt(float amt) {
totalAmount=amt;
}
public float getTotalamt() {
return this.totalAmount;
}
public void setPerson(Person p) {
person=p;
}
public Person getPerson() {
return this.person;
}
public void calculateTotal() {
if(16 > person.getAge())
this.totalAmount = ticketPrice - (float) (ticketPrice * 0.50);
else if(person.getAge() < 60)
this.totalAmount = ticketPrice - (float) (ticketPrice * 0.25);
else if (person.getGender() == 'f' || person.getGender() == 'F')
this.totalAmount = ticketPrice - (float) (ticketPrice * 0.10);
else
this.totalAmount = ticketPrice;
}
}
calculateTotal
方法没有给出正确的输出。对于每张票价,输出的金额是其一半。在 calculateAmount
函数的 if-else 条件中没有正确执行。
为了获得我期望的结果,我需要做出什么改变?
测试用例
其中姓名不相关,基础票价为 $100.00
。
+-----|--------|-------------------|-----------------------------+
| 年龄 | 性别 | 预期折扣 | 预期总票价 |
|-----|--------|-------------------|-----------------------------|
| 15 | 男 | 0.50 | $50.00 |
| 15 | 女 | 0.50 | $50.00 |
| 4 | 男 | 0.50 | $50.00 |
| 12 | 女 | 0.50 | $50.00 |
|-----|--------|-------------------|-----------------------------|
| 61 | 男 | 0.25 | $75.00 |
| 61 | 女 | 0.25 | $75.00 |
| 99 | 男 | 0.25 | $75.00 |
| 75 | 女 | 0.25 | $75.00 |
|-----|--------|-------------------|-----------------------------|
| 16 | 女 | 0.10 | $90.00 |
| 27 | 女 | 0.10 | $90.00 |
| 48 | 女 | 0.10 | $90.00 |
| 60 | 女 | 0.10 | $90.00 |
|-----|--------|-------------------|-----------------------------|
| 16 | 男 | 0.00 | $100.00 |
| 27 | 男 | 0.00 | $100.00 |
| 48 | 男 | 0.00 | $100.00 |
| 60 | 男 | 0.00 | $100.00 |
+-----|--------|-------------------|-----------------------------+
英文:
The program needs to issue the correct ticket price based on the age
and gender
of the customer.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Person p1 = new Person();
System.out.println("Enter the passenger name:");
String name = sc.next();
p1.setName(name);
System.out.println("Enter the gender:");
char gen = sc.next().charAt(0);
p1.setGender(gen);
System.out.println("Enter the age:");
int age = sc.nextInt();
p1.setAge(age);
BusTicket b1 = getTicketDetails();
b1.setPerson(p1);
b1.calculateTotal();
System.out.println("Ticket no:"+b1.getTicketno());
System.out.println("Passenger Name:"+p1.getName());
System.out.println("Price of a ticket:"+b1.getTicketprice());
System.out.println("Total Amount:"+b1.getTotalamt());
}
public static BusTicket getTicketDetails() {
Scanner sc=new Scanner(System.in);
System.out.println("Enter the ticket no:");
int no=sc.nextInt();
BusTicket t1=new BusTicket();
t1.setTicketno(no);
System.out.println("Enter the ticket price:");`enter code here`
float cost=sc.nextFloat();
t1.setTicketprice(cost);
return t1;
}
}
public class Person {
private String name;
private char gender;
private int age;
public void setName(String name){
this.name=name;
}
public String getName() {
return this.name;
}
public void setGender(char gender){
this.gender = gender;
}
public char getGender() {
return this.gender;
}
public void setAge(int age){
this.age = age;
}
public int getAge() {
return this.age;
}
}
public class BusTicket {
private int ticketNo;
private float ticketPrice;
private float totalAmount;
private Person person;
public void setTicketno(int no) {
ticketNo = no;
}
public int getTicketno() {
return this.ticketNo;
}
public void setTicketprice(float price){
ticketPrice = price;
}
public float getTicketprice(){
return this.ticketPrice;
}
public void setTotalamt(float amt) {
totalAmount=amt;
}
public float getTotalamt() {
return this.totalAmount;
}
public void setPerson(Person p) {
p=new Person();
person=p;
}
public Person getPerson() {
return this.person;
}
public void calculateTotal() {
if(16 > person.getAge())
this.totalAmount = ticketPrice - (float) (ticketPrice * 0.50);
else if(person.getAge() < 60)
this.totalAmount = ticketPrice - (float) (ticketPrice * 0.25);
else if (person.getGender() == 'f' || person.getGender() == 'F')
this.totalAmount = ticketPrice - (float) (ticketPrice * 0.10);
else
this.totalAmount = ticketPrice;
}
}
The calculateTotal
method is not giving the correct output. For every ticket price, the output is giving the amount as half of it. The if-else condition in the calculateAmount
function is not being properly executed.
What do I need to change it to in order to give me the results I expect?
Test Cases
Where Name is irrelevant and base ticket price is $100.00
.
+-----|--------|-------------------|-----------------------------+
| Age | Gender | Expected Discount | Expected total ticket price |
|-----|--------|-------------------|-----------------------------|
| 15 | M | 0.50 | $50.00 |
| 15 | F | 0.50 | $50.00 |
| 4 | M | 0.50 | $50.00 |
| 12 | F | 0.50 | $50.00 |
|-----|--------|-------------------|-----------------------------|
| 61 | M | 0.25 | $75.00 |
| 61 | F | 0.25 | $75.00 |
| 99 | M | 0.25 | $75.00 |
| 75 | F | 0.25 | $75.00 |
|-----|--------|-------------------|-----------------------------|
| 16 | F | 0.10 | $90.00 |
| 27 | F | 0.10 | $90.00 |
| 48 | F | 0.10 | $90.00 |
| 60 | F | 0.10 | $90.00 |
|-----|--------|-------------------|-----------------------------|
| 16 | M | 0.00 | $100.00 |
| 27 | M | 0.00 | $100.00 |
| 48 | M | 0.00 | $100.00 |
| 60 | M | 0.00 | $100.00 |
+-----|--------|-------------------|-----------------------------+
答案1
得分: 3
问题是你在做以下操作时覆盖了 person:
public void setPerson(Person p){
p = new Person();
person = p;
}
用以下的 setter 替换它:
public void setPerson(Person p){
this.person = p;
}
英文:
The problem is you are overwritting person when you doing :
public void setPerson(Person p){
p =new Person();
person=p;
}
Replace this setter with:
public void setPerson(Person p){
this.person=p;
}
答案2
得分: 2
Here, something like immutability will be your friend.
@Ner is correct by pointing out that the setPerson()
method is what breaks your code since you instantiate a new Person
object instead of using the one that is passed to the setter method, setPerson
, in the BusTicket
class.
This causes you to lose the data within the passed‑in Person
object that is essential to the calculation.
The Person's name
defaults to null
, the gender
character will default to 'u0000'
, and the age
will default to 0
.
That age
value is what catches the first if‑statement in the calculation method of the BusTicket
class every time, since 0
is less than 16
.
One change to make could be to take:
public void setPerson(Person p) {
p=new Person();
person=p;
}
and transform it to:
public void setPerson(final Person person) {
this.person = person;
}
Notice the usage of the final
keyword here. This is a great way to protect incoming method arguments from having their reference altered in the scope of the method.
英文:
Here, something like immutability will be your friend.
@Ner is correct by pointing out that the setPerson()
method is what breaks your code since you instantiate a new Person
object instead of using the one that is passed to the setter method, setPerson
, in the BusTicket
class.
This causes you to lose the data within the passed‑in Person
object that is essential to the calculation.
The Person's name
defaults to null
, the gender
character will default to 'u0000'
, and the age
will default to 0
.
That age
value is what catches the first if‑statement in the calculation method of the BusTicket
class every time, since 0
is less than 16
.
One change to make could be to take:
public void setPerson(Person p) {
p=new Person();
person=p;
}
and transform it to:
public void setPerson(final Person person) {
this.person = person;
}
Notice the usage of the final
keyword here. This is a great way to protect incoming method arguments from having their reference altered in the scope of the method.
Alternative Code Structure
I would propose the following alternatives to your classes, as they exemplify better practices that would prevent something like this bug from ever occurring.
import java.util.Scanner;
import java.util.function.Function;
public class Main {
public static void main(final String[] args) {
try(final Scanner scanner = new Scanner(System.in)) {
final Person person = getPersonUsing(scanner);
final BusTicket busTicket = getBusTicketForPersonUsing(scanner).apply(person);
System.out.printf("%n%s", busTicket);
}
}
private static Person getPersonUsing(final Scanner scanner) {
System.out.print("Enter the passenger name: ");
final String name = scanner.nextLine();
System.out.print("Enter the gender: ");
final Person.Gender gender = Person.Gender.valueOf(scanner.next().charAt(0));
System.out.print("Enter the age: ");
final int age = scanner.nextInt();
return new Person(name, gender, age);
}
private static Function<Person, BusTicket> getBusTicketForPersonUsing(final Scanner scanner) {
return person -> {
System.out.print("Enter the ticket number: ");
final int ticketNumber = scanner.nextInt();
System.out.print("Enter the base ticket price: ");
final float baseTicketPrice = scanner.nextFloat();
return new BusTicket(ticketNumber, baseTicketPrice, person);
};
}
}
public class Person {
private final String name;
private final Person.Gender gender;
private final int age;
public Person(
final String name,
final Person.Gender gender,
final int age) {
this.name = name;
this.gender = gender;
this.age = age;
}
public String getName() {
return this.name;
}
public Person.Gender getGender() {
return this.gender;
}
public int getAge() {
return this.age;
}
@Override
public String toString() {
return String.format(
"%s (%02d %s)",
getName(),
getAge(),
getGender().asSingleLetter());
}
public enum Gender {
FEMALE,
MALE;
public String asSingleLetter() {
return String.valueOf(name().charAt(0));
}
public static Gender valueOf(final char gender) {
switch (Character.toUpperCase(gender)) {
case 'F': return FEMALE;
case 'M': return MALE;
default:
throw new IllegalArgumentException(String.format("Gender [%s] could not be determined.", gender));
}
}
}
}
import java.util.function.Function;
public class BusTicket {
private final int ticketNumber;
private final float baseTicketPrice;
private final float totalAmount;
private final Person person;
public BusTicket(
final int ticketNumber,
final float baseTicketPrice,
final Person person) {
this.ticketNumber = ticketNumber;
this.baseTicketPrice = baseTicketPrice;
this.totalAmount = calculateTotal(person).apply(baseTicketPrice);
this.person = person;
}
public int getTicketNumber() {
return this.ticketNumber;
}
public float getBaseTicketPrice() {
return this.baseTicketPrice;
}
public float getTotalAmount() {
return this.totalAmount;
}
public Person getPerson() {
return person;
}
@Override
public String toString() {
return String.format(
"%nTicket no: %d%n" +
"Passenger: %s%n" +
"Base price of a ticket: $%.2f%n" +
"Total Amount: $%.2f%n",
getTicketNumber(),
getPerson(),
getBaseTicketPrice(),
getTotalAmount());
}
private static float calculateDiscountForPerson(final Person person) {
// 50% discount for age of 16
if(person.getAge() < 16) {
return 0.50f;
// 25% discount for age over 60
} else if(person.getAge() > 60) {
return 0.25f;
// 10% discount for females
} else if (person.getGender() == Person.Gender.FEMALE) {
return 0.10f;
// 0% discount for men between 16 and 60
} else {
return 0.00f;
}
}
private static Function<Float, Float> calculateTotal(final Person person) {
return baseTicketPrice ->
baseTicketPrice * (1.0f - calculateDiscountForPerson(person));
}
}
import org.junit.jupiter.api.Test;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import static com.shaba.Person.Gender.FEMALE;
import static com.shaba.Person.Gender.MALE;
import static org.junit.jupiter.api.Assertions.assertEquals;
class BusTicketTest {
private static final int TICKET_NUMBER = 42;
private static final float BASE_TICKET_PRICE = 100.0f;
@Test
void shouldReturnExpectedTicketPrice() {
// Map of Person and Expected Discounted Ticket Price
final Map<Person, Float> cases = new HashMap<> ();
cases.put(new Person("Tom", MALE, 15), 50.0f);
cases.put(new Person("Jen", FEMALE, 15), 50.0f);
cases.put(new Person("Tom", MALE, 4), 50.0f);
cases.put(new Person("Jen", FEMALE, 12), 50.0f);
cases.put(new Person("Tom", MALE, 61), 75.0f);
cases.put(new Person("Jen", FEMALE, 61), 75.0f);
cases.put(new Person("Tom", MALE, 99), 75.0f);
cases.put(new Person("Jen", FEMALE, 75), 75.0f);
cases.put(new Person("Jen", FEMALE, 16), 90.0f);
cases.put(new Person("Jen", FEMALE, 27), 90.0f);
cases.put(new Person("Jen", FEMALE, 48), 90.0f);
cases.put(new Person("Jen", FEMALE, 60), 90.0f);
cases.put(new Person("Tom", MALE, 16), 100.0f);
cases.put(new Person("Tom", MALE, 27), 100.0f);
cases.put(new Person("Tom", MALE, 48), 100.0f);
cases.put(new Person("Tom", MALE, 60), 100.0f);
cases.forEach(this::assertExpectedTotalTicketPrice);
}
private void assertExpectedTotalTicketPrice(
final Person person,
final float expectedTotal) {
assertEquals(expectedTotal, makeTestBusTicket().apply(person).getTotalAmount());
}
private Function<Person, BusTicket> makeTestBusTicket() {
return person -> new BusTicket(TICKET_NUMBER, BASE_TICKET_PRICE, person);
}
}
Test Cases
These tests cases now occur as expected.
+-----|--------|-------------------|-----------------------------+
| Age | Gender | Expected Discount | Expected total ticket price |
|-----|--------|-------------------|-----------------------------|
| 15 | M | 0.50 | $50.00 |
| 15 | F | 0.50 | $50.00 |
| 4 | M | 0.50 | $50.00 |
| 12 | F | 0.50 | $50.00 |
|-----|--------|-------------------|-----------------------------|
| 61 | M | 0.25 | $75.00 |
| 61 | F | 0.25 | $75.00 |
| 99 | M | 0.25 | $75.00 |
| 75 | F | 0.25 | $75.00 |
|-----|--------|-------------------|-----------------------------|
| 16 | F | 0.10 | $90.00 |
| 27 | F | 0.10 | $90.00 |
| 48 | F | 0.10 | $90.00 |
| 60 | F | 0.10 | $90.00 |
|-----|--------|-------------------|-----------------------------|
| 16 | M | 0.00 | $100.00 |
| 27 | M | 0.00 | $100.00 |
| 48 | M | 0.00 | $100.00 |
| 60 | M | 0.00 | $100.00 |
+-----|--------|-------------------|-----------------------------+
Sample Output
Enter the passenger name: Tom
Enter the gender: M
Enter the age: 98
Enter the ticket number: 2346
Enter the base ticket price: 100
Ticket no: 2346
Passenger: Tom (98 M)
Base price of a ticket: $100.00
Total Amount: $75.00
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论