C++ Programming Series: Dynamic Arrays (Part 2, Last)

Dynamic arrays can be used with functions in exactly the same way as I have told in this post. Just keep in mind that we have to pass the size of array into the function.

void printIntegerArray(int* pArr, int totalElements)
{
  for(int i = 0; i < totalElements; i++)
  {
    cout << pArr[i] << endl;
  }
}

int main()
{
  int* array = new int[5] { 3, 4, 7, 8, 12 };

  printIntegerArray(array, 5);

  return 0;
}

Note how I allocated the memory and also, set the value of all the elements in the dynamic array in the highlighted line.

That initialization of dynamic array is what the real purpose of this small post is. Why? Because dah! I learned that very late. Very very late.

At least, I am able to save others from this.

array[0] = 3;
array[1] = 4;
//...till the end :p

Also, there is another purpose of this post.

Tell me my mistake in the code.

If you already knew it before reaching this part, you must be a keen observer. There is no delete[] array; at the end of the code.

Damn those memory bees. (By the way, it is a genuine mistake)

This ends my C++ Programming Series. Now, to ease your path, there will be another post in this series. Keep coming back and you will always find bunch of useful stuff here.

Advertisements

C++ Programming Series: Pointers (Part 3)

Pointers and Arrays are same things!

This statement might confuse you. How is this possible that pointers and arrays are same? They never looks to be same!

This post will clear this point to you. Lets get started with the code below.

int array[5] = { 3, 4, 7, 8, 12 };

//Look! We have not put square brackets
//with a number after the name of array
cout << array << endl;

What will it print? Will it print the first member of the array? No, it will print the memory address of the first member of the array.

Now, you see that there is no ampersand(&) needed for getting the memory address of the array. Don’t you think that it is something that is similar to pointers? Yeah, but this is not all!

int array[5] = { 3, 4, 7, 8, 12 };

//'pArray' is now pointed to the first member of the 'array'
int* pArray = array;

//Now, we can use 'pArray' similar to that of 'array'
cout << pArray[2] << endl; //Prints 7; same as 'array[2]'

The above code explains that pointers are actually arrays! We can have square brackets with pointers and just use it exactly as an array.

Another point to tell you that when we use a pair of empty square brackets([]) after a pointer or an array, it will still give us the memory address of the array. But when we mention the number in it, pointer or array will give us that particular value under the index.

Pointers and arrays are same things but there is only one difference between them.

An array knows that how many elements it has. If we use sizeof() method for an array, we will get right number of bytes that it occupy.

int array[5] = { 3, 4, 7, 8, 12 };

//We can use empty square brackets as well
cout << sizeof(array[]) << endl; //Prints (sizeof(int) * 5)

Note: Size of integer may be different for your device. Mine is 4 so, it will result in 20. It may result 10 as well.

A pointer never knows that how many elements it has. It may or may not be an array as well. If we use sizeof() with pointer. we will not get the right number of bytes that it occupy. A pointer do know about the size of type that it is of.

int array[5] = { 3, 4, 7, 8, 12 };
int* pArray = array;

cout << sizeof(pArray[]) << endl; //Prints 2, 4 or 8 (not true in any case)

What if we want to pass array to a function? We have never discussed that topic before. Now, there is something that I have to tell! We can’t pass array to a function! So, there you go. The topic ends.

Of course, there is a solution to this problem. We can’t pass arrays but we can pass pointers to a function. Unfortunately, we can’t get the size of array that is passed as a pointer. Therefore, we have to pass the total number of elements to the function as well.

void printIntegerArray(int* pArr, int totalElements)
{
  for(int i = 0; i < totalElements; i++)
  {
    cout << pArr[i] << endl;
  }
}

int main()
{
  int array[5] = { 3, 4, 7, 8, 12 };

  //We don't need to make any pointer
  //Pointer is just a memory address
  //So, we can pass array directly
  printIntegerArray(array, 5);

  return 0;
}

Just keep in mind, the concept that pointers are arrays but they don’t keep track of their number of elements. There are few things that are not clear. We still don’t know what happens behind that pair of square brackets with a number in it. We will discuss pointer arithmetic in the next post along with the working behind square brackets.

Exercise: Make a function that takes an integer array and prints only even numbers.

C++ Programming Series: References

I believe that my series is getting complex with every post being published! This has to be done because we should also be getting more complex and more logical with every topic we discuss.

Today’s topic is References. Before proceeding on, let us discuss few problems with functions. The first one is that we don’t know any methods of getting multiple outputs. The second one is that we don’t make any change in the variable that we pass into the function via parameters.

