Something wrong in my coding in java with numbers and strings - java

I tried to develop a java program using netbeans in which a GUI accepts subject marks from five text fields and displays the total marks, percentage and the grade in their respective text fields.
The problem is I am getting errors while executing the GUI. I tried replacing int with double to hold decimal values of percentage but that didn't help. I am unable to find any errors and since I am a beginner i am unable to understand the errors given in the monitor by my netbeans. Please help.
ERRORS: Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: " 34"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:481)
at java.lang.Integer.parseInt(Integer.java:527)
at NewJFrame.submit_buttonActionPerformed(NewJFrame.java:173)
at NewJFrame.access$000(NewJFrame.java:4)
at NewJFrame$1.actionPerformed(NewJFrame.java:60)
Here's the coding I've done.
int sub1_ = Integer.parseInt(sub1.getText());
int sub2_ = Integer.parseInt(sub2.getText());
int sub3_ = Integer.parseInt(sub3.getText());
int sub4_ = Integer.parseInt(sub4.getText());
int sub5_ = Integer.parseInt(sub5.getText());
// Here each subject holds a max. of 100 marks.
int a = sub1_+sub2_+sub3_+sub4_+sub5_;
total_marks.setText(""+a);
// Since each subject holds a max. of 100 marks, the total marks of five subjects sums up to 500.
int b = (a/500)*100;
percentage.setText(b+"%");
if(b<=100&&b>=91)
{grade.setText("A1");}
else if(b<=90&&b>=81)
{grade.setText("A2");}
else if(b<=80&&b>=71)
{grade.setText("B1");}
else if(b<=70&&b>=61)
{grade.setText("B2");}
else if(b<=60&&b>=51)
{grade.setText("C1");}
else if(b<=50&&b>=35)
{grade.setText("C2");}
else if(b<=34&&b>=0)
{grade.setText("D");}
else {grade.setText("");}

java.lang.NumberFormatException: For input string: " 34"
Trim the String of whitespace before using the parse methods.
try {
int sub1_ = Integer.parseInt(sub1.getText().trim());
int sub2_ = Integer.parseInt(sub2.getText().trim());
int sub3_ = Integer.parseInt(sub3.getText().trim());
int sub4_ = Integer.parseInt(sub4.getText().trim());
int sub5_ = Integer.parseInt(sub5.getText().trim());
} catch (NumberFormatException e) {
// invalid input
}

At some point you are trying to parse the integer " 34", the leading space is a problem for the parsing method.
You should either make sure your integer has no whitespace when you create it, or use the trim() function to remove leading and trailing whitespace,

In addition to the issues already reported, the line int b = (a/500)*100; should be int b = (a * 100) / 500; or, simpler, int b = a/5;. The division by 500 rounds down to an integer, so if a is less than 500 the result is zero.

In addition to the question asked, there is a way to reduce the clutter in your code.
For example, you have multiple if-statements that all do the same thing, but with different numbers.
In this case, you can just create a function.
private boolean inRangeOf(int value, int max, int min) {
return value <= max && value >= min;
}
You can then replace your conditions with calls to inRangeOf(x, a, b)
if( inRangeOf(b, 100, 91) ) {
grade.setText("A1");
}
else if( inRangeOf(b, 90, 81) ) {
grade.setText("A2");
}
else if( inRangeOf(b, 80, 71) ) {
grade.setText("B1");
}

Related

Reading a file -- pairing a String and int value -- with multiple split lines

