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!

C++ Programming Series: Precedence, Order and sizeof()

In the previous post, we learned complex but still, simple looking conditions.

Instead of using boolean variables for complex conditions, we can directly use them in the conditional statements. Below is an example of a ‘complex looking’ complex condition:

int a = 5;
int b = 10;
int c = 15;

if( b == a + a || a == c - b && b != c - a && c > a )
{
  cout << "True!" << endl;
}
else
{
  cout << "False!" << endl;
}

Now, guess the output without executing it (or running it). It looks hard or complex to tell whether it is true or false. Actually, this will run in a specific order due to difference in the precedence. Precedence is the priority to check or run something in a statement. The precedence of AND logical operator(&&) is more than that of OR logical operator(||) which means that first, all AND logical operators will get executed and then, at last, the OR logical operator. The position do not justify the precedence; it is a property of an operator having a specific value.

Precedence helps to reduce errors. But it may be possible that programmer don’t want the order of execution in accordance with the precedence. The precedence factor can be overwritten with the use of round brackets. Following code shows the order of running or executing code due to precedence, using round brackets:

if( (b == a + a || (a == c - b && b != c - a && c > a)) )
{
  cout << "True!" << endl;
}
else
{
  cout << "False!" << endl;
}

The inner round brackets run before the outer ones. If there is only a pair of round brackets, it will run before all other code. This is how, precedence decides it to run. And the output is, “True!”. Now, below is the overwritten precedence order using round brackets:

if( ( (b == a + a || a == c - b) && b != c - a) && c > a )
{
  cout << "True!" << endl;
}
else
{
  cout << "False!" << endl;
}

In the above code, the OR logical operator will be executed first. The change in precedence is clear as the output, this time, is “False!”.

Same is the case with the arithmetic operators i.e +, -, /, *, %, ++, –, and all other operators. Here is C++ Operator Precedence Table (There are many operators that we don’t know yet! It will be helpful in future as well.)

In the post of Primitive Types, we learned types which have different memories. Sometimes, using lesser memory is a good thing and optimizes the program. How can we know the amount of memory allocated (or used) by a type or a variable? The sizeof() operator is for this purpose.

float i_am_float = 10.99f;
double i_am_double = 99.101010;

//sizeof() will return the amount of memory allocated by the type or variable, mentioned in the round brackets.
cout << sizeof(long long int) << endl;
cout << sizeof(char) << endl;
cout << sizeof(i_am_float) << endl;
cout << sizeof(i_am_double) << endl;
cout << sizeof(double) << endl; 
cout << sizeof(string) << endl; //Non-primitive type. Remember, to include string

The memory allocated by the type is not universal for all platforms and IDEs (like Visual Studio).

We will see later on, how important precedence and sizeof() is, to our programming. But for now, just do as many experiments as possible with the precedence thing. Try 2+2-2/2*2 or something like that! Try 2+value++! Just keep trying until you reveal the precedence of the operators you know at that time. Then, get the output of the above sizeof() code.

Programming is something, boring before and interesting after learning!