We introduced two-dimensional arrays or tables. Multidimensional arrays are homogenous structures; that is, they store data of only one type. No mixing and matching. For example, it's possible to represent a table (2-dim array) of int's or a table of char's, but not a table with a mixture of int's and char's. This is actually a feature of all arrays, one-dimensional as well as multidimensional.
Example. Write a program that inputs and outputs a gradebook. In particular, the user is asked for the number of students and quizzes respectively. The scores are read in one by one and then a table with headings is output to the screen.
//File: TestTable0.java
import CSLib.*;
public class TestTable0
{
public static void main (String [] args)
{
int [] [] score = new
int [30] [15];
InputBox in = new InputBox();
in.setPrompt("How many students are
enrolled? ");
int students = in.readInt();
in.setPrompt("How many quizzes were given?
");
int quizzes = in.readInt();
for (int
student = 0; student < students; student++)
{
in.setPrompt
("Enter scores for student " + (student+1));
for (int
quiz=0; quiz < quizzes; quiz++)
{
score [student] [quiz] = in.readInt();
}
}
OutputBox out = new
OutputBox();
out.setSize(300, 200);
//The following sets up the headers for the
table
out.println ("The gradebook is as follows:
");
out.print ("Quiz\t");
for (int k=1;
k<=quizzes; k++)
{
out.print (k +
"\t");
}
out.println();
out.println();
for (int s=0;
s<students; s++)
{
out.print (s+1);
for (int
q=0; q<quizzes; q++)
{
out.print ("\t" + score [s] [q]);
}
out.println();
}
}
}
You may remember that we collected several useful list processing methods into the NumberList class. We could do the same here. In particular, suppose we abstract the code for displaying the table. We could actually add two such methods. The first asks the user to supply (as parameters) the table as well as the number of rows and columns in the table.
//IN: OutputBox, Table, Number of rows and columns
public static void display (OutputBox box, int
[] [] x, int rows, int cols)
{
for (int
row=0; row<rows; row++)
{
for (int
col=0; col<cols; col++)
{
box.print ("\t" + x [row] [col]);
}
box.println();
}
}
//The following recognizes that a two-dimensional array is just a
one-dimensional array (rows)
//of one-dimensional arrays (columns)
//IN: OutputBox and Table
public static void display (OutputBox box, int
[] [] x)
{
//x.length is the number of rows in the table
for (int
row=0; row<x.length; row++)
{
//x[row].length is the
number of columns (for that row)
for (int
col=0; col<x[row].length; col++)
{
box.print ("\t" + x [row] [col]);
}
box.println();
}
}
The next version of our table testing program employs the "just in time" instantiation we used with one-dimensional arrays. That is, we won't instantiate (allocate memory) until after we know how many students and quizzes are to be represented.
//File: TestTable1.java
import CSLib.*;
public class TestTable1
{
public static void main (String [] args)
{
int [] [] score;
InputBox in = new InputBox();
in.setPrompt ("How many students are
enrolled? ");
int students = in.readInt();
in.setPrompt ("How many quizzes were
given? ");
int quizzes = in.readInt();
score = new int
[students] [quizzes];
for (int
student = 0; student < students; student++)
{
in.setPrompt
("Enter scores for student " + (student+1));
for (int
quiz=0; quiz < quizzes; quiz++)
{
score [student] [quiz] = in.readInt();
}
}
OutputBox out = new
OutputBox();
out.setSize(300, 200);
//The following sets up the headers for the
table
out.println ("The gradebook is as follows:
");
out.print ("Quiz\t");
for (int k=1;
k<=quizzes; k++)
{
out.print (k +
"\t");
}
out.println();
out.println();
//Choose either of the table display methods
//NumberList.display (out, score);
NumberList.display (out, score, students,
quizzes);
}
}
Finally, if the two-dimensional array can be viewed as just a one-dimensional array of one-dimensional arrays, then perhaps the rows can be of variable length. What follows is a new version of our TestTable program that allows for just that possibility.
//File: TestTable2.java
import CSLib.*;
public class TestTable2
{
public static void main (String [] args)
{
int [] [] score;
InputBox in = new InputBox();
in.setPrompt ("How many students are
enrolled? ");
int students = in.readInt();
/* EACH STUDENT HAS DIFFERENT NUMBER OF QUIZZES
in.setPrompt ("How many quizzes were
given? ");
int quizzes = in.readInt();
*/
//CREATE AN ARRAY OF ARRAYS
score = new int [students] [];
//NEED TO KEEP TRACK OF LARGEST NUMBER OF
QUIZZES TAKEN
//IN ORDER TO SET UP TITLE FOR DISPLAYED TABLE
int maximum_quizzes = 0;
for (int
student = 0; student < students; student++)
{
in.setPrompt ("How
many scores for student " + (student+1) + "?");
int
number_of_quizzes = in.readInt();
//UPDATE
MAXIMUM_QUIZZES
if
(number_of_quizzes > maximum_quizzes)
maximum_quizzes = number_of_quizzes;
//INITIALIZE ARRAY OF
QUIZZES FOR THIS STUDENT
score[student] =new
int [number_of_quizzes];
in.setPrompt
("Enter scores for student " + (student+1));
for (int
quiz=0; quiz<number_of_quizzes; quiz++)
{
score [student] [quiz] = in.readInt();
}
}
OutputBox out = new
OutputBox();
out.setSize(300, 200);
//The following sets up the headers for the
table
out.println ("The gradebook is as follows:
");
out.print ("Quiz\t");
for (int k=1;
k<=maximum_quizzes; k++)
{
out.print (k +
"\t");
}
out.println();
out.println();
NumberList.display (out, score);
}
}
The following function inputs a table of ints from fileName and returns the number of rows and columns.
public static int [] readTable (String
fileName, int [] [] list)
{
int row=0;
int col=0;
String s;
try
{
//Step 2. FileReader
object (stream of chars)
FileReader fr = new
FileReader(fileName); //throws FileNotFoundException
//Step 3.
BufferedReader object (buffers input allowing access from RAM instead of file)
BufferedReader br = new
BufferedReader (fr);
//Step 4. readLine()
message to Buffered Reader object returns String reference to first line of input
String line =
br.readLine(); //throws IOException
while
(line != null)
{
StringTokenizer tokenizer = new StringTokenizer (line);
int ncols = tokenizer.countTokens();
//countTokens() is member function in StringTokenizer class
//It's perfect for this application.
for (col=0; col<ncols; col++)
{
s=tokenizer.nextToken();
list [row] [col] = Integer.parseInt (s);
}
row++;
line = br.readLine();
}
br.close(); //not
invoked if throws exception
}
catch (FileNotFoundException
e)
{
System.out.println
("The file " + fileName + " was not found.");
}
catch (IOException e)
{
System.out.println (e);
}
int [] temp = new int
[2];
temp[0]=row;
temp[1]=col;
return temp;
}
Lab Exercise. Rewrite TestTable0.java using the readTable() method which has now been added to NumberList.java. Use my data file. (If you get frustrated, you can look at my version, TestTable.java. But TRY IT YOURSELF FIRST.)
Lab Exercise. The bubble sort algorithm repeatedly scans the array from left to right interchanging adjacent elements that are out of order; the scan is repeated until no out-of-order pairs are found on a scan. The name of this sorting algorithm comes from the way larger elements "bubble up" toward the right end of the array. Implement the bubble sort and add it to our collection of list processing routines (NumberList.java). Test it on my data file.