I am working on an exercise with the following criteria:
"The input consists of pairs of tokens where each pair begins with the type of ticket that the person bought ("coach", "firstclass", or "discount", case-sensitively) and is followed by the number of miles of the flight."
The list can be paired -- coach 1500 firstclass 2000 discount 900 coach 3500 -- and this currently works great. However, when the String and int value are split like so:
firstclass 5000 coach 1500 coach
100 firstclass
2000 discount 300
it breaks entirely. I am almost certain that it has something to do with me using this format (not full)
while(fileScanner.hasNextLine())
{
StringTokenizer token = new StringTokenizer(fileScanner.nextLine(), " ")
while(token.hasMoreTokens())
{
String ticketClass = token.nextToken().toLowerCase();
int count = Integer.parseInt(token.nextToken());
...
}
}
because it will always read the first value as a String and the second value as an integer. I am very lost on how to keep track of one or the other while going to read the next line. Any help is truly appreciated.
Similar (I think) problems:
Efficient reading/writing of key/value pairs to file in Java
Java-Read pairs of large numbers from file and represent them with linked list, get the sum and product of each pair
Reading multiple values in multiple lines from file (Java)
If you can afford to read the text file in all at once as a very long String, simply use the built-in String.split() with the regex \\s+, like so
String[] tokens = fileAsString.split("\\s+");
This will split the input file into tokens, assuming the tokens are separated by one or more whitespace characters (a whitespace character covers newline, space, tab, and carriage return). Even and odd tokens are ticket types and mile counts, respectively.
If you absolutely have to read in line-by-line and use StringTokenizer, a solution is to count number of tokens in the last line. If this number is odd, the first token in the current line would be of a different type of the first token in the last line. Once knowing the starting type of the current line, simply alternating types from there.
int tokenCount = 0;
boolean startingType = true; // true for String, false for integer
boolean currentType;
while(fileScanner.hasNextLine())
{
StringTokenizer token = new StringTokenizer(fileScanner.nextLine(), " ");
startingType = startingType ^ (tokenCount % 2 == 1); // if tokenCount is odd, the XOR ^ operator will flip the starting type of this line
tokenCount = 0;
while(token.hasMoreTokens())
{
tokenCount++;
currentType = startingType ^ (tokenCount % 2 == 0); // alternating between types in current line
if (currentType) {
String ticketClass = token.nextToken().toLowerCase();
// do something with ticketClass here
} else {
int mileCount = Integer.parseInt(token.nextToken());
// do something with mileCount here
}
...
}
}
I found another way to do this problem without using either the StringTokenizer or the regex...admittedly I had trouble with the regular expressions haha.
I declare these outside of the try-catch block because I want to use them in both my finally statement and return the points:
int points = 0;
ArrayList<String> classNames = new ArrayList<>();
ArrayList<Integer> classTickets = new ArrayList<>();
Then inside my try-statement, I declare the index variable because I won't need that outside of this block. That variable increases each time a new element is read. Odd elements are read as ticket classes and even elements are read as ticket prices:
try
{
int index = 0;
// read till the file is empty
while(fileScanner.hasNext())
{
// first entry is the ticket type
if(index % 2 == 0)
classNames.add(fileScanner.next());
// second entry is the number of points
else
classTickets.add(Integer.parseInt(fileScanner.next()));
index++;
}
}
You can either catch it here like this or use throws NoSuchElementException in your method declaration -- As long as you catch it on your method call
catch(NoSuchElementException noElement)
{
System.out.println("<###-NoSuchElementException-###>");
}
Then down here, loop through the number of elements. See which flight class it is and multiply the ticket count respectively and return the points outside of the block:
finally
{
for(int i = 0; i < classNames.size(); i++)
{
switch(classNames.get(i).toLowerCase())
{
case "firstclass": // 2 points for first
points += 2 * classTickets.get(i);
break;
case "coach": // 1 point for coach
points += classTickets.get(i);
break;
default:
// budget gets nothing
}
}
}
return points;
The regex seems like the most convenient way, but this was more intuitive to me for some reason. Either way, I hope the variety will help out.
simply use the built-in String.split() - #bui
I was finally able to wrap my head around regular expressions, but \s+ was not being recognized for some reason. It kept giving me this error message:
Invalid escape sequence (valid ones are \b \t \n \f \r " ' \ )Java(1610612990)
So when I went through with those characters instead, I was able to write this:
int points = 0, multiplier = 0, tracker = 0;
while(fileScanner.hasNext())
{
String read = fileScanner.next().split(
"[\b \t \n \f \r \" \' \\ ]")[0];
if(tracker % 2 == 0)
{
if(read.toLowerCase().equals("firstclass"))
multiplier = 2;
else if(read.toLowerCase().equals("coach"))
multiplier = 1;
else
multiplier = 0;
}else
{
points += multiplier * Integer.parseInt(read);
}
tracker++;
}
This code goes one entry at a time instead of reading a whole array void of whitespace as a work-around for that error message I was getting. If you could show me what the code would look like with String[] tokens = fileAsString.split("\s+"); instead I would really appreciate it :)
you need to add another "\" before "\s" to escape the slash before "s" itself – #bui

