Java Passing variables, avoiding toString hash - java

I know this has been asked before, but not in a way I understood, because I am dumb.
So.
I need to take some variables into a class, compare them against something, and then return the higher of the two. In the long run, I need to compare against a running total, but for my problem, I think the issue is considerably more fundamental. I'm not understanding how to pass a variable BACK to my main class.
import java.io.*;
public class testing123 {
public static void main(String[] args) {
InputStreamReader input = new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(input);
Integer a;
Integer b;
Integer numbersCombined;
try {
System.out.println("Please enter a number");
a = Integer.parseInt(reader.readLine());
System.out.println("Please enter a number");
b = Integer.parseInt(reader.readLine());
numbersCombined = (a + b);
testClass Check = new testClass();
System.out.println("Your numbers combined is " +numbersCombined);
System.out.println(Check);
} catch (IOException e){
System.out.println("Error reading from user");
}
}
}
class testClass {
public static Integer testClass (Integer numbersCombined) {
if (numbersCombined > 100) {
numbersCombined = numbersCombined;
}
else {
numbersCombined = 100;
}
System.out.println(numbersCombined);
return numbersCombined;
}
}
If I remove the return, this will print the numbersCombined, but that's all it does. With the return in place, it doesn't execute the print line above the return, and first prints the original numbersCombined (which it shouldn't if you use, say, 10 and 20, since that's less than 100), and then prints testClass#76046e53 rather than the actual value. I know there's a way to override it, but the answers I've found don't work for me.
I know this answer: http://www.google.com/url?q=http%3A%2F%2Fstackoverflow.com%2Fquestions%2F29140402%2Fhow-do-i-print-my-java-object-without-getting-sometype2f92e0f4&sa=D&sntz=1&usg=AFQjCNGIzxlBSH8xIS7hurKe6_Euc7B8RQ
is the basic problem I'm encountering, but the overrides listed aren't really working for me, and I want integer anyway, rather than string.
In the end, what I'm "really" doing is taking a series of 4 numbers from a user, then using this function to compare whether THIS series of numbers is higher than the previous maximum, and if it is, that's the new maximum moving forward, with a loop until the user is done entering serieses of 4 numbers, and then finally printing the maximum.
I was able to write this without ANY functions, all inline, easy as pie. But once I send the comparison to a function, I don't understand how to send it back, and I've spent all day trying to understand the concept. ALL DAY. So, while I know it's going to be a stupid answer, that's because I'm stupid, but not because I didn't try (sorry, kind of defensive. Frustrated).
Fundamentally, I want to send two (this example is just one) variables to a class, compare them, change ONE of them, and return it to the main class. In this example, I'm just trying to send ONE variable, compare it, and the send it back.

You need to call the method within TestClass. Your code is already returning an integer from that method.
Once you instantiate the class run testClass.testClass(numbers)
The way you're throwing around pseudo-global variables between classes is probably the problem. Pass them through the calls like above, rather than implicitly.

Try to do something like this:
import java.io.*;
public class HelloWorld{
public static void main(String []args){
InputStreamReader input = new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(input);
Integer a;
Integer b;
Integer numbersCombined;
try {
System.out.println("Please enter a number");
a = Integer.parseInt(reader.readLine());
System.out.println("Please enter a number");
b = Integer.parseInt(reader.readLine());
numbersCombined = (a + b);
testClass Check = new testClass(numbersCombined); // constructor should be like this
System.out.println("Your numbers combined is " + numbersCombined);
System.out.println(Check);
} catch (IOException e){
System.out.println("Error reading from user");
}
}
}
class testClass {
Integer numbersCombined;
// This is a constructor
public testClass (Integer numbersCombined) {
if (numbersCombined > 100) {
this.numbersCombined = numbersCombined; // use this to represent the object
} else {
this.numbersCombined = 100;
}
System.out.println(numbersCombined);
}
// Add method toString()
public String toString() {
return this.numbersCombined.toString();
}
}

Related

How do I reuse my scanner?

