How can I fix my code so it can input letters [duplicate] - java

This question already has answers here:
How to insist that a users input is an int?
(7 answers)
Closed 9 years ago.
So i'm just learning java and I know this issue is very stupid, this is from the book Head Frist Java. When I try to put a letter instead of a number it crashes, how do I fix that? If I want it to say "pleasse try again with a number" when letter is entered.
public class Game {
public static void main(String[] args)
{
int numOfGuesses = 0;
GameHelper helper = new GameHelper();
SimpleDotCom theDotCom = new SimpleDotCom();
int randomNum = (int) (Math.random() * 5);
int[] locations = {randomNum, randomNum+1, randomNum+2};
theDotCom.setLocationCells(locations);
boolean isAlive = true;
while (isAlive == true)
{
String guess = helper.getUserInput("enter a number");
String result = theDotCom.checkYourself(guess);
numOfGuesses++;
if (result.equals("kill")) {
isAlive = false;
System.out.println("You took " + numOfGuesses + " guesses");
}
}
}
}
public class GameHelper {
private static final String alphabet = "abcdefg";
private int gridLength = 7;
private int gridSize = 49;
private int [] grid = new int[gridSize];
private int comCount = 0;
public String getUserInput(String prompt) {
String inputLine = null;
System.out.print(prompt + " ");
try {
BufferedReader is = new BufferedReader(
new InputStreamReader(System.in));
inputLine = is.readLine();
if (inputLine.length() == 0 ) return null;
} catch (IOException e) {
System.out.println("IOException: " + e);
}
return inputLine.toLowerCase();
}
public class SimpleDotCom {
int[] locationCells;
int numOfHits = 0;
public void setLocationCells(int[] locs)
{
locationCells = locs;
}
public String checkYourself(String stringGuess) {
int guess = Integer.parseInt(stringGuess);
String result = "miss";
for (int cell: locationCells)
{
if (guess == cell) {
result = "hit";
numOfHits++;
break;
}
}
if (numOfHits == locationCells.length)
{
result = "kill";
}
System.out.println(result);
return result;
}

In the following -
int guess = Integer.parseInt(stringGuess);
the parsing succeeds only if stringGuess contains some integer (within the range of [-2147483648 - 2147483647]. Otherwise, it fails with an exception.
To avoid that you have to make sure that stringGuess contains the right value.
Following is where the value comes from -
String guess = helper.getUserInput("enter a number");
String result = theDotCom.checkYourself(guess);
It's the getUserInput() method -
public String getUserInput(String prompt) {
String inputLine = null;
System.out.print(prompt + " ");
try {
BufferedReader is = new BufferedReader(new InputStreamReader(System.in));
inputLine = is.readLine();
if (inputLine.length() == 0)
return null; // this cannot be parsed
} catch (IOException e) {
System.out.println("IOException: " + e);
}
return inputLine.toLowerCase(); //this might not be an integer
}
And that's the part that you need to fix.
Following should do the job -
//...
BufferedReader is = new BufferedReader(new InputStreamReader(System.in));
while (true) { //keep reading
try {
inputLine = is.readLine();
int num = Integer.parseInt(inputLine); //make sure it's an integer
if(num > -1 && num < 10) { // if it is, and within [0-9]
break; // stop reading
}
} catch (Exception e) { // if not prompt again
System.out.println("pleasse try again with a number within [0-9]");
}
}
return inputLine; // no to lower case, it's a number
You can still better it up, by say just returning an int form this method, instead of String.

If you don't know if stringGuess is an integer or not, you can put Integer.parseInt(stringGuess) in a try { } catch construct. parseInt throws an exception if its input cannot be turned into an integer, so catch it. In the catch block, we know that it was not an integer. Otherwise it was an integer. Now do the logic you want to do (displaying a message, choosing to loop or not, etc)
(If you have not yet done exception handling, look up try and catch in Java)

as suggested by #patashu you can use try{ } catch() { }
as Integer.parseInt(argument) throws NumberFormatException if the argument is not a number(number in the form of string).
and about calling your input function again if user enters letter then you can simply do it by giving that particular input method a call inside catch block like:
try{
int guess = Integer.parseInt(stringGuess);
-----
-----
}
catch(NumberFormatException e){
System.out.println("Oooppps letter entered - try again with number ");
/**
now here make call to your method that takes input i.e getUserInput() in your case
**/
}

Related

Unable to match the first word from a file using Java

I am trying to match words from array to create a Symbol Table for Lexical Analysis (compiler lab). I am reading a C code file from Java. I am able to find everything from the file except the first word. No matter what I try the first word does not match with anything although it is a valid word.
In my file, the first word is int (initialization of two variable) and second line is float (initialization). If I swap it, my code can match int but did not match float.
here is the file I am reading:
float d, e;
int a, b, c;
Here is the code to read from file:
public static void fileRead(String fileName)
{
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(fileName));
try {
String x;
while ( (x = br.readLine()) != null )
{
// printing out each line in the file
System.out.println(x);
parser(x);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
System.out.println(e);
e.printStackTrace();
}
}
parser is another method and it is used to parse out different words:
public static void parser(String line)
{
String text = "";
for(int i = 0; i < line.length(); i++)
{
String temp = line.charAt(i) + "";
if(!(temp.equals(" ")
|| temp.equals(",")
|| temp.equals(";")
|| temp.equals(")")
|| temp.equals("}")
|| temp.equals("(")
|| temp.equals("{")
|| temp.equals("[")
|| temp.equals("]")
))
{
text = text + temp;
}
else
{
text = text.trim();
if(text.equals("int"))
{
System.out.println("Say cheese");
}
addToarray(text);
text = "";
}
}
I thought there might a space at the end so I trimmed it as well as backup.
and this is how I am adding to an array:
if(item.equals(text))
Here the "int" seemed to lose and never went inside the if block
public static void addToarray(String text)
{
boolean flag = false;
//look for keyWords first.
for (String item : keyWords)
{
if(item.equals(text))
{
if(resultKey.size() == 0)
{
System.out.println("Size zero> "+resultKey.size());
resultKey.add(text);
text = "";
flag = true;
break;
}
else
{
boolean checker = true;
for(String key : resultKey)
{
if(key.equals(text))
{
checker = false;
break;
}
}
if(checker)
{
resultKey.add(text);
flag = true;
text = "";
}
}
}
}
This is the array I am using to match:
final static String []keyWords = {"float", "if", "else",
"long", "double", "BigInteger","int"};
and these are the ArrayList to store variables.
static ArrayList <String> resultKey, resultIdent , resultMath,
resultLogic, resultNumeric, resultOthers;
Thanks for your help.
Lauching this simple app it works, don't know why you are unable to read the first word. EDIT: 100% it's the starting BOM in your file as #Fildor noticed.
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
public class Parser {
final static String[] keyWords = { "float", "if", "else", "long", "double", "BigInteger", "int" };
static ArrayList<String> resultKey = new ArrayList<>();
public static void main(String[] args) {
fileRead("src/test/resources/test.txt");
for (final String key : resultKey) {
System.out.println(key);
}
}
public static void fileRead(String fileName) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(fileName));
try {
String x;
while ((x = br.readLine()) != null) {
// printing out each line in the file
System.out.println(x);
parser(x);
}
br.close();
} catch (final IOException e) {
e.printStackTrace();
}
} catch (final FileNotFoundException e) {
System.out.println(e);
e.printStackTrace();
}
}
public static void parser(String line) {
String text = "";
for (int i = 0; i < line.length(); i++) {
final String temp = line.charAt(i) + "";
if (!(temp.equals(" ") || temp.equals(",") || temp.equals(";") || temp.equals(")") || temp.equals("}")
|| temp.equals("(") || temp.equals("{") || temp.equals("[") || temp.equals("]"))) {
text = text + temp;
} else {
text = text.trim();
if (text.equals("int")) {
System.out.println("Say cheese");
}
addToarray(text);
text = "";
}
}
}
public static void addToarray(String text) {
boolean flag = false;
// look for keyWords first.
for (final String item : keyWords) {
if (item.equals(text)) {
if (resultKey.size() == 0) {
System.out.println("Size zero> " + resultKey.size());
resultKey.add(text);
text = "";
flag = true;
break;
} else {
boolean checker = true;
for (final String key : resultKey) {
if (key.equals(text)) {
checker = false;
break;
}
}
if (checker) {
resultKey.add(text);
flag = true;
text = "";
}
}
}
}
}
}
And the file test.txt contains exactly
float d, e;
int a, b, c;
Launching it prints
float d, e;
Size zero> 0
int a, b, c;
Say cheese
float
int
"int" is not matched, because your input file probably contains a Byte-Order-Mark.
You can check for it in code or with a Hex-Editor. Most likely it will be one of 0xEFBBBF (UTF-8) , 0xFEFF (UTF-16 Big Endian) or 0xFFFE (UTF-16 Little Endian). But there are more. I already referenced a W3C-Document on the topic in the comments. Here is the Wikipedia-Article with even more BOMs.
Sidenote:
Which teacher hands out a "dirty" input file!? He must be some kind of sadist or (which would be even worse, imho) he did not do it on purpose. I would try to copy the (printable) content of the file to a new file and test this as input. So if the clean file works to your satisfaction, you can find some means of sanitizing input.

How can I make this Java read the whole last line, and not just each byte at a time?

I have a simple Java IO program which reads from a text file of numbers that looks like this :
1
2
3
4
5
6
7
8
9
17
It's supposed to simply print the lines in this text file to the console, and then tell me what the last line was. But it's printing the last line, here 17, as just 7 -
Here's my code so far :
import java.lang.*;
import java.io.*;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class ParentClass3{
static int lastLine = 0;
public static void main(String[] args) {
File file = new File("C:\\Java_Scratch_\\someFile.txt");
try {
Scanner sc = new Scanner(file);
while (sc.hasNextLine()) {
try {
int i = sc.nextInt();
System.out.println(i);
} catch (Exception e) {
System.out.println (" here is the stack trace " + e.getStackTrace() );
System.out.println (" here is the stack trace " );
}
}
sc.close();
} // END big-outer-Try
catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
int i = ParentClass3.countLines("C:\\Java_Scratch_\\someFile.txt");
System.out.println("There are " + i + " lines");
}
catch (IOException ioe) {
System.out.print("ioe" + ioe.getStackTrace() );
}
}
// putting the count function
public static int countLines(String filename) throws IOException {
InputStream is = new BufferedInputStream(new FileInputStream(filename));
try {
byte[] c = new byte[1024];
int count = 0;
int readChars = 0;
int lastline = 0;
boolean empty = true;
while ( (readChars = is.read(c)) != -1) {
for (int i = 0; i < readChars; ++i){
Byte b = c[i];
int xx = b.intValue();
lastLine = xx;
if (c[i] == '\n'){
++count;
empty = true;
} else {
empty = false;
}
}
}
if (!empty) {
count++;
}
int asciiVal = lastLine;
int lastLine2 = Character.getNumericValue(asciiVal);
System.out.println("the last line was " + lastLine2);
return count;
} finally {
is.close();
}
}//END method countLines
// end-count_func
}
How would I fix it, so that it says "the last line was 17" , rather just just 7 ?
the methos nextLine() should work, although I don't remember if that input would be parsed to a String, I guess that wouldn't affect, but anyway...

Reading and writing to file not working correctly

I have been working on this code for the day and am almost at the finish line. What I want is that the code should work as a clip card, remembering the number of purchased coffees, and awarding the customer a free coffee every 10th purchase. I'm writing to a file and reading from it in order for a customer to be able to continue his clip card where he left of last time. So to my problem...I have properly been able to write my "count" variable to a file, and it is storing it correctly. However, every time I run the program again it starts off a 0 and I don't see why. I need it to save the current count, and read the count once run again. For example, if a customer has previously purchased 7 coffees and is returning to the store, his counter needs to start at 7. For some reason it is not doing that.
Here's what I have so far:
public class FelixNeww {
public static void main(String [] args) {
Scanner key;
String entry;
int count = 0;
String password = "knusan01";
FelixNeww f = new FelixNeww();
System.out.println(f.readFromFile());
while(true) {
System.out.println("Enter password: ");
key = new Scanner(System.in);
entry = key.nextLine();
if(entry.compareTo(password) == 0){
count++;
System.out.println("You're one step closer to a free coffe! You have so far bought "
+ count + " coffe(s)");
f.saveToFile(count);
}
if(count == 10 && count != 0){
System.out.println("YOU'VE GOT A FREE COFFE!");
count = 0;
}
if(entry.compareTo(password) != 0){
System.out.println("Wrong password! Try again.\n");
}
}
}
public void saveToFile(int count)
{
BufferedWriter bw = null;
try
{
bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("C:\\Temp\\countStorage.txt"))));
bw.write(Integer.toString(count));
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
if(bw != null)
{
try
{
bw.close();
}
catch(IOException e) {}
}
}
}
public int readFromFile()
{
BufferedReader br = null;
try
{
br = new BufferedReader(new InputStreamReader(new FileInputStream(new File("C:\\Temp\\countStorage.txt"))));
String line = br.readLine();
int count = Integer.parseInt(line);
return count;
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
if(br != null)
{
try
{
br.close();
}
catch(IOException e) {}
}
}
return 0;
}
}
You are currently setting your count variable to 0. You should set it to the value that's in the file. Do this just before the while loop:
count = f.readFromFile();
while(true) {
You should also implement a way to gracefully exit the while loop. For example, if the user enters "q", you can execute the break; statement to exit the while loop. And after your while loop, call key.close(); to close the Scanner object.
The scope of count variable is local in both instances
public static void main(String [] args) {
Scanner key;
String entry;
int count = 0;
String password = "knusan01";
System.out.println(f.readFromFile());
public int readFromFile()
{
BufferedReader br = null;
try
{
br = new BufferedReader(new InputStreamReader(new FileInputStream(new File("C:\\Temp\\countStorage.txt"))));
String line = br.readLine();
int count = Integer.parseInt(line);
return count;
In the readFromFile function, you read it from the file, return it, but don't keep track of it in a variable, why don't you replace the println with this inside your main:
count=f.readFromFile

Integer.parseint exceptions

The question was :
Write a program that processes an input.txt file that contains data regarding ticket type followed by mileage covered and reports how many frequent-flier miles the person earns.
1 frequent flyer mile is earned for each mile traveled in coach.
2 frequent flyer miles are earned for each mile traveled in first class.
0 frequent flyer miles are earned on a discounted flight.
For example, given the data in input.txt below, your method must return 15600 (2*5000 + 1500 + 100 + 2*2000).
Input.txt:
firstclass 5000 coach 1500 coach
100 firstclass 2000 discount 300
My code gives me a problem with the parseint method. Any help would be appreciated :)
//InInteger class
import java.lang.NumberFormatException;
public class IsInteger {
public static boolean IsaInteger (String s)throws NumberFormatException
{
try
{
Integer.parseInt(s);//converts the string into an integer
return true;
}
catch (NumberFormatException e)
{
return false;
}
}
}
//main class
import java.io.*;
import java.util.StringTokenizer;
public class LA5ex2 {
public static void main(String[] args) throws FileNotFoundException {
BufferedReader input= new BufferedReader (new InputStreamReader (new FileInputStream("C:/Users/user/workspace/LA5ex2/input.txt")));
String str;
int TotalMiles=0;
try {
int mileage,lines=0;
String check,copy=null;
String word=null;
boolean isString=false;
while ((str = input.readLine()) != null)
{
lines++;
StringTokenizer token = new StringTokenizer(str);
while (token.hasMoreTokens())
{
if ((lines>1) && (isString))
{
//do nothing
}
else
{word= token.nextToken();
copy=word;}
if (token.hasMoreTokens())
mileage= Integer.parseInt(token.nextToken());
else
{
if (!(IsInteger.IsaInteger(word)))
{
copy=word;
isString=true;
}
break;
}
if (copy.equals("firstclass"))
TotalMiles+= (2*mileage);
else if (copy.equals("coach"))
TotalMiles+= (1*mileage);
else if (copy.equals("discount"))
TotalMiles+= (0*mileage);
}
}
System.out.println("Frequent-flier miles the person earns: "+ TotalMiles);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
This is the stacktrace that I get when running your code:
Exception in thread "main" java.lang.NumberFormatException: For input string: "firstclass"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:481)
at java.lang.Integer.parseInt(Integer.java:514)
at LA5ex2.main(LA5ex2.java:30)
I assume this is the error that you mention in your comment. However, the NumberFormatException does not occur in your IsaInteger() method in the IsInteger class (where you try-catch it by returning true or false), but in the LA5ex2 class (where you also try-catch it, but if it crashes, only the stacktrace gets printed). The exception occurs when Integer.parseInt() tries to parse the string firstclass as an integer, which of course fails:
if(token.hasMoreTokens()) mileage = Integer.parseInt(token.nextToken());
I rewrote your code in LA5ex2.java with two ArrayLists (to keep track of the various flier classes and the various mileages) using your IsaInteger method:
import java.io.*;
import java.util.ArrayList;
import java.util.StringTokenizer;
public class LA5ex2 {
public static void main(String[] args) throws FileNotFoundException {
BufferedReader input = new BufferedReader(new InputStreamReader(new FileInputStream("input.txt")));
String str = null;
String token = null;
int totalMiles = 0;
int lines = 0;
ArrayList<String> flierClasses = new ArrayList<String>();
ArrayList<Integer> mileages = new ArrayList<Integer>();
try {
while((str = input.readLine()) != null) {
lines++; // Why are we counting the lines, anyway?
StringTokenizer tokenizer = new StringTokenizer(str);
while(tokenizer.hasMoreTokens()) {
token = tokenizer.nextToken();
if(!(IsInteger.IsaInteger(token))) {
flierClasses.add(token); // if it's not an int, we assume it's a flier class
} else {
mileages.add(Integer.parseInt(token)); // if it's an int, it's a mileage
}
}
}
} catch(NumberFormatException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
} catch(IOException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
// Add everything up
for(int i = 0; i < flierClasses.size(); i++) {
totalMiles += calculateFlierMiles(flierClasses.get(i), mileages.get(i));
}
System.out.println("Frequent-flier miles the person earns: " + totalMiles);
}
private static int calculateFlierMiles(final String flierClass, final int mileage) {
if(flierClass.equals("firstclass")) return(2 * mileage);
else if(flierClass.equals("coach")) return(1 * mileage);
else if(flierClass.equals("discount")) return(0 * mileage);
return 0;
}
}
This code gives me the desired output: Frequent-flier miles the person earns: 15600
I'm assuming the problem is in IsaInteger (which should be stylized as isAnInteger). In that case, add a line that prints out the value of s before the try/catch and tell me what you get.
Also, why are you using tokens when you could use a BufferedReader and its nextLine() method?

StringIndexout of range

I got an error: StringIndex out of range: -1 with error line is String anEmail = lineFromFile.substring(s+1, e). As you can see im trying to print a part of a line in an input file but i doesn't work. Can someone help me explain why?
import java.io.*;
public class Email13
{
static boolean isValidEmailCharacter(char c)
{
boolean result = false;
if((c>='A'&&c<='Z')||(c>='a'&&c<='z')||(c>='0'&&c<='9')||(c=='.')||(c=='-')||(c=='+'))
result = true;
return result;
}
public static void main(String[] args) throws Exception{
BufferedReader cin, fin;
cin = new BufferedReader(new InputStreamReader(System.in));
//Description
System.out.println("Programmer: Minh Nguyen");
System.out.println("Description: This program is to start the final project.");
System.out.println();
String nameIn, nameOut, deIn, deOut;
nameIn="";
nameOut="";
deIn = "fileContainingEmails.txt";
System.out.print("Enter input filename [default:" + deIn + "]: ");
nameIn = cin.readLine();
if(nameIn.compareTo("")==0){
nameIn = deIn;
deOut = "copyPasteMyEmails.txt";
System.out.print("Enter output filename [default:" + deOut + "]: ");
nameOut = cin.readLine();
if(nameOut.compareTo("")==0)
nameOut = deOut;
}
else if(nameIn.compareTo("")>0){
deOut = nameIn;
System.out.print("Enter output filename [default:" + deOut + "]: ");
nameOut = cin.readLine();
if(nameOut.compareTo("")==0)
nameOut = nameIn;
}
fin = new BufferedReader(new FileReader(nameIn));
//Read the input file
while(true)
{
if(!fin.ready()) break;
String lineFromFile;
lineFromFile = fin.readLine();
int s, e, hasDot;
for (int i = 0; i < lineFromFile.length(); i++) // for each char in the string...
{
if(lineFromFile.charAt(i)=='#')
{
for(s=i;s>-1;s--)
{
if(isValidEmailCharacter(lineFromFile.charAt(s))==false)
for(e=1; e< lineFromFile.length(); e++)
{
if(isValidEmailCharacter(lineFromFile.charAt(e))==false)
{
String anEmail = lineFromFile.substring(s+1, e);
System.out.println(anEmail);
break;
}
}
}
}
}
}
fin.close();
PrintWriter fout;
fout = new PrintWriter(new FileWriter(nameOut));
fout.close();
}
}
Suppose a line has 10 characters. So i loop goes from 0 to 9.
You then have a s loop, which goes from i to 0.
And inside that, you access `linefromFile.subString(s+1);
So when i is 9, your s loop starts at 9, and you try to access index 9+1, which is index 10, which is outside of your line.
Since Arrays are zero based indices, your lineFromFile.substring(s+1, e) is throwing an error.
for(s=i;s>-1;s--){
//lines of code
String anEmail = lineFromFile.substring(s+1, e)
This would fail for i = lineFromFile.length
as it would translate to lineFromFile[i+1] where lineFromFile[i] is the last element.

Categories

Resources