How can I keep track of an int and hold the 0's

Java question,
Say I have a number such as 0000102 and the 0s are important, as in they need to be there.
How can I save this information in an int(or some other way that would allow me to increment it)
For example, after checking the number 0000102 it would then add one to it and check for 0000103
When I try saving it as in int it just reverts to 102 and gets rid of the 0's, and therefore doesn't match as I search through a database since it is no longer the same. Does anyone know of a way I can do this without it removing the 0's. Thanks
EDIT:
My final solution for addition with leading zeros was this function, it takes a string with leading 0's adds one to it, then returns the string
String nextNum(String s){
int number =0;
String newNum ="";
int len = s.length();
int newLength =0;
for(int i =0; i < s.length()-1; i++){
if (s.charAt(i) == '0')
newNum+="0";
else
break;
}
number = Integer.parseInt(s);
number++;
newNum += String.valueOf(number);
newLength = newNum.length();
if(newLength == len)
return newNum;
else
return newNum.substring(1); //incase number was 000099 it doesnt go to 0000100 it goes to 000100 instead
}
You can use string formatting by combining printf with "%0d" as follows:
String num = "000123";
Integer n = Integer.parseInt(num);
n++;
int len = num.length();
System.out.printf("%0" + len + "d", n); // 000124
// and if you want to store the result
// back into a string:
String res = String.format("%0" + len + "d", n);
System.out.println(res); // 000124
You would store the value as an int (without zeroes) but could convert it into a String with leading zeroes when you want to print or display it. Here is an example conversion method.
public String addZeroes(int value, int desiredLength) {
String valueString = value + "";
int valueLength = valueString.length();
for (int i = 0; i < desiredLength - valueLength; i++) {
valueString = "0" + valueString;
}
return valueString;
}
The number itself is separate from the representation of the number. The number associated with what we usually call "ten" is always the quantity that counts these: ||||||||||, but it has many possible string representations: "10", "0000010", "0x0a", "1010(2)"... (not all of these are valid Java representations, just various representations that humans are using)
Your number will always be stored in the computer in such a way that the quantity can be (mostly) accurately handled. The string representation is normally not stored; it is calculated each time. For example, when you do System.out.println(102), it is actually handled as System.out.println(Integer.toString(102, 10)).
Between 102 and "0000102", figure which one you want to store and which one you want to display, and convert appropriately when you need the other one.
You'll need to use a String.
The decimal numbers 000102 and 0102 and 102 (and for that matter, the hex number 0x66) are all the same integer value, there is no way to distinguish between them once you store them as an int.
If you want to preserve a specific character representation of your integer, then you need a string.
To increment the String you'll need to parse it to an Integer, and then reformat it.
String increment(String s) {
int n = Integer.parseInt(s, 10)
return ("%0" + s.length() + "d").format(n+1);
}
You say you need to keep track of the leading zeroes, but that's separate from the number itself. I would keep the number itself as an int, and keep a different variable with the required number of zeroes. This will let the number keep its semantic meaning of the number as a number (and allow incrementing, as you said), and when displaying it, pad or fill with zeroes when needed, based on the second value.

Java error when converting String in ArrayList to int

