while (myStringTokenizer.countTokens() > numberOfTokens-n+2)
output += ";" + myStringTokenizer.nextToken();
output += ";" + "n";
// We now read the token we replaced but don't record it.
s = myStringTokenizer.nextToken();
// Now we go through the rest of the tokens and add them to the
// String output.
while (myStringTokenizer.countTokens() > 0)
output += ";" + myStringTokenizer.nextToken();
// Now we are ready to write the String back to the file so we
// again declare a FileWrite object and a PrintWriter object.
FileWriter file1 = new FileWriter("Eratosthenes.data");
PrintWriter outputFile = new PrintWriter(file1);
// We write the string to the file.
outputFile.println(output);
// We now close the file.
outputFile.close();
}
public static void main(String[] args) throws IOException {
// In order to get input from the user we must use the InputStreamReader
// and BufferedReader classes.
InputStreamReader stream = new InputStreamReader(System.in);
BufferedReader keyboard = new BufferedReader(stream);
System.out.println("Please enter n");
// We now use a wrapper class to turn the String that the user input
// into an int.
int n = new Integer(keyboard.readLine()).intValue();
// Now we set up an output file and prepare it to be written to. We
// use the FileWriter and PrintWriter classes.
FileWriter file = new FileWriter("Eratosthenes.data");
PrintWriter outputFile = new PrintWriter(file);
// We initialize our output String with a beginning "y".
String output = "y";
// Now we add in "y"s corresponding to all numbers up to n.
for (int counter=3;counter<=n;counter++)
output += ";" + "y";
// Now we write the String to our output file.
outputFile.println(output);
// Now we close the output file.
outputFile.close();
// We now set up two loops. The outer loop will go from 2 to the
// integer portion of the square root of n. The inner loop will
// go from counter+1 to n. If the counter variable in the inner
// for loop has a zero remainder when we divide it by the counter
// variable in the outer for loop, when we then change the string
// in the position corresponding to the counter variable in the inner
// loop in the String stored in Eratosthenes.data to an "n".
for (int counter=2;counter<=(int)(Math.sqrt(n));counter++)
for (int counter1=counter+1;counter1<=n;counter1++)
if (counter1 % counter == 0)
Write.change_string(counter1);
// Now that the string is set up, we read it from the file, and
// tokenize it. For each token we get to, if it is a "y" we report
// that the number corresponding to that position is a prime
// number. Otherwise we report that the number corresponding to
// that position is not a prime number.
FileReader file1 = new FileReader("Eratosthenes.data");
BufferedReader inputFile = new BufferedReader(file1);
String s = inputFile.readLine();
StringTokenizer myStringTokenizer = new StringTokenizer(s,";");
int counter = 2;
while (myStringTokenizer.countTokens() > 0)
if (myStringTokenizer.nextToken().equals("y"))
System.out.println(counter++ + " is prime.");
else
System.out.println(counter++ + " is not prime.");
}
}
Write.java
There is a runtime error/logic error that comes up sometimes in Object-Oriented
Programming that may be very difficult to correct. This runtime error/logic error is
a NullPointerException. Consider the following code.
public class Test {
String a;
public Test(String b) {
String a = b;
}
public void display() {
a = a.concat(" ");
}
public static void main(String[] args) {
Test myTest = new Test("3");
myTest.display();
}
}
The code compiles without errors. However, when the program is run the
following error is reported.
java.lang.NullPointerException
at Test.display(Test.java:9)
at Test.main(Test.java:15)
The reason for this is the following.
Recall that String is an object. When we make the declaration String a, we
are declaring a new reference to a String object. When
the object is created, this reference is by default set to null. That is,
the reference points nowhere. So we can't do some of the things with
this reference that we would normally do with a reference to an actual
object.
When a method is entered by Java, its allocates space for all of the parameters in
its formal parameter list and also any variables declared within the
method. However, these variables are only allocated space as long as
Java is executing that method. When Java is done executing that method,
all space that was allocated for variables within the method is
deallocated and those variable references are no longer valid.
Notice that when the class is instantiated a new reference called a is created
and by default set to null. When the compiler enters the constructor a
local variable called a is created and given the value b.
So when the constructor is finished executing, the new reference a is
no longer valid. So any reference to a in other parts of the class refers
to the instance variable a, which is still set to null.
In the method display() we try to concatenate something onto the String
object pointed to by a. However, a still points to nothing. Therefore,
Java reports a NullPointerException.
There are a few definitions related to this concept.
Scope - The scope of an identifier refers to the region of a
program in which an identifier can be used.
Class Scope - An identifier with class scope is accessible from
it point of declaration throughout the entire class. Examples of these
would be instance variables and class variables.
Block - A block is a section of code beginning with an {, ending
with a }, and containing declarations and executable statements.
Block Scope - An identifier with block scope is only accessible
from its point of declaration to the end of the block.
Consider the following two programs.
public class Test1 {
public static void main(String[] args) {
String a = "2";
String a = "3";
}
}
When this program is compiled the following error is reported.
Test1.java:6: Variable 'a' is already defined in this method.
String a = "3";
^
1 error
public class Test2 {
public static void main(String[] args) {
for (int counter=1;counter<=10;counter++) {
String a = "3";
}
String a = "2";
}
}
The second program compiles with no problem. The reason for this is
that in the second program the first declaration of the String object
a is within a block. So after the block is finished executing, the object
reference a is no longer accessible. That is, Java doesn't know about
a variable called a.
Lifetime - the lifetime of an identifier is the period during
which an identifier is known to the computer.
Heap - the heap is a special area of memory reserved for the dynamic
allocation of computer memory to objects during run-time.
Garbage - after an object is allocated space on the heap and we lose
the reference to the object, then the object is considered garbage.
Garbage Collection - instead of allowing unreferenced space to take
up computer memory we perform garbage collection to remove all objects
that are garbage. In Java this is done automatically.
Recall the points we mentioned about primitive data types.
When dealing with ints, floats, doubles, and other numeric data types Java can perform automatic type conversion if it can
safely store one data type in another.
For example,
int a = 3;
double b = a;
is legal because Java can safely store an int as a double.
However,
double a = 3.0;
int b = a;
is not allowed because Java can't safely store a double as an int.
Java can safely store one data type as another if it can do so without losing any bits. Since a double is stored in 8 bytes
and can contain much larger numbers than ints, we won't lose any bits if we store an int as a double. However, since an int
is only stored in 4 bytes, its possible that we could lose some bits if we tried to store a double as an int.
We now come to the last major construct we will discuss this semester. Before we discuss let's consider the following
problem.
Suppose you are put in charge of collecting information about customers. Since your business is very small you only have five
customers. So to store their names you might use variable references like the following.
String customer1 = "Karl Gauss";
String customer2 = "Neils Henrik Abel";
String customer3 = "Evariste Galois";
String customer4 = "Augustin Louis Cauchy";
String customer5 = "Karl Weierstrass";
Similarly you could contain their addresses in variables address1, address2, ..., address5. You could also collect other
information about them.
You could then print out reports based on their purchases.
This process will work very well while you have only five customers. But what happens when your business grows to ten
customers, one hundred customers, or one thousand customers?
There must be a more efficient way of storing information about these customers than to create ten, one hundred, or one
thousand different variables.
There is a more efficient way of doing this. It is called an array.
The Array
An array is a named collection of entities all of the same type. That is an array might be a collection of ints, floats,
doubles, Strings, or other objects.
The elements stored in an array are accessed by the name of the array and the position in the array in which the element is
stored.
An array can have more than one-dimension but let us begin our discussion with a one-dimensional array.
To declare an array we can use the following syntax.
data-type[] arrayname = new data-type[number of entries];
For example if we want to declare a one-dimensional array of Strings called customer we could use the following syntax.
String[] customer = new String[5];
As always Java begins counting at 0.
So the first element in the array is in position 0.
In order to get experience using an array consider the following problem.
Suppose you wish to create an array whose elements are 5-minute blocks of time from 7:00 am to 11:00 pm. For times after Noon
we will use military time.
For example the array should contain the following.
times[0] = 700;
times[1] = 705;
times[2] = 710;
times[3] = 715;
times[4] = 720;
times[5] = 725;
times[6] = 730;
times[7] = 735;
times[8] = 740;
times[9] = 745;
times[10] = 750;
times[11] = 755;
times[12] = 800;
...
As another exercise try rewriting the Sieve of Eratosthenes with an array? Do you find it much easier?