-1

I am currently taking a cs50 course (free version, so i dont have classmates or instructor feedback) and we are asked to write a program that reads text input from the user, and analyzes the text for:

  • number of letters
  • number of words
  • number of sentences
  • L = avg # of letters per 100 words
  • S = avg # of sentences per 100 words
  • grade level = (((0.0588) * L) - ((0.296) * S)) - 15.8)

Sample text:

"Would you like them here or there? I would not like them here or there. I would not like them anywhere."

I have run debugging on the code and it successfully counts letters, words, and sentences.

The first issue arises here:

    float calculate_avg_letters(int letters, int 
    words)
    {
        float L = ((letters) / (words)) * 100;
   
        return (L);
    } 

I have tried everything (i think) from changing the data type, rearranging the parentheses, using two separate functions to perform the division first then multiply the resulting variable, changing the data type of the preceding variable. Step by step debugging shows (letters = 80), (words = 21), and (sentences = 3), so L = ((80 / 21) * 100). It should be ~380, but the closest I was able to get was 300, and most variations output something like 1.44e13

for context, here is the entire code:

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


    float count_letters(string paragraph);
    float count_words(string paragraph);
    float count_sentences(string paragraph);
    float calculate_avg_letters(int letters, int 
    words);
    float calculate_avg_sentences(int sentences, int 
    words);
    int calculate_grade_level(int L, int S);


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

        float letters = count_letters(text);
        float words = count_words(text);
        float sentences = count_sentences(text);
        float L = calculate_avg_letters(letters, 
    words);
        float S = calculate_avg_sentences(sentences, 
    words);
        int grade = calculate_grade_level(L, S);

        // print results
        if (grade < 1)
        {
            printf("Before Grade 1\n");
        }
        else if (grade >= 16)
        {
            printf("Grade 16+\n");
        }
        else
        {
            printf("Grade %i\n", grade);
        }




    }






    int calculate_grade_level(int L, int S)
    {

        int grade = (((0.0588 * L) - (0.296 * S)) - 
    15.8);
        return round(grade);

    }



    float count_letters(string paragraph)
    {
        int length = strlen(paragraph);
        float letters = 0;

        for (int i = 0; i < length; i++)
        {
            if (isalpha(paragraph[i]))
            letters++;
        }
        printf("%.1f letters\n", letters);
        return letters;

    }




    float count_words(string paragraph)
    {
        int length = strlen(paragraph);
        float words = 0;

        for (int i = 0; i < length; i++)
        {
            if (paragraph[i] == ' ')

                words++;

        }
        words = words + 1;
        printf("%.1f words\n", words);
        return words;
    }




    float count_sentences(string paragraph)
    {
        int length = strlen(paragraph);
        float sentences = 0;

        for (int i = 0; i < length; i++)
        {
            if (paragraph[i] == '.' || paragraph[i] 
    == '!' || paragraph[i] == '?')
            {
                sentences++;
            }
        }
        printf("%.1f sentences\n", sentences);
        return sentences;
    }



    float calculate_avg_letters(int letters, int 
    words)
    {
        float L = ((letters) / (words)) * 100;

        return L;
    }



    float calculate_avg_sentences(int sentences, int 
    words)
    {
        float S = ((sentences / words) * 100);
        return S;

    }
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
jaudiola
  • 1
  • 1
  • Welcome to Stack Overflow. Please read [ask] and [mre], and try to show *all, but only* code *that is needed to demonstrate the specific problem you are asking about.* – Karl Knechtel Jul 29 '22 at 22:55
  • Very simple... The division is done using integers (truncating), THEN converted and stored into a float. Try using `float L = (float)words/letters * 100.0; – Fe2O3 Jul 29 '22 at 23:45

1 Answers1

1

I have tried everything (i think) from changing the data type, rearranging the parentheses, using two separate functions to perform the division first then multiply the resulting variable, changing the data type of the preceding variable.

You just need to use the correct type, the one that makes more sense given what each variable need to store and how it needs to be used.

Let's consider the functions (and variables) like

float letters = count_letters(text);

An integral type, let's say an int, should be your first choice, when it comes to counting something. I'd write a function with the following signature

int count_letters(char const *paragraph);

// Then, in 'main'
int letters = count_letters(text);

Now, let's consider calculate_avg_letters

float calculate_avg_letters(int letters, int words)
{
    float L = ((letters) / (words)) * 100;
    //                  ^^^                That's an integral division.   
    return (L);
} 

That's a common mistake. Given all the terms of the operation are int, what is performed is an integer division and only after that the result is converted to a float.

See e.g. What is the behavior of integer division?

What you need to do is just to explicitly convert at least one of the operands to a floating point number.

double average_per_100_words(int item, int words)
{
    return (double)item / words * 100;
    //                    ^^^^^   ^^^  Those will be implicitly converted to double
}

// Then, in 'main'
double L = average_per_100_words(letters, words);
double S = average_per_100_words(sentences, words);

Then again, the prototype and the definition of calculate_grade_level should be changed accordingly.

int grade_level(double L, double S)
{ //            ^^^^^^    ^^^^^^                       Avoid truncation
    return round(((0.0588 * L) - (0.296 * S)) - 15.8);
}
Bob__
  • 12,361
  • 3
  • 28
  • 42
  • This solved it! Thank you for giving an in-depth explanation. Really helped me understand the process better. However, the cs50 check program gave me 8/11 smiley faces -__- ... so i have an issue elsewhere, but I will see if I can fix it before coming back here for help.. Thank you, again! – jaudiola Jul 30 '22 at 01:44
  • I'm back. So I have now gotten my code to 10/11 smiley faces (almost there). The last remaining issue seems to be occurring with the rounding of the grade level and the ints (doubles) its handling. There is a text prompt that is expected to be grade level 7, yet my code returns grade level 8. After doing some very quick and somewhat sloppy rounding on paper, I noticed the final answer i received is 7.45 (which is awfully close to 7.5, and I assume the extra decimal points that the doubles are handling are pushing this to round to 8. Any advice? – jaudiola Jul 30 '22 at 02:35
  • @jaudiola Well, if `double` is too precise, you can go back using `float`, which may be the expected type. It's hard to tell without knowing the exact conditions of the failing test. – Bob__ Jul 30 '22 at 05:13
  • found it. it was a silly mistake on my part. forgot to change input types when defining function...INCORRECT: int calculate_grade_level(int L, int S).....CORRECT: int calculate_grade_level(double L, double S)....and likewise when declaring before main. silly me......lol – jaudiola Jul 30 '22 at 16:10