Java "break" seems to be breaking both nested for loops - java

This code reads in each line from a plain text file (each line has a "list" of arrays of integers) and basically breaks it down into single integers, which are stored in a temporary array. Each line of the document must be arranged into a 2 dimensional array with an equal number of rows and columns.
The line of code that tests a condition using an "if" statement is supposed to break ONLY the inner for loop, and go back to the outer one, increment i, and move on to the next array in that line.
So far, the code I have will take only the FIRST array in each line, place it into the FIRST row of a 2D array, but will skip all the other arrays in the line and move on to the next line, where it does the same thing. So the inner loops goes once, but the outer loop never increments. Every post I've read says that "break" in a nested for loop only exits the inner loop. That doesn't seem to be the case in this situation.
So how could I make sure that the outer loop increments and all the arrays in the line are accounted for?
if (!thisLine.equals("*")) {
String [] firstSplit = thisLine.split(" ");
String [] secondSplit = new String [firstSplit.length * firstSplit.length];
int [][] numbers = new int [firstSplit.length][firstSplit.length];
int value = 0;
int count = 0;
for (int i = 0; i < firstSplit.length; i++) {
firstSplit[i] = firstSplit[i].replace("[", "").replace("]", "");
secondSplit = firstSplit[i].split(",");
for (int j = 0; j < secondSplit.length; j++) {
value = Integer.parseInt(secondSplit[j]);
if (count >= firstSplit.length) {
break;
}
numbers[i][count] = value;
count++;
System.out.println(value);
}
}
System.out.println(Arrays.deepToString(numbers));
}
For example: there is a line in the file that reads:
[6,10,15,13] [16,2,14,7] [11,8,9,3] [5,4,1,12]
'firstSplit' would break up the line by whitespace, making an array of length 4.
Then the brackets would be removed.
For each item in firstSplit, secondSplit would break it up by commas, making an array of length 16 (of individual integers).
Each item in secondSplit would be converted to an integer and placed in an array like so:
6 at [0][0], 10 at [0][1], 15 at [0][2], 13 at [0][3].
The next array [16, 2, 14, 7] is completely ignored.

You never reset count, so once it becomes higher than firstSplit.length, every repetition after that will break immediately.
You should move the initialization of count inside the outermost for loop, so that it gets reset to 0 after each time through the inner loop.
That should fix the problem you're seeing, but there's a few other things in there which I think could be improved. Your initial declaration of secondSplit is unnecessary, since you always assign it a new value (firstSplit[i].split(",")) before you use it. I'd suggest deleting that declaration, and changing the line inside the outer loop to this: String[] secondSplit = firstSplit[i].split(",");. That will avoid needlessly allocating a chunk of memory.
Second, unless I'm not understanding your goal, you're going to encounter problems when the array width is different from it's height. You only need count because you initialize numbers[i]'s length to be firstSplit.length, rather than the actual size it needs to be. I'd change your code to this:
String [] firstSplit = thisLine.split(" ");
int [][] numbers = new int [firstSplit.length][];
for (int i = 0; i < firstSplit.length; i++) {
firstSplit[i] = firstSplit[i].replace("[", "").replace("]", "");
String[] secondSplit = firstSplit[i].split(",");
numbers[i] = new int[secondSplit.length];
for (int j = 0; j < secondSplit.length; j++) {
int value = Integer.parseInt(secondSplit[j]);
numbers[i][j] = value;
System.out.println(value);
}
}
Now it's only declaring the variables where they're actually needed, and setting the inner arrays to be the size they need.

Related

Using the Random() class with enhanced for loops

