Lesson 9 - Strings in VB.NET - Working with single characters
In the previous exercise, Solved tasks for Visual Basic .NET lessons 7-8, we've practiced our knowledge from previous lessons.
Lesson highlights
Are you looking for a quick reference on characters and ASCII codes in VB.NET instead of a thorough-full lesson? Here it is:
Getting the character at a given position:
{VBNET_CONSOLE}
Dim s As String = "Hello ICT.social"
Console.WriteLine(s(2))
{/VBNET_CONSOLE}
Characters in an existing String
can't
be changed, a new String
has to be created.
Using Asc()
and Chr()
for converting between
characters and their ASCII value:
{VBNET_CONSOLE}
Dim c As Char ' character
Dim i As Integer ' ordinal (ASCII) value of the character
' conversion from text to ASCII value
c = "a"
i = Asc(c)
Console.WriteLine("The character '{0}' was converted to its ASCII value of {1}", c, i)
' conversion from an ASCII value to text
i = 98
c = Chr(i)
Console.WriteLine("The ASCII value of {1} was converted to its textual value of '{0}'", c, i)
{/VBNET_CONSOLE}
Would you like to learn more? A complete lesson on this topic follows.
In the last lesson, Solved tasks for Visual Basic .NET lessons 7-8, we learned to work with arrays in Visual
Basic .NET. If you noticed some similarities between arrays and strings, then
you were absolutely onto something. For the others, it may be a surprise that
a String
is essentially an array of characters
(Char
s) and we can work with it like so.
First, we'll check out how it works by simply printing the character at a given position:
{VBNET_CONSOLE}
Dim s As String = "Hello ICT.social"
Console.WriteLine(s)
Console.WriteLine(s(2))
Console.ReadKey()
{/VBNET_CONSOLE}
The output:
Console application
Hello ICT.social
l
We can see that we can access characters of a String through the parentheses as it was with the array. It may be disappointing that characters at the given positions are read-only in VB.NET, so we can't write the following:
' This code doesn't work string s = "Hello ICT.social" s(1) = "o" Console.WriteLine(s) Console.ReadKey()
Of course, there is a way to do it, but we'll go over it later. For now, we'll be just reading characters.
Character frequency analysis
Let's write a simple program that analyzes a given sentence for us. We'll
search for the number of vowels, consonants and non-alphanumeric characters
(e.g. space or !
).
We'll hard-code the input string in our code, so we won't have to enter it
again every time. Once the program is complete, we'll replace the string with
Console.ReadLine()
. We'll iterate over characters using a loop. I
should start out by saying that we won't focus as much on program speed here,
we'll choose practical and simple solutions.
First, let's define vowels and consonants. We don't have to count non-alphanumeric characters since it'll be the string length minus the number of vowels and consonants. Since we don't want to deal with the letter case, uppercase/lowercase, we'll convert the entire string to lowercase at the start. Let's set up variables for the individual counters, and also, because it's a more complex code, we'll add comments.
' the string that we want to analyze Dim s As String = "A programmer gets stuck in the shower because the instructions on the shampoo were: Lather, Wash, and Repeat." Console.WriteLine(s) s = s.ToLower() ' Counters initialization Dim vowelsCount As Integer = 0 Dim consonantsCount As Integer = 0 ' definition of character groups Dim vowels As String = "aeiouy" Dim consonants As String = "bcdfghjklmnpqrstvwxz" ' the main loop For Each c As Char In s Next Console.ReadKey()
First of all, we prepare the string and convert it to lowercase. Then, we
reset the counters. For the definition of characters groups, we only need
ordinary string
s. The main loop iterates over each character in the
string s
, so in each iteration of the loop the variable
c
will contain the current character.
Now let's increment the counters. For simplicity's sake, I'll focus on the loop instead of rewriting the code repeatedly:
' the main loop For Each c As Char In s If vowels.Contains(c) Then vowelsCount += 1 Else If consonants.Contains(c) consonantsCount += 1 End If Next
The Contains()
method on a String
is already known
to us. As a parameter, it can take both a substring or a character. Firstly, we
try to find the character c
from our sentence in the String
vowels
and possibly increase their counter. If it's not included in
vowels, we look in consonants and possibly increase their counter.
Now all we're missing is the printing, displaying text, part at the end:
{VBNET_CONSOLE}
' the string that we want to analyze
Dim s As String = "A programmer gets stuck in the shower because the instructions on the shampoo were: Lather, Wash, and Repeat."
Console.WriteLine(s)
s = s.ToLower()
' Counters initialization
Dim vowelsCount As Integer = 0
Dim consonantsCount As Integer = 0
' definition of character groups
Dim vowels As String = "aeiouyaeeiouuy"
Dim consonants As String = "bccddfghjklmnpqrrssttvwxzz"
' the main loop
For Each c As Char In s
If vowels.Contains(c) Then
vowelsCount += 1
Else If consonants.Contains(c)
consonantsCount += 1
End If
Next
Console.WriteLine("Vowels: {0}", vowelsCount)
Console.WriteLine("Consonants: {0}", consonantsCount)
Console.WriteLine("Non-alphanumeric characters: {0}", s.Length - (vowelsCount + consonantsCount))
Console.ReadKey()
{/VBNET_CONSOLE}
The output:
Console application
A programmer gets stuck in the shower because the instructions on the shampoo were: Lather, Wash, and Repeat.
Vowels: 33
Consonants: 55
Non-alphanumeric characters: 21
That's it, we're done!
The ASCII value
Maybe you've already heard about the ASCII table. Especially, in the MS-DOS
era when there was practically no other way to store text. Individual characters
were stored as numbers of the byte
datatype, so of a range from
0
to 255
. The system provided the ASCII table which
had 256 characters and each ASCII code (numerical code) was assigned to one
character.
Perhaps you understand why this method is no longer as relevant. The table
simply could not contain all the characters of all international alphabets, now
we use Unicode (UTF-8) encoding where characters are represented in a different
way. In VB.NET, we have the option to work with ASCII values of individual
characters. The main advantage is that the characters are stored in the table
next to each other, alphabetically. For example, at the position 97
we can find "a"
, at 98
"b"
etc. It's the
same with numbers, but unfortunately, the accent characters are messed up.
Now, let's convert a character into its ASCII value and vice versa create the character according to its ASCII value:
{VBNET_CONSOLE}
Dim c As Char ' character
Dim i As Integer ' ordinal (ASCII) value of the character
' conversion from text to ASCII value
c = "a"
i = Asc(c)
Console.WriteLine("The character {0} was converted to its ASCII value of {1}", c, i)
' conversion from an ASCII value to text
i = 98
c = Chr(i)
Console.WriteLine("The ASCII value of {1} was converted to its textual value of {0}", c, i)
Console.ReadKey()
{/VBNET_CONSOLE}
These conversions are called type casts, which we'll get into later on.
The Caesar cipher
Let's create a simple program to encrypt text. If you've ever heard of the
Caesar cipher, then you already know exactly what we're going to program. The
text encryption is based on shifting characters in the alphabet by a certain
fixed number of characters. For example, if we shift the word
"hello"
by 1 character forwards, we'd get "ifmmp"
. The
user will be allowed to select the number of character shifts.
Let's get right into it! We need variables for the original text, the
encrypted message, and the shift. Then, we need a loop iterating over each
character and we'll print the encrypted message at the end. We'll hard-code the
message into our code again, so we won't have to enter it over and over during
the testing phase. Once we finish the program, we'll replace the contents of the
variable with the Console.ReadLine()
method. The cipher doesn't
work with accent characters, spaces and punctuation marks. We'll just assume the
user won't enter them. Ideally, we should remove accent characters before the
encryption, as well as anything except letters.
' variable initialization Dim s As String = "blackholesarewheregoddividedbyzero" Console.WriteLine("Original message: {0}", s) Dim message As String = "" Dim shift As Integer = 1 ' loop iterating over characters For Each c As Char in s Next ' printing Console.WriteLine("Encrypted message: {0}", message) Console.ReadKey()
We'll now move into the loop. We'll cast the character in c
to
its ASCII value, its ordinal value, increase the value by the number of
shifts
and cast it back to a character. This character will be
added to the final message:
{VBNET_CONSOLE}
' variable initialization
Dim s As String = "blackholesarewheregoddividedbyzero"
Console.WriteLine("Original message: {0}", s)
Dim message As String = ""
Dim shift As Integer = 1
' loop iterating over characters
For Each c As Char in s
Dim i As Integer = Asc(c)
i += shift
Dim character As Char = Chr(i)
message &= character
Next
' printing
Console.WriteLine("Encrypted message: {0}", message)
Console.ReadKey()
{/VBNET_CONSOLE}
The output:
Console application
Original message: blackholesarewheregoddividedbyzero
Encrypted message: cmbdlipmftbsfxifsfhpeejwjefecz{fsp
Let's try it out! The result looks pretty good. However, we can see that the
characters after "z"
overflow to ASCII values of other characters
({
in the output above). Therefore, the characters are no longer
just alphanumeric, but other nasty characters. Let's enclose our characters as a
cyclical pattern, so the shifting could flow smoothly from "z"
to
"a"
and so on. We'll get by with a simple condition that decreases
the ASCII value by the length of the alphabet so we'd end back up at
"a"
.
Dim i As Integer = Asc(c) i += shift ' overflow control If i > Asc("z") Then i -= 26 End If Dim character As Char = Chr(i) message &= character
If i
exceeds the ASCII value of z
, we reduce it by
26
characters (the number of characters in the English alphabet).
The -=
operator does the same as we would do with
i = i - 26
. It's simple and our program is now working properly.
Notice that we don't use direct character codes anywhere. There's an
(int)'z'
in the condition even though we could write
122
there directly. We did it this way so that our program is fully
independent from explicit ASCII values, so it'd be clearer how it works. Try to
code the decryption program as practice for yourself.
In the next lesson, Solved tasks for Visual Basic .NET lesson 9, we'll see that there are still a couple more
things we haven't touched base on that string
s can do. Spoiler:
We'll learn how to decode "Morse code".
In the following exercise, Solved tasks for Visual Basic .NET lesson 9, we're gonna practice our knowledge from previous lessons.
Did you have a problem with anything? Download the sample application below and compare it with your project, you will find the error easily.
Download
By downloading the following file, you agree to the license terms
Downloaded 15x (103.22 kB)
Application includes source codes in language VB.NET