14. Check Character Case

Easy ⏱️ 10 min

Problem Statement

Check whether the given character is in upper case or lower case or none

Input Format:
Enter a Character as input
Output Format:
Print the output as "UPPERCASE" or "LOWERCASE" or "NONE"
Constraints:
0 <= INPUT <= 2^7
Sample Input 1:
z
Sample Output 1:
LOWERCASE
Sample Input 2:
Z
Sample Output 2:
UPPERCASE
🔤 Character Comparisons & ASCII Magic
📊 Understanding ASCII - The Secret Code Behind Characters

What is ASCII?

ASCII (American Standard Code for Information Interchange) is a character encoding standard that assigns numeric values (0-127) to characters.

Why ASCII matters for this problem:

When you write 'A' or 'z' in C++, the computer stores them as numbers!

  • 'A' is stored as 65
  • 'Z' is stored as 90
  • 'a' is stored as 97
  • 'z' is stored as 122

Complete ASCII character ranges:

Character Type ASCII Range Decimal Values Total Count
Uppercase Letters A-Z 65-90 26 letters
Lowercase Letters a-z 97-122 26 letters
Digits 0-9 48-57 10 digits
Space (space) 32 1 character

🔍 Key observation:

  • Uppercase: Continuous range from 65 to 90
  • Lowercase: Continuous range from 97 to 122
  • Difference between upper and lower of same letter: 32
  • Example: 'a' (97) - 'A' (65) = 32

Complete uppercase ASCII table:

Char ASCII Char ASCII Char ASCII
A65 J74 S83
B66 K75 T84
C67 L76 U85
D68 M77 V86
E69 N78 W87
F70 O79 X88
G71 P80 Y89
H72 Q81 Z90
I73 R82

Complete lowercase ASCII table:

Char ASCII Char ASCII Char ASCII
a97 j106 s115
b98 k107 t116
c99 l108 u117
d100 m109 v118
e101 n110 w119
f102 o111 x120
g103 p112 y121
h104 q113 z122
i105 r114
🎯 How Character Comparison Works - The Magic Behind >=

Our condition: ch >= 'A' && ch <= 'Z'

What really happens behind the scenes:

  1. User enters: M
  2. Stored in ch as: 77 (ASCII value)
  3. Comparison ch >= 'A' becomes: 77 >= 65 → TRUE ✅
  4. Comparison ch <= 'Z' becomes: 77 <= 90 → TRUE ✅
  5. Combined: TRUE && TRUE → TRUE ✅

Breaking down ch >= 'A' && ch <= 'Z':

Part 1: ch >= 'A'

  • Checks if character is at or after 'A' in ASCII table
  • Equivalent to: ch >= 65
  • Rules out: Everything before 'A' (0-64)

Part 2: ch <= 'Z'

  • Checks if character is at or before 'Z' in ASCII table
  • Equivalent to: ch <= 90
  • Rules out: Everything after 'Z' (91-127)

Part 3: && (AND operator)

  • Both conditions must be TRUE
  • Creates a "range check" between 65 and 90
  • Only passes if: 65 ≤ ch ≤ 90

Visual representation:

ASCII: 0 ... 64 | 65...90 | 91...96 | 97...122 | 123...127
NONE | A...Z | NONE | a...z | NONE
| ✅ | | |

Why this works for ANY letter:

Input ASCII ch >= 'A' (65)? ch <= 'Z' (90)? Result
A 65 TRUE (65≥65) TRUE (65≤90) ✅ UPPERCASE
M 77 TRUE (77≥65) TRUE (77≤90) ✅ UPPERCASE
Z 90 TRUE (90≥65) TRUE (90≤90) ✅ UPPERCASE
a 97 TRUE (97≥65) FALSE (97>90) ❌ Not uppercase
5 53 FALSE (53<65) TRUE (53≤90) ❌ Not uppercase

💡 Key insight: We're not comparing characters - we're comparing their ASCII numbers!

🔍 Step-by-Step Execution Examples

Example 1: Uppercase letter (input = 'Z')

  1. Declare: char ch;
  2. Read: cin >> ch; → User enters Z
  3. Store: ch = 'Z' (internally: ch = 90)
  4. Check condition 1: ch >= 'A' && ch <= 'Z'
    • 90 >= 65 → TRUE ✅
    • 90 <= 90 → TRUE ✅
    • TRUE && TRUE → TRUE ✅
  5. Execute: cout << "UPPERCASE";
  6. Output: "UPPERCASE"

