I have a basic greeting program that is supposed to come up with a response based on the user's input. I am trying to accomplish it using for loops; however, whenever the user replies with the "bad" or "you" values stored in different arrays, the console prints out the same response multiple times. How could this problem be approached?
I'm a noob here, and in java.
I apologize if this answer has been previously answered. I searched but couldn't find.
Thank you for your time.
import java.util.Scanner;
public class Greeter {
public static void main(String[] args) {
String[] greetings = { "well", "good", "great", "awesome", "fabulous" };
String[] bad_greetings = { "bad", "awful" };
String[] responses = { "you", "yourself" };
System.out.println("Hello there, how are you?");
String response;
Scanner scan = new Scanner(System.in);
response = scan.nextLine();
for (String greeting : greetings) {
if (response.contains(greeting)) {
System.out.println("Well, good for you!");
}
for (String b_greet : bad_greetings) {
if (response.contains(b_greet)) {
System.out.println("At least you have me.");
}
}
for (String reply : responses) {
if (response.contains(reply)) {
System.out.println("I'm well, thank you.");
// } else {
// System.out.println("Let's move on then.");
// }
}
}
}
}
}
Change yout Main(). Your problem was that you have bad } for first loop also I recommand you break the cycle (or instead of break use return; from function) cause it is not neccesary to run all cycle if you already find your answer.
public static void main(String[] args) {
String[] greetings = {"well", "good", "great", "awesome", "fabulous"};
String[] bad_greetings = {"bad", "awful"};
String[] responses = {"you", "yourself"};
System.out.println("Hello there, how are you?");
String response;
Scanner scan = new Scanner(System.in);
response = scan.nextLine();
for (String greeting : greetings) {
if (response.contains(greeting)) {
System.out.println("Well, good for you!");
break;//return;
}
}
for (String b_greet : bad_greetings) {
if (response.contains(b_greet)) {
System.out.println("At least you have me.");
break;//return;
}
}
for (String reply : responses) {
if (response.contains(reply)) {
System.out.println("I'm well, thank you.");
break;//return;
// } else {
// System.out.println("Let's move on then.");
// }
}
}
}
Milkmaid's answer is correct. To further elaborate on his response is that you are going to print your response 5 times (one for each item in your "greetings" array).
I can think of three options to solve your problem:
keep what you have now, but use a break; statement to discontinue the for loop.
Split up your for loops as Milkmaid did and include the break.
Change your array to a list instead which has a built in "contains" method.
How can I test if an array contains a certain value?
option 3 would be the cleanest :) You can convert it on the fly or just start with a list altogether. Seems like your program can just start with a list though.
You can try below
public static void main(String[] args) {
String[] greetings = {"well", "good", "great", "awesome", "fabulous"};
String[] bad_greetings = {"bad", "awful"};
String[] responses = {"you", "yourself"};
System.out.println("Hello there, how are you?");
String response;
Scanner scan = new Scanner(System.in);
response = scan.nextLine();
if(Arrays.asList(greetings).contains(response)){
System.out.println("Well, good for you!");
break;//return;
}
if(Arrays.asList(bad_greetings).contains(response)){
System.out.println("At least you have me.");
break;//return;
}
if(Arrays.asList(responses).contains(response)){
System.out.println("I'm well, thank you.");
break;//return;
}
// } else {
// System.out.println("Let's move on then.");
// }
}
Related
I need help developing my text message abbreviation decoder I'm trying to put together. The first part of the program should do this: "If a user's input string matches a known text message abbreviation, output the unabbreviated form, else output: Unknown. Support two abbreviations: LOL -- laughing out loud, and IDK -- I don't know." Then: "Expand to also decode these abbreviations. BFF -- best friends forever, IMHO -- in my humble opinion and TMI -- too much information.
This is the code I have so far:
import java.util.Scanner;
public class TextMsgAbbreviation {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String textMsg = "";
{
String BFF = "best friends forever";
String IMHO = "in my humble opinion";
String TMI = "too much information";
String LOL = "laughing out loud";
String IDK = "i don't care";
System.out.println("Input an abbreviation:" + " ");
textMsg = input.next();
if (textMsg.compareTo("LOL") == 0) {
System.out.println(LOL);
} else if (textMsg.compareTo("IDK") == 0) {
System.out.println(IDK);
} else if (textMsg.compareTo("BFF") == 0) {
System.out.println(BFF);
} else if (textMsg.compareTo("IMHO") == 0) {
}
}
}
}
This is the output I get:
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1371)
at TextMsgAbbreviation.main(TextMsgAbbreviation.java:17)
What am I doing wrong?
According to the Java API docs, the next() method throws a NoSuchElementException when there aren't any more tokens available to be read. So, it is recommended to call the hasNext() method before calling the next() method in Scanner class to make sure that there is a token available to be read. So, try something like below :
if(input.hasNext()) {
textMsg = input.next();
}
On a side-note, from Java 7 onwards, the switch statements can take a String input, so you may try using that in your code. In my personal opinion, it will be more readable than using the multiple if-else loops.
An example :
switch(textMsg) {
case "LOL" : System.out.println(LOL);
break;
case "IDK" : System.out.println(IDK);
break;
case "BFF" : System.out.println(BFF);
break;
case "IMHO": System.out.println(IMHO);
break;
default : System.out.println("Unknown");
}
The values displayed 862 1371 17 need to be typed into the input box.Below is working code for the problem.
import java.util.Scanner;
public class TextMsgDecoder {
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
String userInput;
System.out.println("Enter text:");
userInput = scnr.nextLine();
System.out.println("You entered: " + userInput);
if(userInput.indexOf("BFF") != -1) {
System.out.println("BFF: best friend forever");
}
if(userInput.indexOf("IDK") != -1) {
System.out.println("IDK: I don't know");
}
if(userInput.indexOf("JK") != -1) {
System.out.println("JK: just kidding");
}
if(userInput.indexOf("TMI") != -1) {
System.out.println("TMI: too much information");
}
if(userInput.indexOf("TTYL") != -1) {
System.out.println("TTYL: talk to you later");
}
}
}
I want to remove all special characters from a string,i tried many options which were given in stackoverflow, but none of them work for me.
here is my code :
public class convert {
public static void main(String[] args) {
try {
List<List<String>> outerList = new ArrayList<List<String>>();
outerList.add(new ArrayList<String>(asList("11-","2")));
outerList.add(new ArrayList<String>(asList("(2^","1")));
outerList.add(new ArrayList<String>(asList("11","3)")));
int i,j;
for(i=0;i<outerList.size();i++){
for(j=0;j<outerList.get(0).size();j++){
outerList.get(i).get(j).replaceAll("[^\\w\\s]", "");
if(outerList.get(i).get(j).matches("-?\\d+"){
continue;
}else{
System.out.println("special characters not removed");
System.exit(0);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
The (simple) error is that s.replaceAll(...) does not change s but yields a new changed string:
String s = outerList.get(i).get(j).replaceAll("[^\\w\\s]", "");
outerList.get(i).set(j, s);
in the case of not alphanumeric you can use
String value = "hello#() world";
value = value.replaceAll("[^A-Za-z0-9]", "");
System.out.println(value) // => helloworld
something similar has already been asked here
Use StringUtils at Apache Commons Lang (http://commons.apache.org/proper/commons-lang/):
http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html
Original Question
For the following small code I'm getting the error...
import java.io.*;
class test
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int i;
System.out.println("Enter no of processes ");
int no_of_process=Integer.parseInt(br.readLine());
int process[]=new int[no_of_process];
System.out.println("Enter the values");
for(i=0;i<no_of_process;i++)
process[i]=Integer.parseInt(br.readLine());
for(i=0;i<no_of_process;i++)
System.out.println(process[i]);
}
}
Input:
Enter no of processes
5
Enter the values
1
2
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Integer.parseInt(Integer.java:470)
at java.lang.Integer.parseInt(Integer.java:499)
at test.main(test.java:17)
Process completed.
I think I have written the code properly and proper integer input is also given. How do I get rid of the above error without using any explicit exception handling statements?
Further Question:
Thanks guys for your answers...it is working. But there is one new question in my mind.
I tried the following modification in the code and executed it. To my surprise, input was accepted properly without any run time error.
for(i=0;i<no_of_process;i++)
{
System.out.println(Write anything or even keep it blank);
process[i]=Integer.parseInt(br.readLine());
}
By adding just one Print statement before (or even after) the input statement in the for loop, my program worked correctly and no exception was thrown while giving input.
Can you guys explain the reason behind this?
Again if I remove the Print statement from there, the same error gets repeated. I am really confused about the reason behind this. Please help.
Without any error handling statements? check to see if br.readLine() is returning "" before you attempt to parse it, like so:
String line = br.readLine();
if(!String.isEmpty(line))
{
//Do stuff
}
else
{
//Do other stuff
}
How to get rid of above error without using any explicit exception handling statements?
for (i = 0; i < no_of_process; i++) {
String input;
do {
input = br.readLine();
if (isInteger(input)) {
process[i]=Integer.parseInt(input);
} else {
//error handling here
System.err.println("you entered an invalid input");
}
} while(isInteger(input));
}
And isIntegerlooks like this:
public static boolean isInteger(String s)
{
try {
Integer.parseInt(s);
}
catch (Exception e) {
return false;
}
return true;
}
I think I have written properly and proper integer input is also given.
I think not ;) i think you pressed the return with out typing anything
Try this:
import java.io.*;
public class test
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int i;
System.out.println("Enter no of processes ");
try{
int no_of_process=Integer.parseInt(br.readLine());
int process[]=new int[no_of_process];
System.out.println("Enter the values");
for(i=0;i<no_of_process;i++)
process[i]=Integer.parseInt(br.readLine());
for(i=0;i<no_of_process;i++)
System.out.println(process[i]);
}
catch(NumberFormatException n)
{
System.out.println(n.getMessage());
}
}
}
This question already has answers here:
How to check if a String is numeric in Java
(41 answers)
Closed 5 years ago.
I have conversion to Map problem in Core Java.
Below is requirement:
Given a String array below
String str[] = {"abc","123","def","456","ghi","789","lmn","101112","opq"};
Convert it into a Map such that the resultant output is below
Output
====== ======
key Value
====== ======
abc true
123 false
def true
456 false
The above should be printed for each element in the array. I have written the code but it's not working and I'm stuck. Please let me know how it can be resolved. Thanks in advance.
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class CoversionToMap {
/**
* #param args
*/
public static void main(String[] args) {
String str[] = {"abc","123","def","456","ghi","789","lmn","101112","opq"};
Map m = new HashMap();
for(int i=0;i<str.length;i++){
if(Integer.parseInt(str[i]) < 0){
m.put(str[i],true);
}else{
m.put(str[i],false);
}
}
//Print the map values finally
printMap(m);
}
public static void printMap(Map mp) {
Iterator it = mp.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
System.out.println(pairs.getKey() + " = " + pairs.getValue());
}
}
}
exception:
Exception in thread "main" java.lang.NumberFormatException: For input string: "abc"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at CoversionToMap.main(CoversionToMap.java:22)
Everyone is suggesting using exception handling for this, there is nothing exceptional here to warrant using exceptions like this, you don't try turning left in your car and if you crash go right do you? Something like this should do it
Map<String, Boolean> m = new HashMap<String, Boolean>();
for (String str: strs) {
m.put(str, isInteger(str));
}
public boolean isInteger(String str) {
int size = str.length();
for (int i = 0; i < size; i++) {
if (!Character.isDigit(str.charAt(i))) {
return false;
}
}
return size > 0;
}
Much clearer and more efficient that catching throwing exception, even when there are 99% integers as the integer value is not even needed so no conversion required.
Integer.parseInt(..) throws an exception for invalid input.
Your if clause should look like this:
if (isNumber(str[i])) {
...
} else {
...
}
Where isNumber can be implemented in multiple ways. For example:
using try { Integer.parseInt(..) } catch (NumberFormatException ex) (see this related question)
using commons-lang NumberUtils.isNumber(..)
You check if parseInt returns a number smaller than 0 to see if the input is non-numeric.
However, that method doesn't return any value at all, if the input is non-numeric. Instead it throws an exception, as you have seen.
The simplest way to do what you want is to catch that exception and act accordingly:
try {
Integer.parseInt(str[i]);
// str[i] is numeric
} catch (NumberFormatException ignored) {
// str[i] is not numeric
}
If you want to check if the string is a valid Java number you can use the method isNumber from the org.apache.commons.lang.math (doc here: http://commons.apache.org/lang/api-2.4/org/apache/commons/lang/math/NumberUtils.html).
This way you won't have to write your own implementation of isNumber
You need to use a try/catch block instead of testing the return value for parseInt.
try {
Integer.parseInt(str[i]);
m.put(str[i],true);
} catch(NumberFormatException e) {
m.put(str[i],false);
}
Your error occurs here:
if(Integer.parseInt(str[i]) < 0){
Integer.parseInt throws a NumberFormatException when the input isn't a number, so you need to use a try/catch block, for example:
try{
int number = Integer.parseInt(str[i]);
m.put(str[i],false);
}catch NumberFormatException nfe{
m.put(str[i],true);
}
Assuming you won't use any external libraries, you can also use a Regular Expression Matcher to do that. Just like
for (String element : str) {
m.put(element, element.matches("\\d+"));
}
Note that this works only with non-negative integers, but you can adapt the regular expression to match the number formats you want to map as true. Also, if element is null, you'll get a NullPointerException, so a little defensive code is required here.
Here is an improved answer which can be used for numbers with negative value, decimal points etc. It uses Regular Expressions.
Here it it:
public class StringValidator {
public static void printMap(Map<String, Boolean> map) {
Iterator it = map.entrySet().iterator();
for(Map.Entry<String, Boolean> entry:map.entrySet()){
System.out.println(entry.getKey()+" = "+ entry.getValue());
}
}
}
class ValidateArray{
public static void main(String[] args) {
String str[] = {"abcd", "123", "101.112", "-1.54774"};
Map<String, Boolean> m = new HashMap<String, Boolean>();
for (String s : str) {
m.put(s, isNumber(s));
}
StringValidator.printMap(m);
}
public static boolean isNumber(String str) {
Pattern pattern = Pattern.compile("^-?\\d+\\.?\\d*$");
Matcher matcher = pattern.matcher(str);
return matcher.matches();
}
}
Replace your parseInt line with a call to isInteger(str[i]) where isInteger is defined by:
public static boolean isInteger(String text) {
try {
new Integer(text);
return true;
} catch (NumberFormatException e) {
return false;
}
}
I would like to enter the contrary view on 'don't use exception handling' here. The following code:
try
{
InputStream in = new FileInputStream(file);
}
catch (FileNotFoundException exc)
{
// ...
}
is entirely equivalent to:
if (!file.exists())
{
// ...
}
else
try
{
InputStream in = new FileInputStream(file);
}
catch (FileNotFoundException exc)
{
// ...
}
except that in the former case:
The existence of the file is only checked once
There is no timing-window between the two checks during which things can change.
The processing at // ... is only programmed once.
So you don't see code like the second case. At least you shouldn't.
The present case is identical except that because it's a String there is no timing window. Integer.parseInt() has to check the input for validity anyway, and it throws an exception which must be caught somewhere anyway (unless you like RTEs stopping your threads). So why do everything twice?
The counter-argument that you shouldn't use exceptions for normal flow control just begs the question. Is it normal flow control? or is it an error in the input? [In fact I've always understood that principle to mean more specifically 'don't throw exceptions to your own code' within the method, and even then there are rare cases when it's the best answer. I'm not a fan of blanket rules of any kind.]
Another example detecting EOF on an ObjectInputStream. You do it by catching EOFException. There is no other way apart from prefixing a count to the stream, which is a design change and a format change. So, is EOF part of the normal flow, or is it an exception? and how can it be part of the normal flow given that it is only reported via an exception?
Here's a more general way to validate, avoiding exceptions, and using what the Format subclasses already know. For example the SimpleDateFormat knows that Feb 31 is not valid, as long as you tell it not to be lenient.
import java.text.Format;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
public class ValidatesByParsePosition {
private static NumberFormat _numFormat = NumberFormat.getInstance();
private static SimpleDateFormat _dateFormat = new SimpleDateFormat(
"MM/dd/yyyy");
public static void printMap(Map<String, Boolean> map) {
for (Map.Entry<String, Boolean> entry : map.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
public static void main(String[] args) {
System.out.println("Validating Nums with ParsePosition:");
String numStrings[] = { "abcd", "123", "101.112", "-1.54774", "1.40t3" };
Map<String, Boolean> rslts = new HashMap<String, Boolean>();
for (String s : numStrings) {
rslts.put(s, isOk(_numFormat, s));
}
ValidatesByParsePosition.printMap(rslts);
System.out.println("\nValidating dates with ParsePosition:");
String dateStrings[] = { "3/11/1952", "02/31/2013", "03/14/2014",
"05/25/2014", "3/uncle george/2015" };
rslts = new HashMap<String, Boolean>();
_dateFormat.setLenient(false);
for (String s : dateStrings) {
rslts.put(s, isOk(_dateFormat, s));
}
ValidatesByParsePosition.printMap(rslts);
}
public static boolean isOk(Format format, String str) {
boolean isOK = true;
int errorIndx = -1;
int parseIndx = 0;
ParsePosition pos = new ParsePosition(parseIndx);
while (isOK && parseIndx < str.length() - 1) {
format.parseObject(str, pos);
parseIndx = pos.getIndex();
errorIndx = pos.getErrorIndex();
isOK = errorIndx < 0;
}
if (!isOK) {
System.out.println("value \"" + str
+ "\" not parsed; error at char index " + errorIndx);
}
return isOK;
}
}
boolean intVal = false;
for(int i=0;i<str.length;i++) {
intVal = false;
try {
if (Integer.parseInt(str[i]) > 0) {
intVal = true;
}
} catch (java.lang.NumberFormatException e) {
intVal = false;
}
m.put(str[i], !intVal);
}
I'm a beginner, so please don't blast my work so far :)
I'm trying to read in a CSV file and then see if it matches certain commands. Some of the data in the CSV has a period and I think it's messing up when I'm trying to split it. When I try to dump my arrays to see what's there, it always gets cut off after the period. Here is a data sample. Any help would be appreciated. Again I'm a beginner so simplicity would be appreciated.
Sample data
create,Mr. Jones,blah,blah
create,Mrs. Smith,blah,blah
public class TestHarness {
public static void main(String[] args) throws IOException, FileNotFoundException {
Scanner input = new Scanner(new File("C:\\Users\\Ree\\Desktop\\SPR\\commands.txt"));
String[] validCommands = { "create", "move", "useWeapon", "search", "heal" };
boolean proceed = false;
while (!proceed)
{
for (int i = 0; i < validCommands.length; i++)
{
String line = input.next();
String[] nline = line.split (",");
if (nline[0].equals("create"))
{
String soldierName = nline[1];
String soldierType = nline[2];
String weapon = nline[3];
Soldier aSoldier = new Soldier(soldierName,weapon);
System.out.println("Command: "+ nline[0] +","+ soldierName +","+ soldierType+","+ weapon);
if (soldierType.equals("enlisted"))
{
Soldier s = new Enlisted(soldierName,weapon);
System.out.println(s.toString());
}
else if (soldierType.equals("officer"))
{
Soldier s = new Officer(soldierName,weapon);
System.out.println(s.toString());
}
}
else if (nline[0].equals("useWeapon")) {
System.out.print("weapon " + nline[0] + "\n");
}
else if (nline[0].equals("move")) {
System.out.print("move " + nline[0] + "\n");
}
else if (nline[0].equals("search")) {
System.out.print("search " + nline[0] + "\n");
}
else if (nline[0].equals("heal")) {
System.out.print("heal " + nline[0] + "\n");
}
}
}
}
}
Calling Scanner.next will only return the next word (separated by whitespace).
You need to call nextLine to read entire lines at a time.
There are several open source CSV parers available for Java:
http://supercsv.sourceforge.net/
http://commons.apache.org/sandbox/csv/
That was a rather quick mistake, wasn't it?
This is not an answer to your question but a recommendation to use a hash.
First define an interface
public interface InputDance
{
public void dance(String[] input);
}
I recommend that your main routine should be
public static void main(String[] args)
throws IOException, FileNotFoundException{
Scanner input = new Scanner(
new File("C:\\Users\\Ree\\Desktop\\SPR\\commands.txt"));
String line = input.nextLine();
String[] nline = line.split (",");
InputDance inputxn = inputActions.get(nline[0]);
if (inputxn!=null)
inputxn.dance(nline);
}
You would be using a hash to store all the actions outlined by the interface InputDance.
So that your input reading routine would be simplified to
retrieve action from hash of actions
using word0 of input as key.
execute that action
If you have only five types of soldiers, it would ok to place all your logic in one routine.
However, for more than 10 types of personnel, it would be cleaner to place the actions outside the routine.
If you are writing a computer game, or keeping personnel records on a military database, you would frequently encounter enhancement requests to include new personnel types or exceptions to the rule. Then your if-then-else-if chain would become increasingly longer and confusing. Especially when there are special requirements for soldiers dancing to a different tune. Or when your game canvas or personnel database needs to include non-battle units. But, of course, you still need to update the hash in the main class every time you have a new personnel type.
Notice that in my recommendation all your routine would do is to perform the dance(String[]) method. Any complication would be handled by the individual class implementing the dance.
Next define an implementing class
public class SoldierDance
implements InputDance
{
public void dance(String[] nline){
String soldierName = nline[1];
String soldierType = nline[2];
String weapon = nline[3];
System.out.println(
"Command: "+ nline[0] +","+ soldierName +","+ soldierType+","+ weapon);
Soldier s;
if (soldierType.equals("enlisted")){
s = new Enlisted(soldierName,weapon);
}
else if (soldierType.equals("officer")){
s = new Officer(soldierName,weapon);
}
else{
s = new Soldier(soldierName,weapon);
}
System.out.println(s.toString());
}
}
Then define your main class. Notice that the hash is a static instance.
Also, there is a placeholder dance so that when you have a new personnel type, but you don't know what to do with it yet, you just hash the new personnel type to this placeholder dance.
Notice, for example in the "useWeapon" hash key, that an interface can be implemented anonymously too
public class TestHarness
{
static public class PlaceHolderDance
implements InputDance
{
public void dance(String[] nline){
System.out.print("Action=" + nline[0] + "\n");
}
}
static public Hashtable<String, InputDance> inputActions;
// A static enclosure is to execute all the class definition once.
static {
inputActions = new Hashtable<String, InputDance>();
InputDance placeHolderAction = new PlaceHolderDance();
inputActions.put("create", new SoldierDance());
inputActions.put("move", placeHolderAction);
inputActions.put("search", placeHolderAction);
inputActions.put("heal", placeHolderAction);
// Can also anonymously implement an interface
inputActions.put("useWeapon",
new InputDance(){
public void dance(String[] nline){
System.out.print("weapon " + nline[0] + "\n");
}
}
);
}
// The static main method
public static void main(String[] args)
throws IOException, FileNotFoundException{
Scanner input = new Scanner(
new File("C:\\Users\\Ree\\Desktop\\SPR\\commands.txt"));
String line = input.nextLine();
String[] nline = line.split (",");
InputDance inputxn = inputActions.get(nline[0]);
if (inputxn!=null)
inputxn.dance(nline);
}
}
And, if there is a one-one correspondence between a soldier class and its inputdance, you could even implement InputDance in the soldier class and provide the dance method.