0

I am trying to check if the whole word is upper case, if this is true it should return true, else return false.

My current code is:

#include "UpperCaseFilter.h"
#include "ReadFilteredWords.h"
#include "ReadWords.h"
#include <locale>

bool UpperCaseFilter::filter(string word) {
    if(!word.empty()) {
        for(int i = 0; i < word.length(); i++) {
            if(isupper(word[i])) {
                return true;

            }
            else {
                return false;
            }
        }
    }
}

The problem with this code is, if i have for example HeLLO, it will return true because my last character is true. How would I only return true if the whole string is true. I did it using a counter method but it is not the most efficient.

I also tried using the all_of method but I think I dont have the correct compiler version because it says all_of isn't defined (Even with correct imports).

I'm not sure what other approaches there are to this.

beastlycplus
  • 21
  • 1
  • 1
  • 2
  • 4
    It is only checking the first letter – Ed Heal Jan 03 '18 at 17:18
  • 4
    `return std::all_of(begin(word), end(word), [](char c){ return isupper(c); });` – Cory Kramer Jan 03 '18 at 17:18
  • what if string is empty, what will the function return? – Killzone Kid Jan 03 '18 at 17:19
  • 1
    @CoryKramer Missing cast to unsigned char. https://stackoverflow.com/q/21805674/3002139 Alternatively, make the lambda's argument explicitly unsigned. – Baum mit Augen Jan 03 '18 at 17:19
  • @EdHeal well, isn't it checking every word since I have a for loop that goes through each character? – beastlycplus Jan 03 '18 at 17:19
  • 1
    @beastlycplus -- Your function fails to return anything if the string is empty. Thus it is faulty and will invoke undefined behavior if the string is empty. – PaulMcKenzie Jan 03 '18 at 17:20
  • 2
    @beastlycplus Stepping through this code with a debugger would immediately tell you what's wrong. – Baum mit Augen Jan 03 '18 at 17:20
  • @CoryKramer I can't use all_of , i get an error saying `all of is not a member of std` i dont think i have the correct c++ version. – beastlycplus Jan 03 '18 at 17:21
  • @beastlycplus It requires at least C++11 and to `#include ` – Cory Kramer Jan 03 '18 at 17:21
  • @beastlycplus you need to `#include ` for that – Killzone Kid Jan 03 '18 at 17:21
  • 1
    @beastlycplus "_well, isn't it checking every word since I have a for loop that goes through each character?_" No, since it returns, unconditionally (both `if` branches have `return` statement), after the first check. – Algirdas Preidžius Jan 03 '18 at 17:22
  • @PaulMcKenzie i believe it doesn't need to return anything if the string is empty, as long as it is not empty it should continue the check – beastlycplus Jan 03 '18 at 17:22
  • 4
    @beastlycplus -- C++ does not work this way. If your function returns `bool`, you **must** return something, regardless. Otherwise it is undefined behavior. – PaulMcKenzie Jan 03 '18 at 17:23
  • 1
    *"I also tried using the all_of method*" - Why don't you show us what you've tried? *"but I think I dont have the correct compiler version"* - You could put that in a separate question if you cannot find out whether your compiler is new enough. – Christian Hackl Jan 03 '18 at 17:23

6 Answers6

9

Alternatively utilize the std::all_of function in combination with std::isupper in predicate:

#include <iostream>
#include <string>
#include <algorithm>

int main() {
    std::string s = "HELLo";
    if (std::all_of(s.begin(), s.end(), [](unsigned char c){ return std::isupper(c); })) {
        std::cout << "Is uppercase." << '\n';
    } else {
        std::cout << "Is not uppercase." << '\n';
    }
}

Used as part of a function:

