C++ function to count all the words in a string
Assuming words are white space separated:
unsigned int countWordsInString(std::string const& str)
{
std::stringstream stream(str);
return std::distance(std::istream_iterator<std::string>(stream), std::istream_iterator<std::string>());
}
Note: There may be more than one space between words. Also this does not catch other white space characters like tab new line or carriage return. So counting spaces is not enough.
The stream input operator >> when used to read a string from a stream. Reads one white space separated word. So they were probably looking for you to use this to identify words.
std::stringstream stream(str);
std::string oneWord;
stream >> oneWord; // Reads one space separated word.
When can use this to count words in a string.
std::stringstream stream(str);
std::string oneWord;
unsigned int count = 0;
while(stream >> oneWord) { ++count;}
// count now has the number of words in the string.
Getting complicated:
Streams can be treated just like any other container and there are iterators to loop through them std::istream_iterator. When you use the ++ operator on an istream_iterator it just read the next value from the stream using the operator >>. In this case we are reading std::string so it reads a space separated word.
std::stringstream stream(str);
std::string oneWord;
unsigned int count = 0;
std::istream_iterator loop = std::istream_iterator<std::string>(stream);
std::istream_iterator end = std::istream_iterator<std::string>();
for(;loop != end; ++count, ++loop) { *loop; }
Using std::distance just wraps all the above in a tidy package as it find the distance between two iterators by doing ++ on the first until we reach the second.
To avoid copying the string we can be sneaky:
unsigned int countWordsInString(std::string const& str)
{
std::stringstream stream;
// sneaky way to use the string as the buffer to avoid copy.
stream.rdbuf()->pubsetbuf (str.c_str(), str.length() );
return std::distance(std::istream_iterator<std::string>(stream), std::istream_iterator<std::string>());
}
Note: we still copy each word out of the original into a temporary. But the cost of that is minimal.
A less clever, more obvious-to-all-of-the-programmers-on-your-team method of doing it.
#include <cctype>
int CountWords(const char* str)
{
if (str == NULL)
return error_condition; // let the requirements define this...
bool inSpaces = true;
int numWords = 0;
while (*str != '\0')
{
if (std::isspace(*str))
{
inSpaces = true;
}
else if (inSpaces)
{
numWords++;
inSpaces = false;
}
++str;
}
return numWords;
}
You can use the std::count or std::count_if to do that. Below a simple example with std::count:
//Count the number of words on string
#include <iostream>
#include <string>
#include <algorithm> //count and count_if is declared here
int main () {
std::string sTEST("Text to verify how many words it has.");
std::cout << std::count(sTEST.cbegin(), sTEST.cend(), ' ')+1;
return 0;
}
UPDATE: Due the observation made by Aydin Özcan (Nov 16) I made a change to this solution. Now the words may have more than one space between them. :)
//Count the number of words on string
#include <string>
#include <iostream>
int main () {
std::string T("Text to verify : How many words does it have?");
size_t NWords = T.empty() || T.back() == ' ' ? 0 : 1;
for (size_t s = T.size(); s > 0; --s)
if (T[s] == ' ' && T[s-1] != ' ') ++NWords;
std::cout << NWords;
return 0;
}