2d char array from a file - java

I am trying to read in a string from a file, extract individual characters and use those characters to fill a 2D char array. So far I have been able to do everything except fill the array. I keep getting an Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: error message. Any help would be appreciated. This is my first time working with 2D arrays. Thanks.
Here are the contents of the test.txt. Each word on a new line. The first 2 integers are the dimensions of the array
4 4
FILE
WITH
SOME
INFO
public class acsiiArt
{
public static void main(String[] args) throws IOException
{
File file = new File("test.txt");
Scanner inputFile = new Scanner(file);
int x = inputFile.nextInt();
int y = inputFile.nextInt();
while (inputFile.hasNext())
{
char [][] array = new char [x][y];
//char c = words.charAt(i);
for (int row =0; row<x;row++)
{
for (int col =0; col<y;col++)
{
String words = inputFile.nextLine();
for (int i=0; i<words.length(); i++)
array[x][y]=words.charAt(i);
}
}
}
}
}

for (int row =0; row<x;row++)
{
for (int col =0; col<y;col++)
{
String words = inputFile.nextLine();
for (int i=0; i<words.length(); i++)
array[x][y]=words.charAt(i);
}
}
The total number of indices in array is x * y. Below, you are filling all the possible indices
for (int row =0; row<x;row++)
{
for (int col =0; col<y;col++)
So when you add this:
for (int i=0; i<words.length(); i++)
you multiplying another factor words.length. So you need x * y * words.length number of indices, but you only have x * y. Thats why you're getting ArrayIndexOutOfBoudsException

I've seen problems like this and I'm assuming that x and y are being initialized to the first two characters which represent the number of rows and the number of columns. If that is the case, then third for loop for (int i=0; i<words.length(); i++) is unnecessary. You can just reffer to the col variable for the word at that point, since it should represent how many characters there are.
All of this is only applicable if the chars are in a rectangular pattern, meaning that there are the same number of columns in every row. Otherwise you will get an IndexOutOfBoundsError as soon as one of the lines is shorter than the the column value initially given.
Edit: If you're final 2d char array is not meant to be rectangular and instead "jagged," a different implementation is required. I'd recommend either a 2d arrayList (an arrayList of arrayLists).
Or you can keep your current implementation with the third for loop, but you have to be sure that the original x value represents the longest row/most amount of columns, and then you'd be able to deal with each row indivually with words.length. You'd also have to be fine with the extra portions of the lines that have a length>x having spaces initialized to null.

ArrayIndexOutOfBoundsException means you are using array beyond its limit. So in your case:
char [][] array = new char [x][y];
//char c = words.charAt(i);
for (int row =0; row<x;row++) {
for (int col =0; col<y;col++){
String words = inputFile.nextLine();
for (int i=0; i<words.length(); i++)
array[x][y]=words.charAt(i);
}
}
Problem may be because your array size is less then input words. problem is because you are putting extra loop, and your loop it self is not correct. Please seen code below.
So you can do 2 things.
change value of y large enough so that any word string can store.
rather than looping on size of word you can loop on your array size like.
.
for (int row =0; row<x;row++) {
String words = inputFile.nextLine();
int size = Math.min(words.length(),y);
for (int i=0; i< size; i++)
array[row][i]=words.charAt(i);
}

The easiest way to do this is with an ArrayList<char[]>. All you have to do is add a new char[] for each new line read:
ArrayList<char[]> chars = new ArrayList<>();
while (inputFile.hasNext()){
chars.add(inputFile.nextLine().toCharArray());
}
char[][] array = chars.toArray(new char[chars.size()][]);
An ArrayList is basically an array of changeable size. This code takes each line in the file, turns it into a char[], then adds it to the ArrayList. At the end, it converts the ArrayList<char[]> into a char[][].
If you can't or don't want to use ArrayList, you could always do this:
char[][] array = new char[1][];
int a = 0;
while(inputFile.hasNext()){
//read line and convert to char[]; store it.
array[a] = inputFile.nextLine().toCharArray();
//if there are more lines, increment the size of the array.
if (inputFile.hasNext()){
//create a clone array of the same length.
char[][] clone = new char[array.length][];
//copy elements from the array to the clone. Note that this can be
//done by index with a for loop
System.arraycopy(array, 0, clone, 0, array.length);
//make array a new array with an extra char[]
array = new char[array.length + 1][];
//copy elements back.
System.arraycopy(clone, 0, array, 0, clone.length);
a++;
}
}
If you know the dimensions of the array beforehand:
char[][] array = new char[dimension_1][];
int a = 0;
while (inputFile.hasNext()){
array[a] = inputFile.nextLine().toCharArray();
a++; //don't need to check if we need to add a new char[]
}
In response to comment:
We know that a char[][] cannot be printed with Arrays.toString() (if we want the contents) because we will get a lot of char[].toString(). However, a char[][] can be printed with one of the following methods:
public static String toString(char[][] array){
String toReturn = "[\n";
for (char[] cArray: array){
for (char c: cArray){
toReturn += c + ",";
}
toReturn += "\n";
}
return toReturn + "]";
}
I personally prefer this one (requires import java.util.Arrays):
public static String toString(char[][] array){
String toReturn = "[\n";
for (char[] cArray: array){
toReturn += Arrays.toString(cArray) + "\n";
}
return toReturn + "]";
}

Related

Is there a way to initialize a 2d array with other arrays?

I have been given a homework assignment as follows:
Read three sentences from the console application. Each sentence should not exceed 80 characters. Then, copy each character in each input sentence in a [3 x 80] character array.
The first sentence should be loaded into the first row in the reverse order of characters – for example, “mary had a little lamb” should be loaded into the array as “bmal elttil a dah yram”.
The second sentence should be loaded into the second row in the reverse order of words – for example, “mary had a little lamb” should be loaded into the array as “lamb little a had mary”.
The third sentence should be loaded into the third row where if the index of the array is divisible by 5, then the corresponding character is replaced by the letter ‘z’ – for example, “mary had a little lamb” should be loaded into the array as “mary zad azlittze lazb” – that is, characters in index
positions 5, 10, 15, and 20 were replaced by ‘z’. Note that an empty space is also a character, and that the index starts from position 0.
Now print the contents of the character array on the console.
The methods, return types, and parameters in the code below are all specified as required so I cannot change any of that information. I am having trouble initializing the 2d array. The instructions say that the sentences must be loaded into the array already reversed etc. but the parameters of the methods for doing this calls for strings. I assume that means I should read the lines as strings and then call the methods to modify them, then use toCharyArray to convert them before loading them into the 2d array. I don't understand how to initialize the 2D array with the values of the char arrays. Is there some kind of for loop I can use? Another issue is that no processing can be done inside of the main method but in the instructions there is no method that I can call to fill the array.
import java.util.regex.Pattern;
public class ReversedSentence {
public static String change5thPosition(String s){
char[] chars = s.toCharArray();
for (int i = 5; i < s.length(); i = i + 5) {
chars[i] = 'z';
}
String newString = new String(chars);
return newString;
}
public static String printChar2DArray(char[][] arr){
for (int x = 0; x < 3; x++) {
for (int y = 0; y < 80; y++) {
// just a print so it does not make new lines for every char
System.out.print(arr[x][y]);
}
}
return null;
}
public static String reverseByCharacter(String s){
String reverse = new StringBuffer(s).reverse().toString();
return reverse;
}
public static String reverseByWord(String s){
Pattern pattern = Pattern.compile("\\s"); //splitting the string whenever there
String[] temp = pattern.split(s); // is whitespace and store in temp array.
String result = "";
for (int i = 0; i < temp.length; i++) {
if (i == temp.length - 1)
result = temp[i] + result;
else
result = " " + temp[i] + result;
}
return result;
}
public static String truncateSentence(String s){
if (s==null || s.length() <= 80)
return s;
int space = s.lastIndexOf(' ', 80);
if (space < 0)
return s.substring(0, 80);
return s;
}
public static void main(String[] args) {
String sentence1 = ("No one was available, so I went to the movies alone.");
String sentence2 = "Ever since I started working out, I am so tired.";
String sentence3 = "I have two dogs and they are both equally cute.";
char[][] arr = new char[3][80];
arr[0] = reverseByCharacter(sentence1).toCharArray();
arr[1] = reverseByWord(sentence2).toCharArray();
arr[2] = change5thPosition(sentence3).toCharArray();
printChar2DArray(arr);
}
}
The error I am getting is:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 52 out of bounds for length 52
at ReversedSentence.printChar2DArray(ReversedSentence.java:20)
at ReversedSentence.main(ReversedSentence.java:71)
.enola seivom eht ot tnew I os ,elbaliava saw eno oN
The problem is that in your printChar2DArray method you assume that every array has the length of 80, but that's actually not the case here. In Java, a 2D array is just an array of arrays. So, when you have this: char[][] arr = new char[3][80], you are creating an array of 3 arrays, and each of these arrays has the length of 80 characters. That may seem ok, but in the next lines you reinitialize the 3 arrays with something different entirely.
arr[0] = reverseByCharacter(sentence1).toCharArray();
arr[1] = reverseByWord(sentence2).toCharArray();
arr[2] = change5thPosition(sentence3).toCharArray();
Now none of these arrays has the length of 80. Each of them has the length of the respective string.
You can solve this in 2 ways (depending on how constrained your task actually is).
First, you can copy the string into arrays, instead of assigning the arrays to the results of the toCharArray method. You can achieve this with a simple loop, but I wouldn't recommend this approach, because you will end up with arrays of 80 characters, even if the strings contain less.
String firstSentence = reverseByCharacter(sentence1);
for (int i = 0; i < firstSentence.length(); i++) {
arr[0][i] = firstSentence.charAt(i);
}
Or:
char[] firstSentence = reverseByCharacter(sentence1).toCharArray();
for (int i = 0; i < firstSentence.length; i++) {
arr[0][i] = firstSentence[i];
}
Second, you can drop the assumption of the arrays' lengths in the printChar2DArray method. I recommend this approach, because it makes you code much more flexible. Your printChar2DArray method will then look like this:
public static String printChar2DArray(char[][] arr){
for (int x = 0; x < arr.length; x++) {
for (int y = 0; y < arr[x].length; y++) {
// just a print so it does not make new lines for every char
System.out.print(arr[x][y]);
}
}
return null;
}
You can see that I've substituted numbers with the length field, which can be accessed for any array.
Also, this way you don't need to initialize the inner arrays, because you reinitialize them in the next lines anyway.
char[][] arr = new char[3][];
arr[0] = reverseByCharacter(sentence1).toCharArray();
arr[1] = reverseByWord(sentence2).toCharArray();
arr[2] = change5thPosition(sentence3).toCharArray();
But this approach may not be suitable for your task, because then the sentences could be of any length, and they wouldn't be constained to 80 characters max.
UPDATE - To answer the question in the comment
To print a newline character you can use System.out.println() without parameters. It's better than putting the newline character into the arrays because it's not a logical part of the sentences.
So your for-loop in the printChar2DArray would look like this:
for (int x = 0; x < 3; x++) {
for (int y = 0; y < 80; y++) {
// just a print so it does not make new lines for every char
System.out.print(arr[x][y]);
}
System.out.println();
}

How can I create a new instance of array dynamically if my array size is full in java

I am working on a java program. where I have taken an input string and I am putting each char from a string in a 4*4 matrix. If the input string length is small than 16 i.e 4*4 matrix, then I am adding padding '#' char.
But Now, suppose the input string length is more than 16 then I want to create a new array and put remaining chars into it. I can't use a vector, set, map. So How can I code now?
here is some code. key=4.
char[][] giveMeNewArray() {
char[][] matrix = new char[key][key];
return matrix;
}
void putCharIntoMatrix() {
int counter = 0;
char[][] myArray = giveMeNewArray();
System.out.println("myArray: " + myArray);
for (int i = 0; i < key; i++) {
for (int j = 0; j < key; j++) {
if (counter >= inputString.length()) {
myArray[i][j] = '#';
} else {
myArray[i][j] = inputString.charAt(key * i + j);
}
counter++;
}
}
for (int i = 0; i < key; i++) {
for (int j = 0; j < key; j++) {
System.out.print(myArray[i][j] + " ");
}
System.out.println();
}
}
So if I'm understanding this question correctly, you want to create a matrix to hold the characters of an input string, with a minimum size of 4*4?
You're probably better off creating a proper matrix rather than expanding it:
Do you want your matrix to always be square?
Get the next-highest (self-inclusive) perfect square using Math.sqrt
int lowRoot = (int)Math.sqrt(inString.length());
int root;
if(lowRoot * lowRoot < inString.length())
root = lowRoot+1;
else
root = lowRoot;
Create your matrix scaled for your input, minimum four
int size = (root < 4) ? 4 : root;
char[][] matrix = new char[size][size];
But if you really want to expand it, you can just create a new matrix of a greater size:
char[][] newMatrix = new char[oldMatrix.length+1][oldMatrix[0].length+1];
And copy the old matrix into the new matrix
for(int i = 0; i < oldMatrix.length; ++i){
for(int j = 0; j < oldMatrix[i].length; ++j){
newMatrix[i][j] = oldMatrix[i][j];
}
}
If you expand by one each time you'll do tons of expands, if you expand by more you might expand too far.
This is really inefficient versus just doing some math at the beginning. Making a properly sized matrix from the start will save you a bunch of loops over your data and regularly having two matrices in memory.
If understand you request correctly, if the string length is bigger than 16 you just create a new array, well how about making a list of array initilized at one array and if there are more than 16 chars just add an array to the list using your method that returns an array.

JAVA 2D String array column numbers

I have a CSV file which I have to read to a 2D string array (it must be a 2D array)
However it has different column number, like:
One, two, three, four, five
1,2,3,4
So I want to read those into an array. I split it everything is good, however I don't know how not to fill the missing columns with NULLs.
The previous example is:
0: one,two,three,four,five (length 5)
1: 1,2,3,4,null (length 5)
However I want the next row's length to be 4 and not 5 without null.
Is this possible?
This is where I've got so far (I know it's bad):
public static void read(Scanner sc) {
ArrayList<String> temp = new ArrayList<>();
while(sc.hasNextLine()) {
temp.add(sc.nextLine().replace(" ", ""));
}
String[] row = temp.get(0).split(",");
data = new String[temp.size()][row.length];
for (int i = 0; i < temp.size(); ++i) {
String[] t = temp.get(i).split(",");
for (int j = 0; j < t.length; ++j) {
data[i][j] = t[j];
}
}
}
Sounds like you want a non-rectangular 2-dimensional array. You'll want to avoid defining the second dimension on your 2D array. Here's an example:
final Path path = FileSystems.getDefault().getPath("src/main/resources/csvfile");
final List<String> lines = Files.readAllLines(path);
final String[][] arrays = new String[lines.size()][];
for (int i = 0; i < lines.size(); i++) {
arrays[i] = lines.get(i).split(",");
}
All lines are read into a List so that we know the first dimension of the 2D array. The second dimension for each row is determined by the result of the split operation.

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
}

