Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

1. Introduction In this program, you will practice working with arrays. Your pro

ID: 3698614 • Letter: 1

Question

1. Introduction

In this program, you will practice working with arrays. Your program will read lines of text from the keyboard and use an array to track the number of times each letter occurs in the input text. You will use the contents of this array to generate a histogram (bar graph) indicating the relative frequencies of each letter entered.

This assignment was adapted from an earlier assignment by Prof. George Cheney.

2. Deliverables

This assignment uses multiple files, all of which you will have to write—there are no starter files for this assignment:

prog6_histogram.c: Source file containing your main function.

prog6_functions.h: Header file containing function prototypes..

prog6_functions.c: Source file containing other user-defined functions

Submit all three files by uploading these files to your Dropbox folder. Ensure your file names match the names specified above. Failure to meet this specification will reduce your grade, as described in the program grading guidelines.

3. Specifications

Note: As discussed in class, there are a couple of inefficient brute-force methods to determine which letter is entered. (These prohibited methods are described in Section 4, Hints and Tips.) Using either method will incur a 10 point deduction.

Program variables: At a minimum, you will need variables in main() to track:

The number of times each letter in the alphabet has occurred in the input:

These values should be stored in an array, in which the first entry represents the number of 'A' or 'a' characters entered, and the last entry represents the number of 'Z' or 'z' characters entered.

§§ For example, if your first input is: Hello World!, the array should hold: {0,0,0,1,1,0,0,1,0,0,0,3,0,0,2,0,0,1,0,0,0,0,1,0,0,0}.

§§ The non-zero values indicate the number of 'D', 'E', 'H', 'L', 'O', 'R', and 'W' characters entered, respectively.

§§ Note that the character inputs are case-insensitive—uppercase and lowercase letters are treated the same.

The maximum number of times any letter occurred—3, in the example above.

These variables are updated every time the user enters the 'R' command followed by a line of input, and reset to 0 every time the user enters the 'C' command. They are used to print the histogram whenever the ‘P’ command is used.

The variables should be updated inside the ReadText() function, and printed using the DrawHist() function.

Program structure: Your program should repeatedly prompt the user to enter a single character command until the user enters the “quit” command. The program should perform the following operations for the listed commands:

'C', 'c': Clear the letter counts to 0 in preparation for analyzing new text.

'R', 'r': Read one line of text from the keyboard. Update the letter counts appropriately, using the ReadText() function.

'P', 'p': Plot the histogram of letter frequencies in all lines of text entered since the last 'C' command, using the DrawHist() function.

'Q', 'q': Quit—exit the program.

Functions: Your program should contain the functions described below, as well as any other functions you choose to add. Prototypes for these functions should be in prog6_functions.h, while their definitions should be written in prog6_functions.c:

void ReadText(int histo[], int *max);

Read one line of text from the keyboard, updating the array histo[] with the number of occurrences of each letter of the alphabet.

Also, use the pointer max to update the variable holding the number of occurrences of the most frequent letter.

void DrawHist(int histo[], int max);

Given the array holding the letter counts (histo[]) and the number of occurrences of the most frequent letter (max), plot a histogram of the letter counts. Note that:

max helps you determine the height of the histogram, and therefore the number of rows to print.

When printing each row:

§§ Print a vertical bar | in the appropriate column if the letter count is large enough to be displayed in that row.

§§ Print a space otherwise.

§§ Remember to leave spaces between columns—your output should line up exactly as shown in the test cases. o Remember that you are printing from the top of the histogram to the bottom— that fact will affect the design of this function.

See Section 5 for test cases that demonstrate the proper format for input and output.

4. Hints and tips

ASCII values: Recall that each character has a corresponding integer value, according to the ASCII standard. You may find it useful to work directly with ASCII values in this program, rather than testing if each input character matches a particular letter. 'A' has the ASCII value 65; 'a' has the ASCII value 97.