I made a utility class with a method that is takes user input, and returns a lower case version of it so I don't have so much repetitive code, but it could only be used once. After that, it wouldn't scan. What can I do to fix this?
p.s. I have seen a lot of people saying it is a bad idea to reuse a scanner. Why is this? Shouldn't it be fine if the scanner is reset?
public String scan() {
String input;
Scanner s = new Scanner(System.in);
if (s.hasNextLine()) {
input = s.nextLine();
} else {
input = "ERROR";
}
s.reset();
s.close();
return input.toLowerCase();
}
You are correct every time you use the scanner its getting reseted. A solution to your problem would be the following:
Add all the parameters that you want to pass to scan() in an array and using a for loop pass them all to scan() while when returning, adding them again in their respective array position so then you can easily reuse them wherever you want.
You could actually reuse your Scanner instead of creating a new one each time you need to read a line , here is an example:
public class Test {
public static void main(String[] args) {
Test t = new Test();
//create your scanner object
Scanner s = new Scanner(System.in);
//send it as a parameter whenever you need to read a line
System.out.println(t.scan(s));
System.out.println(t.scan(s));
System.out.println(t.scan(s));
//close it after finishing
s.close();
}
public String scan(Scanner s) {
String input;
if (s.hasNextLine()) {
input = s.nextLine();
} else {
input = "ERROR";
}
return input.toLowerCase();
}
}
But if you make a reader utility class for you it's more logical to be an Instance variable in the utility class .
For Example:
public class Reader {
Scanner s ;
public Reader() {
s = new Scanner(System.in);
}
public String scan() {
String input;
if (s.hasNextLine()) {
input = s.nextLine();
} else {
input = "ERROR";
}
return input.toLowerCase();
}
public void close(){
s.close();
}
}
And when you use it , it will be like this :
public class Main {
public static void main(String[] args) {
//create your scanner object
Reader r = new Reader();
//send it whenever you need to read a line
System.out.println(r.scan());
System.out.println(r.scan());
System.out.println(r.scan());
//close it after finishing
r.close();
}
}
I have seen a lot of people saying it is a bad idea to reuse a
scanner. Why is this?
It is not a bad idea to reuse a scanner object in most cases. Without further context, it is hard to determine their reasons for saying that. It could've been they were mistaken. Maybe you reused it incorrectly when they stated that. Who knows?
One thing is certain: When you invoke Scanner#close() in an object that is reading from System.in, you are also closing the underlying input stream. And, once the input stream is closed, you cannot reopen it in the life of the application.
Shouldn't it be fine if the scanner is reset?
Scanner#reset() doesn't do what you think it does. In fact, in this code example it does nothing. This method resets the Locale to US, and the radix back to base 10.
Code Analysis
public String scan() {
String input;
Scanner s = new Scanner(System.in);
if (s.hasNextLine()) {
input = s.nextLine();
} else {
input = "ERROR";
}
s.reset();
s.close(); // BAD IDEA!!!!
return input.toLowerCase();
}
This method will only work one time for the reasons I already stated: "once the input stream is closed, you cannot reopen it in the life of the application." So, what you do instead? If you require to reuse this Scanner object over and over, it might be better to make it a global attribute of the class and you should never close it. This is obviously a bad idea. So, you might be better off using some other type of input stream wrapper.
Maybe this is why other people have told you in the past that reusing the scanner object was a bad idea. It is only speculation. But, judging from this code example, it seems like a very strong possibility.

How to sort info from a text file into an array by type in java?

