Get up to 80 % extra points for free! More info:

Lesson 10 - Strings in C++ - Working with single characters

Lesson highlights

Are you looking for a quick reference on ASCII codes in C++ instead of a thorough-full lesson? Here it is:

Converting between characters and their ASCII value:

char c; // character
int i; // ordinal (ASCII) value of a character
// conversion from text to ASCII value
c = 'a';
i = (int)c;
cout << "The character '" << c << "' was converted to its ASCII value of " << i << endl;
// conversion from an ASCII value to text
i = 98;
c = (char)i;
cout << "The ASCII value of " << i << " was converted to its textual value of '" << c << "'" << endl;
cin.get();

Would you like to learn more? A complete lesson on this topic follows.

In the previous lesson of the C++ basics course, Strings in the C++ language, we learned to work with strings and introduced the standard string functions. In today's tutorial, we're going to continue with strings and introduce ASCII values. We'll also create other useful applications.

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 (as 1 byte which is the char type in C/C++), 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. We now use Unicode (UTF-8) encoding where characters are represented in a different way. However, in C++, we tend to use ASCII values in the default configuration. If we wanted to work with UNICODE characters (UTF-8), we'd have to use wide characters. The main advantage of using plain ASCII is that the characters are stored in a table next to each other, alphabetically. For example, at position 97 we'd 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:

char c; // character
int i; // ordinal (ASCII) value of a character
// conversion from text to ASCII value
c = 'a';
i = (int)c;
cout << "The character '" << c << "' was converted to its ASCII value of " << i << endl;
// conversion from an ASCII value to text
i = 98;
c = (char)i;
cout << "The ASCII value of " << i << " was converted to its textual value of '" << c << "'" << endl;
cin.get();

The result:

Console application
The character 'a' was converted to its ASCII value of 97
The ASCII value of 98 was converted to its textual value of 'b'

Character occurrence in a sentence analysis

Let's write a simple program that analyzes a given sentence for us. We'll search for the number of vowels, consonants, digits and non-alphanumeric characters (e.g. space or !).

We'll hard-code the input string in our code, so we won't have to write it again every time. Once the program is complete, we'll replace the string with cin. We'll iterate over characters using a loop. By the way, we won't focus too much on program speed here, we'll mainly choose practical and simple solutions.

First, let's define vowels, consonants, and digits. We don't have to count non-alphanumeric characters since they'll just be the string length minus the number of vowels and consonants. Let's set up variables for the individual counters, also. Since this will feature some relatively complex code, we'll add in comments.

// Counters initialization
int vowelsCount = 0;
int consonantsCount = 0;
int digitsCount = 0;

// the string that we want to analyze
string s = "A programmer gets stuck in the shower because the instructions on the shampoo were: Lather, Wash, and Repeat.";

// definition of character groups
string vowels = "aeiouyAEUOUY";
string consonants = "bcdfghijklmnpqrstvwxzBCDFGHIJKLMNPQRSTVWXZ";
string digits = "0123456789";

cout << "The original message: " << s << endl;

// the main loop will iterate over all the characters
for (int i = 0; i < s.length(); i++)
{

}

cin.get();

First of all, we reset the counters. For the definition of characters groups, ordinary strings will do. The main loop iterates over each character in the string *s*.

Now, let's increment the counters. For simplicity's sake, I'll focus on the loop instead of rewriting the code over and over again:

// the main loop will iterate over all the characters
for (int i = 0; i < s.length(); i++)
{
    if (vowels.find(s[i]) < vowels.length())
        vowelsCount++;
    else if (consonants.find(s[i]) < consonants.length())
        consonantsCount++;
    else if (digits.find(s[i]) < digits.length())
        digitsCount++;
}

Notice that we use the find() method which determines whether a string contains a character. We try to find the current character from our sentence in the vowels string and possibly increase their counter. If it's not included in the vowels, we look in the consonants and possibly increase their counter. We do the same with the digits.

Now, all we're missing is the printing part at the end (displaying the text):

cout << "Vowels: " << vowelsCount << endl;
cout << "Consonants: " << consonantsCount << endl;
cout << "Digits: " << digitsCount << endl;
cout << "Non-alphanumeric characters: " << s.length() - (vowelsCount + consonantsCount + digitsCount) << endl;

Console application
A programmer gets stuck in the shower because the instructions on the shampoo were: Lather, Wash and Repeat.
Vowels: 33
Consonants: 55
Digits: 0
Non-alphanumeric characters: 21

That's it, we're done!

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 printing an encrypted message. We'll also have to hard-code the message defined in the code, so we won't have to write it over and over during the testing phase. After we finish the program, we'll replace the contents of the variable with a value from the cin object. The cipher doesn't work with accent characters, spaces, and punctuation marks. We'll just assume the user won't enter them. To keep things simple, we'll expect the user to only use lowercase characters. Ideally, we would remove accent characters before encryption, as well as anything other than letters.

// variable initialization
string s = "blackholesarewheregoddividedbyzero";
int shift = 1;
cout << "Original message: " << s << endl;

// loop iterating over characters
for (int i = 0; i < s.length(); i++)
{

}

// printing
cout << "Encrypted message: " << s << endl;
cin.get();

/next, we'll move into the loop. We'll increase the ASCII value of the current character by however many shifts.

s[i] = s[i] + shift;

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 picture). Therefore, the characters are no longer just alphanumeric, but other nasty characters. Let's set our characters up 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".

// loop iterating over characters
for (int i = 0; i < s.length(); i++)
{
    s[i] = s[i] + shift;
    if (s[i] > 'z') // overflow control
        s[i] = s[i] - 26;
}

If the value exceeds the ASCII value of 'z', we reduce it by 26 characters (the number of characters in the English alphabet). It's simple and our program is now operational. Notice that we don't use direct character codes anywhere. There's a 'z' in the condition even though we could write 122 there directly. I set it up this way so that our program is fully encapsulated from explicit ASCII values, so it'd be clearer on how it works. Try to code the decryption program as practice for yourself.

In the next lesson, Solved tasks for C++ lessons 9-10, we'll introduce multidimensional arrays in C++.

In the following exercise, Solved tasks for C++ lessons 9-10, 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 2x (890.52 kB)
Application includes source codes in language C++

 

Previous article
Strings in the C++ language
All articles in this section
C++ Basic Constructs
Skip article
(not recommended)
Solved tasks for C++ lessons 9-10
Article has been written for you by David Capka Hartinger
Avatar
User rating:
No one has rated this quite yet, be the first one!
The author is a programmer, who likes web technologies and being the lead/chief article writer at ICT.social. He shares his knowledge with the community and is always looking to improve. He believes that anyone can do what they set their mind to.
Unicorn university David learned IT at the Unicorn University - a prestigious college providing education on IT and economics.
Activities