java: How to split a 2d array into two 2d arrays

I'm writing a program to multiply matrices (2d arrays) as efficiently as possible, and for this i need to split my two arrays into two each and send them off to a second program to be multiplied. The issue I have is how to split a 2d array into two 2d arrays, at specific points (halfway). Does anyone have any ideas?
Lets say you have a 2d array of strings like so
String[][] array= new String[][]
{
{"a","b","c"},
{"d","e","f"},
{"h","i","j"},
{"k","l","m"}
};
Now you need a way to split these arrays at the half way point. Lets get the halfway point. Figure out how big the array is and then cut it in half. Note that you also must handle if the array is not an even length. Example, length of 3. If this is the case, we will use the Math.floor() function.
int arrayLength = array.length;
int halfWayPoint = Math.floor(arrayLength/2);
//we also need to know howmany elements are in the array
int numberOfElementsInArray = array[0].length;
Now we have all the info we need to create two 2d arrays from one. Now we must explicitly copy create and copy the data over.
//the length of the first array will be the half way point which we already have
String [][] newArrayA = new String[halfWayPoint][numberOfElementsInArray];
//this copies the data over
for(int i = 0; i &lt halfWayPoint; i++)
{
newArrayA[i] = array[i];
}
//now create the other array
int newArrayBLength = array.length - halfWayPoint;
String[][] newArrayB = new String[newArrayBLength][numberOfElementsInArray];
/*
* This copies the data over. Notice that the for loop starts a halfWayPoint.
* This is because this is where we left of copying in the first array.
*/
for(int i = halfWayPoint; i &lt array.length; i++)
{
newArrayB[i] = array[i];
}
And your done!
Now if you want to do it a little nicer, you could do it like this
int half = Math.floor(array/2);
int numberOfElementsInArray = array[0].length;
String [][] A = new String[half][numberOfElementsInArray];
String [][] B = new String[array.length - half][numberOfElementsInArray];
for(int i = 0; i &lt array.length; i++)
{
if(i &lt half)
{
A[i] = array[i];
}
else
{
B[i] = array[i];
}
}
And lastly, if you dont want to do it explicitly, you can use the built in functions. System.arraycopy() is one example. Here is a link to its api System.arraycopy()
int half = Math.floor(array/2);
int numberOfElementsInArray = array[0].length;
String [][] A = new String[half][numberOfElementsInArray];
String [][] B = new String[array.length - half][numberOfElementsInArray];
System.arraycopy(array,0,A,0,half);
System.arraycopy(array,half,B,0,array.length - half);

Categories

Resources