bool isUpper(const std::string& s) {
    return std::all_of(s.begin(), s.end(), [](unsigned char c){ return std::isupper(c); });
}
Ron
  • 14,674
  • 4
  • 34
  • 47
  • 1
    That's the C++ solution to the problem. Extra points for working around the terribly broken `isupper` interface. – Christian Hackl Jan 03 '18 at 17:25
  • 1
    C++ way (C++ is ugly without boost but including boost sometimes is annoying for lightweight code). One comment: use !std::islower(c) if one wants to allow non-letters. – fchen Dec 30 '20 at 23:27
5
bool is_all_upper(const std::string& word)
{
    for(auto& c: word) 
        if(!std::isupper(static_cast<unsigned char>(c))) 
            return false;
    return true;
}

I assume that, if the string is empty, it can be considered all-uppercase.

Emilio Garavaglia
  • 20,229
  • 2
  • 46
  • 63
0

You shouldn't have two return conditions inside your loop. Rather, you can use the loop to find problems and, if there are no problems, you'll escape the loop and can tell the user that everything was alright at the end.

In the comments you say "i believe it doesn't need to return anything if the string is empty"; however, a function with a return type, such as this one always returns something. If you don't specify a return value it will give you one, whether you like it or not. Therefore, you must decide what the output should be for every conceivable input. Accordingly, I've added an if statement that emphasizes the special condition of an empty string.

#include "UpperCaseFilter.h"
#include "ReadFilteredWords.h"
#include "ReadWords.h"
#include <locale>

bool UpperCaseFilter::filter(const string &word) {
  if(word.empty()) //You'll need to do the right thing here
    return true;

  //Even if the right thing to do were to return true, so that
  //the check above would be redundant, you'd want to leave a
  //comment here pointing out that you've handled the special case

  for(size_t i = 0; i < word.length(); i++)
    if(!isupper(static_cast<unsigned char>(word[i])))
      return false;

  return true;
}

Note that your previous function signature was:

bool UpperCaseFilter::filter(string word) {

I've changed this to:

bool UpperCaseFilter::filter(const string &word) {

The const guarantees that the function will not alter word and the & symbol passes the string to the function without copying it. This makes the function faster and saves memory.

Richard
  • 56,349
  • 34
  • 180
  • 251
-1
#include "UpperCaseFilter.h"
#include "ReadFilteredWords.h"
#include "ReadWords.h"
#include <locale>

bool UpperCaseFilter::filter(string word) 

 {
    int k=0;
    if(!word.empty()) 
     {
        for(int i = 0; i < word.length(); i++) 
          {
            if(isupper(word[i]))
                k++;

           }
       }

   if(k==word.length())
      return true;

   else
      return false; //this will return false even when word length is 0

}


its more simple now provided if you have done other things right this would run.
sayantan ghosh
  • 426
  • 1
  • 6
  • 8
-2
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
    string str;
    cin >> str;
    bool flag = false;
    int i = 0;
    while(str[i])
    {
        if(isupper(str[i]))
        { 
            flag = true;
        }
        if(!(isupper(str[i])))
        {
            flag = false;
            break;
        }
        i++;
    }
    if(flag == false)
        cout << "false"  << endl;
    else
        cout << "true" << endl;
}
  • Consider adding comments :) – Miguel Lattuada Jan 03 '18 at 17:53
  • 1
    Unprovoked `using namespace std`, no `#include ` (= compilation fail with MSVC), reading a string without `std::getline`, an extra state variable (with a totally generic name) that makes the code harder to read and reason about, `flag == false` instead of `!flag`, no cast to `unsigned char` for `isupper`, C-ish loop condition, pre-C++11 UB for the first `str[i]`... but I think the worst thing is that it makes C++ as a language look bad because it completely ignores the existence of standard functions like `std::all_of` and lambdas, which would encapsulate all logic in a one-liner. – Christian Hackl Jan 03 '18 at 18:21
-2
#include <iostream>
#include <string>
#include <boost/algorithm/string.hpp>
bool IsAllUpperString(string str)
{
    if(boost::to_upper_copy(str)== str) return true;
    return false;
}