2
votes

I'm fairly new to coding. I'm having trouble with my "CountSentences" function. I compare the string to "." , "?" , and ! to count a sentence. It only adds one to the sentence counter no matter how many of the punctuation marks I have in the string. Am I using strcmp wrong to get my desired result and is there another way I can approach this?

#include<cs50.h>

#include<ctype.h>

#include<string.h>

#include<math.h>

//function for letter count
int count_letters(string s)
{
    int numberofLetters = 0; // counter

    //loop as long as string length
    for(int i = 0, n = strlen(s); i < n;  i++)
    {
        //if character is alphanumeric
        if(isalnum(s[i]) != 0)
        {
            numberofLetters++; //increase counter
        };
    };
    return numberofLetters; //return new counter number
};

//function for word count
int count_Words(string w)
{
    int numberofWords = 0;//counter for words declared
    int i = 0; // counter for character in string

    if(w == NULL) // if nothing
    {
        return numberofWords; // return Wordcount of 0
    };


    bool spaces = true; //truth value for space

    //if character is not null terminating character
    while(w[i] != '\0')
    {


        if(isblank(w[i]) != 0) //if character is blank
        {
            spaces = true; //its a space
        }
        else if(spaces) //if no more space and a letter is present add to words
        {
            numberofWords++; //add to number of words counter
            spaces = false;
        };
        i++;// increase chracter count in string w

    };

    return numberofWords; //return total word counter
};

//function to count sentences
int count_Sentences(string l)
{
    //variable counter for marks
    int countMarks = 0;

    //loop iteration using the number of characters in string
    for(int i = 0, n = strlen(l); i < n; i++)
    {
        //check if character is ?, . , or !
        if(strcmp(&l[i], "!") == 0  || strcmp(&l[i], ".") == 0  ||  strcmp(l, "?") == 0)
        {
            countMarks++;// sentence counted
        };

    };
    // return the total number of marks
    return countMarks;
};


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

//to check the functions bug checker
    printf("Number of letters: %i\n", count_letters(text));
    printf("Number of words: %i\n", count_Words(text));
    printf("Number of sentences: %i\n", count_Sentences(text));

    //Coleman Liau Index
    int grade = round(0.0588 * (100 * (count_letters(text)) / (count_Words(text))) - 0.296 * (100 *(count_Sentences(text)) / (count_Words(text))) - 15.8 );



    if(grade <= 1)
    {
        printf("Before Grade 1\n");
    }
    else if(grade < 16)
    {
        printf("Grade %i\n", grade);
    }
    else
    {
        printf("Grade 16+\n");
    };
};
2
Your code is comparing all the rest of the input with a one-char string. I suggest if(l[i] == '!') etc. Aside: it's ill-advised to use l (the letter ELL) as variable name. It is too easily confused with 1 (the digit ONE) making the code hard to read, and open to mistakes.Weather Vane
You might like to know about the function family ispunct() and isspace() and isalpha() and so on, declared in ctype.h.Weather Vane
regarding: ` }; };` do not place a semicolon ; after a closing brace }user3629249
the posted code is missing the statement: #include <stdio.h> for the printf() and similar functionsuser3629249
regarding: if(strcmp(&l[i], "!") == 0 || strcmp(&l[i], ".") == 0 || strcmp(l, "?") == 0) This will NOT work because a single char from l[] is not a string. Suggest: if( l[i] == '!' || l[i] == '.' || i[i] == '?' ) Notice the use of single quotes rather than double quotes so comparing a character rather than a string. Notice the use of appropriate horizontal spacing for readability.user3629249

2 Answers

1
votes
    if(strcmp(&l[i], "!") == 0  || strcmp(&l[i], ".") == 0  ||  strcmp(l, "?") == 0)

strcmp compares two strings. In C, our "string" is essentially "the char-sized data starting at the place this pointer points to, and continuing until a null terminator". The cs50 library does not change this and does not give you a real string type; it only provides a typedef and some helper functions for reading input. (It also, sadly, does not and realistically cannot give you a real text character type, which char also is not; but that is beyond the scope of this answer.)

&l[i] is a pointer into the middle of the l string, starting at offset i. When that pointer is used by strcmp, it will treat the "string" as everything from that character to the end of the original string - because that's where the null terminator is. It will, in particular, not treat the single l[i] char as a separate string, in general, because the next char is in general not a null terminator. So,

It only adds one to the sentence counter no matter how many of the punctuation marks I have in the string.

In fact, it only even adds one because your string ends with one of those marks.

To compare individual chars, don't use strcmp. It is not intended nor fit for the purpose. A char is a single entity, so it can be compared just fine with ==. You just need to have something appropriate on both sides of the comparison.

Recall, in C single quotes are used for char literals, and indexing into the char array (equivalently, "indexing" into a char pointer, which performs the equivalent pointer arithmetic) gives you a char. Thus:

if (l[i] == '!' || l[i] == '.' || l[i] == '?')
2
votes

You indeed need to see if the one character l[i] is any of ., ? or !. To do that, you can test if that is equal to any of these character constants, i.e. l[i] == '!' || l[i] == '.' || l[i] == '?'

Or you can use the function strchr that will look for a given character in a given string and return a pointer to that character, or a null pointer if the character is not found. A null pointer will be considered as falsy in if, and and a non-null pointer truthy. So we can look for l[i] in the string ".?!":

if (strchr(".?!", l[i])) {
    ...
}