Enhanced for loops are weird. Why does
int size = 10;
Random random = new Random();
int[] scores = new int[size];
for (int score : scores) {
scores[score] = random.nextInt(size);
}
System.out.println(Arrays.toString(scores));
Give me a mostly empty array where only the first element is the random number,
whilst:
int size = 10;
Random random = new Random();
int[] scores = new int[size];
for (int i = 0; i < scores.length; i++){
scores[i] = random.nextInt(size);
}
System.out.println(Arrays.toString(scores));
gives me what I want: a 10-element array composed of random digits?
I thought the two loops were substitutions of each other; but when it comes to the Random(), it's only the first element that gets altered?
The enhanced for loop:
for (int score : scores)
iterates over the values of the array, not the indices.
When you instantiate the array with int[] scores = new int[size], The values are all initialized to 0 by default.
Therefore:
scores[score] = random.nextInt(size);
is always:
scores[0] = random.nextInt(size);
When you need to modify an array, you should use the traditional for loop, which iterates over the indices.
These are different constructs. Essentially with the first loop, you are saying "go get all of the elements of scores and loop over them. You don't get the index, you get the actual values which will always be0` in your case!
for (int score : scores){
// score is always 0!
scores[score] = random.nextInt(size);
}
Your second loop, as you've figured out, gives you the index (i) rather than the value in the scores array.
it seems that you have a misconception about the enhanced loop in Java, because it is a foreach loop and iterates over the values of the array, not over the keys:
Look at the following example
String[] my_string_array = new String[]{"Dog","House","Cat"};
for(String s: my_string_array){
System.out.println(s); //prints "Dog", then "House", then "cat"
//s equals one entry of the Array
}
In your example, every entry of the array is 0, because this is the default value for integers.
So in each repetition of your array, the following happens
scores[0] = random.nextInt(size);
I hope you understand the problem with your first code.
Just use the first one, it is working and best practise.
You have two different loops actually,
for (int score : scores){
and
for (int i = 0; i < scores.length; i++){
First one gives the value of array (not an index of specified array) whereas second gives the index. As said, the meaning changes for below code
scores[score] = random.nextInt(size);
So, imagine your array has value 1,2,5, so you would basically accessing index 1, 2 and 5 in first loop, on the other hand, second loop assigning value to specific index, which goes with 0, 1 and 2.
Since scores was initialized with default values 0, so in each iteration, it was updating value at the 0th index.

How to determine ASCII value of a word

I am creating a program that imports a large list of words. This list has been separated by word but I now need to determine the ASCII value of each word in this list, and eventually which one has the highest total ASCII value. I am receiving a few errors and need to know how to get this corrected so that I can get each value.
public static void main(String[] args) throws IOException {
//import list of words
BufferedReader File = new BufferedReader(new FileReader(LOC));
//Create a temporary ArrayList to store data
ArrayList<String> words = new ArrayList<String>();
//Find number of lines in txt file
String line;
String delimiter = "\t";
while ((line = File.readLine()) != null)
//read the file
{
String[] wordsInLine = line.split(delimiter);
//separate the words
for(int i=0, isize = wordsInLine.length; i < isize; i++){
words.add(wordsInLine[i]);//put them in a list
//assess each character in the word to determine the ascii value
int total = 0;
for (int i=0; i < wordsInLine.length(); i++)
Receiving an error on the above line that states - Cannot invoke length() on the array type
String[]
- Duplicate local variable i
{
char c = word.charAt(i);
Receiving an error on the above line that states word cannot be resolved
int j = (int) c;
total += c;
}
I have done some research trying to determine the best way to calculate the ASCII value of each word and I haven't been able to find much information on how to do this. If someone could please take a look at my code I would appreciate it!! Also, before anyone says it let me just say this is NOT a school project. I am on summer break and beginning programming II in the fall and just trying to keep up on coding so that I am not rusty in the fall. THANK YOU!!! :))
Receiving an error on the above line that states - Cannot invoke length() on the array type String[] - Duplicate local variable i
wordsInLine is an array, and length is property of array. So, you have to use:
wordsInLine.length
If wordsInLine was a String, then wordsInLine.length() would have made sense.
Receiving an error on the above line that states word cannot be resolved
Before the line char c = word.charAt(i);, add below:
String word = wordsInLine[i];
For the wordsInLine.length() issue, length() is not a valid method for arrays. You actually have to access the length field thusly: wordsInLine.length without ().
As for word.charAt(i), you haven't declared a variable called word anywhere which is what's causing the problem. What you really want to do is sum up the values for every word in the array, and for that you need a nested loop.
You also said that you wanted to figure out which one had the highest value. To do that, just keep track of the largest one and update it after each iteration like this:
int indexOfMax = 0;
int[] sums = new int[wordsInLine.length];
//Iterate over every word
for(int i = 0; i < wordsInLine.length; i++)
{
//Reset the total for each word
total = 0;
//Iterate over every character in the word
for(int j = 0; j < wordsInLine[i].length(); j++)
{
char c = wordsInLine[i].charAt(j);
total += c;
}
//Remember the sum for this word
sums[i] = total;
//If the word's sum is greater than our previous max,
//make it the new max
if(sums[i] > sums[indexOfMax])
{
indexOfMax = i;
}
}
And now you can get the word with the greatest ASCII value by calling wordsInLine[indexOfMax]. It will have an ASCII sum of sums[indexOfMax].
wordsInLine is an array and therefore it does not have a method to get its length. Instead, to get an array's length, use array.length as opposed to what you were doing: array.length() (which causes an error).
word is not a defined variable, this is why java is saying that it cannot be resolved (it can't find any declaration). Instead you want to use 2 for loops in order to loop over every character in the word in the array wordsInLine. You also have two instances of the variable i, this is not allowed. To fix these errors write the following code after `int total = 0;':
int total = 0; // Don't rewrite this line
int[] totals = new int[wordsInLine.length]; // If you want to add all your totals to an array
for (int j=0; j < wordsInLine.length; j++) {
total = 0;
for (int k=0; k < wordsInLine[j].length(); k++) { // Here wordsInLine[j] is a string so you use .length() instead of .length
char c = wordsInLine[j].charAt(k);
int w = (int) c; // Get ascii of c
total += w; // Add it to total
}
// Do something with the total of this word before it gets reset to 0
// Maybe add it to an array of totals:
totals[j] = total;
}
I hope this helps!
Well your organization of your code needs a little bit of work.
First I would take this whole block of code outside file read in while loop.
for (int i=0; i < wordsInLine.length(); i++)
{
char c = word.charAt(i);
int j = (int) c;
total += c;
}
Why? Lets split what you are doing into two steps. Read in all the words into the word list. After doing this you will find where your core root of the problem is. You aren't reading the words from your word list at all.
Further code cleanup
for(int i=0, isize = wordsInLine.length; i < isize; i++){
This line is a little bit bloated. You don't need isize at all you are essentially doing denoting it for no reason. (Well actually caching the length does improve efficiency, another talk for another day). Cleaning up.
for(int i=0, ; i < wordsInLine.length; i++){
Then fixing the entire project
//import list of words
BufferedReader File = new BufferedReader(new FileReader(LOC));
//Create a temporary ArrayList to store data
ArrayList<String> words = new ArrayList<String>();
//Find number of lines in txt file
String line;
String delimiter = "\t";
// adds all the words into the list.
while ((line = File.readLine()) != null)
{
String[] wordsInLine = line.split(delimiter);
for(int i=0, ; i < wordsInLine.length; i++){
// compute alg and store the value some how to the word.
words.add(wordsInLine[i])
}
}
// notice outside the while loop.
// .size() is used for lists and .length is used for arrays.
for(int i = 0; i < words.size(); i++){
// compare
}

Why does this merge sort give incorrect results?

My assignment is to merge two arrays using int arrays that the user fills and we have to assume that there will be a maximum of 10000 inputs from the user, and the user inputs a negative number to stop. Then sort the array from least to greatest and print it out. Initially i thought that this would be quite easy but when i finished, i began getting outputs such as:
Enter the values for the first array, up to 10000 values, enter a negative number to quit: 1
3
5
-1
Enter the values for the second array, up to 10000 values, enter a negative number to quit
2
4
6
-1
First Array:
1
3
5
Second Array:
2
4
6
Merged Array:
6 1 2 3 4 5
as you can see, the six is out of place and i have no idea how to fix it. Here is the source code, i have included copious comments because I really want you guys to help me out to the best of your abilities. IF it's possible to use the same exact technique without implement new techniques and methods into the code please do so. I know there are methods in java that can do all of this in one line but it's for an assignment at a more basic level.
import java.util.Scanner;
public class Merge
{
public static void main(String [] args)
{
Scanner scan = new Scanner(System.in);
int [] first = new int[10000]; //first array, assume 10k inputs max
int [] second = new int[10000]; //first array, assume 10k inputs max
boolean legal = true; //WILL IMPLIMENT LATER
int end = 0; // set how many elements to put in my "both" array
int end2 = 0;// set how many elements to put in my "both" array
System.out.print("Enter the values for the first array, up to 10000 values, enter a negative number to quit");
//get values
for(int i = 0; i<first.length; i++)
{
first[i] = scan.nextInt(); //fill first with user input
if(first[i] <0) //if negative number, stop loop
{
end = i; //get position of end of user input
break;
}
}
System.out.println("Enter the values for the second array, up to 10000 values, enter a negative number to quit");
for(int i = 0; i<second.length; i++) //exact same as the first get values loop
{
second[i] = scan.nextInt();
if(second[i] <0)
{
end2 = i;
break;
}
}
System.out.print("First Array:\n");
for(int i = 0; i<first.length; i++) //print first array
{
if(i == end) //this prevents from printing thousands of zeros, only prints values that user inputed
break;
System.out.println(first[i] + " ");
}
System.out.print("Second Array:\n");
for(int i = 0; i<second.length; i++) //same as printing first array
{
if(i == end2)
break;
System.out.println(second[i] + " ");
}
int [] both = new int[(end)+(end2)]; //instanciate an int array to hold only inputted values from first[] and second[]
int [] bothF = new int[(end)+(end2)]; //this is for my simple sorter algotithm loop
for(int i = 0; i<both.length; i++) //fill both with the first array that was filled
{
both[i] = first[i];
}
int temp = end; // see below
for(int i = 0;i<both.length; i++) //fill array with the second array that was filled(starting from the end of the first array so that the first set is not overwritten
{
if(temp<both.length){ //this prevents an out of bounds
both[temp] = second[i];
temp++;}
}
//simple sorting algorithm
for(int d = both.length -1;d>=0;d--)
{
for(int i = 0; i<both.length; i++)
{
if(both[d]<both[i])
{
bothF[d] = both[d];
both[d] = both[i];
both[i] = bothF[d];
}
}
}
System.out.println("Merged Array:"); //print the results
for(int i = 0; i<both.length; i++)
{
System.out.print(both[i] + " ");
}
//System.out.println("ERROR: Array not in correct order");
}
Your sorting algorithm is faulty.
It's similar to selection sort, in that you take two elements and swap them if they're out of place. However, you don't stop the comparisons when you should: when the index d is less than the index i, the comparison-and-swap based on arr[d] > arr[i] is no longer valid.
The inner loop should terminate with i=d.
The logic of your sort goes something like this:
On the d-th loop, the elements at d+1 and to the right are correctly sorted (the larger numbers). This is true at the beginning, because there are 0 elements correctly sorted to the right of the right-most element.
On each of the outer loops (with the d counter), compare the d-th largest element slot with every unsorted element, and swap if the other element is larger.
This is sufficient to sort the array, but if you begin to compare the d-th largest element slot with already-sorted elements to its right, you'll end up with a larger number in the slot than should be. Therefore, the inner loop should terminate when it reaches d.
Sure, you can do it like this
for (int i = 0; i < end; i++) {
both[i] = first[i];
}
for (int i = 0; i < end2; i++) {
both[i + end] = second[i];
}
// simple sorting algorithm
for (int d = both.length - 1; d >= 0; d--) {
for (int i = 0; i < d; i++) {
if (both[i] > both[d]) {
int t = both[d];
both[d] = both[i];
both[i] = t;
}
}
}
Output(s) -
Enter the values for the first array, up to 10000 values, enter a negative number to quit3
5
-1
Enter the values for the second array, up to 10000 values, enter a negative number to quit
2
4
6
-1
First Array:
3
5
Second Array:
2
4
6
-1
Merged Array:
2 3 4 5 6
First I will start with some recommendations:
1.Give end1 and end2 the initial value as the array lengths.
The printing part - instead of breaking the loop - loop till i == end(if its not changed by the first part it will stay the array length).
One suggestion is to use a "while" statement on the user input to do the reading part (it seems cleaner then breaking the loop- but its OK to do it like you have done too).
Try to use more functions.
now to the main thing- why not to insert the numbers from both arrays to the join array keeping them sorted?
Guiding:
Keep a marker for each array.
Iterate over the new join array If arr1[marker1]> arr2[marker2]
insert arr2[marker2] to the joint array in the current position.
and add 1 to marker2. and the opposite.
(don't forget to choose what happens if the are equal).
This can be achieved because the arrays were sorted in the first place.
Have fun practicing!
I guess you have sort of a reverse "selection sort"-algorithm going on there. I made an class that run your code and printed out the output after every swap. Here is the code which is the same as you got in your application with the addition of print.
for(int d = both.length -1;d>=0;d--)
{
for(int i = 0; i<both.length; i++)
{
if(both[d]<both[i])
{
int temp = both[d];
both[d] = both[i];
both[i] = temp;
printArray(both);
}
}
}
and when we run this on an example array we get this output
[9, 8, 7, 6]=
-> 6879
-> 6789
-> 6798
-> 6978
-> 9678
The algorithm actually had the correct answer after two swaps but then it started shuffling them into wrong order. The issue is the inner for loops end parameter. When you have run the outer loop once, you can be certain that the biggest number is in the end. 'd' is here 3 and it will swap out a bigger number every time it encounters it. the if clause comparisions in the first loop is 6-9 (swap), 9-8, 9-7, 9-9. All good so far.
Potential problems comes in the second iteration with 'd' as 2. Array is now [6,8,7,9] and comparisons are 7-6, 7-8 (swap with result [6,7,8,9]), 8-8, 8-9 (swap!!) resulting in [6,7,9,8]. the last swap was the problematic one. We knew that the biggest number was already in the last spot, but we still compare against it. with every gotrough of the whole inner loop it will always find the biggest number (and all other bigger than both[d] that is already in place) and swap it to some wrong position.
As we know that the biggest number will be last after one iteration of the outer loop, we shouldn't compare against it in the second iteration. You sort of lock the 9 in the array and only try to sort the rest, being in this case [6,8,7] where d = 3, value 7. hence, your inner loop for(int i = 0; i<both.length; i++) becomes for(int i = 0; i<=d; i++). As an added bonus, you know that in the last iteration i==d, and thus the code inside it, if(both[d]<both[i]) will never be true, and you can further enhance the loop into for(int i = 0; i<d; i++).
In your algorithm you always do four comparisons in the inner loop over four iterations of the outer loop, which means there is a total of 16 comparisons. if we use the i<d we'll just do three comparisons in the inner loop on the first iteration of the outer loop, then two, then one. This brings it to a total of six comparisons.
Sorry if too rambling, just wanted to be thorough.

it works in c but not in java?

The following code to gets the vowel deleted from array, and the array rearranges itself.
public static void main(String[] args) {
int a = 0,k=0;
Scanner obj = new Scanner(System.in);
System.out.println("enter string");
String s= obj.nextLine();
char c[]=new char[s.length()];
c = s.toCharArray();
for(int i =0; i<s.length();i++){
if(c[i]=='a'|| c[i]=='i'|| c[i]=='o'||c[i]=='u'||c[i]=='e'){
for(int j=0;j<s.length();j++){
c[j]=c[j+1];
}
}
}
In the j for loop, you have this statement:
c[j]=c[j+1];
The ArrayIndexOutOfBoundsException comes when j is the last possible index, and you attempt to access the index element one too high.
You can stop when you get to s.length() - 1.
Additionally, you are shifting everything down, not just past where you found a vowel. Start your j for loop not at 0, but at i.
for(int j=i;j<s.length() - 1;j++){
You'll also have to decide what to do with the end of the array, which is not getting overwritten with anything here.
You can't change an array by pointing one location to the next: c[j]=c[j+1]; That line will only replace the character at c[j] but it won't remove that position entirely from the array. You'd need to create a new array with the vowels removed.
This also explains the out-of-bounds exception which happens when you're at the end of the array. You're trying to access the element at j + 1 but that is outside the array.
for(int j=0;j<s.length();j++){
c[j]=c[j+1];
}
Your problem is here. c[j+1] is referencing a location beyond the end of your array. When you assign c[j] a value from that location, you're trying to retrieve a location that does not exist. This causes an ArrayOutOfBoundsException.
You can achieve the same effect by transforming the string with a RegExp:
s.replaceAll("[aioue]","");
This works in C because the size of the string with strlen is one less than the actual size including the \0 at the end. When you copy all the characters down, you are moving the termination character as well. Java doesn't use termination characters and doesn't have a character which is beyond the end of the String.
In Java it is more natural to write a regular expression like this and work with Strings from the start.
System.out.println("enter string");
Scanner scan = new Scanner(System.in);
String line = scan.nextLine();
String noVowels = line.replaceAll("[AEIOUaeiou]", "");
System.out.println("Without vowels the line is '" + noVowels + "'");
Or you can use this regex
// (?i) mean case insensitive
String noVowels = line.replaceAll("(?i)[aeiou]", "");
you have the length of string is 4 and you put it on c[s.length] mean it start from 0-3 array indexing. in the second loop you swap the c[j+1] int c[j]. it cause array index out of bounds.
try this in the second loop
for (int j = 0; j < s.length()-1; j++)
{
System.out.println(c[j+1]);
c[j] = c[j + 1];
}

How to get part of array elements by user input using a loop

I am creating a program that takes various double arrays and displays them. The array is 10 elements and I am asked to get the values for elements 2 through 9 from the user input by using a loop. I have tried a for loop but I just don't understand how to get this done.
int c;
for(c = 0; c >= 2 && c <= 9; c++){
System.out.println("Enter a value for the elements 2-9: ");
}
System.out.println(" ");
If you have a Java array as follows:
double myarr[10];
You access elements in an array by index (assuming the array has been populated with data)
double somenum = myarr[3]; // extracts the *fourth* element from the list
To set a value in the array, you use the assignment operator and specify a value:
myarr[7] = 3.14159; // sets the *eighth* element to value '3.14159'
If you wish to iterate over a range of numbers, you can use a for-loop. For-loops have the following format:
for (initialization; condition; increase)
If you wanted to print all numbers between 1 and 10, you can write:
for (int i=1; i<=10; i++) {
System.out.println(i);
}
The trick is to use the variable i in the for-loop and ensure the loop iterates over the proper range. Hint: You can use i as an array index.
Here are some good resources:
Java: Array with loop
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html
http://www.tutorialspoint.com/java/java_loop_control.htm
http://www.homeandlearn.co.uk/java/java_for_loops.html
Here's a loop and a means for user input:
Scanner reader = new Scanner(System.in);
for(int i=2; i<8; i++){
System.out.println("Enter Element "+i);
a=reader.nextInt();
//store "a" somewhere
}
c needs to start at 1 (since you want the second elment) and stop at 8 (for the ninth)
so for(int c=1;c<9;c++) should be the loop
When writing loops remember;
array indexes are 0 based, the first element is at 0, the second at 1 up to the last which is at the length of the array minus 1
if your loop increments, then the smallest value it can have is what ever it starts as, so you shouldn't check to make sure its greater then that, (ie if you start at 2 and increment then you don't need to check to if its greater than or equal to 2 because it always is)
Take a look at the syntax for for loops here
Console console = System.console();
double arr[10];
for(int c = 1; c<10; c++){
String input = console.readLine("Enter a value for the elements 2-9: ");
arr[c] = Double.parseDouble(input);
System.out.println(arr[c]);
}

Categories

Resources