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:
string code = Console.ReadLine();if (code == "SUMMER10"){ Console.WriteLine("10% off");}else{ Console.WriteLine("Invalid code");} summer10Invalid codeTo 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";Console.WriteLine(code.Length);Console.WriteLine(code[0]);Console.WriteLine(code[code.Length - 1]);8S0code.Lengthis the number of characters.code[0]is the character with index 0. The last character has indexLength - 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.
For both text and arrays, the length 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[i]; if (c >= '0' && c <= '9') { digits++; }}Console.WriteLine("Digits: " + digits);Digits: 10c >= '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:
char.IsDigit(c),char.IsLetter(c),char.IsUpper(c),char.IsLower(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) 66is'B'. That is why'a' + 1is the number 98, not the letterb. - Without an index:
foreach (char c in phone)goes straight through the characters of the text.
Try it
Which character?
What will the program print?
string word = "Invoice";Console.WriteLine(word[3]);Console.WriteLine(word.Length);The indexes are I 0, n 1, v 2, o 3. The character with index 3 is the fourth one: "o". The length is the count of all the characters, 7. The last index is 6.
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().ToUpper();Console.WriteLine("[" + clean + "]");Console.WriteLine(clean == "SUMMER10");[SUMMER10]TrueTrim() removes the spaces at the front and at the back. ToUpper() 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";Console.WriteLine(email.Contains("@"));Console.WriteLine(email.IndexOf("@"));Console.WriteLine(email.Substring(0, email.IndexOf("@")));Console.WriteLine(email.Replace(".", " "));Console.WriteLine(email.EndsWith(".bg"));True11ivan.petrovivan petrov@mail bgTrue| 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, n) |
a part of the text |
Replace(x, y) |
every x is replaced with y |
StartsWith(x), EndsWith(x) |
whether it starts (ends) with x |
ToLower() |
all letters lowercase |
More precisely, if you are curious
Substring(a, n) takes n characters, starting at index a. The second argument is the count of characters, not an index (in Java it is the other way: there it is the index of the end). With only one argument it takes everything to the end:
string date = "2026-10-24";Console.WriteLine(date.Substring(5, 2));Console.WriteLine(date.Substring(8));1024The idea
Text does not change
There is one quirk that confuses everyone at first:
string name = "maria";name.ToUpper();Console.WriteLine(name);name = name.ToUpper();Console.WriteLine(name);mariaMARIAThe second line does nothing you can see. ToUpper() 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.ToUpper();.
string name = "maria";name.ToUpper();Console.WriteLine(name);name = name.ToUpper();Console.WriteLine(name);Step by step, in words
- name holds the text "maria": 5 characters with indexes from 0 to 4.
- ToUpper() does not touch "maria". It makes a new text, "MARIA".
- Nobody stores the new text, and it is lost.
- name still holds "maria", and that is what gets printed.
- Another new text, "MARIA", but now = stores it in name. The old "maria" is dropped.
- 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 isStringBuilder, an object that can be changed. You will meet it when we get to objects.
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.
email.Trim(); returns a new text without the spaces, but it is not stored anywhere. email still has the spaces. The fix is email = email.Trim();, just like on line 2.
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(',');Console.WriteLine("Items: " + items.Length);for (int i = 0; i < items.Length; i++){ Console.WriteLine((i + 1) + ". " + items[i]);}Items: 41. milk2. bread3. eggs4. cheeseThe 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:
string[] parts = Console.ReadLine().Split(' ');int sum = 0;foreach (string p in parts){ sum += int.Parse(p);}Console.WriteLine(sum);42 38 51 47 60238More precisely, if you are curious
- Two spaces next to each other give an empty part
""between them.Split(' ', StringSplitOptions.RemoveEmptyEntries)skips the empty parts. - There can be several separators:
Split(',', ';'). - The opposite of
Splitisstring.Join(", ", items): it joins the parts with a separator.
Try it
Is it the same?
In C#, == compares the content of texts, letter by letter. But an uppercase and a lowercase letter are different characters. The input is Sofia:
What will the program print?
string city = Console.ReadLine();Console.WriteLine(city == "Sofia");Console.WriteLine(city == "sofia");Console.WriteLine(city.ToLower() == "sofia");city == "Sofia" is True: the letters are the same. "sofia" starts with a lowercase "s", which is a different character, so it is False. If uppercase and lowercase don't matter, compare both texts in lowercase: city.ToLower() == "sofia".
There is also a method for this: string.Equals(city, "sofia", StringComparison.OrdinalIgnoreCase). In Java, == for text does not compare the letters, and there you use equals. Keep that in mind if you ever read Java code.
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.
MariaairaM2. 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).
Today is a holidayWords: 43. 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.
Never odd or evenIt is a palindromeCoffee with milkNot a palindromeExercise
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 char.IsDigit, char.IsUpper, char.IsLower.
coffeecoffee2026Coffee2026Password: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 lettercisc - '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