In this course I
have decided to have programs that read and write directly to the
console window from which you issue Linux commands. I have also decided
to use only code that is provided directly as part of the Java system.
This means that some fairly complicated looking code has to be
provided to enable you to read and write things. You needn't worry
about this code, it isn't part of the course that you have to
understand
it, or be able to remember it and reproduce it under exam conditions.
If you like, just forget it and take it on trust that it works as
stated.
But I give a little more explanation of it
below for anyone who is interested.
The code presented in these revision notes can be found here.
import java.util.*;Assuming this code is held in a file called
import java.io.*;
class CountNumber1
// A program to read a list of numbers then read one number and
// count the number of times it occurs in the list.
{
public static void main(String[] args) throws Exception
{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter a list of numbers (all on one line):");
String line = in.readLine();
StringTokenizer toks = new StringTokenizer(line);
int[] a = new int[toks.countTokens()];
for(int i=0; i<a.length; i++)
a[i] = Integer.parseInt(toks.nextToken());
System.out.print("Enter a number: ");
line = in.readLine();
int n = Integer.parseInt(line);
int count=0;
for(int j=0; j<a.length; j++)
if(a[j]==n)
count++;
System.out.print("The number "+n);
System.out.println(" occurs "+count+" times in the list");
System.out.println("That's all");
}
}
CountNumber1.java
,
issuing the Linux command javac CountNumber1.java
will
cause a file called CountNumber1.class
to be produced,
and then
issuing the Linux command java CountNumber1
will
cause
the program to be executed, issuing a prompt for a list of numbers to
be typed in, a prompt for a further number to be typed in, and then
printing
the number of times this further number occurs in the list. For
example,
the following shows one possible run of the program:
Enter a list of numbers (all on one line):
21 67 8 19 21 3 64 52 21 12
Enter a number: 21
The number 21 occurs 3 times in the list
That's all
You will note immediately that some of the code doesn't look like the sort of things you have covered. That is because the code includes what is necessary to read the numbers from the screen, using only what is provided as a built-in part of the Java language. Up till now, in the Procedural Programming course you have had simplified input/output using a package provided by the author of the text book you used. The code here doesn't assume any pre-existing code except that provided as a standard part of Java. But, at this stage, don't worry about that. In fact the only code here that really does the main thing we are interested in: counting the number of times a number occurs in a list of numbers is the following lines:
for(int j=0; j<a.length; j++)With these lines, if the variable
if(a[j]==n)
count++;
a
refers to an array
of integers, and the variable n
holds a particular
integer, after the code is executed, the variable count
will hold an integer which is a count of the number of times the
integer in variable n
occurs in the array referenced by
variable a
.
This is why the indentation (putting spaces on the left-hand side)
is important, since though you can't draw the boxes when writing Java
code to show where one statement is inside another, you can show it
by indentation. The line reading if(a[j]==n)
starts a
few spaces to the right of the line reading
for(int j=0; j<a.length; j++)
to show
that it is inside the for-loop headed by that line. The line reading
count++;
starts a few more spaces to the right to show
that
it is inside the if-statement which is headed with if(a[j]==n)
.
The line of code reading System.out.print("The number "+n);
which comes after the important bit of code and just prints out a
message giving the result is indented the same number of spaces as
the line reading for(int j=0; j<a.length; j++)
,
which shows that it is not part of the for-loop, it is a
separate
statement that comes after the for-loop. This could be shown
diagrammatically as:
The indentation is purely to enable human viewers of the code to be
able
to make out its structure easily. Java treats any number of spaces and
new lines equally as if it were a single space, so whether the code is
indented or not does not alter how Java treats the code. So how does
Java know which statement is inside which, for example that
count++;
is inside the if-statement which is inside the
for-loop, while System.out.print("The number "+n);
is not?
The answer is that a for-loop is defined as the header for(...;...;...)
followed by a single statement,
while an if-statement has two forms: either if(...)
followed by a single statement, or if(...)
followed by a single statement followed by else
followed
by another statement. So, following the for(...;...;...)
header, only the next statement is in the for-loop. The only way
multiple statements can be put into a for-loop is to use the brackets
{
and }
. These are defined as turning
a list of statements within the brackets into a single statement, so
the following:
{is regarded as a single statement, made up of
statement1;
statement2;
.
.
.
statementn;
}
n
substatements.
This means that when we have:
for(int j=0; j<a.length; j++)we can see that following
if(a[j]==n)
count++;
System.out.print("The number "+n);
for(int j=0; j<a.length; j++)
there is no {
so just the next statement is in the
for-loop. The next statement starts with if(a[j]==n)
so it must be an if-statement, but there is no {
following
that, so only the next statement is in the part of the if-statement
obeyed if the test, a[j]==n
evaluates to true
.
The next statement is count++;
that is not followed by
the
word else
so we know this is an if-statement without an
else part. This means that the following statement System.out.print("The number "+n);
is not part
of the if-statement, and since only the if-statment is in the for-loop,
is not part of the for loop either.
If we changed the code, putting in brackets so it read:
for(int j=0; j<a.length; j++)everything from the
if(a[j]==n) {
count++;
System.out.print("The number "+n);
System.out.println(" occurs "+count+" times in the list"); }
System.out.println("That's all");
{
to the }
would
form a single statement with three substatements. This means
that running the code with the same number as above would cause
Enter a list of numbers (all on one line):to be printed. This is because the single statement which would be better written:
21 67 8 19 21 3 64 52 21 12
Enter a number: 21
The number 21 occurs 1 times in the list
The number 21 occurs 2 times in the list
The number 21 occurs 3 times in the list
That's all
{is inside the if-statement which is inside the for-loop. Diagrammatically, this could be shown as:
count++;
System.out.print("The number "+n);
System.out.println(" occurs "+count+" times in the list");
}
If that is the effect your really want, your code should be laid out to make the structure clear:
for(int j=0; j<a.length; j++)This is the style that was recommended to you previously. The closing bracket is directly below the start of the word which starts the statement. That's fine as a layout style, although my personal preference is to have the opening bracket on a line of its own below the header of the statement and indented, with its matching closing bracket directly below it, in this case:
if(a[j]==n) {
count++;
System.out.print("The number "+n);
System.out.println(" occurs "+count+" times in the list");
}
System.out.println("That's all");
for(int j=0; j<a.length; j++)Either way makes the structure of the code clear by its layout. You will note that all recommendation for programming style in Java and similar languages say that individual lines of code should be consistently indented to show the depth within the structure. No-one recommends that closing brackets be put at the end of lines of code, where they would easily be missed. You should always think of the opening bracket and closing bracket as forming a pair with the code in between forming a block. If, when you are programming, you think in terms of moving or putting in or taking out individual
if(a[j]==n)
{
count++;
System.out.print("The number "+n);
System.out.println(" occurs "+count+" times in the list");
}
System.out.println("That's all");
{
s
and }
s, it suggests you have the wrong approach to
programming and need to change your way of thinking. Unfortunately,
this wrong approach to programming can be encouraged by bad teaching,
and badly-designed programming languages which you may have encountered
beforehand outside university.
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));and just take it for granted that it reads from the screen in such a way that the array
System.out.println("Enter a list of numbers (all on one line):");
String line = in.readLine();
StringTokenizer toks = new StringTokenizer(line);
int[] a = new int[toks.countTokens()];
for(int i=0; i<a.length; i++)
a[i] = Integer.parseInt(toks.nextToken());
System.out.print("Enter a number: ");
line = in.readLine();
int n = Integer.parseInt(line);
a
is set to an array of a list of
numbers typed in, and the variable n
is set to a further
number that is types in.
You may have noticed that whereas previously you wrote the code
for a class, called say Fred
with header
class Fred extends basichere the code is written with header just
class CountNumber1that is, without the
extends basic
. That was the bit that
gave you access to the code written by the author of the textbook
you used in your first programming course,
which provided some simple input/output methods.
We are not using that textbook in this course, though it is assumed you
are
familiar with the basic programing it covered. So I have decided not to
carry on using the I/O methods from that textbook. Instead, I have
decided
to use I/O provided as part of the Java language, access to which is
gained
by the use of the import
statements you see in the code
example.
For a little more explanation, BufferedReader
is
a type of object defined in the Java package java.io
.
Because it is in this package, if you want to make use of it you
have to put the line
import java.io.*;
in the file where you use it, above the class definition where
it
is used. An import statement like this is the only part of Java
code that occurs outside a class definition.
The line
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));is actually a declaration of a variable called
in
of type
BufferedReader
. The variable could be called anything, it
needn't be called in
, although the variable that does
what it
does usually is. The declaration also contains an initialisation. The
expression new BufferedReader(new InputStreamReader(System.in))
created a new object of type BufferedReader
which reads
from window the Linux command to run the Java program was issued from,
and in
is set to this. You needn't worry about why the
expression has the form it has, if you wish to find out more, consult
some Java reference.
The only thing you need to know about a BufferedReader
object is that if buf
is a variable referring to the
object, then buf.readLine()
is an expression which
returns, as a Java String
the next line of whatever
the object is reading from, and sets it to read the line after that
next time buf.readLine()
is called. So, with in
declared and initialised as above, in.readLine()
will
read the next line of text typed into the console window, and set the
reader so the line after that is read if it is called again.
This means that the line
String line = in.readLine();reads in the whole line of text making up the list of numbers. This line is broken up into individual numbers using something available in Java called a "string tokenizer". At this stage I am not going to give details on how it works, just take it that the lines of code
StringTokenizer toks = new StringTokenizer(line);cause an array of integers of length equal to the number of integers in the line of code to be created, then puts the individual numbers into the array in order. The type
int[] a = new int[toks.countTokens()];
for(int i=0; i<a.length; i++)
a[i] = Integer.parseInt(toks.nextToken());
StringTokenizer
is
given in the Java package java.util
, which is why
the import statement import java.io.*;
was required.
The code is not designed to handle anything but a list of integers
separated only by spaces being typed in. If anything else is typed
in when the program is executed, it will "crash", but that just means
it
will halt and print a lengthy error message, which you won't understand
at this point.
It is worth discussing how to convert a string of characters representing an integer into the actual integer. The lines
line = in.readLine();do this. The first reads a line of text from the screen which it is assumed are the characters which together represent a single integer. The variable called
int n = Integer.parseInt(line);
line
is set to refer to it. Note,
this
is the same variable that was declared and set to a line of text
representing a list of numbers in the statement
String line = in.readLine();Now the variable is being reused to store something else, the line of characters typed in next to represent the integer being counted.
It is important to be aware of the fact that, for example, the
string "365"
is not at all the same thing as the
integer 365. The first is the list of characters '3'
,
'6'
and '5'
. The second is a number, which
in
the computer will be stored in a way that doesn't use 3, 6 or 5 at
all, since that's just what is used in the decimal representation of
the number. Computers, of course, store numbers in binary form. When
programming in Java, if you have a string of characters which
are the characters the decimal representation of an integer would
take, you have to do something to get the actual integer.
The statement
int n = Integer.parseInt(line);declares a new integer variable
n
and sets it to
the value obtained by converting the string referenced by variable
line
into an integer. For any string referenced by
variable str
, the expression Integer.parseInt(str)
will give the integer equivalent of the string. If str
does not represent an integer, trying to convert it in this way
will cause Java to "throw an exception". You needn't worry what
"throwing an exception" means now, just assume for now it means the
program will crash and some error message will be printed.
If this were a course on "how to use Java", we could go on in a lot more detail about Java input/output. We might move from what is here to discussing how Java is really meant for applications with a graphical user interface, not a plain text interface, and go into the details of graphics provided by Java. But this isn't that sort of course, it's a course on algorithms and data structures which just happens to use Java to give working programs because Java, for various reasons, has been adopted as the main language for teaching programming in Computer Science at Queen Mary. The important thing, however, is not Java, but the algorithms and data structures. We will only cover enough Java to support the programs you have to run, write and understand to learn about the algorithms and data structures this course is really about. Even then, most of the code to do with input/output you can just take on trust and don't need to think about too much. Obviously, if the intricacies of Java do interest you, you could study more about them in your own time out of interest. A good place to start would be the official Java tutorial. You might also find some useful links on a page I maintain, Useful and interesting links for new Java programmers.
Last modified: 13 December 2002