Perhaps my title is not very clear, but I try to understand this problem.
Problem: I have many assignments and different persons solve them using their own way. They may need input from user process it and do what they want, I want to individually run their solutions as well as in a framework which run all solutions in one go. Below is the overall simplistic approach I designed as a framework.
But as this code straight showing me that I will get NoSuchElementException (using Scanner) StreamClosed (using BufferedReader) approach.
How can I achieve this or am I thinking very wrong or missing any core concepts?
I don't want a scanner in main and pass its instance to all my code,( is this the only approach I can solve it)
public class AssignmentRunner {
public static void main(String[] args) {
AssignmentRunner runner = new AssignmentRunner();
AssignmentExecutor executor = new AssignmentExecutor();
executor.execute();
}
}
public interface Assignment {
void execute();
}
class AssignmentExecutor {
public List<Assignment> assignmentList ;
private void addAssignments(){
assignmentList = new ArrayList<Assignment>();
assignmentList.add(new Assignment1());
assignmentList.add(new Assignment2());
}
public void execute() {
addAssignments();
for (Assignment assigment : assignmentList) {
assigment.execute();
}
}
}
public class Assignment1 implements Assignment {
String inputString;
#Override
public void execute() {
input();
System.out.println(inputString);
}
private void input() {
Scanner scanner = new Scanner(System.in);
try {
inputString = scanner.nextLine();
}
catch (Exception e) {
System.err.println(e.getMessage());
}
finally {
scanner.close();
}
}
}
public class Assignment2 implements Assignment {
String inputString;
#Override
public void execute() {
input();
System.out.println("Hello"+inputString);
}
private void input() {
Scanner scanner = new Scanner(System.in);
try {
inputString = scanner.nextLine();
}
catch (Exception e) {
System.err.println(e.getMessage());
}
finally {
scanner.close();
}
}
}
EDIT: As per some comments and one answer I have made few modifications,kindly help me to understand is this the only best thing we can do or any other way to design my need.
NEED Different students can have different assignments for example (some may need input,others may not need any input)
simply print hello world
input string and show word count
input number show factorial
input number print its table
We want to execute each assignment class individually as well as from one Runner class as shown above.
MODIFICATION I did these modifications to all classes, showing sample for understanding what I did.
class AssignmentExecutor {
public List<Assignment> assignmentList ;
private void addAssignments(){
assignmentList = new ArrayList<Assignment>();
assignmentList.add(new Assignment1());
assignmentList.add(new Assignment2());
}
public void execute() {
Scanner scanner = new Scanner(System.in);
addAssignments();
for (Assignment assigment : assignmentList) {
assigment.execute(scanner);
}
scanner.close();
}
}
public class Assignment1 implements Assignment {
String inputString;
public static void main(String args[]) {
Assignment1 assignment1 =new Assignment1();
Scanner scanner = new Scanner(System.in);
assignment1.execute(scanner);
scanner.close();
}
#Override
public void execute(scanner) {
input(scanner);
System.out.println(inputString);
}
private void input(scanner) {
scanner = new Scanner(System.in);
try {
inputString = scanner.nextLine();
}
catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
Related
I wanted to create a simple program for user to insert 3 strings to a private string array in a class and then print it back by creating a new object using object reference but I think I am facing problem in the setter/getter.(Pretty new to class and setter/getter) Here is what I have so far:
import java.util.Scanner;
public class Stringtest {
public static void main(String[] args)
{ Scanner input=new Scanner(System.in);
Stringer Strung=new Stringer();
System.out.println("Strings:"+Strung.print());
}
}
class Stringer
{ Scanner input=new Scanner(System.in);
private String[] aa=new String[3];
aa[0]="zero";
aa[1]="one";
aa[2]="two";
Stringer()
{}
{ System.out.println("Please enter 3 strings:");
for(int i=0;i<4;i++)
{
aa[i]=input.next();
}
}
public void setaa(String[] a)
{
aa=a;
}
public String[] getaa()
{
return aa;
}
public void print(String[] a)
{
for(int b=0;b<4;b++)
{
System.out.printf("%s",a[b]);
}
}
}
Due to populating the array while creating a class instance, you don't require any setters. The only getter requires.
Divide the logic from the runner.
Always use array.length() while looping or use a simple for loop otherwise you'll be getting an indexOfBoudException error.
Didn't get why you are using printf() while printing results.
My solution:
import java.util.Scanner;
public class App {
public static void main(String[] args) {
App.run();
}
private static void run() {
Stringer stringer = new Stringer();
stringer.print(stringer.getStrings());
}
}
class Stringer {
private String[] strings = new String[3];
Stringer() {
System.out.println("Please enter 3 strings:");
for (int i = 0; i < 4; i++) {
Scanner scanner = new Scanner(System.in);
strings[i] = scanner.next();
}
}
String[] getStrings() {
return strings;
}
void print(String[] strings) {
System.out.println("Strings are:");
for (String string : strings) {
System.out.println(string);
}
}
}
I guess my title isn't very clear and needs a code example so here you go:
public class ATM {
public static void main(String[] args) {
Keypad K=new Keypad();
K.mypin(pin);
}
}
That is the main method, now here is a method in another class:
public class Keypad{
public void mypin(int pin) {
System.out.print("Please enter your pin");
pin=scan.nextInt();
System.out.print(pin);
}
}
How to include pin=scan.nextInt(); in my main method and make this work normally?
You might ask me why I want it this way and it is just because that is what I was asked to do.
If I understood you correctly, you want something along those lines :
public class ATM {
public static void main(String[] args) {
System.out.print("Please enter your pin");
Scanner sc = new Scanner(System.in);
Keypad K=new Keypad();
K.mypin(sc.nextInt());
}
}
public class Keypad{
public void mypin(int pin) {
System.out.print(pin);
}
}
You can use Scanner class with input stream System.in.
It is ATM class:
package user.input;
public class ATM {
public static void main(String[] args) {
Keypad keypad = new Keypad();
try {
int userPin = keypad.enterPin();
System.out.printf("User Pin: %s", userPin);
} catch (Exception e) {
System.err.println("Occured error while entering user's PIN.");
e.printStackTrace();
}
}
}
It is Keypad class:
package user.input;
import java.util.Scanner;
public class Keypad {
public int enterPin() throws Exception {
Scanner scanner = null;
try {
scanner = new Scanner(System.in);
System.out.print("Please enter your pin: ");
int inputNum = scanner.nextInt(); // Read user input
return inputNum;
} catch (Exception e) {
throw e;
} finally {
if (scanner != null) {
scanner.close();
}
}
}
}
I'm making an application that quizzes you on politics or astronomy.
My problem is that when you say "politics" or you say "astronomy", it will ask you again 2 more times for your input, before giving the desired output of "test".
Here's the code:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
do {
if (getAnswer().equalsIgnoreCase("neither")) {
System.out.println("Please enter \'astronomy\' or \'politics\'.");
}
getAnswer();
}
while(getAnswer().equalsIgnoreCase("neither"));
System.out.println("test");
}
public static String getAnswer() {
Scanner quizType = new Scanner(System.in);
System.out.println("Would you like to be quizzed on politics or astronomy?");
String typeAnswer = quizType.next();
if (typeAnswer.equalsIgnoreCase("politics")) {
return "politics";
}
else if (typeAnswer.equalsIgnoreCase("astronomy")) {
return "astronomy";
}
else {
return "neither";
}
}
}
Any ideas?
Thanks
There no need to getAnswer() 3 times, just getAnswer() into a String variable and you are good to go.
Like this:
public static void main(String[] args) {
String answer = "";
do {
answer = getAnswer();
if (answer.equalsIgnoreCase("neither")) {
System.out.println("Please enter \'astronomy\' or \'politics\'.");
}
} while (answer.equalsIgnoreCase("neither"));
System.out.println("test");
}
public static String getAnswer() {
Scanner quizType = new Scanner(System.in);
System.out.println("Would you like to be quizzed on politics or astronomy?");
String typeAnswer = quizType.next();
if (typeAnswer.equalsIgnoreCase("politics")) {
return "politics";
} else if (typeAnswer.equalsIgnoreCase("astronomy")) {
return "astronomy";
} else {
return "neither";
}
}
If you're learning do-while, then you only need to prompt inside your do. Currently you're calling getAnswer three times, which forces the repeated prompt.
Here is a quick way to solve it using do-while
public static void main(String[] args) {
List<String> validAnswers = Arrays.asList("neither","politics","astronomy");
String answer;
do {
answer = promptForAnswer();
} while(!validAnswers.contains(answer));
System.out.println("test");
}
public static String promptForAnswer() {
System.out.println("Would you like to be quizzed on politics or astronomy?");
return new Scanner(System.in).next();
}
Or you can go with the while loop...
public static void main(String[] args) {
List<String> validAnswers = Arrays.asList("neither","politics","astronomy");
while(!validAnswers.contains(promptForAnswer())) {
System.out.println("That was not a valid response, try again!");
}
System.out.println("test");
}
public static String promptForAnswer() {
System.out.println("Would you like to be quizzed on politics or astronomy?");
return new Scanner(System.in).next();
}
So I developing this very simple game of TicTacToe. I want to test the method given below:
public class Board {
private Scanner scan = new Scanner(System.in);
public int inputBoardSize() {
while (flag) {
System.out.print("Enter the number of grids you want to play with:");
try {
boardSize = Integer.parseInt(scan.next());
if (boardSize < 3 || boardSize > 10) {
System.out.println("Please choose a board size between 3 and 10");
continue;
}
flag = false;
break;
} catch (NumberFormatException e) {
e.getMessage();
System.out.println("Please enter a number");
continue;
}
}
printBoard(boardSize);
return boardSize;
}
But I am new to unit testing and need a little help. I am not able to figure out how to test two conditions
the NumberFormatException
When the input is not between 3 and 10.
My testing class for the second condition is something like this:
public class BoardTest extends TestCase {
#Test
public void test() {
Board board = new Board();
String input = "2";
InputStream in = new ByteArrayInputStream(input.getBytes());
System.setIn(in);
}
}
I am not able to figure out what to do next.
You can extract the validation logic into a separate method and then test that method. This removes the need to interact or inject a Scanner object. The extracted code would resemble
public int inputBoardSize() {
while (flag) {
System.out.print("Enter the number of grids you want to play with:");
validateBoardSize(scan.next());
}
printBoard(boardSize);
return boardSize;
}
protected void validateBoardSize(String input) {
try {
boardSize = Integer.parseInt(input);
if (boardSize < 3 || boardSize > 10) {
System.out.println("Please choose a board size between 3 and 10");
}
else {
flag = false;
}
}
catch (NumberFormatException e) {
e.getMessage();
System.out.println("Please enter a number");
}
}
Some JUnit test cases to exercise the validateBoardSize method would be:
public class BoardTest {
private static final String OUT_OUT_BOUNDS_ERROR_MESSAGE = "Please choose a board size between 3 and 10";
private static final String NFE_ERROR_MESSAGE = "Please enter a number";
private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
private Board board;
#Before
public void setUp() {
System.setOut(new PrintStream(outContent));
board = new Board();
}
#Test
public void setBoardSizeOf2EnsureErrorMessageDisplayed() {
board.validateBoardSize("2");
assertOutOfBoundsErrorMessageDisplayed();
}
private void assertOutOfBoundsErrorMessageDisplayed() {
assertEquals(OUT_OUT_BOUNDS_ERROR_MESSAGE, outContent.toString().trim());
}
#Test
public void setBoardSizeOf3EnsureNoErrorMessageDisplayed() {
board.validateBoardSize("3");
assertNoErrorMessageDisplayed();
}
private void assertNoErrorMessageDisplayed() {
assertEquals("", outContent.toString().trim());
}
#Test
public void setBoardSizeOf4EnsureNoErrorMessageDisplayed() {
board.validateBoardSize("4");
assertNoErrorMessageDisplayed();
}
#Test
public void setBoardSizeOf9EnsureNoErrorMessageDisplayed() {
board.validateBoardSize("9");
assertNoErrorMessageDisplayed();
}
#Test
public void setBoardSizeOf10EnsureNoErrorMessageDisplayed() {
board.validateBoardSize("10");
assertNoErrorMessageDisplayed();
}
#Test
public void setBoardSizeOf11EnsureErrorMessageDisplayed() {
board.validateBoardSize("11");
assertOutOfBoundsErrorMessageDisplayed();
}
#Test
public void setBoardSizeWithInvalidNumberEnsureInvalidNumberMessageDisplayed() {
board.validateBoardSize("blah");
assertInvalidNumberMessageDisplayed();
}
private void assertInvalidNumberMessageDisplayed() {
assertEquals(NFE_ERROR_MESSAGE, outContent.toString().trim());
}
}
Note that since your program denotes errors through messages sent through standard output (as opposed to throwing exceptions), the tests must intercept the output message sent to standard output and do a string compare to see what the message says. Hence, within setUp(), the OutputStream for standard output is set to an OutputStream instance whose string value can be compared against by the test methods: System.setOut(new PrintStream(outContent)). To test the output, you can just extract the string value of the OutputStream: outContent.toString().trim(). Note that trim() is used to remove the trailing newline character(s), since println will include them in the error message. Newlines are OS-sensitive, so removing them makes comparing the string much more straightforward.
For more information, see JUnit test for System.out.println().
Add the following constructors:
public class Board {
private Scanner;
public Board() {
this(System.in);
}
public Board(InputStream in) {
scan = new Scanner(in);
}
}
Then you can provide provide an InputStream from the outside when testing the class.
I need to know how to fetch the input for the operator for this simple program I am making that does this; the person enters a number, and if it's greater than 10, it displays the message "it worked". Where it says "NEED INPUT" is where I need the system scanner entry to go.
Operators class:
class Classes {
private int Numbers;
public Classes() {}
Classes(String namez) {
Numbers = Numbers;
}
public int getNumbers() {
return Numbers;
}
public void setNumbers(int numberz) {
if((Integer.parseInt(INPUT HERE.getText().toString()) )<=10) {
System.out.print("It worked.");
}
}
}
Main class:
import java.util.Scanner;
public class OneTwoThree {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
System.out.print("Enter a number: ");
Classes.Numbers(keyboard.nextLine());
}
}
package mavens.dais.test;
public class ClassesTest {
private int Numbers;
public ClassesTest() {}
ClassesTest(String namez) {
Numbers = Integer.parseInt(namez);
}
public int getNumbers() {
return Numbers;
}
public void setNumbers(int numberz) {
if(numberz > 10){
System.out.print("It is worked.");
}else{
System.out.print("It is not worked.");
}
}
}
package mavens.dais.test;
import java.util.Scanner;
public class OneTwoThre {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
System.out.print("Enter a number: ");
new ClassesTest().setNumbers(Integer.parseInt(keyboard.nextLine()));
}
}
Firstly
Classes.Numbers(keyboard.nextLine());
this should be replaced by Classes(keyboard.nextLine()); to begin with, in your class named OneTwoThree
Secondly
Classes(String namez) {
Numbers = Numbers;
}
this seems pretty much wrong.
Should be replaced by something like
Classes(String namez) {
Numbers = Integer.parseInt(namez); //if you are entering integers only through keyboard
}
As far as I could understand your question,
you can go like this then,
Classes(String namez) {
Numbers = Integer.parseInt(namez); //if you are entering integers only through keyboard
performOperation(Numbers);// call a method you want,pass number as arg
}
public static void performOperation(int num){
if(Numbers >10){
//do stuff
}
else{
//else part
}
}
}
Also ,just as a good practice you should name your variable Numbers to number.
I Hope it helped.
You just need to pass the String.
public static void testScanner() {
try (Scanner keyboard = new Scanner(System.in);) {
System.out.print("Enter a number: ");
while (true) {
String input = keyboard.nextLine();
if (input.equalsIgnoreCase("exit")) {
break;
}
Handler.handleInput(input);
}
System.out.println("Done.");
}
}
static class Handler {
public Handler() {
}
public static void handleInput(String input) {
try {
int x = Integer.parseInt(input);
if (x <= 10) {
System.out.println("It worked!");
} else {
System.out.println("Aw, Id didn't work.");
}
} catch (Exception ex) {
System.out.println("Hey, watch it buddy. Don't throw any letters in there, I don't like them.");
}
}
}