home *** CD-ROM | disk | FTP | other *** search
- Chapter 9 - Standard Input/Output
-
-
- THE STDIO.H HEADER FILE
-
- Load the file SIMPLEIO.C for our first look at a file
- with standard I/O. Standard I/O refers to the most usual
- places where data is either read from, the keyboard, or
- written to, the video monitor. Since they are used so much,
- they are used as the default I/O devices and do not need to
- be named in the Input/Output instructions. This will make
- more sense when we actually start to use them so lets look
- at the file in front of you.
-
- The first thing you will notice is the first line of
- the file, the #include "stdio.h" line. This is very much
- like the #define we have already studied, except that
- instead of a simple substitution, an entire file is read in
- at this point. The system will find the file named
- "stdio.h" and read its entire contents in, replacing this
- statement. Obviously then, the file named "stdio.h" must
- contain valid C source statements that can be compiled as
- part of a program. This particular file is composed of
- several standard #defines to define some of the standard I/O
- operations. The file is called a header file and you will
- find several different header files on the source disks that
- came with your Turbo C compiler. Each of the header files
- has a specific purpose and any or all of them can be
- included in any program.
-
- The Turbo C compiler uses the double quote marks to
- indicate that the search for the "include" file will begin
- in the current directory, and if it not found there, the
- search will continue in the "include" directory as set up in
- the environment. It also uses the "less than" and "greater
- than" signs to indicate that the file search should begin in
- the directory specified in the environment. Most of the
- programs in this tutorial have the double quotes in the
- "include" statements. The next program uses the "<" and ">"
- to illustrate the usage. Note that this will result is a
- slightly faster (but probably unnoticeable) compilation
- because the system will not bother to search the current
- directory.
-
- INPUT/OUTPUT OPERATIONS IN C
-
- Actually the C programming language has no input or
- output operations defined as part of the language, they must
- be user defined. Since everybody does not want to reinvent
- his own input and output operations, the compiler writers
- have done a lot of this for us and supplied us with several
- input functions and several output functions to aid in our
- program development. The functions have become a standard,
- and you will find the same functions available in nearly
-
-
- Page 59
-
-
-
-
-
-
-
-
-
- Chapter 9 - Standard Input/Output
-
-
- every compiler. In fact, the industry standard of the C
- language definition has become the book written by Kernigan
- and Ritchie, and they have included these functions in their
- definition. You will often, when reading literature about
- C, find a reference to K & R. This refers to the book
- written by Kernigan and Ritchie. You would be advised to
- purchase a copy for reference.
-
- You should print out the file named "stdio.h" and spend
- some time studying it. There will be a lot that you will
- not understand about it, but parts of it will look familiar.
- The name "stdio.h" is sort of cryptic for "standard
- input/output header", because that is exactly what it does.
- It defines the standard input and output functions in the
- form of #defines and macros. Don't worry too much about the
- details of this now. You can always return to this topic
- later for more study if it interests you, but you will
- really have no need to completely understand the "stdio.h"
- file. You will have a tremendous need to use it however, so
- these comments on its use and purpose are necessary.
-
- OTHER INCLUDE FILES
-
- When you begin writing larger programs and splitting
- them up into separately compiled portions, you will have
- occasion to use some statements common to each of the
- portions. It would be to your advantage to make a separate
- file containing the statements and use the #include to
- insert it into each of the files. If you want to change any
- of the common statements, you will only need to change one
- file and you will be assured of having all of the common
- statements agree. This is getting a little ahead of
- ourselves but you now have an idea how the #include
- directive can be used.
-
- BACK TO THE FILE NAMED "SIMPLEIO.C"
-
- Lets continue our tour of the file in question. The
- one variable "c" is defined and a message is printed out
- with the familiar "printf" function. We then find ourselves
- in a continuous loop as long as "c" is not equal to capital
- X. If there is any question in your mind about the loop
- control, you should review chapter 3 before continuing. The
- two new functions within the loop are of paramount interest
- in this program since they are the new functions. These are
- functions to read a character from the keyboard and display
- it on the monitor one character at a time.
-
- The function "getchar()" reads a single character from
- the standard input device, the keyboard being assumed
- because that is the standard input device, and assigns it to
-
-
- Page 60
-
-
-
-
-
-
-
-
-
- Chapter 9 - Standard Input/Output
-
-
- the variable "c". The next function "putchar(c)", uses the
- standard output device, the video monitor, and outputs the
- character contained in the variable "c". The character is
- output at the current cursor location and the cursor is
- advanced one space for the next character. The system is
- therefore taking care of a lot of the overhead for us. The
- loop continues reading and displaying characters until we
- type a capital X which terminates the loop.
-
- Compile and run this program for a few surprises. When
- you type on the keyboard, you will notice that what you type
- is displayed faithfully on the screen, and when you hit the
- return key, the entire line is repeated. In fact, we only
- told it to output each character once but it seems to be
- saving the characters up and redisplaying them. A short
- explanation is in order.
-
- DOS IS HELPING US OUT (OR GETTING IN THE WAY)
-
- We need to understand a little bit about how DOS works
- to understand what is happening here. When data is read
- from the keyboard, under DOS control, the characters are
- stored in a buffer until a carriage return is entered at
- which time the entire string of characters is given to the
- program. When the characters are being typed, however, the
- characters are displayed one at a time on the monitor. This
- is called echo, and happens in many of the applications you
- run.
-
- With the above paragraph in mind, it should be clear
- that when you are typing a line of data into "SIMPLEIO", the
- characters are being echoed by DOS, and when you return the
- carriage, the characters are given to the program. As each
- character is given to the program, it displays it on the
- screen resulting in a repeat of the line typed in. To
- better illustrate this, type a line with a capital X
- somewhere in the middle of the line. You can type as many
- characters as you like following the "X" and they will all
- display because the characters are being read in under DOS,
- echoed to the monitor, and placed in the DOS input buffer.
- DOS doesn't think there is anything special about a capital
- X. When the string is given to the program, however, the
- characters are accepted by the program one at a time and
- sent to the monitor one at a time, until a capital X is
- encountered. After the capital X is displayed, the loop is
- terminated, and the program is terminated. The characters
- on the input line following the capital X are not displayed
- because the capital X signalled program termination.
-
- Compile and run "SIMPLEIO.C". After running the
- program several times and feeling confidant that you
-
-
- Page 61
-
-
-
-
-
-
-
-
-
- Chapter 9 - Standard Input/Output
-
-
- understand the above explanation, we will go on to another
- program.
-
- Don't get discouraged by the above seemingly weird
- behavior of the I/O system. It is strange, but there are
- other ways to get data into the computer. You will actually
- find the above method useful for many applications, and you
- will probably find some of the following useful also.
-
- ANOTHER STRANGE I/O METHOD
-
- Load the file named SINGLEIO.C and display it on your
- monitor for another method of character I/O. Once again, we
- start with the standard I/O header file using the "<" and ">
- method of defining it. Then we define a variable named "c",
- and finally we print a welcoming message. Like the last
- program, we are in a loop that will continue to execute
- until we type a capital X, but the action is a little
- different here.
-
- The "getch()" is a new function that is a "get
- character" function. It differs from "getchar()" in that it
- does not get tied up in DOS. It reads the character in
- without echo, and puts it directly into the program where it
- is operated on immediately. This function therefore reads a
- character, immediately displays it on the screen, and
- continues the operation until a capital X is typed.
-
- When you compile and run this program, you will find
- that there is no repeat of the lines when you hit a carriage
- return, and when you hit the capital X, the program
- terminates immediately. No carriage return is needed to get
- it to accept the line with the X in it. We do have another
- problem here, however, there is no linefeed with the
- carriage return.
-
- NOW WE NEED A LINE FEED
-
- It is not apparent to you in most application programs
- but when you hit the enter key, the program supplies a
- linefeed to go with the carriage return. You need to return
- to the left side of the monitor and you also need to drop
- down a line. The linefeed is not automatic. We need to
- improve our program to do this also. If you will load and
- display the program named BETTERIN.C, you will find a change
- to incorporate this feature.
-
- In BETTERIN.C, we have two additional statements at the
- beginning that will define the character codes for the
- linefeed (LF), and the carriage return (CR). If you look at
- any ASCII table you will find that the codes 10 and 13 are
-
-
- Page 62
-
-
-
-
-
-
-
-
-
- Chapter 9 - Standard Input/Output
-
-
- exactly as defined here. In the main program, after
- outputting the character, we compare it to CR, and if it is
- equal to CR, we also output a linefeed which is the LF. We
- could have just left out the two #define statements and used
- "if (c == 13) putchar(10);" but it would not be very
- descriptive of what we are doing here. The method used in
- the program represents better programming practice.
-
- Compile and run BETTERIN.C to see if it does what we
- have said it should do. It should display exactly what you
- type in, including a linefeed with each carriage return, and
- should stop immediately when you type a capital X.
-
- WHICH METHOD IS BEST?
-
- We have examined two methods of reading characters into
- a C program, and are faced with a choice of which one we
- should use. It really depends on the application because
- each method has advantages and disadvantages. Lets take a
- look at each.
-
- When using the first method, DOS is actually doing all
- of the work for us by storing the characters in an input
- buffer and signalling us when a full line has been entered.
- We could write a program that, for example, did a lot of
- calculations, then went to get some input. While we were
- doing the calculations, DOS would be accumulating a line of
- characters for us, and they would be there when we were
- ready for them. However, we could not read in single
- keystrokes because DOS would not report a buffer of
- characters to us until it recognized a carriage return.
-
- The second method, used in BETTERIN.C, allows us to get
- a single character, and act on it immediately. We do not
- have to wait until DOS decides we can have a line of
- characters. We cannot do anything else while we are waiting
- for a character because we are waiting for the input
- keystroke and tying up the entire machine. This method is
- useful for highly interactive types of program interfaces.
- It is up to you as the programmer to decide which is best
- for your needs.
-
- I should mention at this point that there is also an
- "ungetch" function that works with the "getch" function. If
- you "getch" a character and find that you have gone one too
- far, you can "ungetch" it back to the input device. This
- simplifies some programs because you don't know that you
- don't want the character until you get it. You can only
- "ungetch" one character back to the input device, but that
- is sufficient to accomplish the task this function was
- designed for. It is difficult to demonstrate this function
-
-
- Page 63
-
-
-
-
-
-
-
-
-
- Chapter 9 - Standard Input/Output
-
-
- in a simple program so its use will be up to you to study
- when you need it.
-
- The discussion so far in this chapter, should be a good
- indication that, while the C programming language is very
-
- flexible, it does put a lot of responsibility on you as the
- programmer to keep many details in mind.
-
- NOW TO READ IN SOME INTEGERS
-
- Load and display the file named INTIN.C for an example
- of reading in some formatted data. The structure of this
- program is very similar to the last three except that we
- define an "int" type variable and loop until the variable
- somehow acquires the value of 100.
-
- Instead of reading in a character at a time, as we have
- in the last three files, we read in an entire integer value
- with one call using the function named "scanf". This
- function is very similar to the "printf" that you have been
- using for quite some time by now except that it is used for
- input instead of output. Examine the line with the "scanf"
- and you will notice that it does not ask for the variable
- "valin" directly, but gives the address of the variable
- since it expects to have a value returned from the function.
- Recall that a function must have the address of a variable
- in order to return the value to the calling program.
- Failing to supply a pointer in the "scanf" function is
- probably the most common problem encountered in using this
- function.
-
- The function "scanf" scans the input line until it
- finds the first data field. It ignores leading blanks and
- in this case, it reads integer characters until it finds a
- blank or an invalid decimal character, at which time it
- stops reading and returns the value.
-
- Remembering our discussion above about the way the DOS
- input buffer works, it should be clear that nothing is
- actually acted on until a complete line is entered and it is
- terminated by a carriage return. At this time, the buffer
- is input, and our program will search across the line
- reading all integer values it can find until the line is
- completely scanned. This is because we are in a loop and we
- tell it to find a value, print it, find another, print it,
- etc. If you enter several values on one line, it will read
- each one in succession and display the values. Entering the
- value of 100 will cause the program to terminate, and
- entering the value 100 with other values following, will
- cause termination before the following values are
- considered.
-
-
- Page 64
-
-
-
-
-
-
-
-
-
- Chapter 9 - Standard Input/Output
-
-
-
- IT MAKES WRONG ANSWERS SOMETIMES
-
- If you enter a number up to and including 32767, it
- will display correctly, but if you enter a larger number, it
- will appear to make an error. For example, if you enter the
- value 32768, it will display the value of -32768, entering
- the value 65536 will display as a zero. These are not
- errors but are caused by the way an integer is defined. The
- most significant bit of the 16 bit pattern available for the
- integer variable is the sign bit, so there are only 15 bits
- left for the value. The variable can therefore only have
- the values from -32768 to 32767, any other values are
- outside the range of integer variables. This is up to you
- to take care of in your programs. It is another example of
- the increased responsibility you must assume using C rather
- than a higher level language such as Pascal, Modula-2, etc.
-
- Compile and run this program, entering several numbers
- on a line to see the results, and with varying numbers of
- blanks between the numbers. Try entering numbers that are
- too big to see what happens, and finally enter some invalid
- characters to see what the system does with nondecimal
- characters.
-
- CHARACTER STRING INPUT
-
- Load and display the file named STRINGIN.C for an
- example of reading a string variable. This program is
- identical to the last one except that instead of an integer
- variable, we have defined a string variable with an upper
- limit of 24 characters (remember that a string variable must
- have a null character at the end). The variable in the
- "scanf" does not need an & because "big" is an array
- variable and by definition it is already a pointer. This
- program should require no additional explanation. Compile
- and run it to see if it works the way you expect.
-
- You probably got a surprise when you ran it because it
- separated your sentence into separate words. When used in
- the string mode of input, "scanf" reads characters into the
- string until it comes to either the end of a line or a blank
- character. Therefore, it reads a word, finds the blank
- following it, and displays the result. Since we are in a
- loop, this program continues to read words until it exhausts
- the DOS input buffer. We have written this program to stop
- whenever it finds a capital X in column 1, but since the
- sentence is split up into individual words, it will stop
- anytime a word begins with capital X. Try entering a 5 word
- sentence with a capital X as the first character in the
-
-
-
- Page 65
-
-
-
-
-
-
-
-
-
- Chapter 9 - Standard Input/Output
-
-
- third word. You should get the first three words displayed,
- and the last two simply ignored when the program stops.
-
- Try entering more than 24 characters to see what the
- program does. In an actual program, it is your
- responsibility to count characters and stop when the input
- buffer is full. You may be getting the feeling that a lot
- of responsibility is placed on you when writing in C. It
- is, but you also get a lot of flexibility in the bargain
- too.
-
- INPUT/OUTPUT PROGRAMMING IN C
-
- C was not designed to be used as a language for lots of
- input and output, but as a systems language where a lot of
- internal operations are required. You would do well to use
- another language for I/O intensive programming, but C could
- be used if you desire. The keyboard input is very flexible,
- allowing you to get at the data in a very low level way, but
- very little help is given you. It is therefore up to you to
- take care of all of the bookkeeping chores associated with
- your required I/O operations. This may seem like a real
- pain in the neck, but in any given program, you only need to
- define your input routines once and then use them as needed.
-
- Don't let this worry you. As you gain experience with
- C, you will easily handle your I/O requirements.
-
- One final point must be made about these I/O functions.
- It is perfectly permissible to intermix "scanf" and
- "getchar" functions during read operations. In the same
- manner, it is also fine to intermix the output functions,
- "printf" and "putchar".
-
- IN MEMORY I/O
-
- The next operation may seem a little strange at first,
- but you will probably see lots of uses for it as you gain
- experience. Load the file named INMEM.C and display it for
- another type of I/O, one that never accesses the outside
- world, but stays in the computer.
-
- In INMEM.C, we define a few variables, then assign some
- values to the ones named "numbers" for illustrative purposes
- and then use a "sprintf" function. The function acts just
- like a normal "printf" function except that instead of
- printing the line of output to a device, it prints the line
- of formatted output to a character string in memory. In
- this case the string goes to the string variable "line",
- because that is the string name we inserted as the first
- argument in the "sprintf" function. The spaces after the
-
-
- Page 66
-
-
-
-
-
-
-
-
-
- Chapter 9 - Standard Input/Output
-
-
- 2nd %d were put there to illustrate that the next function
- will search properly across the line. We print the
- resulting string and find that the output is identical to
- what it would have been by using a "printf" instead of the
- "sprintf" in the first place. You will see that when you
- compile and run the program shortly.
-
- Since the generated string is still in memory, we can
- now read it with the function "sscanf". We tell the
- function in its first argument that "line" is the string to
- use for its input, and the remaining parts of the line are
- exactly what we would use if we were going to use the
- "scanf" function and read data from outside the computer.
- Note that it is essential that we use pointers to the data
- because we want to return data from a function. Just to
- illustrate that there are many ways to declare a pointer
- several methods are used, but all are pointers. The first
- two simply declare the address of the elements of the array,
- while the last three use the fact that "result", without the
- accompanying subscript, is a pointer. Just to keep it
- interesting, the values are read back in reverse order.
- Finally the values are displayed on the monitor.
-
- IS THAT REALLY USEFUL?
-
- It seems sort of silly to read input data from within
- the computer but it does have a real purpose. It is
- possible to read data from an input device using any of the
- standard functions and then do a format conversion in
- memory. You could read in a line of data, look at a few
- significant characters, then use these formatted input
- routines to reduce the line of data to internal
- representation. That would sure beat writing your own data
- formatting routines.
-
- STANDARD ERROR OUTPUT
-
- Sometimes it is desirable to redirect the output from
- the standard output device to a file. However, you may
- still want the error messages to go to the standard output
- device, in our case the monitor. This next function allows
- you to do that. Load and display SPECIAL.C for an example of
- this new function.
-
- The program consists of a loop with two messages
- output, one to the standard output device and the other to
- the standard error device. The message to the standard
- error device is output with the function "fprintf" and
- includes the device name "stderr" as the first argument.
- Other than those two small changes, it is the same as our
- standard "printf" function. (You will see more of the
-
-
- Page 67
-
-
-
-
-
-
-
-
-
- Chapter 9 - Standard Input/Output
-
-
- "fprintf" function in the next chapter, but its operation
- fit in better as a part of this chapter.) Ignore the line
- with the "exit" for the moment, we will return to it.
-
- Compile and run this program, and you will find 12
- lines of output on the monitor. To see the difference, run
- the program again with redirected output to a file named
- "STUFF" by entering the following line at the Dos prompt;
-
- A> special >stuff
-
- More information about I/O redirection can be found in
- your DOS manual. This time you will only get the 6 lines
- output to the standard error device, and if you look in your
- directory, you will find the file named "STUFF" containing
- the other 6 lines, those to the standard output device. You
- can use I/O redirection with any of the programs we have run
- so far, and as you may guess, you can also read from a file
- using I/O redirection but we will study a better way to read
- from a file in the next chapter.
-
- WHAT ABOUT THE exit(4) STATEMENT?
-
- Now to keep our promise about the exit(4) statement.
- Redisplay the file named SPECIAL.C on your monitor. The
- last statement simply exits the program and returns the
- value of 4 to DOS. Any number from 0 to 9 can be used in
- the parentheses for DOS communication. If you are operating
- in a BATCH file, this number can be tested with the
- "ERRORLEVEL" command.
-
- A check of the documentation for my COMPAQ, resulted in
- a minimal and confusing documentation of the "ERRORLEVEL"
- command, so a brief description of it is given in this file.
-
-
- PROGRAMMING EXERCISE
-
- 1. Write a program to read in a character using a loop,
- and display the character in its normal "char" form.
- Also display it as a decimal number. Check for a
- dollar sign to use as the stop character. Use the
- "getch" form of input so it will print immediately. Hit
- some of the special keys, such as function keys, when
- you run the program for some surprises. You will get
- two inputs from the special keys, the first being a
- zero which is the indication to the system that a
- special key was hit.
-
-
-
-
-
- Page 68
-