Java Question:
I want to take an undetermined number of lines of input from a user. For instance, I want the user to continue entering names of people as strings until the user has no other names to enter. I want a user-friendly way to easily indicate that the user has no more input. The loop may look like the following. Any good ideas? Any tips on improving the snippet of code is appreciated as well.
BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
while( <user still has more input> ) {
System.out.println("Enter name: ");
String s = read.readLine();
...
<do something with s>;
...
}
thank you!
You need a value that isn't a name but indicates no more data. An empty line would be good. You also want to query if they really want to quit, so in case they accidentally hit return they haven't lost all their data.
name = read.readLine();
Pattern p = Pattern.compile("^\\s$"); //empty line or one of just space chareacters
if (p.matcher(name).matches()) {
System.out.println("Are you done?[y/n]");
if (Pattern.matches("[yY]", read.readLine()) {
//quit your loop
}
}
You could have a boolean variable, such as finished, and check if the user enters 'Q' or another item to indicate that they are finished. If so, set finished to true and you will exit your loop on the next iteration.
Here is a quick example,
boolean finished = false;
String name = null; // initialized to a default value.
System.out.println("Enter 'Q' to quit");
while(!finished) {
System.out.println("Enter name: ");
name = read.readLine(); // moved declaration outside of loop
if(name.equals("Q")) {
finished = true;
}
// do work with name
}
I have also modified your code a bit,
I have added a message to the user to indicate what terminates the input.
I have renamed your variable s to something more meaningful, because you are storing the user's name it seemed reasonable to change it to name.
As a force of habit, I have also initialized my variables with default values, so I assigned the name variable to null. Not totally necessary, but I consider it good practice.
Since I have assigned name a default value, I have moved it outside of your loop.
A simple way is to have users enter an empty line when they are done. You'd just check if line.equals("") or maybe trim it before.
Related
Why doesn't the method hasNextLine() work in Netbeans 8.1? When I press ctrl+z or ctrl+d nothing happens.Thanks
while (kb.hasNextLine()) {
String str = kb.nextLine();//reads the transaction
//isVallid checks if the transaction is valid
if (!isValid(str)) {
throw new IllegalArgumentException("The transaction is not valid");
}
int x, y;//the valuse of x and y
x = getX(str);//recognize and convert the valu of x to integer.
y = getY(str);//recognize and convert the valu of y to integer.
if (buyOrSell(str))//buyOrSell can recongnoize we buy or we sell.
{
justAddToQueueu(myQueue, x, y);// buy
} else {
capitalGain += removeAndCalculate(myQueue, x, y);// sell
}
System.out.println("Please enter the next valid transaction:"
+ "\nor press ctrl+D(ctrl+Z for mac) for exit.");
//for exit you can press ctrl+D (or
Please note that due to the OP creating a moving target question, this answer is no longer applicable.
The reason is once you call the hasNextLine, it passes that and won't go back to it. So the String str=kb.nextLine(); is now looking past that. Also, keep in mind the scope of a variable is inside the brackets it's declared in. So your 'str' isn't accessible in the rest of the program. What you'll have to do is something like this:
String check;
String str = "";
while(true){
check = kb.nextLine();
if (check.matches("^.+"))
str += check;
else
break;
}
Assuming, of course, that the purpose of your while loop was to accumulate all the user input into one String. If not, just remove the + from the +=.
Hope this helps!
I think you cound be use hasNext() rather than hasNextLine(). this is the reason :
You did not specify which version of hasNext() you meant, but basically, as long as there is another token in the data source that the scanner has encapsulated, hasNext() returns true.hasNextLine() on the other hand returns true if there is another line of input available, not just another token.
Trying to print a file based off the user's input as mentioned in the title. Basically, my program has been altered from one that I previously created which reads data from a file, so I know that the file has been imported correctly (not the problem).
The problem I have is that I'm trying to make the program print the entirety of the .txt file if the user chooses a specific number, in this case '1'. My current code so far is:
import java.io.FileReader;
import java.util.Scanner;
public class InputOutput {
public static void main(String[] args) throws Exception {
// these will never change (be re-assigned)
final Scanner S = new Scanner(System.in);
final Scanner INPUT = new Scanner(new FileReader("C:\\Users\\JakeWork\\workspace\\Coursework\\input.txt"));
System.out.print("-- MENU -- \n");
System.out.print("1: Blahblahblah \n");
System.out.print("2: Blahblahblah \n");
System.out.print("Q: Blahblahblah \n");
System.out.print("Pick an option: ");
if (S.nextInt() == 1) {
String num = INPUT.nextLine();
System.out.println(num);
}
I feel as if my if statement is totally off and I'm heading in the entire wrong direction, could anyone point me in the right and give me a helping hand?
You're close, but not quite there.
You a reading the user input correctly, but now you need the file contents in a loop.
if(S.nextInt() == 1) {
while (INPUT.hasNextLine()) {
System.out.println(INPUT.nextLine());
}
}
This will keep looking as long as the file contents hasNextLine
You can safely remove the String option = S.next();
Also, just a small bit of naming convention nitpicking, don't use all upper case letters for variable names unless they are meant to be static. Also, the first letter of a variable is generally lower case.
if (S.nextInt() == 1) {
// check if there is input ,if true print it
while((INPUT.hasNextLine())
System.out.println(INPUT.nextLine());
}
Also, for menu scenarios like this, consider using a switch statement, then place a call to the menu-printing (that you move to a separate method) in the default case, so that if you enter something wrong, you can reprint the menu choices. Also, the switch statement is more readable (arguably) than a bunch of if's, like this:
int option = S.nextInt();
switch(option) {
case 1 :
while(INPUT.hasNextLine()) {
System.out.println(INPUT.nextLine());
}
break;
case 2 :
//Do stuff
break;
default :
//Default case, reprint menu?
}
}
I'm currently doing a project in my computer science class and we are suppose to validate each character of a variable to see if it is legal or not. If it starts with a number it's illegal. If it starts with a special character it's legal but bad style. If it has a space it is again illegal. I'll post my current code now:
import java.util.Scanner;
public class classOfValidation {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String theVariable = null;
System.out.println("This program checks the validity of variables");
System.out.println("Please enter a variable (or press 'q' to quit");
theVariable = scan.nextLine();
do {
System.out.println("The variable is illegal");
theVariable = scan.nextLine();
} while (theVariable.startsWith("[0123456789]"));
do {
System.out.println("The variable is illegal");
theVariable = scan.nextLine();
} while (theVariable.contains("[ ]"));
do {
System.out.println("The variable is legal, but has bad style");
theVariable = scan.nextLine();
} while (theVariable.startsWith("[!##$%^&*]"));
}
}
If you couldn't already tell i'm new to programming and as confused as i possibly could be. If you have any advice or anything else you need me to explain then please leave a comment. Thanks everyone
You can use the single regex to validate your input via String#matches() method. But as for the example you've provided, you should use while loop, but not do-while, because in do while case, you are always running it's body once befor condition checked. So, you better do it like:
theVariable = scan.nextLine();
while (theVariable.startsWith("[0123456789]")) {
System.out.println("The variable is illegal");
theVariable = scan.nextLine();
}
while (theVariable.contains("[ ]")) {
System.out.println("The variable is illegal");
theVariable = scan.nextLine();
}
while (theVariable.startsWith("[!##$%^&*]")) {
System.out.println("The variable is legal, but has bad style");
theVariable = scan.nextLine();
}
The second, in your solution, you are using String.startsWith() method and passing into it some regex. Take a look at javadoc for this method. It's said there:
Tests if this string starts with the specified prefix.
That means, that this method doesn't support regexes, but simply checks whether the string starts with the passed string. So, your conditions seems, never to become true. I don't think, someone will input the [0123456789] or [!##$%^&*].
One more, any conditions are checked once, but after that user can modify the input and the previewsly passed condition will not be checked again. Seems, it's better to run into infinite loop with continue and break in some conditions, like:
//infinit loop, until user enter the `q` or the input is correct
while (true) {
//read the input
theVariable = scan.nextLine();
//chtck, whether is `quit` command entered
if ("q".equals(theVariable)) {
break;
}
//if string starts with digit or contains some whitespaces
//then print alert and let the user to
//modify the input in a new iteration
if (theVariable.matches("^\d+.*|.*\s+.*")) {
System.out.println("The variable is illegal");
continue;
}
//if string contains some special characters print alert
//and let the user to modify the input in a new iteration
if (theVariable.matches("^[!##$%^&*].*")) {
System.out.println("The variable is legal, but has bad style");
continue;
}
//if all the conditions checked, then break the loop
break;
}
I think the best way if you are use regex.
Here is an answer how to do that.
I want to read user input like: 11 12 13 14 15 16
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
System.out.println(sc.next());
}
System.out.println("Test");
but it newer goes out of while loop and prints "Test".
How could i read that input?
The method hasNext() works like this:
If it sees the end of the file, it returns false;
If it sees another valid, non-whitespace input, it returns true;
If neither of the above is true, it waits for the next input the user is going to enter, and doesn't return until he does.
Usually, if you use Scanner for files, such a loop will work correctly, because a file has a definite end, and it usually doesn't get stuck waiting for more input.
But when you are working with console input (System.in, not redirected), then usually the user does not send the end-of-file signal. He just presses Return, and so, hasNext() sits and waits to see if the user will enter more input on the next line and so on.
There are two general ways to deal with this:
The user has to actually terminate the input. After you finish entering all your numbers and press Return, you also need to send the end-of-file sequence, which is usually ctrlD or ctrlZ.
If you do that, you will not be able to enter any more input to that program.
The program tells the user to enter some particular value that will tell it that the input is over. For example, the string "DONE". When you do that, you have to change the loop to something like:
String nextInput;
while( sc.hasNext() && ! (nextInput = sc.next()).equals( "DONE" ) ){
System.out.println(nextInput);
}
You can break the loop depending whether you want to quit or not E.g.
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String next = sc.next();
if (next.equals("q")) { //if user press q then break the loop
break;
}
System.out.println(next);
}
System.out.println("Test");
}
Use api like:
while(sc.hasNextInt()){
int aba= sc.nextInt();
if (aba == 0) {//or even non numeric value here would let this loop exit
break;
}
}
So you need to enter 0 or even in other way enter non numeric value inorder to come out of loop. nextLine method will read whole line just once and then you will need to parse it and then convert to integer so it's good to use sc.nextInt which will do the work for you.
I'm having trouble with passing a string and double to another class because it keeps on crashing at double cost = input.nextDouble();. Also, i was wondering if i am correct with the appending method used in public boolean addPARTDETAILS(String partDESCRIPTION, double partCOST).
For example. If the user enters the parts and cost, i want it to store that in a list and print it out with the cost appended.
Parts used:
brake pads ($50.00)
brake fluids ($25.00)
Note. Assuming that i have declared all variables and the array.
System.out.print("Enter registration number of vehicle");
String inputREGO = input.next();
boolean flag = false;
for(int i=0; i<6; i++){
if(inputREGO.equalsIgnoreCase(services[i].getregoNUMBER())){
System.out.print("Enter Part Description: ");
String parts = input.nextLine();
double cost = input.nextDouble();
services[i].addPARTDETAILS(parts, cost);
//System.out.println(services[i].getregoNUMBER());
flag = true;
}
}if(flag==false);
System.out.println("No registration number were found in the system.");
public boolean addPARTDETAILS(String partDESCRIPTION, double partCOST){
if(partDESCRIPTION == "" || partCOST <= 0){
System.out.println("Invalid input, please try again!");
return false;
}
else{
partCOST=0;
StringBuffer sb = new StringBuffer(40);
String[] parts = new String[50];
for (int i=0;i<parts.length;i++){
partDESCRIPTION = sb.append(partCOST).toString();
}
System.out.println(partDESCRIPTION);
totalPART+=partCOST;
return true;
}
}
it keeps on crashing at double cost = input.nextDouble();.
It is highly unlikely that your JVM is crashing. It is far more likely that you are getting an Exception which you are not reading carefully enough and have forgotten to include in your question.
It is far more likely your code is incorrect as you may have mis-understood how scanner works. And so when you attempt to read a double, there is not a double in the input. I suspect you want to call nextLine() after readDouble() to consume the rest of the the line.
I suggest you step through the code in your debugger to get a better understanding of what it is really doing.
Just to expand a bit on Joop Eggen's and Peter Lawrey's answers because I feel some may not understand.
nextLine doesn't play well with others:
nextDouble is likely throwing a NumberFormatException because:
next, nextInt, nextDouble, etc. won't read the following end-of-line character, so nextLine will read the rest of the line and nextDouble will read the wrong thing.
Example: (| indicates current position)
Start:
|abc
123
def
456
After nextLine:
abc
|123
def
456
After nextDouble:
abc
123|
def
456
After nextLine (which reads the rest of the line, which contains nothing):
abc
123
|def
456
Now nextDouble tries to read "def", which won't work.
If-statement issues:
if(flag==false);
or, rewritten:
if(flag==false)
;
is an if statement with an empty body. Thus the statement following will always execute. And no need to do == false, !flag means the same. What you want:
if (!flag)
System.out.println("No registration number were found in the system.");
String comparison with ==:
partDESCRIPTION == ""
should be:
partDESCRIPTION.equals("")
or better:
partDESCRIPTION.isEmpty()
because == check whether the strings actually point to the exact same object (which won't happen unless you assign the one to the other with = at some point, either directly or indirectly), not just whether the have the same text (which is what equals is for).
Data dependent error.
if(flag==false);
System.out.println("No registration number were found in the system.");
should be (because of the ;):
if (!flag) {
System.out.println("No registration number was found in the system.");
}
And
partDESCRIPTION == ""
should be:
partDESCRIPTION.isEmpty()