Convert a String to Uppercase Without Built-in Methods
Return the uppercase form of a string using only character arithmetic, not String.toUpperCase().
For each character, check whether it lies between 'a' and 'z'. If it does, subtract 32 from its code to get the matching uppercase letter, because 'a' - 'A' is 32 in ASCII. Leave every other character untouched and join the results.
Problem Statement
Given a string, return a new string with every lowercase letter converted to
uppercase, but without calling String.toUpperCase() or
Character.toUpperCase(). You must do the conversion using character
arithmetic only.
Only the letters a-z are affected. Uppercase letters, digits, spaces and
punctuation are copied to the output exactly as they appear. For example,
"hello" becomes "HELLO" and "Java 8!" becomes "JAVA 8!".
Input: A single string s.
Output: The string with all lowercase letters converted to uppercase.
Examples
Input: "hello"
Output: "HELLO"Each of h, e, l, l, o is shifted up by 32 in ASCII to H, E, L, L, O.
Input: "Java 8!"
Output: "JAVA 8!"The lowercase a, v, a become A, V, A; the J, space, 8 and ! stay as they are.
Constraints
0 <= s.length() <= 10000Do not use toUpperCase(); only arithmetic on char values
Think Before You Code
Reveal the questions to ask yourself first
- What is the numeric difference between 'a' and 'A' in ASCII?
- How do you test that a character is a lowercase letter, and only then convert it?
- Which characters must you leave completely unchanged?
Hints
Open them one at a time — try after each before revealing the next.
Hint 1
Hint 2
Hint 3
Approach
Reveal the step-by-step approach
Rebuild the string one character at a time.
- Create an empty
StringBuilder. - For each character
c:- If
cis in the range'a'to'z', append(char)(c - 32). - Otherwise append
cunchanged.
- If
- Return the assembled string.
Subtracting 32 works because the uppercase and lowercase Latin letters are laid out in the same order in ASCII, a fixed 32 apart.
Dry Run
Walk through the example step by step
Converting "Java 8!":
index | char | in a..z? | appended
------+------+----------+---------
0 | J | no | J
1 | a | yes | (char)('a'-32) = A
2 | v | yes | V
3 | a | yes | A
4 | ' ' | no | ' '
5 | 8 | no | 8
6 | ! | no | !
result: "JAVA 8!"
Solution
Reveal the full Java solution
public class ToUpperManual {
public static String toUpper(String s) {
StringBuilder sb = new StringBuilder(s.length());
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c >= 'a' && c <= 'z') {
sb.append((char) (c - 32));
} else {
sb.append(c);
}
}
return sb.toString();
}
public static void main(String[] args) {
System.out.println(toUpper("hello")); // HELLO
System.out.println(toUpper("Java 8!")); // JAVA 8!
}
}
The only characters that change are those between 'a' and 'z'. For each of
them, subtracting 32 from the character code lands exactly on the matching
uppercase letter. The explicit (char) cast is needed because subtracting an
int from a char promotes the expression to int.
All other characters — already-uppercase letters, digits, spaces, symbols — are simply appended unchanged, so the output preserves everything except lowercase letters' case.
O(n) where n is the length of the stringSpace: O(n) for the resulting stringCommon Mistakes
- Forgetting the range check and shifting every character by 32, corrupting digits and symbols.
- Omitting the `(char)` cast, so the append adds an int code point or fails to compile as intended.
Edge Cases to Test
- An empty string returns an empty string.
- A string that is already uppercase (like "ABC") is returned unchanged.
- Non-English Unicode letters are not handled by the 32-offset and stay as-is.
Interview Follow-Ups
- How would you write the reverse — lowercasing without built-in methods?
- Why does the ASCII 32-offset trick break for accented or non-Latin letters?
Practising for Java interviews?
CodeBegun's Java Full Stack with AI program builds this problem-solving muscle with mentor review and mock interviews.
Explore the Java Full Stack program →