count word problem

this is my code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <string>
using namespace std;
int countWord(string);
int main()
{ 
    string inputstring;
	cout << "Enter your string: " << endl;
    getline(cin, inputstring);        
    cout << "The string \""<<inputstring<<"\" has "<<countWord(inputstring)<<" words"<<endl;
    return 0;
}
int countWord(string word)
{
    int words = 1;                          
    for (int i = 0; i<word.length(); i++)
		{        
		if (word[i] == ' ' && word[i-1] != ' ') 
		words++;
		}
    return words;
}


this prgm should count the amount of word the user input in. i tried to figure out how to allow the the user to input in space or more than 1 space before inputting in a word.
   hello there!
 yea i guess so...

but i cant seem to figure out how to do it. how do i make it so that the prgm will look at [0] and see if its a ' ' or not and check the next one and see if its a ' ' too and so on until it reaches a word. then it would start counting from there? i was thinking of adding another line
if (word[i] == ' ' && word[i+1] != ' ') but the only thing i see is that it will look at all the word inside the bracket [i]
Okay from my understanding of your dilemma, you want the user to input more than one space between words and then count the words after you have entered them.

There are a number of ways to do this. The quick and dirty way of doing so is arguably the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <string>
using namespace std;
int main()
{ 
    string inputstring;
    
    int count(0);

    while(cin.get() != '\n'){
      cin >> inputstring;
      count++;
    }
    
    cout << "The string \""<<inputstring<<"\" has "<< count <<" words"<<endl;
    
    cin.get();
    cin.ignore();
    return 0;
}


This works because cin skips whitespace unless specified by either using a manipulator such as noskipws or use of cin.get() which reads every character. However, the only problem with the above is that it skips over the whitespace - which is not necessarily a good thing depending on what you want to do.

So, with a little modification to your code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int countWord(string word);
int main()
{ 
    string inputstring;
    
    cout << "Enter your string: " << endl;  
    
    getline(cin, inputstring);
    
    cout << "The string \""<< inputstring <<"\" has "<<countWord(inputstring)<<" words"<<endl;
     
    cin.get();
    cin.ignore();
    return 0;
}
int countWord(string word)
{   
    int words(0);                       
    for (int i = 0; i<word.length(); i++)
    {        
       if ((!isspace(word[i]))&&(isspace(word[i+1]))||(word[i+1] == '\0'))
       { 
           words++;		  
       }
    }
   return words;
}


The above works as it parses the entire string stored from cin up to the newline character (when "Enter is pressed") - which was what you were doing. However, you desire to find contiguous data between spaces. That is what the above code does. But, what happens when there is no space at the end of the stream entered in cin? Without the inclusion of
word[i+1] == '\0'
in the if statement in countWords means that data between that space and the null character that terminates every string, would be completely neglected and your answer would be off by one.

In coding as in Math, Engineering and Physics - always test upper, lower and middle boundary conditions as in the above. Cheers! :)
...But, what happens when there is no space at the end of the stream entered in cin? Without the inclusion of
word[i+1] == '\0'
in the if statement in countWords means that data between that space and the null character that terminates every string, would be completely neglected and your answer would be off by one.

In coding as in Math, Engineering and Physics - always test upper, lower and middle boundary conditions as in the above. Cheers! :)

if i change int words(0); into int words=1; and remove ||(word[i+1] == '\0') then it should works too! =)
and i just learned what isspace is and what it does. thank you very much jrd1
What if the user inputs no words, just whitespace?
@filipe:
What if the user inputs no words, just whitespace?


Excellent question and also an excellent catch. ;) My code misses that completely - I didn't test the boundary conditions well LOL. That being said, below is the corrected version:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int countWord(string word);
int main()
{ 
    string inputstring;
    cout << "Enter your string: " << endl;
    
    getline(cin, inputstring);        
    cout << inputstring << endl;
    
    cout << "The string \""<< inputstring <<"\" has "<<countWord(inputstring)<<" words"<<endl;
    
    
    cin.get();
    return 0;
}
int countWord(string word)
{   
    int words(0);
    int spaces(0);                       
    for (int i = 0; i<word.length(); i++)
    {        
        if((!isspace(word[i]))&&(isspace(word[i+1]))||(word[i+1] == '\0'))
        { 
            words++;
        }
        if(isspace(word[i]))
        {
            spaces++;
            if(spaces == word.length())
            {
                words = 0;
            }
        }
    }
    return words;
}


Why the added peice and not:
int words=1;
? Note, it works and gets the problem solved, but does not flow logically with what is going on. Because, as filipe implies, which I endorse, is that if the user entered only whitespace, it will print 1, which is incorrect. The corrections that I made above ensures that if the string is indeed whitespace, the total words will always be zero. Additionally, the last part of the if statement that I wrote:
||(word[i+1] == '\0')
was written to ensure that the information between the last space and the null character was picked up. In so doing, you do not need
int words=1;
if you wanted to perform other operations on the substrings.

I hope that answers your question dznguy or any other questions you may have had. If not, let us know. :)

Thank you filipe for your guidance on the above.
ty for point that out filipe.
so i tested it out and found that if there is a whitespace at the end of the input, the prgm will also count the last whitespace too...which will display the incorrect amount of words counted
i tried adding a bit of code to jrd1 corrected version and found that it still doesnt work.
im assuming that word.length() give you the total length of the input, include the space in between, at the start, and the end. so i set int a=word.length(); and added
1
2
3
4
if(word[a]==' ')  //or if(isspace(word[a])) if your prefer
{
words--;
}
the code would check the last number in the array and see if its a space or not so that if there is a space at the end of the input, it should words-- by 1 and give the correct countwords.
so what happened? how come it didnt work?

edit: tried
1
2
3
4
if(word.at(a)==' ')
			{
			words--;
			}
and so far no luck too
edit2: never i solved it =]
this solves everything
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <string>
using namespace std;
int countWord(string word);
int main()
{ 
	int wordcount;
	string word;
	getline(cin,word);
	if (word.at(0)==' ')
		wordcount=0;
	else 
		wordcount=1;
	for(int i=1; i<word.length() ;i++)
		if (word[i] != ' ' && word[i-1] == ' ')
		wordcount++;
	cout<<"The string has "<<wordcount<<" words"<<endl;
}


thx for the helps
Last edited on
Topic archived. No new replies allowed.