Primer in Reading Input for CS1020
Types of Input Reading
Although there can be theoretically infinitely many ways to read input in CS1020, many of the sit-in lab problems can be reduced into three basic block. From these three basic blocks of input reading methodology, many combinations can be made. Practice these three input types carefully and know when to use them appropriately.
1. Type 1: Given N, Read The Next N Lines
The first input reading is the easiest among the three. So, it is good if we start with this one first. In this input type, the description is as follows:
The first line is N which is the number of next inputs. The next N lines consists of the inputs.
The format generally reduces to such statements. In essence, you are given the number of elements you are supposed to read.
So, directly from the statement, we know that there should be a loop in our input reading. This loop should go for N times, regardless of the way we do the looping. Inside the loop, we should read the input based on the format of the input (which is ignored in this abstraction to show you the barebone of the input reading method).
A direct translation of the description above into a pseudo-code will yield the following:
- N = integer;
- LOOP: from i = 1 to N
- // Read the rest of the input
To translate this pseudo-code into a working code, we have to do it step-by-step. Starting from the first line “N = integer”, we convert it to read from the Standard Input using Scanner Class. Since the type is integer, we have to use the method: Scanner.nextInt() which returns exactly what we need, an integer type. The code becomes: “int N = sc.nextInt();” where sc is declared as Scanner sc = new Scanner(System.in).
The second line is a loop. There are two useful loop-construct available in JAVA (or in most other programming languages). The first construct is called the for-loop. In the for-loop, we specify three statements: 1. The initial condition, 2. The continuing condition, and 3. The end statement (what statement is executed at the end of each for-loop block). To iterate for N-times, the usual method is: “for (int i=0; i<N; i++)”. Notice that although in the pseudo-code we specify that we are looping from 1 to N, in the for-loop construct, we are looping from o to N-1. Both are equivalent.
Now, combining both, we will get the following:
- int N = sc.nextInt();
- for(int i=0; i<N; i++) {
- // Read the rest of the input
- }
2. Type 2: Read Until Special Character/Number
In this second type of input reading, we do not know how many inputs will be available. However, we will know that in the input, there will be special characters/numbers which signals the end of input sequence. The input specification might be written as follows:
Read the input until you read 0.
It is very important to elaborate about the underlined part. The statement above may as well be written to be “Read the input until you read -1″ or “Read the input until you read exit”. Nevertheless, you should know what the terminating sequence is.
After you know what the terminating sequence is, it is important to know the data type of the terminating sequence. When you read until 0 or -1, it is easy to assume that we should read integer. This, in fact, might lead to an error. The data type of the terminating sequence cannot be determined independently by itself but it has to follow the more general between the terminating character and the first input in the input format.
To explain this, let’s take a look at the following input specification:
The input consists of the following: Name (in String), Age (in Integer), and Height (in Double). Read the sequence until you read -1 in the input.
The bracket is what you should highlight yourself, it might not be given in the question. Now, what should the data type of the terminating character -1 be? To answer that, notice that the input sequence will start with Name, which is a String. -1 will appear in the place of Name. So, we should be taking the more general of the two, which is the String. As such, the terminating character should be regarded as a String.
After determining the data type of the terminating character, the next step is to write the pseudo-code. Rephrasing the problem helps to design the pseudo-code too. The following two rephrases are equivalent to the input statement above:
A. While the input is not [terminating character], read the input sequence.
B. Read input sequence unless we encounter [terminating character], if so, exit the loop.
Let’s follow the method A first. In method A, we can write the pseudo-code as follows:
- name = String;
- LOOP: while name is not “-1″
- age = integer;
- height = double;
- // since we will go back to loop after this
- // we should read name one more time to be checked at line 2
- name = String;
What you should note in the above pseudo-code is that the checking is done at line 2. So, before we execute line 2, the variable name has to reflect the latest value so that age and height is not read at all. That’s why at line 7, we re-read the name because in a while-loop, we will go back to line 2 after we execute the last statement in the block. In addition, the checking of -1 should be done as String comparison, which in JAVA, should use String.equals(String) method. Lastly, because we are rewriting the value of name at line 7, in between line 4 (where all the inputs have been collected) and line 7 (where we rewrite the value), the data should be processes (either used, or stored). The code will then look as follows:
- name = sc.next();
- while(!name.equals(“-1″)) {
- age = sc.nextInt();
- height = sc.nextDouble();
- // PROCESS THE DATA HERE
- name = sc.next();
- }
Now, following the method B, we arrive at the following pseudo-code:
- LOOP: infinitely
- name = String;
- if (name is “-1″)
- exit the loop;
- age = integer;
- height = double;
In this second method, we do not know when will the terminating character is encountered. As such, the loop should run possibly infinitely. The exit from the loop itself is done at line 4. The checking of the terminating character should be done right after the reading of the first input (which is name). Lastly, the data can be used/stored anywhere after line 6 as long as it is still inside the while-loop block. The code would look like the following:
- while (true) {
- name = sc.next();
- if (name.equals(“-1″)) {
- break; // exit from the loop
- }
- age = sc.nextInt();
- height = sc.nextDouble();
- // PROCESS DATA HERE
- }
3. Type 3: Read Until End-of-File
This last basic block of input reading is notably where most of the past students have problems. One reason is because of the rarity in which it occurs in past sit-ins that when it comes, most have forgotten how to use it. Another reason is the lack of available practice in this type of input because again, the rarity on which it occurs. Nevertheless, it may still come out in sit-in labs, or other scenarios as well. This type of input will have input statement similar to the following:
Read the input sequence until there’s no more input.
The phrase “until there’s no more input” indicates that you should read until End-of-File character (or EOF) is read. The difference between this input type and the previous one is that in this third type, there’s no terminating character at all. So how do we know when we have reached the end of the input? The good news is JAVA provide exactly such function:
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Scanner.html#hasNext%28%29
Firstly, recognize that the hasNext method has several variants which corresponds to the data type (similar to Scanner.next() variants). Afterwards, we can construct the following pseudo-code:
- LOOP: until there’s no more input
- // Read input and process
hasNext method returns a boolean, which is perfect to use in a while loop as follows:
- while(sc.hasNext()) {
- // Read input and process
- }
This last input type is not too hard once you understand the basic of input reading. You should practice on these three input reading methodology well as they can come in several variants, each of which is related to these three basic building block in making complex input reading.
Combining Input Reading Method
1. Matrix Type: Two Type 1 Input Reading
In this matrix type variants, the essence is that, the first two numbers dictates the size of the matrix. The input will be in the shape of a matrix, and we have to process it as such. For example, the following input statement is matrix type:
The first line consists of two numbers, N and M. The next N lines will consists of M numbers.
The visualization of such input is this:
1.1 1.2 1.3 … 1.M
2.1 2.2 2.3 … 2.M
…
N.1 N.2 N.3 … N.M
So, we know that we need two loops, since we are given a matrix. The problem is, how to construct the loop. Fortunately, we should know the size of the matrix in advance. So, we should have created the following matrix: int[][] matrix = new int[N][M];. Now, all we need is just to loop twice like in this pseudo-code:
- N = integer; M = integer;
- LOOP: from i=1 to N
- LOOP: from j=1 to M
- // Read input and put in matrix
which can be easily transformed into the following code:
- int N = sc.nextInt(); int M = sc.nextInt();
- for (int i=0; i<N; i++) {
- for (int j=0; j<M; j++) {
- matrix[i][j] = sc.nextInt();
- }
- }
2. Combination of Type 2 and Type 1
In this combination, there can be two possibilities: 1. Type 2 is outside, type 1 is inside type 2, or 2. Type 1 is outside, type 2 is inside type 1. We will discuss both here.
A. Type 2 Outside, Type 1 Inside
In this input reading method, the input is further divided into smaller cases. One possible input statement is as follows:
You should read the number of input until you encounter -1. If it is not -1, it means it will be greater than 0. Let this number be N, this number indicates in the next N-lines will be the items.
Visualization of the input is as follows:
N1
item 1
item 2
…
item N1
N2
item 1
item 2
…
item N2
…
-1
Notice that we can just put the block corresponding to type 1 input inside the type 2 directly. The following pseudo-code does exactly that:
- N = integer;
- LOOP: as long as N != -1
- LOOP: for i=1 to N
- // Type 1 Input
- END LOOP
- N = integer; // for next check
- END LOOP
The outer loop is of type 2 input while the inner loop is of type 1. We can easily convert this to the following code:
- int N = sc.nextInt();
- while (N != -1) {
- for (int i=0; i<N; i++) {
- // Type 1 Input
- }
- N = sc.nextInt();
- }
B. Type 1 Outside, Type 2 Inside
The same idea also applies for the reverse. However, we end up with the following pseudo-code:
- N = integer;
- LOOP: for i=1 to N
- term_char = String;
- LOOP: while term_char is not equal to [terminating character]
- // Type 2 Input
- term_char = String;
- END_LOOP
- END_LOOP
and end up with the following code:
- int N = sc.nextInt();
- for (int i=0; i<N; i++) {
- String term_char = sc.next();
- while (!term_char.equals(TERMINATING_CHARACTER)) {
- // Type 2 Input
- term_char = sc.next();
- }
- }
3. Combination of Type 3 and Type 1/2
Unlike the point above, this type cannot have type 3 inside the type 1 or type 2 for the simple reason that type 3 reads until there’s no more input, so it has to be outside. I hope by now you should be familiar with this kind of combination that you can easily construct this. As such, I will just give the code directly.
A. Type 3 Outside, Type 1 Inside
- while (sc.hasNext()) {
- int N = sc.nextInt();
- for (int i=0; i<N; i++) {
- // Type 1 Input
- }
- }
B. Type 3 Outside, Type 2 Inside
- while (sc.hasNext()) {
- while(true) {
- name = sc.next();
- if (name.equals(“0″)) {
- break;
- }
- // Type 2 Input (the rest)
- }
- }
Conclusion
The basic building block of input reading is the three simple block (named Type 1, Type 2, and Type 3). From these three basic building block, we can combine them into a more complex input reading. These three are expected in the sit-in lab, but there are more variants of input reading when you take Competitive Programming. More advanced input reading includes having whitespaces separating legal input (which will cause the Scanner.nextInt() to only read partial value, which is wrong), having non-whitespace as delimiter (so you cannot use Scanner.next() correctly), etc.
However, for the purpose of CS1020, in most cases, the combination of these three will suffice. Make sure you master them.