Example 2: Lowercase letter (input = 'z')

  1. Read: ch = 'z' (internally: ch = 122)
  2. Check condition 1: ch >= 'A' && ch <= 'Z'
    • 122 >= 65 → TRUE ✅
    • 122 <= 90 → FALSE ❌
    • TRUE && FALSE → FALSE ❌
  3. Skip to else-if
  4. Check condition 2: ch >= 'a' && ch <= 'z'
    • 122 >= 97 → TRUE ✅
    • 122 <= 122 → TRUE ✅
    • TRUE && TRUE → TRUE ✅
  5. Execute: cout << "LOWERCASE";
  6. Output: "LOWERCASE"

Example 3: Digit (input = '5')

  1. Read: ch = '5' (internally: ch = 53)
  2. Check condition 1: ch >= 'A' && ch <= 'Z'
    • 53 >= 65 → FALSE ❌
    • Short-circuit! Second part not evaluated
    • Result: FALSE ❌
  3. Check condition 2: ch >= 'a' && ch <= 'z'
    • 53 >= 97 → FALSE ❌
    • Short-circuit!
    • Result: FALSE ❌
  4. Go to else
  5. Execute: cout << "NONE";
  6. Output: "NONE"

Example 4: Special character (input = '@')

  1. Read: ch = '@' (internally: ch = 64)
  2. Check uppercase: 64 >= 65 → FALSE ❌
  3. Check lowercase: 64 >= 97 → FALSE ❌
  4. Output: "NONE"

Example 5: Space (input = ' ')

  1. Read: ch = ' ' (internally: ch = 32)
  2. Check uppercase: 32 >= 65 → FALSE ❌
  3. Check lowercase: 32 >= 97 → FALSE ❌
  4. Output: "NONE"
🆚 Why NOT Use Switch? When If-Else is Better

Question: Why didn't we use switch for this problem?

❌ Switch would be TERRIBLE here:

switch (ch) {
  case 'A': case 'B': case 'C': case 'D': case 'E':
  case 'F': case 'G': case 'H': case 'I': case 'J':
  case 'K': case 'L': case 'M': case 'N': case 'O':
  case 'P': case 'Q': case 'R': case 'S': case 'T':
  case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
    cout << "UPPERCASE";
    break;
  case 'a': case 'b': case 'c': // ... 26 more cases!
    cout << "LOWERCASE";
    break;
  default:
    cout << "NONE";
}

Problems with switch approach:

  • ❌ Need to list 52 individual cases (26 uppercase + 26 lowercase)
  • ❌ Over 60 lines of code (vs 10 with if-else)
  • ❌ Error-prone: Easy to forget a letter
  • ❌ Hard to maintain and read
  • ❌ Doesn't show the underlying pattern

✅ If-else with range checking is perfect:

if (ch >= 'A' && ch <= 'Z')
  cout << "UPPERCASE";
else if (ch >= 'a' && ch <= 'z')
  cout << "LOWERCASE";
else
  cout << "NONE";

Advantages:

  • ✅ Only 10 lines of code
  • ✅ Handles all 52 letters with 2 conditions
  • ✅ Clear and readable
  • ✅ Shows the pattern (continuous range)
  • ✅ Easy to understand the logic

When to use switch vs if-else:

Use Switch Use If-Else
Discrete values (1, 2, 3, etc.) Range checks (1-10, A-Z)
Few specific cases (menu: 1-5) Many values in a range
Exact equality (day == 1) Comparisons (>=, <=, >, <)
Enums, day/month numbers Complex conditions (&&, ||)

💡 Rule of thumb: If you need >= or <=, use if-else. If you need == with specific values, consider switch!

🔧 Alternative Approaches & Library Functions

Method 1: Our approach (manual range checking)

if (ch >= 'A' && ch <= 'Z')
  cout << "UPPERCASE";
else if (ch >= 'a' && ch <= 'z')
  cout << "LOWERCASE";
else
  cout << "NONE";

✅ No library needed
✅ Full control
✅ Educational - shows ASCII logic

Method 2: Using ASCII values explicitly

if (ch >= 65 && ch <= 90)
  cout << "UPPERCASE";
else if (ch >= 97 && ch <= 122)
  cout << "LOWERCASE";
else
  cout << "NONE";

✅ Functionally identical
❌ Less readable (magic numbers)
❌ Not recommended

Method 3: Using <cctype> library functions

#include <cctype>

if (isupper(ch))
  cout << "UPPERCASE";
else if (islower(ch))
  cout << "LOWERCASE";
else
  cout << "NONE";

✅ Clean and professional
✅ Self-documenting code
✅ Handles locale-specific characters
❌ Requires library include

Useful <cctype> functions:

