So, I'm trying to make an "Unlimited" Array List of names and ages that the user inputs, specifically when they're asked if they want to enter another name and age, and say "yes". However, I'm able to only get the name and age that's been inputted the most recently by the user.
I'm trying to have the program the names and ages to the Console when the user says "no" to inputting another name and age. However, it will print the name and age before I even it an answer to that question.
I'll post the code in question below.
String add;
String answer;
ArrayList<String> names = new ArrayList<>();
ArrayList<int[]> ages = new ArrayList<>();
do
{
// Get the users name
System.out.println("What's your name? ");
name = keyboard.nextLine();
// Get the users name
System.out.println("What's your age? ");
age = keyboard.nextInt();
// Adds the names and ages from the user input into the Arrays
names.add(name);
ages.add(age);
// Ask the user if they want to enter in another record
System.out.println("Do you want to enter an additional record? ");
answer = keyboard.nextLine();
}
while (answer.equals("yes"));
do
{
// System.out.println(name);
// System.out.println(age);
/* System.out.println(Arrays.asList(print) ", " (ages));
// Printing the records to different lines of the console
System.out.println("");
*/
for (String print : names)
{
// System.out.println(names);
// System.out.println(ages);
System.out.println(print ", " (ages));
// Printing the records to different lines of the console
System.out.println("");
break;
}
}
while (answer.equals("no"));
Also, I'm asking the user if they want to write the name and age Arrays to a file. Yes means write to the file, no means I write a message that says "Thanks for playing". However, depending on where I the following if I type in "yes" or "no", it will either not give the file prompt, or goes into an infinite loop with the names and ages printed, depending on where I put it.
String answer2;
String write;
String fileName;
ArrayList<String> names = new ArrayList<>();
ArrayList<String> ages = new ArrayList<>();
// If I put it here, it will do a infinite loop of the names and ages inputted.
// Prompt the user if they want to write to a file.
System.out.println("Do you want to write to a file? ");
answer2 = keyboard.nextLine();
do
{
// If I put it here, it will continue to ask me the question infinitely.
// Prompt the user if they want to write to a file.
// System.out.println("Do you want to write to a file? ");
//answer2 = keyboard.nextLine();
}
while (answer.equals("no"));
do
{
// Prompt for the filename
System.out.println("Enter your filename: ");
fileName = keyboard.nextLine();
//break;
//PrintWriter outputFile;
try
{
PrintWriter outputFile = new PrintWriter(fileName);
// Write the name(s) and age(s) to the file
outputFile.println(names);
outputFile.println(ages);
outputFile.close();
}
catch (FileNotFoundException e)
{
//
e.printStackTrace();
break;
}
}
while (answer2.equals("yes"));
do
{
System.out.println("Thanks for playing!");
break;
}
while (answer2.equals("no"));
keyboard.close();
CodePudding user response:
Missing
names.add(name);
ages.add(age);
CodePudding user response:
Don't store two lists of names and ages separately, it makes your solution very brittle. Use the power of objects instead.
Properties name
and age
has to associated not via indices of lists but has to be combined into an object.
Now you have two attributes of the user. And you have to modify both list simultaneously while adding or removing user. And what if you decide that you need the third and the fourth user property? Adding more lists is not an option. User
must be an object.
With Java 16 a special kind of class call record
was introduced in the language. Records are transparent carriers of data with a very concise syntax, to define a record with two properties name
and age
you need only this line:
public record User(String name, int age) {}
That is the equivalent of a class with a constructor, getter, equals/hasCode
and toString()
(all this code will be generated by the compiler for you).
In order to organize the code nicer, I suggest you to extract the functionality for adding a user and printing the user list into separate methods.
public class UserManager {
public record User(String name, int age) {}
public Scanner keyboard = new Scanner(System.in);
public List<User> users = new ArrayList<>();
public void startMainMenu() {
System.out.println("""
To add a new record enter N
To print existing records enter P
To exit enter Q""");
boolean quit = false;
while (!quit) {
String command = keyboard.nextLine().toUpperCase();
switch(command.charAt(0)) {
case 'N' -> addNewUser();
case 'P' -> print();
case 'Q' -> quit = true;
}
}
}
public void addNewUser() {
String answer = "no";
do {
System.out.println("What's your name? ");
String name = keyboard.nextLine(); // Get the users name
System.out.println("What's your age? ");
int age = keyboard.nextInt(); // Adds the names and ages from the user input into the Arrays
keyboard.nextLine();
users.add(new User(name, age));
// Ask the user if they want to enter in another record
System.out.println("Do you want to enter an additional record? ");
answer = keyboard.nextLine();
} while (answer.equalsIgnoreCase("yes"));
System.out.println("--- Main menu --- enter N, P or Q");
}
public void print() {
for (User user: users) System.out.println(user);
System.out.println("--- Main menu --- enter N, P or Q");
}
}
main()
- demo
public static void main(String[] args) {
UserManager userManager = new UserManager();
userManager.startMainMenu();
}
Writing to a file
public static void writeToFile(List<String> names, List<String> ages) {
// Prompt for the filename
System.out.println("Enter your filename: ");
String fileName = keyboard.nextLine();
try(PrintWriter outputFile = new PrintWriter(fileName)) {
for (int i = 0; i < names.size(); i ) {
outputFile.println("name: " names.get(i) ", age: " ages.get(i));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
CodePudding user response:
You last loop for printing should be more like:
for (int i = 0; i < names.length; i ) {
System.out.println(names.get(i) " is " ages.get(i) " years old");
}
It's never a good idea to have a separate data structure (in this case a List) for each attribute of your objects. Rather, create a class for the object and have a single data structure (ie List) for your objects, which you create using the input.
For example:
public record Person (String name, int age) {}
Then at the top of your method:
List<Person> people = new ArrayList<>();
and in your input loop:
people.add(new Person(name, Integer.parseInt(age));
then to print:
people.forEach(System.out::println);
The print uses the default toString()
implementation, but you can override it as you like.