2.2 SIMPLE PROGRAMS:TERMINAL IO


2.2 SIMPLE PROGRAMS:TERMINAL I/O

Let's now compare simple C, C++, and Java programs for eliciting information from a user and then printing something out in response on the terminal.

Here is a C program that asks the user to type in a sequence of integers, all in one line. The integers are allowed to be anywhere in a line, not necessarily starting at the beginning, and the entry of the data is considered completed when the user presses ‘Enter’ on the keyboard. The program sums up all the integers and types out the sum.

Therefore, if a user types in

     ####3#######56##20#1#####19########<Enter> 

where # stands for a space, the program should print out 99. The following C program does the job.

 
/* TermIO.c */ #include <stdio.h> main() { int i; int sum = 0; char ch; printf("Enter a sequence of integers: "); while ( scanf( "%d", &i ) == 1 ) { /* (A) */ sum += i; /* (B) */ while ( ( ch = getchar() ) & = ' ') /* (C) */ ; if ( ch == '\n' ) break; ungetc( ch, stdin ); /* (D) */ } printf( "The sum of the integers is: %d\n", sum ); return 0; }

The integers are read in by the scanf() function call in line (A) and the summing of the numbers done in line (B). Lines (C) through (D) take care of the following property of scanf: Most conversion specifiers for this function skip over the whitespace characters—meaning the tabs, the space, the newline character, and so on—before the beginning of an input item (and not after). Therefore, after consuming an integer, scanf will simply wait for the next integer, ignoring any blank spaces and the end of the data entry line. This creates a problem at the end of the data line when the user hits "Enter"—scanf will simply gobble up the newline character and wait for the next integer. The statements in lines (C) through (D) peek ahead, while consuming blank spaces, and look for the newline character in case the user has hit "Enter" on the keyboard. If the character found after all the blank spaces have been consumed does not turn out to be a newline character, we put it back in the input stream in line (D).

Here is a C++ program that does the same thing:

 
//TermIO.cc #include <iostream> using namespace std; int main() { int sum = 0; cout << "Enter a sequence of integers: "; int i; while ( cin >> i ) { //(A) sum += i; while ( cin.peek() == ' ' ) cin.get(); //(B) if ( cin.peek() == '\n' ) break; //(C) } cont << "Sum of the numbers is: " << sum << endl; return 0; }

This program uses the input stream object cin whose name is usually pronounced "c-in" for "console-in." This object is of type istream and it knows how to read data from a user's terminal. The expression in line (A)

    cin >> i; 

causes the input operator ’>>’, which is also known as the extraction operator, to extract one int at a time from the input stream object cin. As the user makes keystrokes, the corresponding characters are entered into the operating system's keyboard buffer and then, when the user hits the "Enter" key on the keyboard, the operating system transfers the contents of the keyboard buffer into the cin stream's internal buffer. The operator ’>>’ then extracts the needed information from this buffer. Clearly, the program will block if the user did not provide the necessary keystrokes.[11] The operator ’>>’, originally defined to be the right bitwise shift operator, has been overloaded in C++ for extracting information from input stream objects when used in the manner shown here. Because the operator has been overloaded for all the built-in data types, it can be used to extract an int, a float, a double, a string, and so on, from an input stream object.

To understand the controlling expression in line (A) of the while loop:

    while ( cin >> i ) 

the expression

    cin >> i 

returns the input stream object itself, meaning cin. However, the returned cin will evaluate to false when either the end-of-file is encountered or when the extraction operator runs into an illegal value. As an example of the latter case, if you were trying to read a floating point number into an int variable, the extraction operator, when it runs into the decimal point, would place the input stream object in an error state and cause cin to evaluate to false.

Lines (B) and (C) deal with the fact that the default behavior of the extraction operator ’>>’ skips over the white space characters, which includes blank space, tabs, newlines, and so on. So the controlling expression in line (A) will not by itself stop the while loop when the user hits "Enter" after entering the desired number of integers in a line. We invoke[12] peek() on the object cin in lines (B) and (C) to ascertain the character immediately after the most recently consumed integer. If it's a blank space, we consume it in line (B) by invoking get() on the object cin; and do the same to all the successive blank spaces until there are no more blank spaces left. If the next character is a newline, it would be trapped in line (C) and the while loop of line (A) exited. Otherwise, we continue reading the data in the next iteration of the loop.