I am very new at Java. I am trying to write a lottery simulator. I have the following code:
Scanner input = new Scanner(System.in);
System.out.println("Enter six whole numbers between 1 and 49 in a comma-separated list: ");
String userNumbersString = input.nextLine();
String[] userNumbersArray = userNumbersString.replaceAll("\\s+","").split(",");
ArrayList userNumbers = new ArrayList(Arrays.asList(userNumbersArray));
boolean validNumbers = true;
for(int v = 0; v <= 6; v++){
if((int)userNumbers.get(v) > 49){
validNumbers = false;
v = 7;
}else{
v++;
}
}
if(validNumbers == false){
String[] str = new String[0];
main(str);
}
It compiles properly. However, when I input a series of numbers, I get this error:
java.lang.ClassCastException:
java.lang.String cannot be cast to java.lang.Integer.
I am very confused about why this string can't be cast to an integer.
Sorry if this is a long-winded question, but I would hugely appreciate any help.
I have just realised that the OutOfBounds exception was due to a stupid maths mistake on my part; v was starting at 0; there were five values in the array, but I gave the for loop the condition <= 6. Sorry about that.
Thank you everybody for all your help. Together, you have resolved my question.
In simple terms
int is a primitive type for representing a 32-bit integer number.
String is a reference type wrapped arround an array of chars to represent a sequence of characters.
You cannot just change the type from int to String and make the character sequence in the string magically becomes a number.
Think about how you would implement this conversion. You would look at each character, make sure it is a valid digit etc.
Change:
if((int)userNumbers.get(v) > 49)
To:
if(Integer.parseInt(userNumbers.get(v)) > 49)
Further, when creating Generic type containers like ArrayList make sure you also declare what type of objects they store for type safety reasons.
Change:
ArrayList userNumbers = new ArrayList(Arrays.asList(userNumbersArray));
To:
ArrayList<String> userNumbers = new ArrayList<String>(Arrays.asList(userNumbersArray));
This way you calling userNumber.get() will return a String.
If you don't put this it will return an Object so you would actually call Integer.parseInt(Object) which is invalid. You would get a pretty self-explanatory error looking like this:
The method parseInt(String) in the type Integer is not applicable for the arguments (Object)
EDIT:
For your IndexOutOfBounds error, you are trying to access more elements than you have. Basically, you want to have 6 values but your for loop says from 0 until 6 (included). That is a total of 7 elements: 0, 1, 2, 3, 4, 5, 6
You can fix this by changing the <= 6 to < 6 in your loop but the best way to fix it so it will work no matter how many elements you have is to use the size() property of ArrayList:
Change:
for(int v = 0; v <= 6; v++)
To:
for(int v = 0; v < userNumbers.size(); v++)
First, you should use generics for ArrayList. Please replace
ArrayList userNumbers = new ArrayList(Arrays.asList(userNumbersArray));
with
ArrayList<String> userNumbers = new ArrayList<>(Arrays.asList(userNumbersArray));
However, this is not your problem. The misconception here is that casting will infer what type of conversion you need; it won't. Replace (int)userNumbers.get(v) with Integer.parseInt(userNumbers.get(v)) to parse the int from a String.
Type casting is not meant to parse an Integervalue from an String.
You should use Integer.parseInt for that.
if(Integer.parseInt(userNumbers.get(v)) > 49
should solve your error.
First, you will get an ArrayIndexOutOfBounds exception because of the <= 6 in your for loop.
Secondly, you should use the Integer.parseInt(String intStr) method to turn each number into its int equivalent.
Here is a stripped down version that I think works:
public static void main(String[] args)
{
String testInputOne = "14,22,18,2,5,11";
boolean allNumbersAreValid = true;
String[] userNumbersStrArray = testInputOne.split(",");
for (String numberStr: userNumbersStrArray)
{
Integer number = Integer.parseInt(numberStr.trim());
if (number > 49)
{
allNumbersAreValid = false;
break;
}
}
System.out.println("Testing " + testInputOne + ": " + (allNumbersAreValid?"All valid!":"At least one invalid"));
}
If you want to further guard against bad input such as someone entering an alpha character, you could wrap the Integer.parseInt call in a try catch block and catch the NumberFormatException and output a suitable error message.
I'm frankly a little scared as to what the recursive call to main is supposed to do? :)

Java substring difficulty

I know how to use substring() but why isn't this working, the user inputs an equation like
"5t + 1" with a space before and after the "+". I want tVariable to hold the integer before it, in this case 5 and constant should hold the constant integer in this case 1, but I get an out of range error.
import java.util.*;
import javax.swing.JOptionPane;
public class project3030 {
public static void main(String[] args) {
String L1x, tVariable, constant;
L1x = JOptionPane.showInputDialog("This is the format (x=5t + 1)");
int endIndex = L1x.indexOf("t");
tVariable = L1x.substring(0, endIndex);
int beginIndex = L1x.lastIndexOf(" ");
int endIndex2 = L1x.indexOf("");
constant = L1x.substring(beginIndex, endIndex2);
System.out.println(tVariable + constant);
}
}
You need to change it to something more like
constant = L1x.substring(L1x.lastIndexOf(" ")).trim();
Then when you add the numbers, you have to Parse them before you add them.
int constantInt = Integer.parseInt(constant);
Or you could use this solution:
String[] input = L1x.split(" ");
// remove the 't'
String tNum = input[0].substring(0, input[0].length() - 1);
int t = Integer.parseInt(tNum);
int constant = Integer.parseInt(input[2]);
String operator = input[1];
if (operator == "-")
constant *= -1;
The reason you are getting this error is because your substring() range is off.
You are passing into substring() an invalid range because the first index is beginIndex which you set equal to lastIndexOf(" ") while endIndex2 you set equal to indexOf("") which will occur at the beginning of the string.
Thus, you have your ranges mixed up. When you make this statement:
constant = L1x.substring(beginIndex, endIndex2);
You're giving it an invaid range
and will cause the specified error.
You could also do it different way. Let's say you create a JFrame and there you could put a textfield for every value, so for every "t" or constants, and then it would be much more simple to get those values. For characters like t or = you could use JLabels, so it would be a mixture of JTextFields and JLabels and I think it wouldn't be that ugly. I used this solution few times.

Array Index Out OfBounds Help (Java)

This Java program does a simple computation and it is suppose to output the numerical value of 123+1
(The output should be 124.) (Ignore the last "+" string.)
I got an error inside the if statement:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
I did a printout for arrayz[i-1] and arrayz[i+1] and it seems to printout 123 and 1 receptively, which is correct. So, I'm not sure what's wrong.
String math = "123+1+";
String arrayz[]={"123","+","1","+"};
double total =0.0;
int i=0;
while(i<=(math.length()-1)) //don't bother with the last char
{ i++;
if(arrayz[i].equals("+"))
{
total = Double.parseDouble((String)arrayz[i-1]) + Double.parseDouble((String)arrayz[i+1]);
}
}
System.out.println(total);
while(i<=(math.length()-1))
math length is 6 and and in side loop your array length is 4
You might want to write
while(i<=(arrayz.length-1))
Since you are using the index i with the array arrayz, you must use arrayz.length instead of math.length()
Edit
This should work:
public static void main(String[] args)
{
String math = "123+1+";
String arrayz[] = { "123", "+", "1", "+" };
double total = 0.0;
int i = 0;
// arrayz.length - 2 -> because you are accessing "arrayz[i + 1]",
// arrayz.length - 1 would be OK if the maximum index you were using were "arrayz[i] "
while (i <= (arrayz.length - 2)) //don't bother with the last char
{
if (arrayz[i].equals("+")) {
total = Double.parseDouble((String) arrayz[i - 1]) + Double.parseDouble((String) arrayz[i + 1]);
}
i++; // Increment at the end of the loop
}
System.out.println(total);
}
You are looping over the string math, at the same time accessing elements of arrayz inside your loop, and thinking that they have the same elements and the same length.
What I suggest you, is to use instead of math String (you can omit it in this case but I assume you can't in general for some criteria), you can use an array of type String, so that 123 in your example would be the first element arrayz[0].

Categories