The following code expresses the second problem with functions:

void multiplyBy2(int variable)
{
  variable *= 2;
  //No returning
}

int main()
{
  int variable = 2;
  mulitplyBy2(variable); //This should change the variable's value to 4
  cout << variable << endl; //Prints 2, not 4
  return 0;
}

NOTE: We can have same names for variables having completely isolated scopes. Note that multiplyBy2 has a parameter called variable and main function also has a variable called variable. Sounds confusing!

We have a solution for that and that is, to return that variable in the function and then, put that into any variable or just call that temporary return value directly.

But we expect the method above to change the variable’s value which is not the case here! Why? Well, the point is that when we pass the variable via the parameter of the function, we are actually copying that variable into another completely new variable. This new variable has a very limited scope i.e we can only access it inside the function.

Let us discuss a very simple example of what copying is:

int value1 = 2;

int value2 = value1; //Here, value1 is copied into value2
value2*=2; //value2 is a different variable; it will not effect value1 in any case!

cout << value1 << endl; //Prints 2, not 4
cout << value2 << endl; //Prints 4

The highlighted codes shows what is actually happening in the function, multiplyBy2() in the example, given above.

How to do it in the way that we want? The answer is right inside the topic of this post: References. There is another way and that one is through Pointers which is way more complex but we will discuss it later on.

What is a reference? Reference is just another name given to the same variable. In our real life, we can have the reference case of a bird called ‘raven’. Raven is a black bird. So, people can refer to ‘raven’ by calling it as ‘black bird’. In a very similar way, variables can have references as well.

//Consider that there is a bird called 'raven'
int raven = 10;

//That 'black_bird' is a reference to 'raven' 
int& black_bird = raven;

//Now, what we do with 'black_bird' is actually,
//what we are doing with 'raven' as well and vice versa...
black_bird*=2; //Both gets 20
raven+=5; //Both gets 25

cout << raven << endl; //Prints 25
cout << black_bird << endl; //Prints 25

The highlighted line shows how to make reference to a variable. It is pretty simple; just put ampersand or ‘&’ after the type of the variable that we are going to refer to.

int& is considered a type which we can call as ‘reference to an integer’. Same will be for any type reference as well.

Time to make some change in the multiplyBy2() function!

//Notice the ampersand before the variable's name
void multiplyBy2(int& variable)
{
  variable *= 2;
}

int main()
{
  int variable = 2;
  mulitplyBy2(variable); //Now, we are not copying, we are referencing!
  cout << variable << endl; //This time, it prints 4
  return 0;
}

Now that, the second problem is solved, the first problem is solved as well. We can have multiple outputs by having more parameters to the function. These parameters are going to be references and whatever is going to be changed with these references, this change is going to happen with the actual variables which are passed as parameters in the function.

//The first two parameters represent inputs
//and the next three represent outputs
void get3TimesDivision( float number1, float number2,
float& division1, float& division2, float& division3 )
{
  division1 = number1 / number2;
  division2 = division1 / number2;
  division3 = division2 / number2;
}

int main()
{
  //Multiple Outputs using References
  float div1 = 0.0f, div2 = 0.0f, div3 = 0.0f;
  get3TimesDivision( 8.0f, 2.0f, div1, div2, div3 );

  cout << div1 << endl; //Prints 4
  cout << div2 << endl; //Prints 2
  cout << div3 << endl; //Prints 1

  return 0;
}

Note the point that where we want to have references, we cannot have constants or temporary values there. In the above case, if the parameters, number1 and number2, are references to float, we cannot pass 8.0f and 2.0f into the function. We must pass variables of type float with the respective values, into the function.

That’s all! References are a great way to deal with outputs. Just try to modify all the previous functions that we created together, to have references and not copies. Practice them very well. They are going to be used extensively!

C++ Programming Series: Headers and Prototypes (Part 2, Last)

In this post, we are going to discuss some confusions that you might have got in the previous post. You might have read #include "func.h" in that post and not #include <func.h>. Actually, both have different meanings!

If we type angle brackets (<>) instead of double quotes (“”) for func.h, the compiler will check for that file in the C++ base files directory and project specified include directory. From C++ base files, I mean those files which also includes the most commonly used iostream, math.h, string, etc, that are the files of standard C++. All these C++ standard files are header files although they may not have .h at the end of their names.

If we type double quotes as in the previous post, the compiler will check for that file in local project directory. This directory is the same directory where the IDE adds all our files to.

