0

One of my problem sets requires me to take create a subroutine that will take a String variable as a parameter and return that same string except with the first letter of each word capitalized. The examples in the text use non-standard class the Professor specifically designed. I don't want to do this as I would think it makes more sense to learn with standard classes than see what else is out there. The problem I am having though is my subroutine is returning a String in all capitals. Here is my code:

import java.util.Scanner;

public class Capitalize {

static String capitalizeString(String x) {

    String completedConversion = "";

    for (int i=0; i < x.length(); i++) {

        if (i == 0) {
            char ch = x.charAt(i);
            ch = Character.toUpperCase(ch);
            completedConversion = completedConversion + ch;
            i++;
        }

        if (Character.isLetter(i - 1)) {

            char ch = x.charAt(i);
            completedConversion = completedConversion + ch;
         }

        else {

            char ch = x.charAt(i);
            ch = Character.toUpperCase(ch);
            completedConversion = completedConversion + ch;
        }

    }

    return completedConversion;

} // End of subroutine

I have not yet added any commenting etc. but it should be pretty straightforward.

SOLVED: Using Keammoort's answer

public class Capitalize {

    static String capitalizeString(String x) {

        String completedConversion = "";

        for (int i=0; i < x.length(); i++) {

            if (i == 0) {
                char ch = x.charAt(i);
                ch = Character.toUpperCase(ch);
                completedConversion = completedConversion + ch;
            }

            else if (!Character.isWhitespace(x.charAt(i - 1))) {

                char ch = x.charAt(i);
                completedConversion = completedConversion + ch;

            }

            else {

                char ch = x.charAt(i);
                ch = Character.toUpperCase(ch);
                completedConversion = completedConversion + ch;
            }

        }

return completedConversion;

4 Answers4

2

Identifying the problem

This part code causes problems:

if (Character.isLetter(i - 1)) {
    char ch = x.charAt(i);
    completedConversion = completedConversion + ch;
} else {
    char ch = x.charAt(i);
    ch = Character.toUpperCase(ch);
    completedConversion = completedConversion + ch;
}

First of all method Character.isLetter() with parameter of type int returns true when passed parameter converted to a character (using codePoint) is a letter character. So for quite a few initial iterations you'll get a false. If Character.isLetter() returns false then you're changing a leter to uppercase anyway.

Getting actual character

I think there should be:

if (Character.isLetter(x.charAt(i - 1))) { //added getting character from input String
    char ch = x.charAt(i);
    completedConversion = completedConversion + ch;
} else {
    char ch = x.charAt(i);
    ch = Character.toUpperCase(ch);
    completedConversion = completedConversion + ch;
}

Using isWhitespace() instead of isLetter()

Even better: use isWhitespace() method. It will prevent situations when a digit is inside a word (then character after digit would be uppercase too).

if (!Character.isWhitespace(x.charAt(i - 1))) {
    //if previous char is not a whitespace don't change case
    char ch = x.charAt(i);
    completedConversion = completedConversion + ch;
} else {
    //if previous char is a whitespace change to uppercase
    char ch = x.charAt(i);
    ch = Character.toUpperCase(ch);
    completedConversion = completedConversion + ch;
}

Then all characters that are right after spaces, tabs, etc. will be uppercase.

Using a StringBuilder

Putting all this together plus using a StringBuilder to avoid creating many temporary Strings would be:

static String capitalizeString(String x) {
    StringBuilder completedConversion = new StringBuilder();

    for (int i = 0; i < x.length(); i++) {
        if (i == 0) {
            char ch = x.charAt(i);
            ch = Character.toUpperCase(ch);
            completedConversion.append(ch);
            i++;
        }

        if (!Character.isWhitespace(x.charAt(i - 1))) {
            char ch = x.charAt(i);
            completedConversion.append(ch);
        } else {
            char ch = x.charAt(i);
            ch = Character.toUpperCase(ch);
            completedConversion.append(ch);
        }

    }

    return completedConversion.toString();
}
Keammoort
  • 3,075
  • 15
  • 20
  • This is the correct solution but my reputation is not yet high enough. I will point out though: if I use your solution under "Getting Actual Character", the resulting String will be correct UNLESS there is punctuation, in which case the character after is capitalized. However, when I sub out .isLetter for the .isWhitespace as you suggested, everything works properly. I also want to say I appreciate that you edited my incorrect code instead of providing just an entirely different way to perform the task. That furthers the learning process, and I was restricted from Arrays in this set. – TheArchitect Dec 16 '15 at 23:25
  • Actually, building on what I just said this is part of my problem with people sometimes freaking out that the answer is already posted somewhere. It may be a correct solution to the same problem, but if the student or amateur coder does not know WHY their code was wrong, they are unlikely to learn from their mistakes by just switching to a totally new solution they don't understand or didn't discover themselves. – TheArchitect Dec 16 '15 at 23:29
  • @TheArchitect If your reputation is not high enough you can't vote up, but what you can do is accept this answer (click the green tick next to my answer) so that others that may come across similar problem will know that this solution solved it. As for the second comment I agree sometimes understanding what was wrong is even more important than just getting some other solution. – Keammoort Dec 16 '15 at 23:30
0

This should do it, I split the string up with spaces (so I could tell where to capitalize each) into an array, capitalized each string in the array using toUpperCase() and substring, and returned the string put together again.

public class Capitalize 
{

    static String capitalizeString(String x) 
    {

        String[] splitString = x.split(" "); // Splits the string.
        x = "";
        for (int i = 0; i < splitString.length; i++)
            if (splitString[i].length() > 1)
                x += splitString.substring(0,1).toUpperCase() + splitString.substring(1) + " ";
            else
                x += splitString.substring(0,1).toUpperCase() + " ";
        return x;
    }
}
Riley Carney
  • 804
  • 5
  • 18
  • Thank you, I was going to use split also but we were not to use Arrays in this problem set... should have added that in my post. – TheArchitect Dec 16 '15 at 23:26
0

Use this:

String cap = str.substring(0, 1).toUpperCase() + str.substring(1);
Anoop Kanyan
  • 618
  • 7
  • 19
0

Inside the second if, replace

Character.isLetter(i - 1)

with

Character.isLetter(x.charAt(i - 1))

Eduardo Poço
  • 2,819
  • 1
  • 19
  • 27