It will ask the user for a keyword to search for. Then, it will ask the user to enter sentences over and over. The user can stop the process by typing “stop” instead of a sentence (which means, of course, that we can’t analyze the one word sentence ‘stop’, but that is OK). Once the user has finished entering the sentences, the program should display the following statistics:
The total number of sentences entered
The total number of sentences that contain the keyword
The average starting position of the keyword in the sentences that contain the keyword.
Can somebody help me put this program together? For #3 we only do average position of the sentences that contain the keyword.
I have the loop part, and for #3 I'm guessing we would use indexOf. #2 inputString.contains(keyword) I'm guessing? Can somebody help me with 1-3 and putting them into a Java program? Thanks.
import java.util.Scanner;
public class Lab6Loops {
public static void main(String[] args) {
String keywordString;
String inputString;
Scanner keyboard = new Scanner (System.in);
int numofSentences = 0;
int numofKeyword = 0;
System.out.println ("Enter a keyword. We will search each sentence for this word.");
keywordString = keyboard.nextLine ();
System.out.println ("Please enter a sentence or type 'stop' to finish");
inputString = keyboard.nextLine ();
while( !inputString.equals ("stop"))
{
if(inputString.contains (inputString));
numofSentences = numofSentences + 1;
if(inputString.contains (keywordString));
numofKeyword = numofKeyword + 1;
System.out.println ("Enter a line of text or 'stop' to finish");
inputString = keyboard.nextLine();
}
System.out.println ("You entered " + numofSentences + " sentences");
System.out.println ("You have " + numofKeyword + "sentences that contain the keyword");
}
}
I like having self-documenting code, so here are a couple suggestions for how you can have a nice tight main loop:
functional-ish semantics
public void loop() {
// TODO: ask for the keyword and store it somewhere
while(true) {
try {
updateStatistics(checkOutput(getSentence()));
} catch (EndOfInput) {
printStatistics();
}
}
}
Object-Oriented
public void loop() {
String keyword = myPrompter.getNextSentence();
myAnalyzer.setKeyword(keyword);
while (true) {
String sentence = myPrompter.getNextSentence();
AnalysisResult result = myAnalyzer.analyze(sentence);
if (result.isEndOfInput()) {
myAnalyzer.printStatistics();
return;
}
}
}
What both of these approaches gives you is a simple framework to plug in the specific logic. You could do all of it inside the main loop, but that can get confusing. Instead, it's preferable to have one function doing one task. One function runs the loop, another gets the input, another counts the # of sentences, etc.
Sometimes I'll start with those little functions, and build the app from the bottom-up, so I'd write a method that takes a string and returns true/false depending on if it's the string "stop". You can even write unit tests for that method, so that when you're building the rest of the app, you know that method does what you intended it to. It's nice to have lots of modular components that you can test along the way, rather than writing a huge long loop and wondering why it's not doing what you want.
sounds like you need to prompt the user for an initial input then enter in to a loop that will last until the user presses stop (or whatever), in each iteration you need to prompt the user for a sentence, if the user inputs data increment one counter that stores the number of sentences, test the sentence against the keyword entered and increment a second counter as applicable, you will also need to push the position that the word occured in to a stack to later get the average which should be the sum of the stack divided by the size. you should be able to use indexOf() to get the position.
package console;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Console {
static float averagePositionInSentence = 0;
static String searchTerm = "";
static int noOfSentencesEntered = 0;
static int noOfMatches = 0;
public static void main(String[] args) {
searchTerm = writeToConsoleAndReturnInput("Add phrase to search for.");
writeToConsole("Now type some sentences. To exit type the word 'stop' on its own");
mainInputLoop();
outputResults();
}
public static void mainInputLoop() {
boolean ended = false;
while (!ended) {
try {
String input = readLineFromConsole();
if (!input.equalsIgnoreCase("stop")) {
maintainStatisticalData(input);
} else {
ended = true;
}
} catch (Exception e) {
writeToConsole("There was an error with your last input");
}
}
}
public static void outputResults() {
writeToConsole("You entered " + noOfSentencesEntered + " sentences of which " + noOfMatches + " conatined the search term '" + searchTerm + "'");
writeToConsole("");
writeToConsole("On average the search term was found at starting position " + (averagePositionInSentence / noOfSentencesEntered) + " in the sentence");
}
public static void maintainStatisticalData(String input) {
noOfSentencesEntered++;
if (input.contains(searchTerm)) {
noOfMatches++;
int position = input.indexOf(searchTerm)+1;
averagePositionInSentence += position;
}
}
//terminal helper methods
public static void writeToConsole(String message) {
System.out.println(message);
}
public static String writeToConsoleAndReturnInput(String message) {
System.out.println(message);
try {
return readLineFromConsole();
} catch (IOException e) {
//should do something here
return "Exception while reading line";
}
}
public static String readLineFromConsole() throws IOException {
InputStreamReader converter = new InputStreamReader(System.in);
BufferedReader in = new BufferedReader(converter);
return in.readLine();
}
}
Related
so I'm trying to make a small text adventure for some practice and I want to simplify things a bit. so I made a class that handles my text outputting and hopefully inputs. it worked the first time I tried to input something, but when I try again the code throws a NoSuchElementException.
here is the printer class
'''
package Printer;
import java.util.Scanner;
public class echo {
public static void print(String x) {
System.out.print(x);
}
public static String y;
public static String get(String x) {
Scanner inputx = new Scanner(System.in);
System.out.println(x);
y = inputx.nextLine();
inputx.close();
return y;
}
}
the part I'm working on
package story;
import Printer.echo;
import java.util.concurrent.TimeUnit;
public class MainStory {
public static void main(String[] args) throws InterruptedException {
echo.print("hello user and welcome to my dungeon \n");
echo.get("are you willing to go thru 100 floors each more deadlier "
+ "than the next");
if(echo.y.equals("yes")) {
echo.print("well what ya waiting for, lets hurry up and "
+ "pick your first class \n");
TimeUnit.MILLISECONDS.sleep(500);
echo.print("wait I'm supposed to give a list, "
+ "hold on give me like 2 seconds to fetch the list off my drive \n");
TimeUnit.SECONDS.sleep(2);
echo.print("ok here it is in its full glory");
echo.print("List of classes in Project: Ordus");
echo.print("Tank");
echo.print("Rogue");
echo.print("DPS");
echo.print("each class has a sus set of skills that "
+ "allow it to blossom into a very cool run");
echo.get("what shall it be \n");
String input = echo.y;
if(input.equals("tank") && echo.y.equals("Tank")) {
echo.print("your a tank");
}
if(input.equals("rogue") && echo.y.equals("Rogue")) {
echo.print("your a Rogue");
}
if(input.equals("DPS") && echo.y.equals("dps")) {
echo.print("your a dps");
}
echo.print("this is the end of the story so far");
echo.print("plese wait for a update in the near future");
}
else {
}
}
}
I want to try to clear the string before the user inputs again so I can be rid of the error.
It'd be enough to not close the scanner, so just delete the inputx.close() line.
So this is currently what I have right now!
int downPayment;
System.out.printf("How much will the down payment be?: ");
Scanner keyboardIn = new Scanner(System.in);
downPayment = keyboardIn.nextInt();
System.out.println(downPayment);
However, if I were to have a user enter ' $500 ', the build would fail (as scanner 'scans' for only an integer).
Is there a way to use scanner where it would ignore the first index of an 'integer', as I think that having scanner look at the variable as a string and converting the dollar value to an int while appending the first index is super inefficient.
Thanks!
I think that having scanner look at the variable as a string and converting the dollar value to an int while appending the first index is super inefficient.
Drawing conclusions from thinking is for philosophers, not engineers.
Here's your proposed efficient version:
import java.util.*;
class NextInt {
public static void main(String[] args) {
Scanner keyboardIn = new Scanner(System.in);
int downPayment;
for(int i=0; i<10000000; i++) {
downPayment = keyboardIn.nextInt();
}
}
}
Here's your proposed super inefficient version:
import java.util.*;
class AsString {
public static void main(String[] args) {
Scanner keyboardIn = new Scanner(System.in);
int downPayment;
for(int i=0; i<10000000; i++) {
String input = keyboardIn.next();
if (input.startsWith("$")) input = input.substring(1);
downPayment = Integer.parseInt(input);
}
}
}
We can generate 10 million lines of test data:
yes '1500' | head -n 10000000 > nodollar
yes '$500' | head -n 10000000 > dollar
Now benchmark it (best of 3):
$ time java NextInt < nodollar
real 0m3.544s
user 0m3.759s
sys 0m0.124s
$ time java AsString < dollar
real 0m2.530s
user 0m2.735s
sys 0m0.111s
As it turns out, not only are we talking about upper bound of ~0.4 microseconds saved time per user input, but you are spending your time and effort on a slower implementation. No wonder they say that premature optimization is the root of all evil!
Anyways, that was a tangent that doesn't actually answer the question. Have you considered using skip to skip an optional $?
keyboardIn.skip("[$]?");
downPayment = keyboardIn.nextInt();
Instead of making your program work for users who enter a dollar sign at the start of their number, one option is to tell the user more clearly that they are expected to enter just the number itself. If you put a $ symbol at the end of the prompt, the user will be typing immediately after that $; any sensible user will realise they are not supposed to type an extra $, because it would be visibly wrong on the screen to have two $ signs next to each other.
If anybody is silly enough to type an extra $ anyway, let them see an error message.
System.out.print("How much will the down payment be?: $");
A simple change. Note also that you don't need printf here, just print is sufficient.
This obviously doesn't handle every case, but you could check if the first value is a '$' character, if so remove it, then check if the remaining String can be parsed as an int:
public static void getDownPaymentValue() {
Scanner sc = new Scanner(System.in);
System.out.print("How much will the down payment be?: ");
String input = sc.next();
String validatedInput = validateUserInput(input);
int downPayment = 0;
if(isInteger(validatedInput)) {
downPayment = Integer.parseInt(validatedInput);
} else {
System.out.println("Value is not of type int.");
}
System.out.println("Validated input is: " + validatedInput);
}
public static String validateUserInput(String str) {
int dollarSignIndex = str.indexOf("$");
if(dollarSignIndex == 0) {
str = str.substring(1);
}
return str;
}
public static boolean isInteger(String str) {
try {
Integer.parseInt(str);
return true;
} catch (NumberFormatException e) {
return false;
}
}
You could use one of:
downPayment = Integer.parseInt(keyboardIn.next().replace("$",""));
downPayment = Integer.parseInt(keyboardIn.next().substring(1));
But I don't know if it's the "best way".
If you really must keep your nextInt(), you can catch the exception:
try {
downPayment = keyboardIn.nextInt();
} catch (InputMismatchException ex) {
// handle it
downPayment = Integer.parseInt(keyboardIn.next().replace("$",""));
}
But I don't think it's generally advised to handle any RuntimeException.
A few days ago i posted a topic about if/else and while loops.
I have gotten a bit further and now made a little program to guess a number.
I would like to implement a feature to check if the user has an empty input but i cannot seem to figure it out!
Is there anyone who can help me a bit? Im still a pretty early beginner at JAVA.
Here is my current code:
import java.util.Scanner;
import javax.swing.JOptionPane;
/**
*
* #author henluu
*/
public class Practice {
public static void main(String[] args) {
//create new scanner
Scanner input = new Scanner(System.in);
int raad = 0;
raad = Integer.parseInt(JOptionPane.showInputDialog("Guess the number"));
while (Practice.rn() != raad) {
JOptionPane.showMessageDialog( null, ("Your number is not the same as the random number"));
raad = Integer.parseInt(JOptionPane.showInputDialog("Guess the number"));
//empty check
if (raad == " ") {
Integer.parseInt(JOptionPane.showInputDialog("No Input"));
}
}
JOptionPane.showMessageDialog( null, ("You guesse dit right! The number was: ") + Practice.rn());
}
//method to generate random number
public static int rn() {
int random = (int) Math.floor((Math.random() * 10) + 1);
return random;
}
}
The point is: that JOptionPane is returning a string to you.
You could do something like:
private int fetchIntFromString(String userInput) {
if (userInput.isEmpty()) {
throw new IllegalArgumentException("input must not be empty");
}
return Integer.parseInt(userInput);
}
to be used like:
try {
raad = fetchIntFromString(JOptionPane.show...
} catch (Exception e) {
... give some error message
In other words: when the user gives a number, it is simply turned into a numeric value and returned. If the user input is empty or can't be parsed as number, an exception is thrown; which needs to be caught within the method that calls fetchIntFromString()
Since you are learning i'm not going show you the standard library solutions, but a solution that is library independant and allows you to grasp some logic points to check.
See the comments in the code below.
public boolean isNumeric(String input) {
// First trim input of trailing spaces
input = input.trim();
// test on 0 length
if(input.length == 0) {
return false;
}
// Loop through all characters to test
// if they are valid
for(char c : input.toCharArray()) {
if (!Character.isDigit(c)) return false;
}
return true;
}
You can then call it like this.
if(this.isNumeric(raad)) {
// your code here
}
Further more, learn about the single responsiblity principle.
There are some serious flaws in your code. I'd suggest you post it also on code review to get some useful pointers where to learn.
I am required to create a method that prompts user to input three words and then it has to store the data in an array. The method should then print the three lines in reverse so for example word OVER would come out as REVO.
I have got it done sort of however I don't know how to get the other 2 lines to work. As it is, only the first user input gets reversed.
Here is the code so far;
import java.io.*;
public class Average {
public static void main (String[] args) throws IOException {
BufferedReader getit;
getit = new BufferedReader
(new InputStreamReader (System.in));
System.out.println ("Enter first line:");
System.out.flush ();
String text = getit.readLine();
while (true) {
System.out.println (reverse(text));
System.out.println("Enter 2nd line:");
System.out.flush ();
text = getit.readLine();
System.out.println("Enter 3rd line:");
System.out.flush ();
text = getit.readLine();
System.out.println("Finish");
break;
}
}
public static String reverse (String original) {
String reversed = "";
int pos = original.length() - 1;
while (pos >= 0) {
reversed = reversed + original.charAt(pos);
pos -= 1;
}
return reversed;
}
}
You called the function reverse just once. Try to call it every time you get a string.
What you are doing is, You took the first string as input and your program went into an loop near while(true) you printed the reverse of the string. You took two more strings.
Where are you reversing them? and the break at the end of the loop doesn't make sense.
you may remove the while loop and break and add call the reverse function. I am not writing any code as you could do it easily.
Write System.out.println (reverse(text)); after text = getit.readLine(); each time.
I have a homework assignment which requires input from the user and stores it in various data structures (arrays of linked-lists, stacks, etc.). However, I've been writing the main class of my previous homework assignments and this one in a very similar fashion. I have a very tiny main method. All the main method does is instantiate a new object which I don't want to be destroyed and then loop through the program forever until the user chooses otherwise. I then have a menu() method which prints a list of selections and reads the user's selection. And then from there, I pass that selection to another method which interprets the selection and performs accordingly.
The problem I have been having in the past assignments and now I've never really gotten a good answer for. The problem seems to lie with my menu() method and more specifically, the Scanner object. There always seems to be some junk left in the stream after I call the nextLine() method on a scanner object. So the next time the menu() method is called, it reads in that junk and loops though the rest of the program with that junk until menu() is called a third time. In the past, I would remedy this by calling the next() method right after I received my input and ignoring it. However, I seem to be having issues with that now as well.
In this program in particular, I have a method which request's a user enter a city name. Now, city names can be more than one word (Palm City, West Palm Beach, Satellite Beach, New York, etc.). Now, when the scanner reads in one of those multi-word cities, it does the same thing as before, reads in some junk the next time the menu() method is called and goes though the whole program with it until menu() is called again. In this case, it prints an string "Invalid Selection" and then prints the menu again. I can't for the life of me figure out what's going on. any help would be appreciated.
import java.util.Scanner;
public class CSAir
{
public static Scanner input = new Scanner(System.in);
public static void main(String[] args)
{
CityList flightLog = new CityList();
boolean loop = true;
while(loop)
{
loop = actions(menu(),flightLog);
}
}
private static String menu()
{
System.out.print("Please Make a Selection\n" +
"I) Insert a city\n" +
"A)Add a flight path (One Way)\n" +
"R) Request a flight\n" +
"L) Load from a text file\n" +
"Q) Quit\n" +
"\nSelection: ");
String in = input.next();
//input.next();
System.out.println();
return in;
}
private static boolean actions(String selection, CityList flightLog)
{
if(selection.equalsIgnoreCase("I"))
{
insert(flightLog);
return true;
}
else if(selection.equalsIgnoreCase("A"))
{
add(flightLog);
return true;
}
else if(selection.equalsIgnoreCase("R"))
{
request(flightLog);
return true;
}
else if(selection.equalsIgnoreCase("L"))
{
return true;
}
else if(selection.equalsIgnoreCase("Q")) return false;
else
{
System.out.println("Invalid Selection!\n");
return true;
}
}
private static void request(CityList flightLog)
{
System.out.print("Origin: ");
String origin = input.nextLine();
System.out.print("\nDestination: ");
try
{
flightLog.isPath(origin, input.next());
}
catch (AllDestinationsVisitedException e)
{
e.getMessage();
}
}
private static void add(CityList flightLog)
{
System.out.print("Origin: ");
String origin = input.nextLine();
System.out.print("\nDestination: ");
flightLog.addPath(origin, input.next());
}
private static void insert(CityList flightLog)
{
System.out.print("Enter a City: ");
try
{
flightLog.addCity(input.next());
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
System.out.println();
}
}
Default Deliminator for scanner is white space. So when you enter New York since it has white space now scanner treats it as two tokens if you call next().
A better option would be to use nextLine() method for reading such values.