Computer Science Homework

profileJoshuaTT
asgn06.docx

Programming concepts used: Array of counters, file input, functions, bar graph (histogram), scaling, frequency analysis.

References: a) See http://en.wikipedia.org/wiki/Letter_frequency for information about frequency of letters in typical English text; b) See programming problem P6.21 (page 310) in our textbook for an example of a bar chart/graph.

Do you know which letter is most frequent in typical English text? Which is the least frequent? In this assignment you will read some text from a file and count the number of times each letter appears (its frequency). The frequencies will be stored in an array of integers (size 26). Upper case and lower case letters will not be distinguished. Characters other than letters (such as digits, punctuations, other symbols) may be present. Those non-alphabetic characters will be counted separately (not counted into this array).

Suppose we declare: int [] counters = new int[26]; // allocate storage and initialize

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

The idea is to increment counters[0] when we see an 'a' or an 'A', increment counters[1] when we see a 'b' or a 'B', etc. This is very similar to what we did in Lab 13.

What will be the contents of the array counters after the following text is processed? (The letters are shown just to clarify which array element counts which character, they are not really stored anywhere).

A quick brown fox jumps over the lazy dog.

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

2

1

1

1

2

1

1

1

1

1

1

1

1

1

4

1

1

2

1

1

2

1

1

1

1

1

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

Input to the program

The program would prompt for the name of a file that it should open. It reads the name of the file into a variable of type String, and attempts to open that file[footnoteRef:1]. The program then reads the contents of that file character by character (see below). [1: Reading individual characters from a file using a Scanner is described in section 7.2.2 (page 324), but this is too complicated. Instead, we use a FileInputStream and use the read() method. This method reads a character (as an integer) and returns -1 when the end-of-file is reached. A non-negative value returned by read() is the integer code for the character read and must be type cast into a char type variable. The skeleton code provided takes care of these issues. Also see special topic 7.3 (page 323). ]

Output from the program

Basic Level: You should try to get this level of functionality first. At this level, the program reports:

· The number of alphabetic and non-alphabetic characters in the file.

· If the count of alphabetic characters is > 0, it will then present the frequency data for alphabetic characters in a 2 column table. If there were 0 alphabetic characters, it should just print a message saying that there is no Letter frequency data to display.

After you have achieved the basic level of functionality, you should attempt a higher level of functionality. You can choose standard level for full credit and advanced level for extra credit. To get full credit for this assignment, you need to have your program working at standard level.

Standard level: Display a bar of asterisks whose length is equal to the frequency of the character, next to the numerical value.

Advanced level: For a file containing more than a few paragraphs, the letter frequencies would be larger than the width

of a typical console window, and it would not be useful to have bars of asterisks than span multiple output lines or extend beyond the visible window boundary. At this level, your program must calculate a suitable scale factor, so that the longest bar it has to draw has a reasonable length (as in P6.21). See later in this document about how to find a scale factor. This option requires completing standard level first. So if letter E appeared 100 times and letter A appeared 80 times, and we chose the scale factor to be 4, then the bar next to E has 25 asterisks and the bar next to A has 20 asterisks. A sample output for advanced level will be posted later.

Overall design: See the skeleton program posted. The 'main' function provided is complete, except where you need to add your name. The 'main' function gets the name of the input file from the user, and passes that file name to a function processFile, which really does most of the work. The function called by 'main' could cause an exception, and I provide the code to handle the exception in a minimal way, as we have not learned yet about how to handle exceptions. You need to primarily work on the functions processFile and display.

Functional decomposition

Besides ‘main’, there will be 4 required functions for the basic level.

static int char2int(final char arg) This function receives a character through its parameter and

returns an integer code. For non-letter characters, it just returns -1. For letters, values between 0 and 25 are returned (no case distinction) with 0 being returned when arg = ‘a’ and 25 being returned when arg = ‘z’, similarly for other letters. I will provide this function.

static void processFile(final String fileName) This function declares and initializes some

counter variables and the array of counters. It attempts to open the file as a FileInputStream (may cause exception, handled by 'main'). If the file is opened successfully, its contents are processed character by character. Remember that the read() method returns an integer code of the character, but the code is -1 when it gets to the end of the file.

static void display(final int [] counters) This function displays the frequency data (see sample output). At the basic level the output is a two-column table. At standard or advanced level it also displays a bar of asterisks representing the frequency value. The display function should use (call) the "printChars" function. static void printChars(final int n, final char c) This function prints the character c (n times) on System.out. It should not send the end-of-line character to System.out.

If you want to implement the advanced level, you will need to implement the following function:

static int maxCount(int [] arr) This function returns the largest frequency value stored in the array, useful for deciding on the scale to use for the histogram.

Useful library functions: isLetter, toUpperCase (both are methods in Character). The skeleton posted already uses these functions, so you probably will not need to use them yourself.

Scaling for Advanced level

It is quite possible that the frequency values for certain letters can be larger than the number of characters that can fit on a line of output (typically less than 80). The bar corresponding to each character should still fit on one output line. We solve the problem by finding out the largest count value (use the function maxCount mentioned above), divide (use floating point division) that number by 50. If the result is not an integer, we round up to closest higher integer (the Math.ceil function (see page 883) from Java Math library is useful). If the result is s, then the number of ‘*’ characters used to draw the bar for frequency f is f/s (rounded to nearest integer, use Math.round, then type cast to int).

Sample output (standard level)

Sample output when file cannot be opened

Sample output (Basic level)

Sample output when there are no letters in the input file

Page 1 of 4 Last update: 2014-11-29

Page 1 of 4 Last update: 2014-11-29

Page 5 of 5 Last update: 2014-11-29