Skip to content
wannacode

Working with text

Problem

The code is right, but it does not work

The shop gives 10% off with the code SUMMER10. A customer copies it from the ad, but types it in lowercase and puts a space in front by accident:

Scanner in = new Scanner(System.in);
String code = in.nextLine();
if (code.equals("SUMMER10")) {
System.out.println("10% off");
} else {
System.out.println("Invalid code");
}
Input
summer10
Output
Invalid code

To a person, the code is the same. To the program, summer10 and SUMMER10 are different texts: the first has one more character, and the letters are different. You need to be able to look inside a text and fix it.

The idea

Text is a sequence of characters

Text is characters placed one after another: letters, digits, spaces, signs. Each character has an index, like in an array. The first one has index 0.

String code = "SUMMER10";
System.out.println(code.length());
System.out.println(code.charAt(0));
System.out.println(code.charAt(code.length() - 1));
Output
8
S
0
  • code.length() is the number of characters.
  • code.charAt(0) is the character with index 0. The last character has index length() - 1.

A single character has its own type: char. You write it in single quotes: 'S', '0', ' '. Text goes in double quotes: "S" is a text with one character, not a char.

Watch the parentheses: for text it is length(), with parentheses, because it is a method. For an array it is length, without parentheses.

See it

Character by character

How many digits are in the phone number? You loop through the indexes from 0 to the last one and look at each character:

String phone = "0888 123 456";
int digits = 0;
for (int i = 0; i < phone.length(); i++) {
char c = phone.charAt(i);
if (c >= '0' && c <= '9') {
digits++;
}
}
System.out.println("Digits: " + digits);
Output
Digits: 10

c >= '0' && c <= '9' works because every character is really a number: its code in the character table. The digits from '0' to '9' have consecutive codes, and so do the letters from 'a' to 'z'. That is why characters compare like numbers.

More precisely, if you are curious
  • There are ready-made methods for checks like these: Character.isDigit(c), Character.isLetter(c), Character.isUpperCase(c), Character.isLowerCase(c). They also know letters outside English, like é.
  • You get the code of a character with a cast: (int) 'A' is 65. The other way, (char) 66 is 'B'. That is why 'a' + 1 is the number 98, not the letter b.
  • Without an index: for (char c : phone.toCharArray()) goes through the characters, the way for-each goes through an array.

Try it

Which character?

What will the program print?

String word = "Invoice";
System.out.println(word.charAt(3));
System.out.println(word.length());
Answer

The idea

The methods of text

Text comes with ready-made methods: actions you call with a dot after the text. Here is the fix for the promo code:

String code = " summer10";
String clean = code.trim().toUpperCase();
System.out.println("[" + clean + "]");
System.out.println(clean.equals("SUMMER10"));
Output
[SUMMER10]
true

trim() removes the spaces at the front and at the back. toUpperCase() makes all the letters uppercase. Methods can be chained one after another: the first returns a text, and the second is called on it.

A few more, on an email address:

String email = "ivan.petrov@mail.bg";
System.out.println(email.contains("@"));
System.out.println(email.indexOf("@"));
System.out.println(email.substring(0, email.indexOf("@")));
System.out.println(email.replace(".", " "));
System.out.println(email.endsWith(".bg"));
Output
true
11
ivan.petrov
ivan petrov@mail bg
true
Method What it does
contains(x) whether x is inside
indexOf(x) the index where x first appears (-1 if it is not there)
substring(a, b) a part of the text
replace(x, y) every x is replaced with y
startsWith(x), endsWith(x) whether it starts (ends) with x
toLowerCase() all letters lowercase
More precisely, if you are curious

substring(a, b) takes the characters from index a to index b, without b. Their count is b - a. With only one argument it takes everything to the end:

String date = "2026-10-24";
System.out.println(date.substring(5, 7));
System.out.println(date.substring(8));
Output
10
24

The idea

Text does not change

There is one quirk that confuses everyone at first:

String name = "maria";
name.toUpperCase();
System.out.println(name);
name = name.toUpperCase();
System.out.println(name);
Output
maria
MARIA

The second line does nothing you can see. toUpperCase() does not change name. It makes a new text in uppercase and returns it. Nobody stores it, and it is lost.

Once created, a text cannot be changed. It is called immutable. Every method that "changes" a text actually returns a new one. To keep it, you assign it: name = name.toUpperCase();.

String name = "maria";
name.toUpperCase();
System.out.println(name);
name = name.toUpperCase();
System.out.println(name);
Step by step, in words
  1. name holds the text "maria": 5 characters with indexes from 0 to 4.
  2. toUpperCase() does not touch "maria". It makes a new text, "MARIA".
  3. Nobody stores the new text, and it is lost.
  4. name still holds "maria", and that is what gets printed.
  5. Another new text, "MARIA", but now = stores it in name. The old "maria" is dropped.
  6. Now name holds "MARIA".
More precisely, if you are curious
  • That is why += on text in a long loop is slow: every round makes a new text and copies everything so far. For hundreds of thousands of appends there is StringBuilder, an object that can be changed. We will see it in the module "Text and files".

Try it

Find the bug

The user types their email with uppercase letters and spaces. The program should clean it up and let them in, but it says "No such user.". Which line has the bug?

