Chapter 8
Chapter 8
Chapter 8
in: <ctype.h>
Returns:
isalnum TRUEif c is a letter or a digit. ('A'-'Z', 'a'-'z', '0'-'9').
isalpha TRUEif c is a letter. ('A'-'Z', 'a'-'z')
isascii TRUEif c is in the range 0-127.
iscntrl TRUEif c is a control character. (0-31, 127)
isdigit if c is a digit. ('0'-'9')
TRUE
isgraph if c is a graphical character, i.e. a printable character except for space.
TRUE
(33-126)
islower TRUE if c is a lower case letter. ('a'-'z')
isprint TRUE if c is a printable character. (32-126)
ispunct TRUE if c is a punctuation character.
isspace TRUE if c is a space, tab, newline, or any white space character. (9-13, 32)
isupper TRUE if c is an upper case letter. ('A'-'Z')
isxdigit TRUE if c is a hexadecimal digit. ('0'-'9', 'A'-'F', 'a'-'f')
Description: These are macros that classify a character, c, given as an integer type
(ASCII) value. They return non-zero if TRUE and zero if FALSE.
8.1. THE C STANDARD LIBRARY 315
Character Conversion Routines
toascii Prototype: int toascii(int c) in: <ctype.h>
Returns: converted value of c.
Description: Converts an integer, c, to ASCII format by clearing all but the lower
seven bits. The value returned is in the range 0-127.
tolower Prototype: int tolower(int c) in: < ctype.h >
Returns: Lower case value of c if c was upper case, c otherwise.
toupper Prototype: int toupper(int c) in: < ctype.h>
Returns: Converts c to upper case if c is lower case otherwise, c is left unchanged.
Note that all the above library character routines use an int type argument. Since the value
of a character is its ASCII value of type int, passing a char type argument to these routines is
the same as passing an int type ASCII value.
Character Routines Programming Examples
Let us use some of the above library routines to write a variation on our previous program to pick
out words in the input text. The revised program only picks out valid words namely identiers.
We will assume that a valid identier starts with a letter and may be followed by any number of
letters and/or digits. White space delimits an identier otherwise, it is ignored. Any character
that does not belong in an identier is an illegal character and also delimits an identier.
We will need to test each character to see if it is a letter, a digit, a white space, etc. We will
use library functions isalpha(), isalnum(), and isspace() to test for these characters. The
descriptions for them states that we must include le <ctype.h>. In addition to nding and
printing identiers, the program also keeps a count of them.
The only change in the previous algorithm is that now we start a word if and only if it starts
with a letter. Once a word is started, it continues as long as characters are letters or digits
otherwise, the word is terminated and counted. The program is shown in Figure 8.1.
We test if the rst character after white space is a letter. If so, we build an identier. Otherwise,
if it is EOF, we terminate the loop. Otherwise, it must be an illegal character.
Sample Session:
***Print Identifiers***
/* File: ident.c
Program reads characters one at a time until EOF. It prints out
each identifier in the input text and counts the total number of
identifiers. It ignores white space except as a delimiter for an
identifier. An identifier starts with an alphabetic letter and may be
followed by any number of letters or digits. All other characters are
considered illegal.
*/
#include <stdio.h>
#include <ctype.h>
main()
{ int cnt = 0
signed char c
printf("***Print Identifiers***\n\n")
printf("Type text, terminate with EOF ^Z or ^D)\n")
c = getchar()
while (c != EOF) {
while (isspace(c)) /* skip leading white space */
c = getchar()
The option -l species that a library must be linked with the code and the m species the math
library. Note that this option MUST appear as the last item on the command line.
Most of the functions listed above are self explanatory (and are described in detail in Appendix
C). As an example, let us look at the function, rand() which generates pseudo-random integers
in the range of numbers from 0 to the largest positive integer value. The numbers cannot be com-
pletely random because the range is limited. However, for the most part, the numbers generated
by rand() appear to be quite random. The prototype for the function is:
int rand(void)
Each time the function is called, it returns a random integer number. Figure 8.2 shows an example
which generates and prints some random numbers.
Sample Session:
346
130
10982
1090
11656
The random number generator will always start with the same number unless it is \seeded" rst
by calling the function, srand(). The prototype for it is:
void srand(unsigned x)
In the example in Figure 8.3, we seed the random number generator with a user supplied number.
The program then nds random throws for a single dice. After the random generator is seeded,
every random number generated, n, is evaluated modulo 6, i.e. n % 6 is evaluated. This results
in numbers from 0 to 5. We add one to obtain the dice throws from 1 to 6.
Sample Session:
***Single Dice Throw Program***
318 CHAPTER 8. FUNCTIONS AND FILES
/* File: rand.c
Program uses random number generator to print some random
numbers.
*/
#include <stdio.h>
#include <math.h>
main()
{ int i
int x
/* File: dice.c
Program throws a single dice repeatedly.
*/
#include <stdio.h>
#include <math.h>
main()
{ int i, d1
Similarly, we can write a program that draws a card from a full deck of 52 cards as shown
in Figure 8.4. It starts by seeding the random number generator before its use. Next, a random
number is generated and evaluated modulo 52, resulting in a random number between 0 and
51, representing a card. For a number, n, the value n / 13 is in the range 0 through 3, each
corresponding to a suit: say 0 is clubs, 1 is diamonds, 2 is hearts, and 3 is spades. In addition, n
% 13 + 1 evaluates to a number in the range 1 through 13, corresponding to a card in a suit: say
1 is ace, 2 is deuce, : : : , 11 is jack, 12 is queen, and 13 is king.
Sample Session:
***Single Card Draw Program***
The next program uses the library function, sqrt(), to obtain square roots of randomly gen-
erated numbers. The function, sqrt(), requires its argument to be of type double, and it returns
type double. In the program shown in Figure 8.5, the randomly generated whole number is
assigned to a double variable before nding its square root.
Sample Session:
***Square Root Program - Random Numbers***
These have been just a few examples of using routines available in the math library. A complete
listing of math routines is provided in Appendix C. Rather than writing our own functions all the
time, we will make use of library functions in our code wherever we can in the future.
/* File: card.c
Program draws a card each time from a full deck of 52 cards.
*/
#include <stdio.h>
#include <math.h>
#define CLUB 0
#define DIAMOND 1
#define HEART 2
#define SPADE 3
#define ACE 1
#define JACK 11
#define QUEEN 12
#define KING 13
main()
{ int i, d1, card, suit
/* File sqrt3.c
Program computes and prints square roots of numbers randomly
generated.
*/
#include <stdio.h>
#include <math.h>
main()
{ int i
double x
Figure 8.5: Code for nding the square root of random numbers
discussed many of the conversion specications we now present a more complete description of the
formatted I/O functions together with examples. (While our discussion here concerns printf()
and scanf(), it applies equally well to conversion specications for fprintf() and fscanf()
described in the next Section.
The rst argument of printf() is the format string (we will see what the above type declaration
means in the next chapter). The number of remaining arguments depends on the number of
conversion speciers in the format string. In C, an ellipsis, i.e. \: : : ", is used to indicate an
arbitrary number of arguments. The return value of printf() is an int giving the number
of bytes output, if successful otherwise it returns EOF. This information from printf() is not
generally very useful, and we often simply ignore the return value.
The function, printf(), converts, formats, and prints its arguments on the standard output
using the conversion specications given in the format string. The format string is made up of
two kinds of characters: regular characters, which are simply copied to the output, and conversion
specication characters. A conversion specication indicates how the corresponding argument
value is to be converted and formatted before being printed. The number of conversion speci-
cations in the format string must match exactly the number of arguments that follow otherwise,
the results are undened. The data type of the argument should also match the data type it
322 CHAPTER 8. FUNCTIONS AND FILES
will be converted to for example, integral types for decimal integer formats, float or double
types for oating point or exponential formats, and so on. If the proper type is not used, the
conversion is performed anyway assuming correct data types and the results can be very strange
and unexpected. Of course, character values are integral types so characters can be converted
to ASCII integer values for printing, or printed as characters. We have already seen most of the
conversion characters. Table 8.1 gives a complete list with their meanings. We will discuss some
examples, given the following declarations and initializations:
int i
char c
float f1
double d1
char *s
long x
i = 33
c = 'e'
f1 = 12345.00
d1 = 12345.00
s = "This is a test"
x = 123456789
Dierent conversion characters may be used to print the values of these variables. The space used
to print a value is called the eld, and by default, is exactly the space needed to print the value.
We show examples of conversion characters and default output below:
Conversion Variable Output
Specier
%d i 33
%o i 41
%x i 21
%u i 33
%c c e
%d c 101
%c i !
%s s this is a test
%f f1 or d1 12345.000000
%e f1 or d1 1.234500E+004
%g f1 or d1 12345
So far, we have used very simple conversion speciers, such as %d, %f, and %c. A complete
conversion specication starts with the character % and ends with a conversion character. Between
these two characters, special format characters may be used which can specify justication, eld
width, eld separation, precision, and length modication. The characters that follow the % char-
acter and precede the conversion characters are called format characters. All format characters
are optional, and if they are absent their default values are assumed. (We will indicate the default
value in each case below). The syntax of a complete conversion specier is:
8.2. FORMATTED INPUT/OUTPUT 323
Character Conversion
d The argument is taken to be an integer and converted to decimal integer
notation.
o The argument is taken to be an integer and converted to unsigned octal
notation without a leading zero.
x The argument is taken to be an integer and converted to unsigned
hexadecimal notation without a leading 0x.
u The argument is taken to be an unsigned integer and converted to
unsigned decimal notation.
c The argument is taken to be an ASCII character value and converted
to a character.
s The argument is taken to be a string pointer. Unless a precision is
specied as discussed below, characters from the string are printed out
until a NULL character is reached. (Strings will be discussed further in
the next chapter).
f The argument is taken to be a float or double. It is converted to
decimal notation of the form -]ddd.dddddd, where the minus sign shown
in square brackets may or may not be present. The number of digits, d,
after the decimal point is 6 by default if no precision is specied. The
number of digits, d, before the decimal is as required for the number.
e The argument is taken to be a float or double. It is converted to
decimal notation of the form -]d.ddddddE+/-]xxx, where the leading
minus sign may be absent. There is one digit before the decimal point.
The number of digits, d, after the decimal point is 6 if no precision is
specied. The E signies the exponent, ten, followed by a plus or minus
sign, followed by the exponent. The number of digits in the exponent,
x, is implementation dependent, but not less than two.
g The same as %e or %f whichever is shorter and excludes trailing zeros.
%ld x |123456789
%-12ld x |123456789 |
As we've said, the returned value is the number of items read, or EOF. The format string controls
the input order, conversion of the input data to the specied type, and format specication.
Each conversion specication appearing in the format string is applied, in turn, to the next input
data item in the input stream. After the specied conversion, the item is placed where the next
succeeding argument points so each of the arguments must be an address.
Besides the conversion specications that start with %, the format string may also include
regular characters. Regular white space characters in the format string are ignored. Any regular
non-white space characters must be matched exactly in the input stream. For example:
scanf("x= %d", &x)
The input stream must include the characters x=, which are matched by the corresponding char-
acter in the format string, before an integer value is read. A valid sample input for this format
string is:
x= 1234
The characters, x=, are rst matched, then the integer, 1234, is read and assigned to the variable,
x. If the characters, x=, are not matched in the input stream, no input is possible, and scanf()
will return the value 0.
As before, a conversion specication starts with a % and ends with one of the conversion
characters given in Table 8.2. Between % and the conversion character, there can be an optional
assignment suppression character, *, followed by an optional number indicating the maximum eld
width. The maximum eld width species that no more than that number of characters in the input
stream may be used for the next data item. The converted result is stored where the corresponding
argument points unless the assignment suppression character is used. If the suppression character
is used, the result is discarded. The conversion characters with their meanings are given in Table
8.2. All of these except c and s may be preceded by the length modier, l (ell), where, in the
case of integral type data, the corresponding argument should be long and in the case of oating
point data, the argument should be double. For example, with the following declarations:
int i, k
char c
326 CHAPTER 8. FUNCTIONS AND FILES
Character Conversion
d The input is expected to be a decimal integer. The corresponding
argument should be an integer address.
o The input is expected to be an octal number. The corresponding argu-
ment should be an integer address.
x The input is expected to be a hexadecimal number. The corresponding
argument should be an integer address.
c The input is expected to be a character. Any character including white
space may be input without being skipped over. The corresponding
argument should be a character address.
s The input is expected to be a string of characters, and the correspond-
ing argument should be a character pointer to an array of characters
large enough to accommodate the string plus the terminating NULL
character. (Arrays are discussed in Chapter 7). The input will skip
over initial white space and will terminate when a white space charac-
ter is encountered in the input stream.
f The input is expected to be a oating point number and the corre-
sponding argument should be a float address. The input may have
a sign, followed by a string of digits, optionally followed by a decimal
point and a string of digits, which may be followed by an E or e and a
signed or unsigned integer exponent.
e Same as f.
Consider the following statements with the input as shown below each statement.
scanf("Integer: %4d %f", &i, &f1)
Input is:
Integer: 1234567
First, the regular characters, Integer: are matched. Then a eld of 4 is used to read the integer,
1234. Finally, a float, 567.0 is read. The integer, 1234, will be stored in i, and 567.0 will be
stored in f1.
scanf("%4s %*c %c", s, &c)
Surprise number 1
This time the string "Surprise" will be stored in s, the next string "number" will be discarded,
and the integer 1 will be stored in i.
We begin by initializing the array, digit freq%] to zero and each time a digit character is en-
countered, an appropriate frequency is incremented. The program implementation is shown in
Figure 8.6 and assumes that the le to be read is named test.doc.
The input le, test.doc consists of a single line shown below:
245 87 129 45 28
Sample Session:
***Digit Occurrence Counter***
8.3. DIRECT I/O WITH FILES 329
/* File: cntdigits.c
This program reads characters from a file stream and counts the
number of occurrences of each digit.
*/
#define MAX 10
#include <stdio.h>
#include <ctype.h> /* for isdigit() */
main()
{
int digit_freq%MAX],i
signed char ch
FILE * fin
/* summarize */
for (i = 0 i < MAX i++)
printf("There are %d occurrences of %d in the input\n",
digit_freq%i],i)
}
Let us rst give a summary explanation. In the declaration section of the function, main, a le
pointer variable, fin, is declared to be of type FILE *. The type FILE is dened using a typedef
in <stdio.h> as a special data structure containing the information about a le need to access
it. After the array, digit freq%], is initialized to zero, the le, test.doc, is opened using the
standard library function, fopen():
fin = fopen("test.doc", "r")
The function, fopen(), takes two arguments: a string which gives the name of the physical le,
and a second string which species the mode ("r" (for read) indicates an input le). If the le can
be opened, fopen() returns a le pointer which can be used to access the corresponding stream.
If the le cannot be opened, fopen() returns a NULL pointer, so the program tests if the returned
value of the le pointer, fin, is NULL and, if so, terminates the program after a message is printed.
If the le opened (i.e. fin is not NULL), then fin can be thought of as a \handle" on the le which
is passed to an appropriate I/O routine to access the data. In our case, a character is read from
the stream using the standard library function, getc():
ch = getc(fin)
The function, getc(), reads a character from the stream accessed by the le pointer, fin. It
returns the value of character read if successful, and EOF otherwise. In the program, each character
read is examined to see if it is a digit if it is, the count for that digit is incremented. Once the
end of input le is reached, the le is closed with the statement:
fclose(fin)
declares two le pointer variables, fin and fout. It is now possible to associate these FILE
pointers with desired physical les. We use the terms stream and le pointer interchangeably with
FILE pointer. Standard les are always open and standard le pointer variables are available to
all programs. They are named stdin, stdout, and stderr.
The process of opening a le connects a physical le and associates a mode with the FILE
pointer. The mode species whether a le is opened for input, for output, or for both. The le
open function, fopen(), associates a physical le with a le buer or stream and returns a FILE
pointer that is used to access the le. Here is the prototype:
FILE * fopen(char * fname, char * mode)
The mode string, "r", species that the le is to be opened for reading (i.e. an input le), "w"
species writing mode (i.e. an output le), and "a" species append mode (i.e. both an input and
an output le). If the le was opened successfully, fopen() returns a pointer that will access the
le stream. If it was not possible to open the le for some reason, fopen() returns a NULL pointer
(a pointer whose value is zero | in C, the zero address is guaranteed to be an invalid address).
It is the programmer's responsibility to check to see if the returned pointer is NULL. The most
common reason why a le cannot be opened for reading is that it does not exist, i.e. an erroneous
le name has been used.
Once a le is opened, the library function, getc(), reads single characters from the le stream.
The argument passed to getc() must be a le pointer, and it returns the (integer) value of a
character read or EOF if an end of le is reached.
Files should be closed after their use is completed. Failure to close open les may destroy les
if a program terminates prematurely. The library function that closes a le is fclose(), whose
argument must be a FILE pointer. The process of closing a le frees the le buer.
In the above program, we specied the name of the input le in the code itself. If the program
is to be used with any other input le, we would have to modify the program and recompile.
Instead, a exible program should ask the user to enter le names as needed.
Our next task is to copy one le to another. The algorithm is: simple.
get input and output file names
open files for input and output
while NOT EOF, read a character ch from input stream
write ch to output stream
close files
The library routine, putc(ch, output) writes a character, ch , to a le stream, . The
output
program is shown in Figure 8.7.
Sample Session:
***File Copy Program - Character I/O***
/* File: ccopy.c
This program copies an input file to an output file one
character at a time. Standard files are not allowed.
*/
#include <stdio.h>
main()
{ FILE *input, *output
char infile%15], outfile%15]
signed char ch
where inp and outp, are FILE pointers. The other arguments are the same as those for scanf()
and printf() the format string gives the conversion specications, and the arguments that follow
reference the objects where data is to be stored or whose values are to be written. The return
value of fscanf() is the same as scanf(): number of items read or EOF.
Our next task is to read exam scores into an array from a le and determine the average, the
maximum, and the minimum. It is assumed that the data le of exam scores is prepared using an
editor. The algorithm is simple enough:
get input file name
open input file
read exam scores into an array
process the array to find average, maximum, and minimum
We will use a function, proc aray(), to process the array. It will return the average but will
indirectly store the maximum and minimum values in the calling function. The program is shown
in Figure 8.8.
The sample session assumes that the scores are in an input le scores.dat prepared using an
editor and shown below:
334 CHAPTER 8. FUNCTIONS AND FILES
/* File: avgfile.c
This program reads exam scores from a file and processes them to
find the average, the maximum, and the minimum. */
#include <stdio.h>
#define MAX 100
float proc_aray(int ex%], int lim, int *pmax, int *pmin)
main()
{ int max, min, n, lim = 0, exam_scores%MAX]
char infile%15]
float avg
FILE * inp
Sample Session:
***Exam Scores: Average, Maximum, Minimum***
The driver opens the input le and reads data into the array, exam scores%]. The number of
elements are counted by lim. If lim is zero, the program is terminated otherwise, the program
calls proc aray() to process the array for the average, the maximum, and the minimum. In the
call to proc aray(), main() passes as arguments exam scores, lim, and pointers to max and min.
The function, proc aray(), initializes values of local variables, max and min, to the value of
the rst element of the array, ex%0]. It then traverses the array, maintains a cumulative sum of
the scores, and updates the values of max and min using the following conditional expressions:
max = ex%i] > max ? ex%i] : max
min = ex%i] < min ? ex%i] : min
Here, if an array element, ex%i], is greater than max, max is assigned ex%i] otherwise, max is
assigned max. Similarly, the minimum is updated when an array element is smaller than the
minimum. Finally, the function indirectly stores values of maximum and minimum, and returns
the value of the average score.
With the above input, scanf() will read "this", and NOT the whole string, into memory
pointed to by msg. However, printf() will print the entire string until the terminating
NULL.
8.5 Summary
In this Chapter we have discussed various features available to the programmer in the C standard
library. While we have used some of the functions in previous chapters, particularly those for
I/O, we have given a more detailed description of the library, and the standard I/O routines
336 CHAPTER 8. FUNCTIONS AND FILES
provided there. We have seen that frequently used operations on characters for classifying or
converting which we have written for ourselves in the past, are available from the library. In
addition, routines for common math operations are also provided in the math library (which may
not be automatically linked by the compiler). We have given a few short programs illustrating
the use of some of these functions. A more complete list of available library routines is provided
in Appendix C.
We have also given a complete description of the formatted I/O functions, scanf() and
printf() detailing the options available for formatting input and output. Finally, we have dis-
cussed variations on the I/O routines available, both for characters and formatted, which allow
direct access to data in les from within a program. These new routines include getc(), putc(),
fscanf(), and fprintf(), as well as functions for managing connection to the physical les:
fopen() and fclose().
The full power of the C standard library is now available for future program development in
later chapters.
8.6. EXERCISES 337
8.6 Exercises
1. main()
{ long n
scanf("%d", &n)
}
2. main()
{ long n = 12L
printf("%d\n", n)
}
3. main()
{ double x
scanf("%f", &x)
}
3. Write a program to read the current date in the order: year, month, and day of month. The
program then prints the date in words: Today is the nth day of Month of the year Year.
Example:
Today is the 24th day of December of the year 2000.
4. Write a program that prints a calendar for a year given the day of the week on the rst day
of the year. (Use Problem 3.6 for the denition of a leap year).
5. Write a program that prints a calendar for any year in this century given the day of the
week for the rst day of the current year.
6. Write a function that returns the value of a random throw of two separate dice.
7. Write the following functions:
first\_card() that draws a random card from a full deck.
second\_card() that draws a random card from the remaining deck.
Similarly, write third\_card() and fourth\_card().
For the last three functions, you will need arguments that indicate what cards have already
been drawn from the deck.
8. Write a program using the functions of Problem ? to play a game of "black jack" with the
user. Each side is dealt cards alternately. First each side is dealt two cards, but one at a
time. Then, if necessary a maximum of one more card is allowed for each player. The player
with the highest score, not exceeding 21, wins. In a tie, the user wins. The program should
reshue the cards and play the game as long as the user wishes. The score is obtained by
summing the value of each card. The value of a card is the face value of the card, except
that an ace can be either 1 or 11 and all picture cards are 10.
8.7. PROBLEMS 339
9. Randomly toss a coin: repeat and count the number of heads and tails in 100 tosses, 500
tosses, 1000 tosses.
10. Write a program to play a board game with the user. The game uses a throw of two dice.
The rules of the game are as follows. Each player takes a turn and is allowed a succession
of throws. If a player's rst throw is seven or eleven, he/she loses the turn. Otherwise, the
player's score is increased by the value of each throw until the dice show a seven or a eleven.
The turns continue between the user and the program until a pre-set limit for the score is
reached.
11. Write a program to compare the routine sq root() written in Chapter ? with the standard
library routine. How close are the routines?
12. Write a function that returns the hypotenuse, given the two sides of a right angled triangle.
A hypotenuse is the square root of the sum of the squares of the two sides of a right angled
triangle.
13. Find all the angles of a right angled triangle if the lengths of the two sides are given. Since
it is a right triangle, one angle is pi / 2. Also, the ratio of the two sides in a right triangle
gives the tangent of one of the other angles. Therefore, one angle is the arctangent of the
ratio of the two sides. Use a library function to get the arctangent of a value. The other
angle is easily obtained since the three angles must add up to pi.
14. Use library routines to compare values of sine, cosine, and exponential with those calculated
by Chapter 3 problems 3.1 through 3.3.
15. Write a menu-driven program that handles the grades for a class. The program allows the
following commands.
Get data: gets id numbers and integer scores for a set of 3 projects from a
file. Assume that the id numbers start at 0 and go up to a maximum of 99.
Print data: prints the scores.
Average scores: averages each set of scores.
Change scores: allows the user to make changes in scores for any project
and for any id number.
16. Write a program that reads a text of characters from a le and keeps track of the frequency
of usage of each letter, digit, and punctuation.
17. Write a menu-driven program that reads input data from a le. The program reads and
stores for each student the ID number, course numbers, credits, and grades. Assume a
maximum of 3 courses per student. The program should compute and store the GPR for
each student. At the end of input, the program writes to a le as well as to the standard
output all the input data and GPR for all students.
18. Write a program that shues and deals out all 52 cards of a deck of playing cards to 4 players.
Each card is dealt in sequence around a table to players in the following order: west, north,
east, south. Print out the hands of each player. You must use a random generator, but
discard a possible card if it has already been dealt out. Use an array of 52 elements to keep
track of the cards already dealt out.
340 CHAPTER 8. FUNCTIONS AND FILES
19. Write a program to play the game of 21 with a limit of ve cards for each player. Assume
the program plays south and deals the cards. The other three players are in order west,
north, and east. Cards must be dealt randomly.
20. Write a program that reads a positive integer n it then generates a set of n random numbers
in a range from 0 to 99. Store and count the frequency of occurrence of each number. Print
the frequency of each number.
21. Use an array to read from a le and store the sample values of an experiment at regular
intervals. Plot the graph of the sample values versus time. Time should increase vertically
downwards. Use '*' to mark a point. Write a program to read in sample values and call a
function to plot the values.
22. Repeat Problem 27, but plot a bar chart for the sample values.