In a nutshell,

  • #include <file_name> – searches the file in base and project specified include directory.
  • #include “file_name” – searches the file in local project directory.

Now, we know what double quotes and angle brackets do with #include. But we actually, don’t know what #include do! #include simply, copy the codes from the file and then, paste it into that file where it is called.

This is something that we don’t need to know. What we need to know is the fact that C++ don’t allow more than one definitions. You can’t just do like that:

void func()
{
  //code here...
}

//Another time: gives error!
void func()
{
  //code here...
}

It might be possible that we include things twice or, the other and most common case is that the file that we are including, includes another file that is already included in our file! To make it clear, see the code below:

#include "a" //'a' file contains function 'func()'
#include "b" //'b' file includes file 'a'
//'func()' is defined twice
//So, gives error!

That hash(#) before the include suggests that the command after it, is a preprocessor directive and not a C++ code. These directives runs before the compilation of the actual program. There are many of these. You can check out preprocessor directives in details here.

In order to make sure that something is defined just once, you can use preprocessor directives like that:

#ifndef SOMETHING //This means 'if not defined preprocessor term called SOMETHING'
#define
  //code here
#endif //This ends the '#ifndef' statement

The above code just acts similar to the C++ if-statement that we discussed before.

SOMETHING can be anything. It can be an integer, a group of characters, a float, etc.

#define PI 3.14 //Now, PI is equal to 3.14

int main()
{
  cout << PI << endl; //We can use it as a regular double
  PI++; //Gives error; preprocessor definations are constants!
  return 0;
}

I hope that you got all of the above things. Just practice using headers and prototypes. Find errors and then, try to fix them yourself. I got a new exciting series called My Pixels where I have showcased some of my hand drawn pixel arts or sprites! Just check that out and see ya!

C++ Programming Series: Headers and Prototypes (Part 1)

Until now, we have been working with codes which are present in just a single file. We have been doing single file projects till now, in which all the codes are being typed in one file. This approach is good for tiny projects. However, when we are going to have some medium sized project to be worked on, this approach is really horrible! Imagine a file with a ten thousand lines of codes. Of course, we did all 10000 lines of codes in the form of functions but still, the infrastructure of our program is ugly and hardly, manageable now. It is less likely to be modified by some other programmer or even you. Maybe, you can do some modifications but when you leave your program for a month and then, came back to it, you would like not to read the code because it looks to be too big and lengthy!

The solution for bigger projects is to have multiple files in a project and this approach is called as multiple file project. In this approach, there are three kinds of files: the one with extension ‘.cpp’ which contains the main() function, the other with extension ‘.h’ or ‘.hpp’ which contains all the possible declarations of a group of related functions or entities, and the last one with extension ‘.cpp’ which contains all the definitions of the declarations. Creating, importing and exporting static and dynamic libraries is another topic which we will not discuss in this series.

The files with extension ‘.h’ or ‘.hpp’, are called as Header files which contains the declarations only and not the definitions. Now, the advantage of the header file is to help the programmer to know all the details of the functions that he/she want to use in his/her program without even skipping through all the enormous definitions!

The declaration of a function is often, referred to as Prototypes.

Example of a declaration of an integer:

//Declaration
extern int value0;

//'extern' is a keyword used to write declarations of variables

//Declaration and Definition
int value1;

//Declaration along with Definition and Initialization
int value2 = 15;

Example of a declaration of a function/Prototype:

//Declaration only/Prototype
int square(int value);

//Declaration along with Defination
int square(int value)
{
  return (value*value);
}

In Visual Studio, in order to have multiple file project, just create new files of approriate file extensions. Suppose that we have three files namely, main.cpp, func.h and func.cpp.

Here the codes are shown for both single and multiple file approaches using Prototypes:

Single File Project:
In main.cpp:

//Includings
#include <iostream>

//Prototypes
int square(int value);
int enterAnInt();
void printAnInt(int value);

//Main Function
int main()
{
  //Prints the square of the value given by the user
  printAnInt(square(enterAnInt()));
  return 0;
}

//Definations
int square(int value)
{
  return (value*value);
}
int enterAnInt()
{
  int value;
  cin >> value;
  return value;
}
void printAnInt(int value)
{
  cout << value << endl;
}

Multiple File Project:
In func.h:

//Includings on which the functions depends on
#include <iostream>

//Prototypes
int square(int value);
int enterAnInt();
void printAnInt(int value);

In main.cpp:

//Main Function
#include "func.h" //Including header to access all functions

int main()
{
  //Prints the square of the value given by the user
  printAnInt(square(enterAnInt()));
  return 0;
}

In func.cpp:

#include "func.h" //Including header to access all functions

//Definations
int square(int value)
{
  return (value*value);
}
int enterAnInt()
{
  int value;
  cin >> value;
  return value;
}
void printAnInt(int value)
{
  cout << value << endl;
}

That’s the basics of having multiple file projects! This approach is also a modern approach for projects bigger than tiny! Also, I will use this approach for game development and will avoid the single file approach because it increases the quality of our code and make it more readable.

Your only task is to make a simplistic multiple file project like the one above without errors. Just try to handle the errors and find there fixes on the internet. You can ask me here as well if you encounter some errors.

C++ Programming Series: Functions/Subroutines (Part 4, Last)

In the previous post, I confused you into the depth of the functions and my abstractions although, I hope that you got the concept fairly. The hint that I gave you in the previous post is about the order of the functions. If you modified checkRegistrationEligibility() function by adding enterAString() and enterAnInt(), you may have got some error because checkRegistrationEligibility() function don’t know anything about enterAString() and enterAnInt() since, they are both defined as well as declared below the function. The issue with the order of the functions can be fixed but I will explain this later!

The functions with which we get father’s name, place of living and education in the previous post are very similar to each other. In fact, they are just the same with the exception to the statement being printed out!

Fortunately, there are more ways! Until now, we are just getting outputs from the functions in the form of returning values. But in many cases, it is necessary to have inputs in the functions. If you recall the first post on the topic of Functions/Subroutines, we discussed that a function takes the input, modifies it and then, outputs the modified input. We can always have the user input but there are many many cases where user input is not the solution! A pair of round brackets after the end of each function is not useless; it is for taking data into the function(inputs) or in other words, for taking parameters.

I had given you the task for creating a function which takes the user input for the number to be squared and then, returns the square of that number. Here it is done with a function that takes the input from the parameter, squares it and then, returns it.

int square( int value ) //a parameter of type 'int'
{
  return (value * value);
}

int main()
{
  //In 'square' function, we pass 5 as a parameter, giving us 25 as a return value.
  cout << square(5) << endl; //Outputs 25
  return 0;
}

This might have given you the idea of how parameters of a function works. Let us remove the three functions as described in the previous post namely, enterYourFatherName(), enterYourPlace() and enterYourEducation() and replace it with only one function!

string enterRequiredData( string required_data ) //a parameter of type string
{
  string data = "NULL";
  do
  {
    cout << "Enter your " << required_data << ": " << endl;
    data = enterAString();
    cout << "Is your " << required_data << " " << data << "?" << endl;
 
  } while (!isDataSure());

  cout << "Your " << required_data << " is " << data << "." << endl;
  return data;
}

Now, in the registrationSection() function:

void registrationSection()
{
  enterRequiredData("father\'s name");
  enterRequiredData("place of living");
  enterRequiredData("education");
}

All the other codes will remain same! You can see that a single function is doing quite a job because of the fact that it is more flexible now. The output of a function should depend on the parameters being given into it or else, the function should have no inputs/parameters at all. However, it is not necessary to use the output of a function for something else. In the codes above, we haven’t used the strings being returned by the functions inside the registrationSection(). We can store them in a separate file which is the prime purpose of registration (We will discuss about getting data into and out of a file soon).

That’s all! Function parameters are awesome! But there are still few problems that we may encounter, the first one is the order of functions and the second one is getting multiple outputs. You haven’t seen any example of multiple inputs/parameters as well. There you go!

int clamp(int value, int min, int max)
{
  if(value < min)
    return min;
  else if(value > max)
    return max;

  return value;
}

Try to code functions with multiple parameters and have fun with them!

C++ Programming Series: Functions/Subroutines (Part 3)

In the previous post, we have played with a function called checkRegistrationEligibility(). It was first, a function of return-type, void and now, bool. What is good with this, is the fact that this function is able to connect. From being connected, we mean that the data available in a limited scope of a function, can get available to that other function from which this function is called!

We can get the output from that function in the form of a boolean value. It is not necessary to collect the output of a function by having a specific variable for it. You can have a stupid line of code like 5+5; or true; without having any cout at the back! Sometimes, a function is of return-type int which returns a value 1, 0 or -1 only to indicate whether there is some error in the function or not and so, is not necessarily, taken into account.

In this post, we are not going to change even a bit of checkRegistrationEligibility() function. It is now, perfect. What we will do now, is to create another function for the next section of the registration program. But this time, we will create many small functions which will be grouped into more functions until a big function is created! If you don’t know about the checkRegistrationEligibility() function, please visit this post first!

Two very simple input functions which takes user input and then, return that input:

string enterAString()
{
  string str;
  getline(cin, str);
  return str;
}

int enterAnInt()
{
  int integer;
  cin >> integer; //Remember, getline() is for strings only!

  //the 'cin >>' causes rubbish in the input stream
  //which causes problems with getline()
  //the line below is a fix to it
  //it should be after every 'cin >>'
  cin.ignore();

  return integer;
}

Another function which makes sure than the user said ‘Yes’, ‘yes’, ‘Y’ or ‘y’ for reasons that are going to be obvious in the other functions.

bool isDataSure()
{
  string yes_or_no = enterAString();

  if (yes_or_no == "yes" || yes_or_no == "Yes" ||
    yes_or_no == "y" || yes_or_no == "Y")
    return true;

  //Remember, function stops to go further immediately after the 'return' keyword
  //So, there is no need for 'else'
  return false;
}

If you don’t know or just forgot the complex if conditions or just confused about the condition as the above one, just go through this post.

Now, three more functions for getting father’s name, place of living and education.

string enterYourFatherName()
{
  string father = "NULL";
  do
  {
    cout << "Enter your father\'s name: ";

    //If 'father' is declared inside, we can't return it from outside
    father = enterAString();

    cout << "Is your father\'s name " << father << "?" << endl;

  } while (!isDataSure()); //Remember, semi-colon is necessary after do-while-statement

  cout << "Your father\'s name is " << father << "." << endl;
  return father;
}

string enterYourPlace()
{
  string place = "NULL";
  do
  {
    cout << "Enter your place of living: ";
    place = enterAString();
    cout << "Is your place of living " << place << "?" << endl;
  } while (!isDataSure());
  cout << "Your place of living is " << place << "." << endl;
  return place;
}

string enterYourEducation()
{
  string education = "NULL";
  do
  {
    cout << "Enter your education: ";
    education = enterAString();
    cout << "Is your education " << education << "?" << endl;
  } while (!isDataSure());
  cout << "Your education is " << education << "." << endl;
  return education;
}

Finally, a function to have all the three functions and the main function is all set!

void registerationSection()
{
  //To keep some distance from the first section
  cout << endl;

  //Discarding the returning strings for now...
  //It can be used for various purposes!
  enterYourFatherName();
  enterYourPlace();
  enterYourEducation();
}

int main()
{
  //Instead of making a 'bool' variable and then, storing the value received
  //by checkRegistrationEligibility() method, how about using it directly?

  if (checkRegistrationEligibility() == true)
    registerationSection();

  //We can also use 'if (checkRegistrationEligibility())'
  //instead of 'if (checkRegistrationEligibility() == true)'
  return 0;
}

Here you go! All set for now accept for one thing which you will do yourself! The checkRegistrationEligibility() function requires some changes. Make sure to have enterAString() and enterAnInt() methods in it instead of the old regular methods. It is very important because we need cin.ignore() to ignore the leftovers in the input stream after cin >> to avoid problems with getline() method.

NOTE: The getline() is also a function from the standard C++ library. Same is the case for ignore() after cin. We will face many of standard C++ library functions!

After modifiying the checkRegistrationEligibility() function, it will run fine and you will be happy by the results for sure! It is easy to understand something like enterAString than the regular getline(cin,... method. Same is the case with isDataSure() which actually, gives us the hint that this function belongs to something like conforming the data to be right. In a nut shell, with the help of functions, we can make our own unique language which is understandable to everyone and not just programmers! This is something that we call as abstractions! Abstractions make things very easy. In programming, it is not simple to have even a very small task done with our basic English language. Computers don’t understand what we mean by what we say. But an approach like creating abstractions is possible. All the things we see are 0’s and 1’s which are later on, combined to form complex structures given complex names and so on. The binary can be used to define anything with reference to a name!

We defined our 0’s and 1’s into functions like enterAString(), isDataSure(), etc. The concept is to make abstractions and then, use them as much as possible to make even more abstractions. We can’t say our monitor’s screen consists of something like 0101001… but we can say it as ‘pixels’.

For now, this is it! I hope that this fulfills my promise which I talked about in the previous post and I think this much code is hard to absorb for a beginner! But don’t lose here… If code goes wrong just try, try again! Here’s a hint: See what can go wrong when we change the order of the functions! Or if you are already getting an error, see what can go right when we change the order of the functions!