Grace Louise Grace Louise - 29 days ago 12
C Question

If loop in C not iterating properly

Writing a word counter on C. I'm counting the number of spaces in the string to determine the number of words. I'm guessing there's something wrong with my if statement. Sometimes it counts the number of words and other times it's throwing up random numbers? For instance "my red dog" has three words but "I drink rum" has one word and "this code makes no sense" has three. It's printing the length of the strings fine for each.

Here's the part of the code in question:

void WordCounter(char string[])
{ int counter = 1;
int i = 0;
int length = strlen(string);
printf("\nThe length of your string is %d", length);

for( i=0;i<length;i++){

if (string[i] == ' ')
{
counter+=1;
++i;

}
else

{
counter +=0;
++i;
}
}

printf("There are %d words in this sentence and i is equal to: %d", counter, i);
}

Answer Source

The biggest problem with your posted code is that it incorrectly increments i where it should not.

for( i=0;i<length;i++){

    if (string[i] == ' ')
    {
        counter+=1;
        ++i; // here

    }
    else
    {
        counter +=0;
        ++i; // here
    }
}

Neither of the //here lines above are needed for what you appear to be trying to do. Furthermore, the entire else-block is pointless, as it modifies nothing except i, which it shouldn't be doing. Therefore, a more correct approach would be simply:

for(i=0; i<length; ++i)
{
    if (string[i] == ' ')
        ++counter;
}

This increments counter whenever you index a space ' ' character. For a trivial algorithm, this will probably suffice to what you were trying.


Counting Spaces, Not Words

Your algorithm really doesn't count words, it simply counts the number of space characters encountered, plus one. This mean some inputs, such as those below (quotes used to note content in the string, not actually present), will not return an accurate word-count:

// shoud be zero, but returns one
"" 

// should be zero, but returns four (three spaces)
"   "

// should be one, but returns five (two spaces, either side)
"  word  "

// should be two, but returns three (two spaces between)
"word  word"

etc.  

A more robust algorithm is required. Note this does NOT solve everything, but it makes great leaps in getting you closers to counting what we call "words". That is, non-whitespace characters separated by whitespace characters and potentially buttressing up to the end of the string.

This uses pointers rather than indexes. In my opinion it is simply easier to read, and declutters the code from indexing syntax, thereby amplifying what is really going on: consuming whitespace, then consuming non-whitespace that we call a "word". Comments inline should explain what is going on:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int WordCounter(const char *s)
{
    int counter = 0;

    // while we haven't reached terminating nullchar
    while (*s)
    {
        // discard all whitespace until nullchar or non-whitespace found
        for (; *s && isspace((unsigned char)*s); ++s);

        // if not nullchar, we have the start of a "word"
        if (*s)
        {
            ++counter;

            // discard all text until next whitespace or nullchar
            for (; *s && !isspace((unsigned char)*s); ++s);
        }
    }

    return counter;
}

int main()
{
    const char *s1 = "There should be eight words in this string";
    printf("\"%s\"\nwords: %d\n", s1, WordCounter(s1));


    const char *s2 = "  There   should\t\t\tbe  eight\n in\n this\n string too\n ";
    printf("\"%s\"\nwords: %d\n", s2, WordCounter(s2));

    const char *s3 = "One";
    printf("\"%s\"\nwords: %d\n", s3, WordCounter(s3));

    const char *s4 = "";
    printf("\"%s\"\nwords: %d\n", s4, WordCounter(s4));

    return 0;
}

Output

"There should be eight words in this string"
words: 8
"  There   should           be  eight
 in
 this
 string too
 "
words: 8
"One"
words: 1
""
words: 0

Not Perfect; Just Better

The prior algorithm still isn't perfect. To accurately extract single words would require knowledge of punctuation, potentially hyphenation, etc. But it is much, much closer to what appears to be the goal. Hopefully you get something out of it.