Function Purpose Example
isupper(ch) Check if uppercase isupper('A') → true
islower(ch) Check if lowercase islower('a') → true
isalpha(ch) Check if letter (any case) isalpha('Z') → true
isdigit(ch) Check if digit (0-9) isdigit('5') → true
isalnum(ch) Check if letter or digit isalnum('A') → true
isspace(ch) Check if whitespace isspace(' ') → true
toupper(ch) Convert to uppercase toupper('a') → 'A'
tolower(ch) Convert to lowercase tolower('A') → 'a'

When to use which approach?

  • Learning/Practice: Method 1 (manual range checking)
  • Production code: Method 3 (library functions)
  • Competitive programming: Either, but Method 1 is faster to type
🎯 Common Pitfalls & Edge Cases

Mistake 1: Using OR instead of AND

// ❌ WRONG!
if (ch >= 'A' || ch <= 'Z') // Using || instead of &&
  cout << "UPPERCASE";

Why this is wrong:

  • ANY character satisfies this condition!
  • Example: 'z' (122)
    • 122 >= 65 → TRUE
    • TRUE || anything → TRUE
    • Result: 'z' is "UPPERCASE" ❌ WRONG!

Mistake 2: Forgetting single quotes

// ❌ WRONG!
if (ch >= A && ch <= Z) // A and Z are undefined variables!

// ✅ CORRECT!
if (ch >= 'A' && ch <= 'Z') // 'A' and 'Z' are character literals

Mistake 3: Comparing with strings

// ❌ WRONG!
if (ch >= "A" && ch <= "Z") // "A" is a string, not a character!

Strings use double quotes "", characters use single quotes ''

Mistake 4: Wrong order of conditions

// ❌ WRONG!
if (ch >= 'Z' && ch <= 'A') // Impossible! No char is both ≥90 AND ≤65

Edge cases to test:

Input ASCII Expected Output Why
'A' 65 UPPERCASE First uppercase letter
'Z' 90 UPPERCASE Last uppercase letter
'a' 97 LOWERCASE First lowercase letter
'z' 122 LOWERCASE Last lowercase letter
'@' 64 NONE Just before 'A'
'[' 91 NONE Just after 'Z'
'`' 96 NONE Just before 'a'
'{' 123 NONE Just after 'z'
'0' 48 NONE Digit, not letter
' ' 32 NONE Space character
🌍 Real-World Applications

Where character case checking is used:

1. Password Validation:

// Check password strength
bool hasUpper = false, hasLower = false;
for (char c : password) {
  if (c >= 'A' && c <= 'Z') hasUpper = true;
  if (c >= 'a' && c <= 'z') hasLower = true;
}
if (hasUpper && hasLower)
  cout << "Strong password!";

2. Case-Insensitive Comparison:

// Compare strings ignoring case
// Convert both to lowercase first
char ch1 = 'A', ch2 = 'a';
if (tolower(ch1) == tolower(ch2))
  cout << "Same letter!";

3. Text Processing & Formatting:

  • Title case: "hello world" → "Hello World"
  • Sentence case: "HELLO" → "Hello"
  • Toggle case: "HeLLo" → "hEllO"

4. Data Validation:

// Validate name (only letters allowed)
bool isValidName = true;
for (char c : name) {
  if (!((c >= 'A' && c <= 'Z') ||
        (c >= 'a' && c <= 'z') ||
        c == ' ')) {
    isValidName = false;
    break;
  }
}

5. Encryption/Decryption (Caesar Cipher):

// Shift uppercase letters by 3
if (ch >= 'A' && ch <= 'Z') {
  ch = ((ch - 'A' + 3) % 26) + 'A';
}
// 'A' → 'D', 'B' → 'E', etc.

6. Username Validation:

  • Check if starts with letter
  • Ensure only letters, numbers, underscore
  • Enforce lowercase only

7. Syntax Highlighting (Code Editors):

  • Detect keywords (if, else, for)
  • Identify variable names (start with letter)
  • Highlight function names

8. Spell Checkers:

  • Suggest lowercase version of word
  • Auto-capitalize first letter of sentence

💡 Industry Tip: Character classification is fundamental to text processing, compilers, parsers, and natural language processing!

💡 Key Takeaway: Character comparisons use ASCII values behind the scenes. Range checking with >= and <= is perfect for continuous ranges like A-Z. Always use && for range checks, never ||!

Solution

#include <iostream>

using namespace std;

int main() {
    char ch;
    cin >> ch;
    
    if (ch >= 'A' && ch <= 'Z')
        cout << "UPPERCASE";
    else if (ch >= 'a' && ch <= 'z')
        cout << "LOWERCASE";
    else
        cout << "NONE";
    
    return 0;
}