I am coding in Java and trying to use a while loop to add all of the values of a string to an array that were set up as tokens separated by commas. At some point, the values just turn into 0, and I don't know why.
My array is a double array called "prices". My string is named "values". The loop I am using is this:
StringTokenizer st = new StringTokenizer(values,",");
prices = new double[st.countTokens()];
for (int i = 0; i < st.countTokens(); i++) {
token = st.nextToken();
double price = Double.parseDouble(token);
prices[i] = price;
}
When I use 1, 2, 3, 4, 5, 6, 7, 8, and 9 as the inputs, the output that I expect is to have prices[0] through prices[8] be equal to the 9 values that I input for the tokens, but this is the output I get:
Please enter the price values using numbers and decimals only!
Input 0 at any time to stop entering values!
Enter the price value: 1
Enter the price value: 2
Enter the price value: 3
Enter the price value: 4
Enter the price value: 5
Enter the price value: 6
Enter the price value: 7
Enter the price value: 8
Enter the price value: 9
Enter the price value: 0
Show prices array:
prices[0] = 1.0
prices[1] = 2.0
prices[2] = 3.0
prices[3] = 4.0
prices[4] = 5.0
prices[5] = 0.0
prices[6] = 0.0
prices[7] = 0.0
prices[8] = 0.0
Here is my entire code:
import java.util.Scanner;
import java.util.StringTokenizer;
class ArrayInputShow {
public static void main (String args[]) {
int count = 0, numTokens = 0;
double prices[], temp;
String values = "", tempInput = "", token = "";
Scanner input = new Scanner(System.in);
System.out.println("Please enter the price values using numbers and decimals only!");
System.out.println("Input 0 at any time to stop entering values!");
while (true) {
if (count != 0) {
values = values + ",";
}
System.out.print("Enter the price value: ");
tempInput = input.nextLine();
if (tempInput.equals("0")) {
break;
}
values = values + tempInput;
count++;
}
StringTokenizer st = new StringTokenizer(values,",");
numTokens = st.countTokens();
prices = new double[st.countTokens()];
for (int i = 0; i < st.countTokens(); i++) {
token = st.nextToken();
double price = Double.parseDouble(token);
prices[i] = price;
}
System.out.println(""); //break
System.out.println("Show prices array:");
for (int i = 0; i < prices.length; i++) {
System.out.println("prices[" + i + "] = " + prices[i]);
}
System.out.println(""); //break
System.out.println("Show prices array backwards:");
for (int i = prices.length - 1; i >= 0; i--) {
System.out.println("prices[" + i + "] = " + prices[i]);
}
System.out.println(""); //break
System.out.println("Show prices array sorted from least expensive to most expensive:");
for (int j = 0; j < prices.length - 1; j++) {
for (int i = 0; i < (prices.length - (1 + j)); i++) {
if (prices[i] > prices [i + 1]) {
temp = prices[i + 1];
prices[i + 1] = prices[i];
prices[i] = temp;
}
}
}
for (int i = 0; i < prices.length; i++) {
System.out.println("prices[" + i + "] = " + prices[i]);
}
}
}
This was my first attempt at making an array that declares and initializes depending on the users input and how many inputs the user gives.
I ended up finding a solution to this problem by declaring a variable "numTokens' and using that in place of using st.countTokens itself in the loop. However, I am still confused as to why it didn't work with st.countTokens. Isn't it the same thing?
This is what worked for me:
StringTokenizer st = new StringTokenizer(values,",");
numTokens = st.countTokens();
prices = new double[numTokens];
for (int i = 0; i < numTokens; i++) {
token = st.nextToken();
double price = Double.parseDouble(token);
prices[i] = price;
}
But, like I said, I don't understand why this works, or how to avoid this problem in the future.
Your problem lies in these two lines:
for (int i = 0; i < st.countTokens(); i++) {
token = st.nextToken();
With the st.nextToken();
you basically pop a value from the StringTokenizer, so the st.countTokens()
will decrease every iteration. If you add a debug printline System.out.println(st.countTokens());
between the two lines above, you'll see it'll print 9,8,7,6,5
, at which point i<5
will stop the loop.
The most straight-forward fix is to put the st.countTokens();
in a variable before the loop:
int countTokens = st.countTokens();
for (int i = 0; i < countTokens ; i++) {
token = st.nextToken();
Although usually you'd simply use a while(st.hasMoreElements())
instead like this:
int i = 0;
while (st.hasMoreElements()) {
token = st.nextToken();
double price = Double.parseDouble(token);
prices[i] = price;
i++;
}
As for a general tip: I assume you're first reading all your prices and only then convert it to a double-array, because you don't know beforehand how many prices the user will input and how large the array will be. In that case, there is the ArrayList
. :)
The advantage with the ArrayList is also that you can use builtins for the reversing and sorting, so you won't have to do so manually, like this:
import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
class ArrayInputShow {
public static void main (String args[]) {
ArrayInputShow program = new ArrayInputShow();
List<Double> prices = new ArrayList<Double>();
Scanner input = new Scanner(System.in);
System.out.println("Please enter the price values using numbers and decimals only!");
System.out.println("Input 0 at any time to stop entering values!");
while (true) {
//System.out.print("Enter the price value: ");
double price = input.nextDouble();
if (price == 0) {
break;
}
prices.add(price);
}
program.printLinebreakAndMessage("Show given prices:");
program.printPrices(prices);
program.printLinebreakAndMessage("Show prices backwards:");
Collections.reverse(prices);
program.printPrices(prices);
program.printLinebreakAndMessage("Show prices sorted from least expensive to most expensive:");
Collections.sort(prices);
program.printPrices(prices);
}
private void printLinebreakAndMessage(String msg) {
System.out.println(); //break
System.out.println(msg);
}
private void printPrices(List<Double> prices) {
for (double price : prices) {
System.out.println(price);
}
}
}
Try it online. (Although all inputs have to be given at once, so I've removed the System.out.print("Enter the price value: ");
here.)