0

This code only outputs the number of capital letters. It always outputs numMarks and numSpaces as 0. I've also tried sentence.c_str() with the same results. I cannot understand what's happening.

cout << "Please enter a sentence using grammatically correct formatting." << endl;
string sentence = GetLine();
int numSpaces = 0;
int numMarks = 0;
int numCaps = 0;
char words[sentence.length()];
for(int i = 0; i < sentence.length(); ++i)
{
    words[i] = sentence[i];
    if(isspace(words[i]) == true)
    {
        numSpaces++;
    }
    else if(ispunct(words[i]) == true)
    {
        numMarks++;
    }
    else if(isupper(words[i]) == true)
    {
        numCaps++;
    }
}
cout << "\nNumber of spaces: " << numSpaces;
cout << "\nNumber of punctuation marks: " << numMarks;
cout << "\nNumber of capital letters: " << numCaps;

Edit: Fixed the problem. My compiler is weird. All I had to do was remove == true And it worked perfectly. Thanks for the information though. Now I know for the future

3 Answers3

2

The functions isspace, ispunct, isupper that you are using have return type int. They return 0 if it is not a match, and non-zero if it is a match. They don't necessarily return 1, so testing == true may fail even though the check succeeded.

Change your code to be:

if ( isspace(words[i]) )   // no == true

and it should start working properly (so long as you don't type any extended characters - see below).


Further info: there are two different isupper functions in C++ (and the same for the other two functions). The are:

#include <cctype>
int isupper(int ch)

and

#include <locale>
template< class charT >
bool isupper( charT ch, const locale& loc );

You are currently using the first one, which is a legacy function coming from C. However you are using it incorrectly by passing a char; the argument must be in the range of unsigned char. Related question.

So to fix your code properly, choose one of the following two options (including the right header):

 if ( isupper( static_cast<unsigned char>(words[i]) ) )

or

if ( isupper( words[i], locale() ) )

Other things: char words[sentence.length()]; is illegal in Standard C++; array dimensions must be known at compile-time. Your compiler is implementing an extension.

However this is redundant, you could just write sentence[i] and not use words at all.

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365
1

Please change your code to

char c;
...
c = sentence[i];
if(isspace(c))
{
    ++numSpaces;
}
...

isspace returns zero if it is not a space or tab, but you can not assume that it is always returns 1 if it a space or tab. From http://www.cplusplus.com/reference/cctype/isspace/, it says, "A value different from zero (i.e., true) if indeed c is a white-space character. Zero (i.e., false) otherwise."

But if you test it with true, true is converted to 1 and the test fails because for example, on my machine, it returns 8 for a space.

CS Pei
  • 10,869
  • 1
  • 27
  • 46
  • Ugh. Avoid cplusplus.com, it is poorly written. `true` in C++ is equal to one. However, it's true that the `int` result is only zero or nonzero, which is what [cppreference](http://en.cppreference.com/w/cpp/string/byte/isspace) says. – Potatoswatter Apr 29 '15 at 05:37
0

Two things to consider.

First I would use " else if(ispunct(words[i]) !=0 )", instead of comparing the return of the function against true. Thissince the functions return an integer. The value of the integer returned might not match the case of being equal to whatever true is defined in your platform or compiler.

My second suggestion is to check your locale. In unix you can use the "locale" command. In windows you can ask google how to check your locale, for instance for windows 7.

https://www.java.com/en/download/help/locale.xml

If your locale is a "wide character" locale, you might need to use iswpunct (wint_t wc) instead of ispunct(int c).

I hope this helps

Jorge Torres
  • 1,426
  • 12
  • 21