I see a number of things that may help you improve your code.
Use const
where possible
The word_counter
function does not (and should not) alter the passed string and so the parameter should therefore be declared const
.
int word_counter(const char string[])
Evaluate each character only once
There's no need to back up and test the previous character to see if it's whitespace or not -- it was already evaluated the last time through the loop! What's needed then, is just to remember that result. One way to do that would be to use a boolean variable to keep track of whether we're in a word or not in a word. Here's a rework showing how that might look:
#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
int word_counter(const char string[])
{
int count = 0;
for (bool inword = false; *string; ++string) {
if (isspace(*string)) {
if (inword) {
inword = false;
}
} else { // not whitespace
if (!inword) {
inword = true;
++count;
}
}
}
return count;
}
As noted in the other review, you should use isspace()
because tab, spaces, form-feeds, vertical tabs and newlines are all things that might separate words.
Understand the concept of a locale
It's often ignored or overlooked, but the isspace
function and its siblings in ctype.h
may change behavior under POSIX or POSIX-like environments, depending on the locale
that's currently in use. It's not a reason to avoid using these functions, but it's good to be aware of the subtle details.
Omit return 0
When a C or C++ program reaches the end of main
the compiler will automatically generate code to return 0, so there is no need to put return 0;
explicitly at the end of main
.
Note: when I make this suggestion, it's almost invariably followed by one of two kinds of comments: "I didn't know that." or "That's bad advice!" My rationale is that it's safe and useful to rely on compiler behavior explicitly supported by the standard. For C, since C99; see ISO/IEC 9899:1999 section 5.1.2.2.3:
[...] a return from the initial call to the main
function is equivalent to calling the exit
function with the value returned by the main
function as its argument; reaching the }
that terminates the main
function returns a value of 0.
For C++, since the first standard in 1998; see ISO/IEC 14882:1998 section 3.6.1:
If control reaches the end of main without encountering a return statement, the effect is that of executing return 0;
All versions of both standards since then (C99 and C++98) have maintained the same idea. We rely on automatically generated member functions in C++, and few people write explicit return;
statements at the end of a void
function. Reasons against omitting seem to boil down to "it looks weird". If, like me, you're curious about the rationale for the change to the C standard read this question. Also note that in the early 1990s this was considered "sloppy practice" because it was undefined behavior (although widely supported) at the time.
So I advocate omitting it; others disagree (often vehemently!) In any case, if you encounter code that omits it, you'll know that it's explicitly supported by the standard and you'll know what it means.