Character functions: You may find the following built-in functions from the <ctype.h> library useful. Remember that int and char data types are compatible:

int isalpha(int ch): This function returns a non-zero value if ch is a letter of the alphabet, and zero otherwise.

For example, isalpha('Q') returns a non-zero value; isalpha('3') returns 0.

int tolower(int ch): If ch is an uppercase letter, this function returns the lowercase version. Otherwise, tolower() returns the original value of ch.

For example, tolower('Q') returns 'q'; tolower('a') returns 'a'.

int toupper(int ch): If ch is a lowercase letter, this function returns the uppercase version. Otherwise, tolower() returns the original value of ch. o For example, toupper('q') returns 'Q'; toupper('A') returns 'A'.

Prohibited brute force methods: Brute force methods are inefficient solutions to problems. Such a method can be used to determine which letter was entered and update the appropriate array entry, but I want you to find a more efficient solution. Using a brute force method like the following will therefore incur a 10 point deduction:

Large switch (or if) statement: one case for each letter, with array index as a known constant in each case:

     switch(ch) {      // ch = input char     case ‘A’: case ‘a’:     // modify histo[0] break; case ‘B’: case ‘b’:     // modify histo[1] break;

    

      // Remainder of cases

     }

          

Prohibited brute force methods (continued):

Loop: compares input character against all possible letters, using loop index as array index:

char test = ‘A’; for (i = 0; i < 26; i++) { if (ch == test)   // modify histo[i]

                test++;     // Change test

              }             // to next letter

Note: Each brute force method essentially compares the input character against all possible letters. However, once you know the input character is a letter, you do not need to compare it to anything to determine what array entry to update! There’s a simple “transformation” between the ASCII value of each letter and the corresponding index in the histogram array.

5. Test Cases

The following two pages contain test cases showing a sample run of this program. Your output should match these test cases exactly for the given input values.

I will use these test cases in grading of your program, but will also generate additional cases that will not be publicly available. Note that these test cases may not cover all possible program outcomes. You should create your own tests to help debug your code and ensure proper operation for all possible inputs.

I’ve copied and pasted the output from each test case below, rather than showing a screenshot of the output window. User input is underlined in each test case, but it won’t be when you run the program.

          

5. Test Cases (continued)

Enter command (C, R, P, or Q): R

ENTER A LINE OF TEXT:

A sample line of text.

Enter command (C, R, P, or Q): P

LETTER FREQUENCIES IN TEXT:

        |                                           

|       |             |               |             

|       | |     |     | | | | |     | |       |     

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

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

Enter command (C, R, P, or Q): R

ENTER A LINE OF TEXT:

Yet another line

Enter command (C, R, P, or Q): P

LETTER FREQUENCIES IN TEXT:

        |                                           

        |                                           

        |                             |             

|       |             |   |           |             

|       |       |     |   | |         |             

|       | |   | |     | | | | |   | | |       | |   

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

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

Enter command (C, R, P, or Q): C

Enter command (C, R, P, or Q): P

LETTER FREQUENCIES IN TEXT:

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

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

          

5. Test Cases (continued)

Enter command (C, R, P, or Q): R

ENTER A LINE OF TEXT:

She sells 10 seashells by the seashore

Enter command (C, R, P, or Q): P

LETTER FREQUENCIES IN TEXT:

                                    |               

        |                           |               

        |                           |               

        |                           |               

        |     |       |             |               

        |     |       |             |                

|       |     |       |             |               

| |     |     |       |     |     | | |         |   

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

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

Enter command (C, R, P, or Q): X

Invalid command X

Enter command (C, R, P, or Q): Q

Explanation / Answer

// File name: functions.h

#ifndef _FUNCTIONS
#define _FUNCTIONS
// Prototype of functions
void ReadText(int histo[], int *max);
void DrawHist(int histo[], int max);
#endif // End of header file

-----------------------------------------------------------------------

