print out each character in an input - java

I've been teaching myself Java with http://www.cs.princeton.edu/courses/archive/spr15/cos126/lectures.html as a reference. They have a library called algs4 and it has several classes including StdIn, which I'm trying to implement below.
import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;
public class Tired
{
public static void main(String[] args)
{
//I thought this while statement will ask for an input
//and if an input is provided, it would spell out each character
while (!StdIn.hasNextChar()) {
StdOut.print(1); //seeing if it gets past the while conditional
char c = StdIn.readChar();
StdOut.print(c);
}
}
}
//This is from StdIn class. It has a method called hasNextChar() as shown below.
/*
public static boolean hasNextChar() {
scanner.useDelimiter(EMPTY_PATTERN);
boolean result = scanner.hasNext();
scanner.useDelimiter(WHITESPACE_PATTERN);
return result;
}
*/
If i run the code, it does ask for an input, but regardless of what i type in, nothing happens and nothing gets printed out.
I see that even StdOut.print(1); doesnt get printed out, so for some reason, it just gets stuck on while

It looks like the issue is with the condition for your while loop:
!StdIn.hasNextChar()
This says to continue as long as there isn't a next char. But you want to continue while there is one, so get rid of that ! and you should be good.

Here is some alternative code that works similarly. Not the best coding but works.
import java.util.Scanner;
public class test{
static Scanner StdIn = new Scanner(System.in);
static String input;
public static void main(String[] args){
while(true){
if(input.charAt(0) == '!'){ // use ! to break the loop
break;
}else{
input = StdIn.next(); // store your input
System.out.println(input); // look at your input
}
}
}
}

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.

Scanner is requiring me to type inputs twice just for one to register

I've been doing a ton of research on this for the past few hours, with no luck. I am pretty sure this is a problem with .next() or .nextLine() (according to my searches). However, nothing has helped me solve my problem.
When I run the code below, I have to type in input twice, and only one of the inputs is subsequently added to the arrayList (which can be seen when you print the contents of the arrayList).
import java.io.File;
import java.util.ArrayList;
import java.util.Scanner;
public class Tester{
public static void main(String[] args) {
AddStrings();
}
public static void AddStrings() {
Scanner console = new Scanner(System.in);
ArrayList<String> strings = new ArrayList<String>(); //this arraylist will hold the inputs the user types in in the while loop below
while(true) {
System.out.println("Input file name (no spaces) (type done to finish): ");
if(console.next().equals("done")) break;
//console.nextLine(); /*according to my observations, with every use of .next() or .nextLine(), I am required to type in the same input one more time
//* however, all my google/stackoverflow/ reddit searches said to include
//* a .nextLine() */
//String inputs = console.next(); //.next makes me type input twice, .nextLine only makes me do it once, but doesn't add anything to arrayList
strings.add(console.next());
}
System.out.println(strings); //for testing purposes
console.close();
}
}
Problem with your code is that you are doing console.next() two times.
1st Inside if condition and
2nd while adding to ArrayList.
Correct Code :
public class TestClass{
public static void main(String[] args) {
AddStrings();
}
public static void AddStrings() {
Scanner console = new Scanner(System.in);
ArrayList<String> strings = new ArrayList<String>(); //this arraylist will hold the inputs the user types in in the while loop below
while(true) {
System.out.println("Input file name (no spaces) (type done to finish): ");
String input = console.next();
if(input.equals("done")) break;
strings.add(input);
System.out.println(strings);
}
System.out.println(strings); //for testing purposes
console.close();
}
}
In your code, you are asking for two words to be inserted. Just remove one of them.
Use it this way:
String choice = console.next();
if (choince.equals('done')) break;
strings.add(choice);

How to use boolean statements and return

I am trying to create a piece of code which will;
return true if given an int n, which is with in 10 of 100 or 200.
import java.util.Scanner;
class nearHundred{
public boolean nearHundred(int n){
Scanner input = new Scanner(System.in);
n = input.nextInt();
if(10>=Math.abs(100-n) || 10>=Math.abs(200-n)){
return true;
}
return false;
}
}
Where have I gone wrong?
From comments it looks like your main method is misplaced, wherever it is I hope it exists only once in a project. Call your class from that main() method, for example -
new nearHundred().nearHundred(100); // a call from main method
Now coming to your code there are several things to correct here. Your method should not take care about Scanner, its job is to take input and check for the logic.
For example;
public class Utils {
public static boolean isNearToHundered(int num) {
return Math.abs(num-100)<=10 || Math.abs(num-200)<=10;
}
}
Give the responsibility to main method for parsing the input, this is how it should work.
Now since I made method static, you can call like
Utils.isNearToHundred(105); // TRUE
Here is how the method should look:
public void mainMethod() {
Scanner input=new Scanner(System.in);
int val=input.nextInt();
boolean nearHundredBoolean=nearHundred(val);
//do something with nearHundredBoolean....
//Same logic, but passes the input to the method nearHundred
public boolean nearHundred(int n) {
if(Math.abs(100-n)<=10 || Math.abs(200-n)<=10)
return true;
else return false;
}
You should pass the value of the scanner input into this method's parameter requirement, instead of not using the parameter n in your current method. If there is a problem, it may be due to the 'input.nextInt()' method that overwrites the value of the parameter n.

contains method doesn't work properly

I tried to use the contains method to search for a word in a sentence but it only works for the first word in the sentence.
For example when searching for 'Shakira' in "liked Shakira's photo" my program cannot find it. On the other hand, searching for 'liked' in the same sentence works.
This is the code I'm using:
package fules;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class fule {
public static int i,x,n,k,ba,sh,fe;
public static void main(String[] args) throws FileNotFoundException {
File s=new File("C:/Users/taha/Desktop/tt.in");
Scanner m=new Scanner(s);
fule obj=new fule();
i=m.nextInt();//test case
n=m.nextInt();
k=m.nextInt();
for (int l=0;l<6;l++){
boolean q=contains((m.next()),("taha"));
if(q) {
ba++;
}
boolean w=contains((m.next()),("Shakira"));
if(w)
sh++;
}
boolean e=contains((m.next()),("Fegla"));
if(e) {
fe++;
}
System.out.println("ba="+ba+" sh="+sh+" fe="+fe);
m.close();
}
static boolean contains (String s1,String s2)
{
return s1.contains(s2);
}
}
and this is
the inputs in( tt.in)
1
6 2
liked Badr's photo
liked Shakira's photo
liked Badr's photo
liked Fegla's photo
liked Shakira's photo
commented on Shakira's photo
Can somebody please help me?
You are getting the input with the next() method which Finds and returns the next complete token from this scanner. Therefore you only read the first word of the sentence.
Try to replace next() with nextLine().
And if you want to compare the same String against multiple patterns, store that String in a variable. Currently each of your calls to contains() reads a new String from the scanner.
You should write something like this :
String input = m.nextLine();
boolean q=contains(input,"Badr");
if(q)
{
ba++;
}
boolean w=contains(input,"Shakira");
if(w)
sh++;
}
boolean e=contains(input,"Fegla");
if(e)
{
fe++;
}
This would find "Shakira" in "liked Shakira's photo".
Of course, there are more efficient ways to write the same code.
String input = m.nextLine();
if (input.contains("Badr"))
ba++;
if (input.contains("Shakira"))
sh++;
if (input.contains("Fegla"))
fe++;

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