Make your own custom C++ ToUpperCase and ToLowerCase functions (Intermediate Level)

Converting between upper case and lower case characters can always be useful, depending on what we want to accomplish. In C++ we normally, include <ctype.h> that provides us with two functions: toupper(); and tolower();

Here’s how we would use them:

#include <iostream>
#include <string>
#include <ctype.h> 

using namespace std; 

void main()
{
     string s = "mario";
     string ss = "ZELDA"; 
     for(int i = 0; i<s.length(); i++){
	  s[i] = toupper(s[i]); 
     }

     for(int j = 0; j<ss.length(); j++){
          ss[j] = tolower(ss[j]); 
     } 

     cout << s << endl; 
     cout << ss << endl; 
     cin.get(); 
}

Here’s the result when running this code:

That’s very simple, isn’t it? Yeah! I think it’s too simple, but that’s me. However, what about making our own tolower and toupper functions with C++, completely customized functions, this is way more fun! We’ve got a challenge ahead, so let’s solve it.

I’ll be creating two functions both will return string, I name them, ToUpperCase(); and ToLowerCase(); and they both take one string parameter each:

string ToLowerCase(string text);
string ToUpperCase(string text);

To complete these two functions we need to use the American Standard Code for Information Interchange (ASCII) table, which provides a complete list of different characters including the alphabetic ones. In addition, the ASCII table provides the decimal numbers that represent each character. I’ll be using the ACII table found on http://www.asciitable.com/.

According to the ASCII table:

Upper Case: 65-90
Lower Case: 97-122

The ASCII table is correct, if we declare a char c = 65; and print this, we’ll see ‘A’ in the console window, this means that it is printing an upper case ‘A’, since 65 in the table equals ‘A’.

I’ll start by writing the very first function, the ToUpperCase(); function:

string ToUpperCase(string text){
  for(int i = 0; i<text.length(); i++){
     char c = text[i]; 
     if((c>=97)&&(c<=122)){
	 text[i]&=0xdf; 
     }
   }
   return text; 
}

Once you’ve written this function (or copied it), hit F5 in Visual Studio to run the program in Debug Mode. Don’t forget to invoke the function like below:

string s = "super mario"; 
s = ToUpperCase(s);
cout << s << endl; 
cin.get(); 

If everything went well, and you didn’t encounter any issues while compiling, you should see this:

Awesome, so it works, we succeeded with the first function. Now lets go in-depth and explain the magic behind the success, yes, I will explain what’s happening when we invoke this function and pass a string to it.

Let’s have a look on our string s = “super mario”; I have added a simplified picture of the string index array below:

We can easily loop through it with a For-loop. So far, so good, things remain clear and easy. A char data type gives us the ASCII decimal numbers that each single character equals to. First we check for lower case letters, if((c>=97)&&(c<=122)), next we do the magic that converts an lower case letter to an upper case letter.

The magic happens right here:

 text[i]&=0xdf;

But what happens exactly? Simple, and yet complicated to fully explain, &= is a Bitwise AND operator, remember binary and bits? Yes, to explain what exactly happens here, we have to dive deep into the binary world, yeah! Weird huh?

If we look in our code again, we see that the first single character in our string index array is ‘s’ and in the ASCII table, the decimal value for ‘s’ is 115. The &=0xdf, 0xdf is a hexadecimal value that equals to 223 (decimal).

To understand this, you’ll have to understand the AND gate and use a Truth table remember from the basic electricity courses in school? The AND gate is easy to understand for example, if A = 0 and B = 0 the output becomes 0, and if A = 0 and B = 1 the output becomes 0, the only time the output becomes 1 is if both A & B equals 1. I also marked the zeros with red rectangles to highlight a pattern that simplifies the understanding of this. The number 83 in the ASCII table represents the upper case ‘S’.

Now that I’ve completed the ToUpperCase() function, I will write the next function, ToLowerCase() which converts upper case letters to lower case letters. This is easy, now that we made the first function.

string ToLowerCase(string text){
   for(int i = 0; i<text.length(); i++){
      char c = text[i]; 
      if((c>=65)&&(c<=90)){
	 text[i]|=0x20; 
      }
   }
   return text; 
}

There are some differences between this function and the previous one we wrote, for example, we now check for upper case letters, if((c>=65)&&(c<=90)) and the magic, text[i]|=0x20 now uses the Bitwise OR Assignment Operator |= which differs from the previous Bitwise operator.

Once you’ve written this function (or copied it), hit F5 in Visual Studio to run the program in Debug Mode. Don’t forget to invoke the function like below:

string s = "JAK AND DAXTER"; 
s = ToLowerCase(s);
cout << s << endl; 
cin.get(); 

If everything went well, and you didn’t encounter any issues while compiling, you should see this:

Yeah, again even this function succeeded. However, I want you to understand the magic behind it, so I made another image that explains the Bitwise OR operator:

To better understand this, let’s have look in our code again, we see that the first single character in our string index array is ‘J’ and in the ASCII table, the decimal value for ‘J’ is 74. The &=0x20, 0x20 is a hexadecimal value that equals to 32 (decimal). For upper case ‘J’ to become lower case letter, ‘j’its value must become 106, and that’s what text[i]|=0x20; does. This can easily be explained by the image above.

The Bitwise OR operator is simple to understand, very straight forward, just think of the OR gate, if A = 0 or B = 0, the output becomes 0, and if A = 1 or B = 0, the output becomes 1. The big difference between the OR gate and AND gate is that, if A = 0 or B = 0 then the output becomes a 0, and that’s the only time in the case of the OR gate. For the AND gate, the only time the output becomes 1 is if both A and B equal 1, else it’s simply 0.

Wrapping up, for Now

I’m not quite done with this, I think it’s fun to play around with it, especially the Bitwise operators which allow us to accomplish a lot. I bet there’s someone that can make other functions using the inner code from one of these two functions I made. In addition, I think it’s useful for programmers to sometimes play around with code at this level of difficulty, despite experience.

For now, happy coding!

Leave a Reply