// File name: functions.c
#include"functions.h"
#include<stdio.h>
#include<string.h>

// Function to accept data from the user and count each letter frequency
void ReadText(int histo[], int *max)
{
// Loop variables
int c, d, len;
// Character array to store data entered by the user
char array[100];
fflush(stdin);
// Accept data till enter key is pressed
printf(" ENTER A LINE OF TEXT: ");
scanf("%[^ ]s", array);

// Loops to count the length of the string
for(len = 0; array[len] != ''; len++)
;// Do nothing statement
// Loops 26 times to initialize each element of histo array to zero
for(d = 0; d < 26; d++)
histo[d] = 0;
// Loops till length of the entered data
for(c = 0; c < len; c++)
{
// Loops 26 times for character 'A' to 'Z'
for(d = 0; d < 26; d++)
{
// Converts current character to upper case and compares it with each alphabet 'A' to 'Z'
if(toupper(array[c]) == (char)(d + 65))
// If matches increase the frequency counter of alphabet position of the array by one
histo[d]++;
}// End of inner for loop
}// End of outer for loop
// Stores the starting index position value as maximum
*max = histo[0];
// Loops 26 times to find the maximum frequency
for(d = 1; d < 26; d++)
// Checks if the current frequency value is greater than the previous maximum
if(histo[d] > *max)
// Update the maximum to current index position value of array histo
*max = histo[d];
}// End of function

// Function to draw histogram bar graph
void DrawHist(int histo[], int max)
{
// Loop variable
int d, e;
// Loops from maximum frequency to one reverse order
for(d = max; d >= 1; d--)
{
// Loops 26 times for 'A' to 'Z' alphabets
for(e = 0; e < 26; e++)
// Checks if the current value of d is less than or equals to histo e index position value
if(d <= histo[e])
// Display '|'
printf("| ");
// Otherwise display space
else
printf(" ");
// Displays new line for next row
printf(" ");
}// End of for loop
// Loops 26 times for displaying symbol
for(d = 0; d < 26; d++)
printf("+-");
printf(" ");
// Loops 26 times for 'A' to 'Z' alphabets
for(d = 0; d < 26; d++)
printf("%-2c", d + 65);
}// End of function

----------------------------------------------------------------------------------

// File name: histogram.c
#include"functions.c"
#include<stdio.h>
#include<stdlib.h>
// Function to display menu and return user choice
char menu()
{
// To store user choice
char choice;
printf(" Enter command (C, R, P, or Q): ");
fflush(stdin);
// Accept user choice
scanf("%c", &choice);
// Converts user choice to upper case and returns it
return toupper(choice);
}// End of function

// main function definition
int main()
{
// Array to store frequency of characters
int histo[100];
// To store maximum frequency
int max;
// Loop variable
int d;
// Loops till user choice is not 'Q'
do
{
// Calls the function to accept user choice and calls appropriate function
switch(menu())
{
case 'R':
// Calls the function to accept data and count frequency
ReadText(histo, &max);
break;
case 'P':
// Calls the function to draw bar chart
DrawHist(histo, max);
break;
case 'C':
// Loops 26 times to initialize each element of histo array to zero
for(d = 0; d < 26; d++)
histo[d] = 0;
break;
case 'Q':
exit(0);
default:
printf(" Invalid choice! Try again.");
}// End of switch case
}while(1); // End of do while
}// End of function

Sample Output:

Enter command (C, R, P, or Q): r

ENTER A LINE OF TEXT:
This Is demo for all

Enter command (C, R, P, or Q): p
| | | |
| | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
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
Enter command (C, R, P, or Q): r

ENTER A LINE OF TEXT:
Check this check again this

Enter command (C, R, P, or Q): P
| |
| | |
| | | | | | | |
| | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
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
Enter command (C, R, P, or Q): t

Invalid choice! Try again.
Enter command (C, R, P, or Q): q