CS50 PSet 2: Readability

A guide to the ‘Readability’ problem in CS50 Week 2.

Goal: To write a program that takes an input text and returns the grade level of complexity. This should be calculated using the Coleman-Liau Index, where L represents the average number of letters per 100 words in the text, and S is the average number of sentences per 100 words in the text.

index = 0.0588 * L - 0.296 * S - 15.8

The program should behave like the below example, with ‘Text:’ acting as a prompt for the user to enter the text to be assessed.

$ ./readability
Text: When he was nearly thirteen, my brother Jem got his arm badly broken at the elbow. When it healed, and Jem's fears of never being able to play football were assuaged, he was seldom self-conscious about his injury. His left arm was somewhat shorter than his right; when he stood or walked, the back of his hand was at right angles to his body, his thumb parallel to his thigh.
295 letter(s)
70 word(s)
3 sentence(s)
Grade 9

Where a text is rated below Grade 1, it should return ‘Before Grade 1’ and when it is rated above Grade 16 it should return ‘Grade 16+’.

Before beginning the main function, we must import the <math.h> and <string.h> libraries which we will use later, as well as the usual <stdio.h> and <cs50.h>.

#include <stdio.h>
#include <cs50.h>
#include <math.h>
#include <string.h>

The first step is then to prompt the user for the text, using get_string().

int  main(void)
{
// Ask for text
string text = get_string("Text: ");

Now we can count the number of letters by looping through the length of the text using strlen() and incrementing l if the character is either an upper or lower case letter. The if condition looks for the ASCII codes for the letters. Note that l must be a float as we will be using it to perform calculations later on.

    // Count number of letters
float l = 0;
for (int i = 0, n = strlen(text); i < n; i++)
{
if ((text[i] >= '97' && text[i] <= '122') ||
(text[i] >= '65' && text[i] <= '90'))
{
l++;
}
}

We use a similar loop to calculate the number of words, except we increment w every time we find a space. Note that we start w at 1 this time to account for the first word, which does not have a space before it.

    // Count number of words
float w = 1;
for (int i = 0, n = strlen(text); i < n; i++)
{
if (text[i] == 32)
{
w++;
}
}

Finally we count the number of sentences by searching for full stops, exclamation marks and question marks and incrementing s accordingly.

    // Count number of sentences
float s = 0;
for (int i = 0, n = strlen(text); i < n; i++)
{
if (text[i] == 46 || text[i] == 33 || text[i] == 63)
{
s++;
}
}

After we convert s and l into the averages per 100 words, the Coleman-Liau index can be calculated. The round() function from the math.h library is used here as the final result must be an integer.

    // Calculate average number of letters & sentences per 100 words
float L = 100 * (l / w);
float S = 100 * (s / w);
// Calculate Coleman-Liau index
int index = round(0.0588 * L - 0.296 * S - 15.8);

With the index calculated, we can now print the grade level of the text.

    // Return result
if (index < 1)
{
printf("Before Grade 1\n");
}
else if (index > 16)
{
printf("Grade 16+\n");
}
else
{
printf("Grade %i\n", index);
}
}

This problem was useful for reinforcing the ASCII system and the importance of knowing when to use different data types, without getting too complex.