1

How would I find the number of words in a sentence when the sentence has uneven spacing, for example:

"how     are you?"

Here is my code below, but I'm not getting the expected output.

#include <iostream>
#include <string>

using namespace std;

int main() {
    string s = "how     are you?";

    int vowels = 0;
    int consonants = 0;
    int words = 1;

    for(int i= 0; i < s.length(); i++) {
        if(s[i] == 'A' || s[i] == 'E' || s[i] == 'I' || s[i] == 'O' || s[i] == 'U' || s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u') {
            vowels+=1;
        } else if((s[i] == '     ') {
            words +=1;
        } else if ((s[i] == ' ')) {
            words += 1;
        } else {
            consonants += 1;
        }
    }

    cout << "number of vowels "<< vowels<< endl;
    cout << "number of words "<< words << endl;
    cout << "number of consonants "<< consonants << endl;

    return 0;
}

Rushikesh Talokar
  • 1,515
  • 4
  • 16
  • 32
PatrickLao
  • 11
  • 1
  • Put in words how to recognise another word has begun. – greybeard May 10 '21 at 06:03
  • 1
    In 2021 [UTF-8 is used everywhere](https://utf8everywhere.org/). How would you handle a sentence like "Être ou ne pas être, ô grande question à 1€!". How many vowels do you see in that sentence? You might want to use a library like [POCO](http://pocoproject.org/) – Basile Starynkevitch May 10 '21 at 12:00

4 Answers4

0

Here below is an updated version of your code :

#include <iostream>

#include <sstream>

#include <vector>

using namespace std;

int
main() {
  string s = "how     are you?";

  int vowels = 0;
  int consonants = 0;
  int words = 0;

  std::string buf;
  std::stringstream ss(s);
  std::vector < std::string > tokens;

  while (ss >> buf) {
    words++;

    for (int i = 0; i < buf.length(); i++) {
      if (buf[i] == 'A' || buf[i] == 'E' || buf[i] == 'I' || buf[i] == 'O' ||
        buf[i] == 'U' || buf[i] == 'a' || buf[i] == 'e' ||
        buf[i] == 'i' || buf[i] == 'o' || buf[i] == 'u') {
        vowels++;
      } else {
        consonants++;
      }
    }
  }

  cout << "number of vowels " << vowels << endl;
  cout << "number of words " << words << endl;
  cout << "number of consonants " << consonants << endl;

  return 0;
}

(PS: you might want to modify the code so that characters like "?" does not count as a word)

You can also check other solutions using Boost library : link

uahakan
  • 576
  • 1
  • 6
  • 23
0

You can do something like this:

int main() {
    string s = "how     are you?";

    int vowels = 0;
    int consonants = 0;
    int words = 0;

    for(int i= 0; i < s.length(); i++) {
        if(s[i] == 'A' || s[i] == 'E' || s[i] == 'I' || s[i] == 'O' || s[i] == 'U' || s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u') {
            vowels+=1;
        } else if((s[i] == '     ') {
            words +=1;
        } else if (word == 0 || (i > 0 && s[i] != ' ' && s[i-1] == ' ')) {
            words += 1;
        } else {
            consonants += 1;
        }
    }

    cout << "number of vowels "<< vowels<< endl;
    cout << "number of words "<< words << endl;
    cout << "number of consonants "<< consonants << endl;

    return 0;
}
Rushikesh Talokar
  • 1,515
  • 4
  • 16
  • 32
0

You can simply use a boolean flag to keep track if a word is found. when a space or any other punctuation( or non-alphabets or digits) occurs simply check if the flag is true or false, if the flag is true then increment the word count. The modified code will look something like this,

#include <iostream>
#include <string>

using namespace std;

int main() {
    string s = "how     are you?";

    int vowels = 0;
    int consonants = 0;
    int words = 0;
    bool wordFound=false;
    for(int i= 0; i < s.length(); i++) {
        if(s[i] == 'A' || s[i] == 'E' || s[i] == 'I' || s[i] == 'O' || s[i] == 'U' || s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u') {
            vowels+=1;
            wordFound=true;
        } else if (!((s[i]>='A' && s[i]<='Z') || (s[i]>='a' && s[i]<='z') || (s[i]>='0' && s[i]<='9'))) {
            if(wordFound)
            {
                words+=1;
            }
            wordFound=false;
        } else {
            wordFound=true;
            consonants += 1;
        }
    }
    if(wordFound)words+=1;

    cout << "number of vowels "<< vowels<< endl;
    cout << "number of words "<< words << endl;
    cout << "number of consonants "<< consonants << endl;

    return 0;
}
0

C++ 11 has a regular expression library in the standard. So, unless you want to "do it by hand", you could just use <regex> header file.

#include <iostream>
#include <cinttypes>
#include <string>
#include <regex>

int main(int argc, const char* argv[]) {
  std::regex words("\\w+");

  std::string input("how     are you?");
  size_t nwords = 0;
  for (auto iter = std::sregex_iterator(input.begin(),
                    input.end(),
                    words);
       iter != std::sregex_iterator();
       ++iter) {
    std::cout << (*iter).str() << std::endl;
    nwords++;
  }
  std::cout << nwords << std::endl;
  return 0;
}

If you do want to code this by hand, it might be easiest to think about the problem in terms of finite state machines.

  • There are 2 states: {IN_WORD, IN_SPACES}. The current character in your iteration defines the current state.
  • When in state IN_WORD, you collect the characters into a string.
  • When in state IN_SPACES, you just skip the character.
  • On a transition from IN_WORD -> IN_SPACES, a word is done and you increase your word counter.
  • If you are in state IN_WORD when the iteration is done (past last character), you need to increase your word counter as well.
#include <iostream>
#include <cinttypes>
#include <string>
#include <regex>
#include <cctype>

size_t manual_word_counter( const std::string& input) {
  if (input.empty()) // empty string is easy...
    return UINTMAX_C(0);
  
  enum State { IN_WORD, IN_SPACES };
  size_t index = UINTMAX_C(0);
  auto determine_state = [&input, &index] () -> State {
    auto c = input[index];
    if (std::isspace(c) || std::ispunct(c))
      return IN_SPACES;
    return IN_WORD;
  };
  size_t counter = UINTMAX_C(0);
  State currentState = determine_state();
  for (index = 1; index < input.size(); index++) {
    State newState = determine_state();
    if (currentState == IN_WORD && newState == IN_SPACES)
      counter++;
    currentState = newState;
  }
  if (currentState == IN_WORD)
    counter++;

  return counter;
}

int main(int argc, const char* argv[]) {
  std::regex words("\\w+");

  std::string input("how     are you?");
  size_t nwords = 0;
  for (auto iter = std::sregex_iterator(input.begin(),
                    input.end(),
                    words);
       iter != std::sregex_iterator();
       ++iter) {
    std::cout << (*iter).str() << std::endl;
    nwords++;
  }
  std::cout << nwords << std::endl;
  std::cout
    << "manual solution yields: "
    << manual_word_counter(input) << " words." << std::endl;
  return 0;
}
BitTickler
  • 10,905
  • 5
  • 32
  • 53