Pick the line with the bug.

The idea

Text in parts

Often a text holds several things, separated by a sign: items with a comma, words with a space. split splits it into parts and returns an array of texts:

String list = "milk,bread,eggs,cheese";
String[] items = list.split(",");
System.out.println("Items: " + items.length);
for (int i = 0; i < items.length; i++) {
System.out.println((i + 1) + ". " + items[i]);
}
Output
Items: 4
1. milk
2. bread
3. eggs
4. cheese

The separator is not part of the pieces. From here on you work with a regular array: length, indexes, a loop.

This is also how you read a whole line of numbers from the keyboard: you split it and turn each part into a number. That is exactly what you were missing in the last lesson, on tables:

Scanner in = new Scanner(System.in);
String[] parts = in.nextLine().split(" ");
int sum = 0;
for (String p : parts) {
sum += Integer.parseInt(p);
}
System.out.println(sum);
Input
42 38 51 47 60
Output
238
More precisely, if you are curious
  • split takes a regular expression, not plain text. Most signs work as they are, but . means "any character": for a dot, write split("\\."). Regular expressions come in the module "Text and files".
  • Two spaces next to each other give an empty part "" between them. split(" +") (one or more spaces) solves that.
  • The opposite of split is String.join(", ", items): it joins the parts with a separator.

Try it

== or equals?

On the first card the promo code was compared with equals. Why not with ==, like numbers? The input is admin:

What will the program print?

Scanner in = new Scanner(System.in);
String user = in.nextLine();
System.out.println(user == "admin");
System.out.println(user.equals("admin"));
Answer

The rule: in Java you always compare text with equals. If uppercase and lowercase don't matter, use equalsIgnoreCase.

More precisely, if you are curious

Sometimes == "works": "admin" == "admin" is true, because Java keeps identical texts from the code in one object. That is why the bug slips through a test with text from the code and only shows up with real input. Don't rely on it.

Exercise

Names and words

Solve the exercises in your editor. The text is read from the keyboard as a whole line.

1. The name backward. Read a name and print it from back to front. You go through the indexes from the last one down to 0 and append the characters to a new text.

Input
Maria
Output
airaM

2. Word count. Read a sentence and count the words. There can be more than one space between words, and there can be spaces at the start and at the end. Hint: a word starts where the character is not a space and the one before it is a space (or there is none before it).

Input
Today is a holiday
Output
Words: 4

3. Palindrome. A palindrome reads the same from front to back and from back to front. Spaces and uppercase letters don't count. Remove the spaces, make the letters lowercase, and compare the first character with the last, the second with the one before last, and so on.

Input
Never odd or even
Output
It is a palindrome
Input
Coffee with milk
Output
Not a palindrome

Exercise

Checks and counting

4. Strong password. Ask for a password until the user enters a strong one: at least 8 characters, at least one digit, one uppercase and one lowercase letter. After each weak password, say what is required. Hint: do-while and a check of each character with Character.isDigit, Character.isUpperCase, Character.isLowerCase.

Input
coffee
coffee2026
Coffee2026
Output
Password:
Weak password: at least 8 characters, a digit, an uppercase and a lowercase letter.
Password:
Weak password: at least 8 characters, a digit, an uppercase and a lowercase letter.
Password:
Password accepted.

More exercises

  • Commas instead of spaces. Read a sentence and replace every space with a comma. Tomorrow we leave for Varna → Tomorrow,we,leave,for,Varna.
  • The longest name. Read names separated by commas and print the longest one. Ana,Kristina,Peter → Kristina.
  • Vowels as stars. Replace every vowel (a, e, i, o, u) with *, whether it is uppercase or lowercase. I love coffee → * l*v* c*ff**.
  • Letter frequency. Count how many times each letter appears in the text, uppercase or lowercase alike. Hint: an array of 26 counters, one for each letter from 'a' to 'z'. The index of the letter c is c - 'a'. Print only the letters that appear.
  • Character chart. Like the exercise above, but instead of the number, print that many stars: a: ****.
  • How many times each word. Read a sentence and for each different word print how many times it appears. Hint: split it into words, and for each word check whether it was already counted earlier in the array.
  • Sorting by length. Read words separated by spaces and print them from the shortest to the longest. Sort the array the way you sorted numbers, but compare the lengths.
  • Sentence count. Count the sentences in a text: each one ends with ., ! or ?. Watch out for ... and ?!: they end one sentence, not three.
  • Balanced brackets. Check whether the brackets in a text are balanced. With one kind of bracket, a counter is enough: ( adds 1, ) subtracts 1. The counter must never drop below 0, and at the end it must be 0. With three kinds, (), [], {}, you need an array of characters in which you keep the open brackets, and a counter of how full it is: at a closing bracket, the last open one must be of the same kind. {[()]} is balanced, ([)] is not.

Test

Check yourself

1. What does "Cafe".length() give?
2. What does the line name.toUpperCase(); do on its own, without an assignment?
3. How do you compare two texts by content in Java?
4. What is the difference between 'a' and "a"?
5. What does "Mon,Wed,Fri".split(",") give?

Made by Ivo Gergov as part of Evo Tech's campaign for accessible programming education ·