I am trying to write a method that will read a text file that looks like this:
N 1000.0 NY
R 2000.0 CA 0.09
R 500.0 GA 0.07
N 2000.0 WY
O 3000.0 Japan 0.11 20.0
N 555.50 CA
O 3300.0 Ecuador 0.03 30.0
R 600.0 NC 0.06
The starting letters are the different types of orders. Each type of order has different parameters. I want the method to read the orders from the text file in a format like this:
Type Price Location [TaxRate] [Tariff]. My point of confusion is how to sort the data into the array by type.
public static ArrayList<Order> readOrders (String fileName)
{
File file = new File (fileName);
scan = null;
try {
scan = new Scanner(file);
} catch (FileNotFoundException e) {
System.out.println("Error, file not found: " + file.toString());
e.printStackTrace();
}
Order[] order = new Order[8];
for (int i = 0; i < order.length; i++) {
String data = scan.nextLine(); // you need to use nextLine to read a whole line
String[] val = data.split(" ");
String type = val[0]; // Since its a String
double price = Double.parseDouble(val[1]);
String location = val[2]; // Since its a String
double taxRate = 0.0; // Default values
double tariff = 0.0; // Default values
try { // Incase they are not present - error handling
taxRate = Double.parseDouble(val[3]);
tariff = Double.parseDouble(val[4]);
} catch (ArrayIndexOutOfBoundsException e) {
}
ArrayList <Order> orders =new ArrayList<Order>(Arrays.asList(order));
return orders;
I cannot get it to work with my main method:
public static void main(String[] args)
{
ArrayList<Order> orders2 = readOrders("orders.txt");
for( Order o2 : orders2)
{
System.out.println( o2.printOrder("Long"));
}
for( Order o2 : orders2)
{
System.out.println(o2.printOrder("Short"));
}
}
This is my error code:
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
The method printOrder(String) is undefined for the type Order
The method printOrder(String) is undefined for the type Order
at prob1.OrderTester.main(OrderTester.java:19)
Well. it is a compilation error. The class Order doesn't include the method you are calling. E.g.
printOrder("Long")
Check the class Order. Here you have not provided it
Like already mentioned you got a compilation error. Your Order class need to have a printOrder(String) method.
You should also check your readOrders method.
It seems to always return empty Orders because you create the order array with
Order[] order = new Order[8];
But NEVER assign something with something like:
order[i] = new Order(type, price, location, etc ...);
The catch block seems also wrong
} catch (ArrayIndexOutOfBoundsException e) {
you need to close it!
The best practice for sorting an array list by type is:
If it's not already, make Order implement Comparable and override compareTo(Order o) to return the following, assuming there is a String type field and it has an accessor method getType():
#Override
public int compareTo(Order o) {
return type.compareTo(o.getType());
}
Then simply call Arrays.sort(orders) once you've scanned the file.
Or use a Comparator.
Having said that, here's a short list of some of the wrongest things in your code:
(1) You haven't posted the source for the Order class, which is the main class with regards to the question you've asked. Makes it hard to give a more specific answer.
(2) The readOrders() function you've posted either is incomplete or (even if you add the couple of missing curly braces, and close the for loop) returns a list containing 8 null references. You need to instantiate the Order objects.
(3) Why use an array Order[] instead of just using the list with ArrayList.add()?
(4) Any time the Scanner fails to load the file, it will throw a NullPointerException on the first line after the catch block.
(5) Checking if your array has ended by catching ArrayIndexOutOfBoundsException() is bad practice for a multitude of reasons. Google it if you don't believe me.
(6) You get a compilation error because the Order.printOrder(String) is not defined. Define it, or better yet override Order.toString().
Consider rewriting your code to address these issues. There's likely more, these are just the things that jump out at first glance.
I figured out the answer I was looking for. Here it is:
public static ArrayList<Order> readOrders (String fileName)
{
File file = new File (fileName);
ArrayList<Order> o = new ArrayList<Order>();
scan = null;
try {
scan = new Scanner(file);
} catch (FileNotFoundException e) {
System.out.println("Error, file not found: " + file.toString());
e.printStackTrace();
}
while (scan.hasNext())
{
String fl = scan.next();
if (fl.equals("N"))
{
NonProfitOrder n = new NonProfitOrder(scan.nextDouble(), scan.next());
o.add(n);
}
else if (fl.equals("R"))
{
RegularOrder r = new RegularOrder (scan.nextDouble(), scan.next(), scan.nextDouble());
o.add(r);
}
else
{
OverseasOrder oo = new OverseasOrder(scan.nextDouble(), scan.next(), scan.nextDouble(), scan.nextDouble());
o.add(oo);
}
}
return o;
}

How can I randomly call a method to run in java?

I am writing a program that will generate a geometry Logic Word Problem, and I am having trouble with it. My goal is to have the program randomly create a word problem that is pre-designed. So far, the program takes input from the user, and then uses that information in the Story methods, somewhat like a game of Mad Libs. Anyways, I want to randomly chose a Story method to run each time the user starts the program. So far this is what I have:
import cs1.Keyboard;
public class LogicProof {
//Main method
public void main () {
System.out.println ("Enter 1. to start.");
System.out.println ("Enter 2. to exit.");
int choice = Keyboard.readInt();
if (choice == 1) { //Take info in and send to createStory
//Randomly run methods
}
if (choice == 2) {
System.out.println ("\nGoodbye.");
}
//Create the first story using inputs from main
private void createStory(String adj,String adj2,String adj3,String action) {
//Use values from main() to create a problem
}
There are two other createStory methods as well. Also, I am going to display the proofs of each problem, and each method has its own proof, so would I be able to then display the proof for the same method, basically just link together the proof method, and story method?
I'm fairly new to Java, and appreciate the help.
Thanks in advance.
To only answer your title, you could use random generation with reflection, but that is in no way how you should solve your current problem.
Don't try and randomly invoke methods. Take a look at java.util.Random's nextInt() and use that to do unique operations based on the value it returns.
This seems like Homework which is why I'm not giving you a full solution here.
public class MadLibs {
public static final String[] STARTERS = { /* ... */ };
public static final String[] ENDINGS = { /* ... */ };
public static String generate(String ... adjectives) {
final Random random = new Random();
final StringBuilder string = new StringBuilder(STARTERS[random.nextInt(STARTERS.length-1)]);
for (String adjective : adjectives) {
string.append(adjective);
string.append(TRANSITIONS[random.nextInt(TRANSITIONS.length - 1)]);
}
return string.toString();
}
}
That's an extremely simple and rough implementation to get you started.
Or maybe, if you have only a few concrete variations:
public class MadLibs {
public static String generate(String ... adjectives) {
int result = new Random().nextInt(MAX);
String madLib = null;
switch (result) {
case 0:
// ...
break;
case 1:
// ...
break;
default:
// ...
break;
}
return madLib;
}
}
Like said above, use random number generation to yourself a 1,2,3,4 ect... Then pass that number into your method as a parameter and then use "if, if else" statements to choose the correct operation to perform. Again, like stated above I will not give any code in case this is indeed a homework problem.
You could generate a Word or Phrase object, populate them into a List.
From there us something like Random or Math.random to pull a word or phrase from the list

Try and Catch into a method

I'm trying to put a try-catch into a procedure type method but I'm 95% sure it has to be a function type. What I'm trying to accomplish is to make my code shorter in the main. One of the biggest things I thought of was to put a try-catch into a method and call the method.
The thing is, it will validate the input if it is a integer or not- it even catches the exceptions the problem is that it doesn't "remember" the validated input once it continues on with the program/calculates. Here's the part of the code I'm having trouble with.
public static void tryCatchNum(double value)
{
while(true)
{
try
{
Scanner iConsole = new Scanner(System.in);
value = Double.parseDouble(iConsole.nextLine());
System.out.println(" ");
break;
}
catch(NumberFormatException e)
{
System.out.println("NumberFormatException error has oocured. Please try again.");
}
}
}
And here is the entire program:
import java.util.Scanner;
public class ch7exercise1
{
public static double compound(double oA, double cI)
{
return roundCent((oA*(Math.pow((1+(percent(cI))),10))));
}
public static double percent(double interest)
{
return interest/100.0;
}
public static double roundCent(double amount)
{
return ((Math.round(amount*100))/100.0); //100.0 is mandatory.
}
public static void tryCatchNum(double value)
{
while(true)
{
try
{
Scanner iConsole = new Scanner(System.in);
value = Double.parseDouble(iConsole.nextLine());
System.out.println(" ");
break;
}
catch(NumberFormatException e)
{
System.out.println("NumberFormatException error has oocured. Please try again.");
}
}
}
#SuppressWarnings("unused")
public static void main(String[] args)
{
boolean f = true;
boolean f2 = true;
double origAmount = 0;
double compInterest = 0;
double total = 0;
Scanner iConsole = new Scanner(System.in);
System.out.println("10 year Compound Interest Claculator\n");
System.out.println("Input amount of money deposited in the bank");
tryCatchNum(origAmount);
System.out.println("Input compouded interest rate. (If the compound interest is 3% input 3)");
tryCatchNum(compInterest);
total = compound(origAmount,compInterest);
System.out.println("$"+total);
}
}
Java arguments are passed by value. You're passing 0 to the tryCatchNum method. A copy of the value is passed to the method. This method assigns a new value to its own copy, and then returns. So the original value is still 0.
You must not pass anything to the method. Instead, the method must return the value it has validated. Also, consider using a more appropriate method name:
public double readDoubleValue() {
...
return value;
}
And in the main method:
double origAmount = readDoubleValue();
Since double is a primitive in Java it is passed by value to the method, therefore when you alter the value of the primitive the changes to the method parameter are not reflected in the original variable passed into the method call.
Read the cup story on Java ranch which explains pass by value and pass by reference.
http://www.javaranch.com/campfire/StoryCups.jsp
The next story to read is the Pass By Value story on Java Ranch.
http://www.javaranch.com/campfire/StoryPassBy.jsp
You should alter your method so that it returns a double which is assigned to value in the main method of your program.
I am also very curious as to why you are using a while loop that checks true. I think it is highly likely your program will encounter an infinite loop if the value entered cannot be converted to a double.

JUnit testing with simulated user input

I am trying to create some JUnit tests for a method that requires user input. The method under test looks somewhat like the following method:
public static int testUserInput() {
Scanner keyboard = new Scanner(System.in);
System.out.println("Give a number between 1 and 10");
int input = keyboard.nextInt();
while (input < 1 || input > 10) {
System.out.println("Wrong number, try again.");
input = keyboard.nextInt();
}
return input;
}
Is there a possible way to automatically pass the program an int instead of me or someone else doing this manually in the JUnit test method? Like simulating the user input?
You can replace System.in with you own stream by calling System.setIn(InputStream in).
InputStream can be a byte array:
InputStream sysInBackup = System.in; // backup System.in to restore it later
ByteArrayInputStream in = new ByteArrayInputStream("My string".getBytes());
System.setIn(in);
// do your thing
// optionally, reset System.in to its original
System.setIn(sysInBackup);
Different approach can be make this method more testable by passing IN and OUT as parameters:
public static int testUserInput(InputStream in,PrintStream out) {
Scanner keyboard = new Scanner(in);
out.println("Give a number between 1 and 10");
int input = keyboard.nextInt();
while (input < 1 || input > 10) {
out.println("Wrong number, try again.");
input = keyboard.nextInt();
}
return input;
}
To test drive your code, you should create a wrapper for system input/output functions. You can do this using dependency injection, giving us a class that can ask for new integers:
public static class IntegerAsker {
private final Scanner scanner;
private final PrintStream out;
public IntegerAsker(InputStream in, PrintStream out) {
scanner = new Scanner(in);
this.out = out;
}
public int ask(String message) {
out.println(message);
return scanner.nextInt();
}
}
Then you can create tests for your function, using a mock framework (I use Mockito):
#Test
public void getsIntegerWhenWithinBoundsOfOneToTen() throws Exception {
IntegerAsker asker = mock(IntegerAsker.class);
when(asker.ask(anyString())).thenReturn(3);
assertEquals(getBoundIntegerFromUser(asker), 3);
}
#Test
public void asksForNewIntegerWhenOutsideBoundsOfOneToTen() throws Exception {
IntegerAsker asker = mock(IntegerAsker.class);
when(asker.ask("Give a number between 1 and 10")).thenReturn(99);
when(asker.ask("Wrong number, try again.")).thenReturn(3);
getBoundIntegerFromUser(asker);
verify(asker).ask("Wrong number, try again.");
}
Then write your function that passes the tests. The function is much cleaner since you can remove the asking/getting integer duplication and the actual system calls are encapsulated.
public static void main(String[] args) {
getBoundIntegerFromUser(new IntegerAsker(System.in, System.out));
}
public static int getBoundIntegerFromUser(IntegerAsker asker) {
int input = asker.ask("Give a number between 1 and 10");
while (input < 1 || input > 10)
input = asker.ask("Wrong number, try again.");
return input;
}
This may seem like overkill for your small example, but if you are building a larger application developing like this can payoff rather quickly.
One common way to test similar code would be to extract a method that takes in a Scanner and a PrintWriter, similar to this StackOverflow answer, and test that:
public void processUserInput() {
processUserInput(new Scanner(System.in), System.out);
}
/** For testing. Package-private if possible. */
public void processUserInput(Scanner scanner, PrintWriter output) {
output.println("Give a number between 1 and 10");
int input = scanner.nextInt();
while (input < 1 || input > 10) {
output.println("Wrong number, try again.");
input = scanner.nextInt();
}
return input;
}
Do note that you won't be able to read your output until the end, and you'll have to specify all of your input up front:
#Test
public void shouldProcessUserInput() {
StringWriter output = new StringWriter();
String input = "11\n" // "Wrong number, try again."
+ "10\n";
assertEquals(10, systemUnderTest.processUserInput(
new Scanner(input), new PrintWriter(output)));
assertThat(output.toString(), contains("Wrong number, try again.")););
}
Of course, rather than creating an overload method, you could also keep the "scanner" and "output" as mutable fields in your system under test. I tend to like keeping classes as stateless as possible, but that's not a very big concession if it matters to you or your coworkers/instructor.
You might also choose to put your test code in the same Java package as the code under test (even if it's in a different source folder), which allows you to relax the visibility of the two parameter overload to be package-private.
I managed to find a simpler way. However, you have to use external library System.rules by #Stefan Birkner
I just took the example provided there, I think it couldn't have gotten more simpler:
import java.util.Scanner;
public class Summarize {
public static int sumOfNumbersFromSystemIn() {
Scanner scanner = new Scanner(System.in);
int firstSummand = scanner.nextInt();
int secondSummand = scanner.nextInt();
return firstSummand + secondSummand;
}
}
Test
import static org.junit.Assert.*;
import static org.junit.contrib.java.lang.system.TextFromStandardInputStream.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.TextFromStandardInputStream;
public class SummarizeTest {
#Rule
public final TextFromStandardInputStream systemInMock
= emptyStandardInputStream();
#Test
public void summarizesTwoNumbers() {
systemInMock.provideLines("1", "2");
assertEquals(3, Summarize.sumOfNumbersFromSystemIn());
}
}
The problem however in my case my second input has spaces and this makes the whole input stream null!
You might start by extracting out the logic that retrieves the number from the keyboard into its own method. Then you can test the validation logic without worrying about the keyboard. In order to test the keyboard.nextInt() call you may want to consider using a mock object.
I have fixed the problem about read from stdin to simulate a console...
My problems was I'd like try write in JUnit test the console to create a certain object...
The problem is like all you say : How Can I write in the Stdin from JUnit test?
Then at college I learn about redirections like you say System.setIn(InputStream) change the stdin filedescriptor and you can write in then...
But there is one more proble to fix... the JUnit test block waiting read from your new InputStream, so you need create a thread to read from the InputStream and from JUnit test Thread write in the new Stdin... First you have to write in the Stdin because if you write later of create the Thread to read from stdin you likely will have race Conditions... you can write in the InputStream before to read or you can read from InputStream before write...
This is my code, my english skill is bad I hope all you can understand the problem and the solution to simulate write in stdin from JUnit test.
private void readFromConsole(String data) throws InterruptedException {
System.setIn(new ByteArrayInputStream(data.getBytes()));
Thread rC = new Thread() {
#Override
public void run() {
study = new Study();
study.read(System.in);
}
};
rC.start();
rC.join();
}
I've found it helpful to create an interface that defines methods similar to java.io.Console and then use that for reading or writing to the System.out. The real implementation will delegate to System.console() while your JUnit version can be a mock object with canned input and expected responses.
For example, you'd construct a MockConsole that contained the canned input from the user. The mock implementation would pop an input string off the list each time readLine was called. It would also gather all of the output written to a list of responses. At the end of the test, if all went well, then all of your input would have been read and you can assert on the output.

Categories

Resources