This program also demonstrates that, unlike in C, C++ allows you to declare a variable anywhere in a program. We declared the variable i after the cout statement asking the user to enter data.[13] This feature improves the readability of large C++ programs as one can declare variables just before they are actually needed.

We will now show an equivalent Java program:

 
//TermIO.java import java.io.*; class TermIO { static boolean newline; //(A) public static void main( String[] args ) { int sum = 0; System.out.println( "Enter a sequence of integers:" ); while ( newline == false ) { String str = readString(); //(B) if ( str != null ) { int i = Integer.parseInt( str ); //(C) sum += i; } } System.out.println( "Sum of the numbers is:" + sum ); } static String readString() { //(D) String word = ""; try { int ch; while ( ( ch = System.in.read() ) == ' ' ) //(E) ; if ( ch == '\n' ) { //(F) newline = true; //(G) return null; //(H) } word += (char) ch; //(I) while ( ( ch = System.in.read() ) != ' ' && ch != '\n' ) //(J) word += (char) ch; //(K) if ( ch == '\n' ) newline = true; //(L) } catch( IOException e ) {} return word; //(M) } }

Since Java does not provide a function that can directly read an integer value into an int variable, the logic of the program is slightly more complex than that of the C and the C++ programs shown earlier. To make sense of this program, recall that the program is supposed to extract the integer values from the numbers entered by a user in a single line and the user is allowed to place any number of spaces before the first integer, between the integers, and after the last integer. In other words, we want our program to be able to extract integer numbers from the following sort of a line entered by a user:

     ####3#######56##20#1#####19########<Enter> 

where the symbol # stands for a space. To explain the working of the program:

The program reads each integer value entered by the user as a string which is of type String, a Java class we will discuss in detail in Chapter 4. This is done by invoking the method readString() in line (B). Therefore, for the data entry line shown above, the first string read will correspond to the number 3, the second to the number 56, and so on.

If the string read in the previous step is not null, we invoke the method parseInt of the Integer class in line (C) to convert the string into its integer number value, assuming that the reader did not try to fool the system by typing nondigit characters.[14]

With regard to the readString() method, we strip off all the empty spaces before a string in the while loop in line (E). Each character is read from the user's terminal in this loop by the read() method that of the java.io.InputStream class. The standard input stream System.in is an object of type java.io.InputStream. We invoke the method read() inside a try-catch block since it throws an exception of type IOException that must either be caught or rethrown, as we will explain in Chapter 10.

If the last character read in the while loop in line (E) is the newline character, the test in line (F) causes readString to terminate with null for the returned value in line (H). We also set the newline variable to true in line (G) to tell main that the data entry has come to an end. If the last character read in the while loop in line (E) is not the newline character, we then start a new word with this character in line (I).

The while loop that starts in line (J) keeps on adding fresh characters to the word started in line (I) as long as a new character is neither a space nor a newline. If the latest character read in the while loop of line (J) is a newline, we set our flag newline to true in line (L).

The reader is probably wondering about the qualifier static for the boolean variable newline in line (A) and for the header of the method readString() in line (D). The purpose of static will be explained briefly in Chapter 3 and more fully in Chapter 11.

[11]This is an example of blocking I/O. The other I/O modes are nonblocking and asynchronous. A nonblocking read will fetch the information if it is available or report immediately that the information is not available. In an asynchronous communication link, the information source puts out the information at its convenience and the consumer of the information reads the information at its convenience.

[12]In object-oriented programming, you can invoke a function on an object if that function is either defined for the class of the object or inherited by such a class. Since the function peek() is defined for the class istream in the header file iostream and since cin is an object of type istream, we can invoke peek() on cin in the manner shown.

[13]As we will explain further in Chapter 7, all such local variables have block scope.

[14]If the user does enter nondigit characters, the method parseInt will throw a NumberFormatException. Exceptions are discussed in Chapter 10.




Programming With Objects[c] A Comparative Presentation of Object-Oriented Programming With C++ and Java
Programming with Objects: A Comparative Presentation of Object Oriented Programming with C++ and Java
ISBN: 0471268526
EAN: 2147483647
Year: 2005
Pages: 273
Authors: Avinash Kak

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net